move control socket handling to separate file
authorOlaf Wintermann <olaf.wintermann@gmail.com>
Sat, 5 Jun 2021 17:27:43 +0000 (19:27 +0200)
committerOlaf Wintermann <olaf.wintermann@gmail.com>
Sat, 5 Jun 2021 17:27:43 +0000 (19:27 +0200)
mizucp/Makefile
mizucp/main.c
mizucp/main.h
mizucp/srvctrl.c [new file with mode: 0644]
mizucp/srvctrl.h [new file with mode: 0644]

index a8a1898..8e1e5fd 100644 (file)
@@ -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))
 
index 9dc305a..d8a05d6 100644 (file)
@@ -28,6 +28,8 @@
 
 #include "main.h"
 
+#include "srvctrl.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
 #include <ucx/utils.h>
 
-#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;i<numfds;i++) {
-            if((fds[i].revents & POLLIN) == POLLIN) {
-                CtrlClient *client = clients[i];
-                ssize_t r = read(fds[i].fd, client->buf + 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<numfds;i++) {
-                if(fds[i].events != 0) {
-                    fds[j] = fds[i];
-                    clients[j] = clients[j];
-                    j++;
-                } else {
-                    client_free(clients[i]);
-                    close(fds[i].fd);
-                }
-            }
-            numfds = j;
-        }
-        
-        if(diff >= CLIENT_UPDATE_INTERVALL) {
-            for(int i=1;i<numfds;i++) {
-                client_send_status(clients[i]);
-            }
-        }
-        
-        if(abort) break;
-        
-        timeout = numfds > 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;i<client->pos;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));
-}
index 9192835..f30b12a 100644 (file)
 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 (file)
index 0000000..4b3bbd9
--- /dev/null
@@ -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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <time.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/fcntl.h>
+#include <pthread.h>
+#include <poll.h>
+
+#include <ucx/utils.h>
+#include <libidav/utils.h>
+
+#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;i<numfds;i++) {
+            if((fds[i].revents & POLLIN) == POLLIN) {
+                CtrlClient *client = clients[i];
+                ssize_t r = read(fds[i].fd, client->buf + 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<numfds;i++) {
+                if(fds[i].events != 0) {
+                    fds[j] = fds[i];
+                    clients[j] = clients[j];
+                    j++;
+                } else {
+                    client_free(clients[i]);
+                    close(fds[i].fd);
+                }
+            }
+            numfds = j;
+        }
+        
+        if(diff >= CLIENT_UPDATE_INTERVALL) {
+            for(int i=1;i<numfds;i++) {
+                client_send_status(clients[i]);
+            }
+        }
+        
+        if(abort) break;
+        
+        timeout = numfds > 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;i<client->pos;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 (file)
index 0000000..fadb830
--- /dev/null
@@ -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 <stdlib.h>
+
+#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 */
+