From b0a25671970e6d8c7418ae07f5c2601ba56b413c Mon Sep 17 00:00:00 2001 From: Olaf Wintermann Date: Sat, 5 Jun 2021 19:27:43 +0200 Subject: [PATCH] move control socket handling to separate file --- mizucp/Makefile | 1 + mizucp/main.c | 256 ++++++----------------------------------------- mizucp/main.h | 23 ++--- mizucp/srvctrl.c | 249 +++++++++++++++++++++++++++++++++++++++++++++ mizucp/srvctrl.h | 64 ++++++++++++ 5 files changed, 354 insertions(+), 239 deletions(-) create mode 100644 mizucp/srvctrl.c create mode 100644 mizucp/srvctrl.h diff --git a/mizucp/Makefile b/mizucp/Makefile index a8a1898..8e1e5fd 100644 --- a/mizucp/Makefile +++ b/mizucp/Makefile @@ -32,6 +32,7 @@ include $(BUILD_ROOT)/config.mk CFLAGS += -I../ucx -I.. SRC = main.c +SRC += srvctrl.c OBJ = $(SRC:%.c=$(BUILD_ROOT)/build/mizucp/%.$(OBJ_EXT)) diff --git a/mizucp/main.c b/mizucp/main.c index 9dc305a..d8a05d6 100644 --- a/mizucp/main.c +++ b/mizucp/main.c @@ -28,6 +28,8 @@ #include "main.h" +#include "srvctrl.h" + #include #include #include @@ -46,18 +48,14 @@ #include -#define OPTSTR "hlpsuv" -#define TIMEOUT_IDLE -1 -#define TIMEOUT_CLIENT 1000 -#define CLIENT_UPDATE_INTERVALL 1 -static char *cfgdir; -static char *socket_path; +#define OPTSTR "hlpsuv" + -static int srvctrl; -static int eventp[2]; +static char *cfgdir; +static char *copydir; int main(int argc, char** argv) { int ret = 1; @@ -95,7 +93,7 @@ int main(int argc, char** argv) { // copy settings.from = argv[optind]; settings.to = argv[optind+1]; - ret = uwcp_copy(&settings); + ret = mzcp_copy(&settings); } else { // print usage @@ -104,81 +102,47 @@ int main(int argc, char** argv) { return ret; } -static int check_configdir(void) { - char *home = getenv(UWCP_ENV_HOME); - - cfgdir = util_concat_path(home, UWCP_CFG_DIR); - +static int check_dir(const char *path) { struct stat s; - if(stat(cfgdir, &s)) { + if(stat(path, &s)) { if(errno == ENOENT) { - if(mkdir(cfgdir, S_IRWXU)) { - fprintf(stderr, "Cannot create %s: %s", cfgdir, strerror(errno)); + if(mkdir(path, S_IRWXU)) { + fprintf(stderr, "Cannot create %s: %s", path, strerror(errno)); return 1; } } else { - fprintf(stderr, "Cannot access %s: %s", cfgdir, strerror(errno)); + fprintf(stderr, "Cannot access %s: %s", path, strerror(errno)); return 1; } } - return 0; } -static int create_control_socket(void) { - char *copydir = util_concat_path(cfgdir, UWCP_COPY_DIR); - - struct stat s; - if(stat(copydir, &s)) { - if(errno == ENOENT) { - if(mkdir(copydir, S_IRWXU)) { - fprintf(stderr, "Cannot create %s: %s", copydir, strerror(errno)); - return 1; - } - } else { - fprintf(stderr, "Cannot access %s: %s", copydir, strerror(errno)); - return 1; - } - } - - // 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); +static int check_configdir(void) { + char *home = getenv(MZCP_ENV_HOME); - 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; - } + char *base = util_concat_path(home, MZCP_CFG_BASE); + if(check_dir(base)) return 1; + free(base); + + cfgdir = util_concat_path(home, MZCP_CFG_DIR); + if(check_dir(cfgdir)) return 1; - listen(srvctrl, 4); + copydir = util_concat_path(mzcp_get_cfgdir(), MZCP_COPY_DIR); + if(check_dir(copydir)) return 1; return 0; } -int uwcp_copy(CPSettings *settings) { +const char* mzcp_get_cfgdir(void) { + return cfgdir; +} + +const char* mzcp_get_copydir(void) { + return copydir; +} + +int mzcp_copy(CPSettings *settings) { int ret = 0; if(check_configdir()) { @@ -191,7 +155,7 @@ int uwcp_copy(CPSettings *settings) { } if(settings->printsocket) { - printf("%s\n", socket_path); + printf("%s\n", mzcp_get_socketpath()); } else { printf("copy %s to %s\n", settings->from, settings->to); if(settings->pause) { @@ -206,162 +170,8 @@ int uwcp_copy(CPSettings *settings) { //close(1); //close(2); - ret = uwcp_srvctrl(settings); + ret = mzcp_srvctrl(settings); } return ret; } - -int uwcp_srvctrl(CPSettings *settings) { - if(pipe(eventp)) { - perror("Cannot create event pipe"); - return 1; - } - - 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)); -} diff --git a/mizucp/main.h b/mizucp/main.h index 9192835..f30b12a 100644 --- a/mizucp/main.h +++ b/mizucp/main.h @@ -37,9 +37,10 @@ extern "C" { #endif -#define UWCP_ENV_HOME "HOME" -#define UWCP_CFG_DIR ".uwfile" -#define UWCP_COPY_DIR "copy" +#define MZCP_ENV_HOME "HOME" +#define MZCP_CFG_BASE ".config" +#define MZCP_CFG_DIR ".config/mizunara" +#define MZCP_COPY_DIR "copy" #define CLIENT_MSG_BUFSIZE 512 @@ -53,22 +54,12 @@ typedef struct { CPBool printsocket; } CPSettings; -typedef struct { - int fd; - char buf[CLIENT_MSG_BUFSIZE]; - size_t pos; -} CtrlClient; - -int uwcp_copy(CPSettings *settings); - -int uwcp_srvctrl(CPSettings *settings); +const char* mzcp_get_cfgdir(void); +const char* mzcp_get_copydir(void); -void client_free(CtrlClient *client); +int mzcp_copy(CPSettings *settings); -int handle_messages(CtrlClient *client); -int handle_client_msg(CtrlClient *client, sstr_t msg); -void client_send_status(CtrlClient *client); #ifdef __cplusplus } 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)); +} diff --git a/mizucp/srvctrl.h b/mizucp/srvctrl.h new file mode 100644 index 0000000..fadb830 --- /dev/null +++ b/mizucp/srvctrl.h @@ -0,0 +1,64 @@ +/* + * 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. + */ + +#ifndef SRVTRL_H +#define SRVTRL_H + +#include "main.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + int fd; + char buf[CLIENT_MSG_BUFSIZE]; + size_t pos; +} CtrlClient; + +int create_control_socket(void); + +const char* mzcp_get_socketpath(void); + +int mzcp_srvctrl(CPSettings *settings); + +void client_free(CtrlClient *client); + +int handle_messages(CtrlClient *client); +int handle_client_msg(CtrlClient *client, sstr_t msg); + +void client_send_status(CtrlClient *client); + +#ifdef __cplusplus +} +#endif + +#endif /* SRVTRL_H */ + -- 2.43.5