X-Git-Url: https://develop.uap-core.de/gitweb/mizunara.git/blobdiff_plain/6de1fe1dd8731d4d952657181f871f9723bbb8b2..b0a25671970e6d8c7418ae07f5c2601ba56b413c:/mizucp/srvctrl.c diff --git a/mizucp/srvctrl.c b/mizucp/srvctrl.c new file mode 100644 index 0000000..4b3bbd9 --- /dev/null +++ b/mizucp/srvctrl.c @@ -0,0 +1,249 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2021 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "srvctrl.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define TIMEOUT_IDLE -1 +#define TIMEOUT_CLIENT 1000 +#define CLIENT_UPDATE_INTERVALL 1 + +static char *socket_path; + +static int srvctrl; + + +int create_control_socket(void) { + const char *copydir = mzcp_get_copydir(); + + // create unix domain socket + char *random_str = util_random_str(); + sstr_t socketp = ucx_sprintf("%s/%.*s", copydir, 8, random_str); + free(random_str); + socket_path = socketp.ptr; + + struct sockaddr_un addr; + if(socketp.length > sizeof(addr.sun_path)-1) { + fprintf(stderr, + "path '%s' too long for unix domain socket", + socketp.ptr); + return 1; + } + + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + memcpy(addr.sun_path, socketp.ptr, socketp.length); + + srvctrl = socket(AF_UNIX, SOCK_STREAM, 0); + if(srvctrl == -1) { + fprintf(stderr, + "Cannot create server control socket: %s", + strerror(errno)); + return 1; + } + if(bind(srvctrl, (struct sockaddr*)&addr, sizeof(addr))) { + fprintf(stderr, + "srvctrl socket bind failed: %s", + strerror(errno)); + return 1; + } + + listen(srvctrl, 4); + + return 0; +} + +const char* mzcp_get_socketpath(void) { + return socket_path; +} + +int mzcp_srvctrl(CPSettings *settings) { + + size_t allocfds = 8; + size_t numfds = 1; + + struct pollfd *fds = calloc(allocfds, sizeof(struct pollfd)); + CtrlClient **clients = calloc(allocfds, sizeof(void*)); + + int timeout = TIMEOUT_IDLE; + + fds[0].fd = srvctrl; + fds[0].events = POLLIN; + + int abort = 0; + + time_t tbegin = time(NULL); + + while(poll(fds, numfds, 1000) >= 0) { + time_t tend = time(NULL); + time_t diff = tend - tbegin; + tbegin = tend; + + if((fds[0].revents & POLLIN) == POLLIN) { + printf("accept\n"); + int fd = accept(srvctrl, NULL, 0); + if(fd < 0) { + break; + } + + //int flags = fcntl(fd, F_GETFL, 0); + //flags = flags & ~O_NONBLOCK; + //fcntl(fd, F_SETFL, flags); + + CtrlClient *client = malloc(sizeof(CtrlClient)); + memset(client, 0, sizeof(CtrlClient)); + client->fd = fd; + + printf("add client: %d\n", client->fd); + + fds[numfds].fd = client->fd; + fds[numfds].events = POLLIN; + fds[numfds].revents = 0; + clients[numfds] = client; + numfds++; + } + + // check clients + int remove = 0; + for(int i=1;ibuf + client->pos, CLIENT_MSG_BUFSIZE - client->pos); + if(r <= 0) { + printf("remove client: %d\n", fds[i].fd); + fds[i].events = 0; + remove = 1; + } else { + client->pos += r; + + int msgret = handle_messages(client); + if(msgret == 1) { + fds[i].events = 0; + remove = 1; + } else if(msgret == -1) { + abort = 1; + } + } + } + } + + if(remove) { + int j = 1; + for(int i=1;i= CLIENT_UPDATE_INTERVALL) { + for(int i=1;i 1 ? TIMEOUT_CLIENT : TIMEOUT_IDLE; + } + + unlink(socket_path); + + return 0; +} + + +void client_free(CtrlClient *client) { + free(client); +} + +int handle_messages(CtrlClient *client) { + if(client->pos == CLIENT_MSG_BUFSIZE) { + return 1; + } + + int msgstart = 0; + for(int i=0;ipos;i++) { + if(client->buf[i] == '\n') { + sstr_t msg; + msg.ptr = &client->buf[msgstart]; + msg.length = i - msgstart; + msgstart = i+1; + + int msgret = handle_client_msg(client, msg); + if(msgret) return msgret; + } + } + + if(msgstart < client->pos) { + // incomplete message + memmove(client->buf, client->buf + msgstart, client->pos - msgstart); + client->pos -= msgstart; + } else { + client->pos = 0; + } + + return 0; +} + +int handle_client_msg(CtrlClient *client, sstr_t msg) { + printf("msg: %.*s\n", (int)msg.length, msg.ptr); + + if(!sstrcmp(msg, S("abort"))) { + return -1; + } + + return 0; +} + +void client_send_status(CtrlClient *client) { + char *msg = "s 0\n"; + write(client->fd, msg, strlen(msg)); +}