2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4 * Copyright 2021 Olaf Wintermann. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
39 #include <sys/socket.h>
41 #include <sys/fcntl.h>
45 #include <ucx/utils.h>
46 #include <libidav/utils.h>
48 #define TIMEOUT_IDLE -1
49 #define TIMEOUT_CLIENT 1000
50 #define CLIENT_UPDATE_INTERVALL 1
52 static char *socket_path;
57 int create_control_socket(void) {
58 const char *copydir = mzcp_get_copydir();
60 // create unix domain socket
61 char *random_str = util_random_str();
62 sstr_t socketp = ucx_sprintf("%s/%.*s", copydir, 8, random_str);
64 socket_path = socketp.ptr;
66 struct sockaddr_un addr;
67 if(socketp.length > sizeof(addr.sun_path)-1) {
69 "path '%s' too long for unix domain socket",
74 memset(&addr, 0, sizeof(addr));
75 addr.sun_family = AF_UNIX;
76 memcpy(addr.sun_path, socketp.ptr, socketp.length);
78 srvctrl = socket(AF_UNIX, SOCK_STREAM, 0);
81 "Cannot create server control socket: %s",
85 if(bind(srvctrl, (struct sockaddr*)&addr, sizeof(addr))) {
87 "srvctrl socket bind failed: %s",
97 const char* mzcp_get_socketpath(void) {
101 int mzcp_srvctrl(CPSettings *settings) {
106 struct pollfd *fds = calloc(allocfds, sizeof(struct pollfd));
107 CtrlClient **clients = calloc(allocfds, sizeof(void*));
109 int timeout = TIMEOUT_IDLE;
112 fds[0].events = POLLIN;
116 time_t tbegin = time(NULL);
118 while(poll(fds, numfds, 1000) >= 0) {
119 time_t tend = time(NULL);
120 time_t diff = tend - tbegin;
123 if((fds[0].revents & POLLIN) == POLLIN) {
125 int fd = accept(srvctrl, NULL, 0);
130 //int flags = fcntl(fd, F_GETFL, 0);
131 //flags = flags & ~O_NONBLOCK;
132 //fcntl(fd, F_SETFL, flags);
134 CtrlClient *client = malloc(sizeof(CtrlClient));
135 memset(client, 0, sizeof(CtrlClient));
138 printf("add client: %d\n", client->fd);
140 fds[numfds].fd = client->fd;
141 fds[numfds].events = POLLIN;
142 fds[numfds].revents = 0;
143 clients[numfds] = client;
149 for(int i=1;i<numfds;i++) {
150 if((fds[i].revents & POLLIN) == POLLIN) {
151 CtrlClient *client = clients[i];
152 ssize_t r = read(fds[i].fd, client->buf + client->pos, CLIENT_MSG_BUFSIZE - client->pos);
154 printf("remove client: %d\n", fds[i].fd);
160 int msgret = handle_messages(client);
164 } else if(msgret == -1) {
173 for(int i=1;i<numfds;i++) {
174 if(fds[i].events != 0) {
176 clients[j] = clients[j];
179 client_free(clients[i]);
186 if(diff >= CLIENT_UPDATE_INTERVALL) {
187 for(int i=1;i<numfds;i++) {
188 client_send_status(clients[i]);
194 timeout = numfds > 1 ? TIMEOUT_CLIENT : TIMEOUT_IDLE;
203 void client_free(CtrlClient *client) {
207 int handle_messages(CtrlClient *client) {
208 if(client->pos == CLIENT_MSG_BUFSIZE) {
213 for(int i=0;i<client->pos;i++) {
214 if(client->buf[i] == '\n') {
216 msg.ptr = &client->buf[msgstart];
217 msg.length = i - msgstart;
220 int msgret = handle_client_msg(client, msg);
221 if(msgret) return msgret;
225 if(msgstart < client->pos) {
226 // incomplete message
227 memmove(client->buf, client->buf + msgstart, client->pos - msgstart);
228 client->pos -= msgstart;
236 int handle_client_msg(CtrlClient *client, sstr_t msg) {
237 printf("msg: %.*s\n", (int)msg.length, msg.ptr);
239 if(!sstrcmp(msg, S("abort"))) {
246 void client_send_status(CtrlClient *client) {
248 write(client->fd, msg, strlen(msg));