ambrop7 15 rokov pred
rodič
commit
33f789293b

+ 1 - 0
blog_channels.txt

@@ -62,3 +62,4 @@ PacketProtoDecoder 4
 DPRelay 4
 BThreadWork 4
 DPReceive 4
+BInputProcess 4

+ 4 - 0
generated/blog_channel_BInputProcess.h

@@ -0,0 +1,4 @@
+#ifdef BLOG_CURRENT_CHANNEL
+#undef BLOG_CURRENT_CHANNEL
+#endif
+#define BLOG_CURRENT_CHANNEL BLOG_CHANNEL_BInputProcess

+ 2 - 1
generated/blog_channels_defines.h

@@ -62,4 +62,5 @@
 #define BLOG_CHANNEL_DPRelay 61
 #define BLOG_CHANNEL_BThreadWork 62
 #define BLOG_CHANNEL_DPReceive 63
-#define BLOG_NUM_CHANNELS 64
+#define BLOG_CHANNEL_BInputProcess 64
+#define BLOG_NUM_CHANNELS 65

+ 1 - 0
generated/blog_channels_list.h

@@ -62,3 +62,4 @@
 {.name = "DPRelay", .loglevel = 4},
 {.name = "BThreadWork", .loglevel = 4},
 {.name = "DPReceive", .loglevel = 4},
+{.name = "BInputProcess", .loglevel = 4},

+ 182 - 0
inputprocess/BInputProcess.c

@@ -0,0 +1,182 @@
+/**
+ * @file BInputProcess.c
+ * @author Ambroz Bizjak <ambrop7@gmail.com>
+ * 
+ * @section LICENSE
+ * 
+ * This file is part of BadVPN.
+ * 
+ * BadVPN is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ * 
+ * BadVPN is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <unistd.h>
+
+#include <system/BLog.h>
+
+#include <inputprocess/BInputProcess.h>
+
+#include <generated/blog_channel_BInputProcess.h>
+
+static int init_pipe (BInputProcess *o, int pipe_fd);
+static void free_pipe (BInputProcess *o);
+static void process_pipe_handler_error (BInputProcess *o, int component, int code);
+static void process_handler (BInputProcess *o, int normally, uint8_t normally_exit_status);
+
+int init_pipe (BInputProcess *o, int pipe_fd)
+{
+    // init socket
+    if (BSocket_InitPipe(&o->pipe_sock, o->reactor, pipe_fd) < 0) {
+        BLog(BLOG_ERROR, "BSocket_InitPipe failed");
+        goto fail0;
+    }
+    
+    // init domain
+    FlowErrorDomain_Init(&o->pipe_domain, (FlowErrorDomain_handler)process_pipe_handler_error, o);
+    
+    // init source
+    StreamSocketSource_Init(&o->pipe_source, FlowErrorReporter_Create(&o->pipe_domain, 0), &o->pipe_sock, BReactor_PendingGroup(o->reactor));
+    
+    return 1;
+    
+fail0:
+    return 0;
+}
+
+void free_pipe (BInputProcess *o)
+{
+    // free source
+    StreamSocketSource_Free(&o->pipe_source);
+    
+    // free socket
+    BSocket_Free(&o->pipe_sock);
+}
+
+void process_pipe_handler_error (BInputProcess *o, int component, int code)
+{
+    DebugObject_Access(&o->d_obj);
+    ASSERT(o->pipe_fd >= 0)
+    
+    if (code == STREAMSOCKETSOURCE_ERROR_CLOSED) {
+        BLog(BLOG_INFO, "pipe eof");
+    } else {
+        BLog(BLOG_ERROR, "pipe error");
+    }
+    
+    // free pipe reading
+    free_pipe(o);
+    
+    // close pipe read end
+    ASSERT_FORCE(close(o->pipe_fd) == 0)
+    
+    // forget pipe
+    o->pipe_fd = -1;
+    
+    // call closed handler
+    o->handler_closed(o->user, (code != STREAMSOCKETSOURCE_ERROR_CLOSED));
+    return;
+}
+
+void process_handler (BInputProcess *o, int normally, uint8_t normally_exit_status)
+{
+    DebugObject_Access(&o->d_obj);
+    
+    DEBUGERROR(&o->d_err, o->handler_terminated(o->user, normally, normally_exit_status));
+}
+
+int BInputProcess_Init (BInputProcess *o, const char *file, char *const argv[], const char *username, BReactor *reactor, BProcessManager *manager, void *user,
+                        BInputProcess_handler_terminated handler_terminated,
+                        BInputProcess_handler_closed handler_closed)
+{
+    // init arguments
+    o->reactor = reactor;
+    o->user = user;
+    o->handler_terminated = handler_terminated;
+    o->handler_closed = handler_closed;
+    
+    // create pipe
+    int pipefds[2];
+    if (pipe(pipefds) < 0) {
+        BLog(BLOG_ERROR, "pipe failed");
+        goto fail0;
+    }
+    
+    // init pipe reading
+    if (!init_pipe(o, pipefds[0])) {
+        goto fail1;
+    }
+    
+    // start process
+    int fds[] = { pipefds[1], -1 };
+    int fds_map[] = { 1 };
+    if (!BProcess_InitWithFds(&o->process, manager, (BProcess_handler)process_handler, o, file, argv, username, fds, fds_map)) {
+        BLog(BLOG_ERROR, "BProcess_Init failed");
+        goto fail2;
+    }
+    
+    // remember pipe read end
+    o->pipe_fd = pipefds[0];
+    
+    DebugError_Init(&o->d_err, BReactor_PendingGroup(o->reactor));
+    DebugObject_Init(&o->d_obj);
+    return 1;
+    
+fail2:
+    free_pipe(o);
+fail1:
+    ASSERT_FORCE(close(pipefds[0]) == 0)
+    ASSERT_FORCE(close(pipefds[1]) == 0)
+fail0:
+    return 0;
+}
+
+void BInputProcess_Free (BInputProcess *o)
+{
+    DebugObject_Free(&o->d_obj);
+    DebugError_Free(&o->d_err);
+    
+    // free process
+    BProcess_Free(&o->process);
+    
+    if (o->pipe_fd >= 0) {
+        // free pipe reading
+        free_pipe(o);
+        
+        // close pipe read end
+        ASSERT_FORCE(close(o->pipe_fd) == 0)
+    }
+}
+
+int BInputProcess_Terminate (BInputProcess *o)
+{
+    DebugObject_Access(&o->d_obj);
+    DebugError_AssertNoError(&o->d_err);
+    
+    return BProcess_Terminate(&o->process);
+}
+
+int BInputProcess_Kill (BInputProcess *o)
+{
+    DebugObject_Access(&o->d_obj);
+    DebugError_AssertNoError(&o->d_err);
+    
+    return BProcess_Kill(&o->process);
+}
+
+StreamRecvInterface * BInputProcess_GetInput (BInputProcess *o)
+{
+    DebugObject_Access(&o->d_obj);
+    ASSERT(o->pipe_fd >= 0)
+    
+    return StreamSocketSource_GetOutput(&o->pipe_source);
+}

+ 58 - 0
inputprocess/BInputProcess.h

@@ -0,0 +1,58 @@
+/**
+ * @file BInputProcess.h
+ * @author Ambroz Bizjak <ambrop7@gmail.com>
+ * 
+ * @section LICENSE
+ * 
+ * This file is part of BadVPN.
+ * 
+ * BadVPN is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ * 
+ * BadVPN is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef BADVPN_INPUTPROCESS_BINPUTPROCESS_H
+#define BADVPN_INPUTPROCESS_BINPUTPROCESS_H
+
+#include <misc/debug.h>
+#include <misc/debugerror.h>
+#include <system/DebugObject.h>
+#include <system/BSocket.h>
+#include <process/BProcess.h>
+#include <flow/StreamSocketSource.h>
+
+typedef void (*BInputProcess_handler_terminated) (void *user, int normally, uint8_t normally_exit_status);
+typedef void (*BInputProcess_handler_closed) (void *user, int is_error);
+
+typedef struct {
+    BReactor *reactor;
+    void *user;
+    BInputProcess_handler_terminated handler_terminated;
+    BInputProcess_handler_closed handler_closed;
+    BProcess process;
+    int pipe_fd;
+    BSocket pipe_sock;
+    FlowErrorDomain pipe_domain;
+    StreamSocketSource pipe_source;
+    DebugObject d_obj;
+    DebugError d_err;
+} BInputProcess;
+
+int BInputProcess_Init (BInputProcess *o, const char *file, char *const argv[], const char *username, BReactor *reactor, BProcessManager *manager, void *user,
+                        BInputProcess_handler_terminated handler_terminated,
+                        BInputProcess_handler_closed handler_closed) WARN_UNUSED;
+void BInputProcess_Free (BInputProcess *o);
+int BInputProcess_Terminate (BInputProcess *o);
+int BInputProcess_Kill (BInputProcess *o);
+StreamRecvInterface * BInputProcess_GetInput (BInputProcess *o);
+
+#endif

+ 4 - 0
inputprocess/CMakeLists.txt

@@ -0,0 +1,4 @@
+add_library(inputprocess
+    BInputProcess.c
+)
+target_link_libraries(inputprocess system flow process)