ambrop7 пре 14 година
родитељ
комит
eb57248dbd

+ 1 - 0
blog_channels.txt

@@ -21,6 +21,7 @@ ncd_ip_in_network 4
 ncd_run 4
 ncd_run 4
 ncd_runonce 4
 ncd_runonce 4
 ncd_synchronous_process 4
 ncd_synchronous_process 4
+ncd_call 4
 ncd_process_manager 4
 ncd_process_manager 4
 ncd_net_backend_waitdevice 4
 ncd_net_backend_waitdevice 4
 ncd_net_backend_waitlink 4
 ncd_net_backend_waitlink 4

+ 4 - 0
generated/blog_channel_ncd_call.h

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

+ 65 - 64
generated/blog_channels_defines.h

@@ -21,67 +21,68 @@
 #define BLOG_CHANNEL_ncd_run 20
 #define BLOG_CHANNEL_ncd_run 20
 #define BLOG_CHANNEL_ncd_runonce 21
 #define BLOG_CHANNEL_ncd_runonce 21
 #define BLOG_CHANNEL_ncd_synchronous_process 22
 #define BLOG_CHANNEL_ncd_synchronous_process 22
-#define BLOG_CHANNEL_ncd_process_manager 23
-#define BLOG_CHANNEL_ncd_net_backend_waitdevice 24
-#define BLOG_CHANNEL_ncd_net_backend_waitlink 25
-#define BLOG_CHANNEL_ncd_net_backend_badvpn 26
-#define BLOG_CHANNEL_ncd_net_backend_wpa_supplicant 27
-#define BLOG_CHANNEL_ncd_net_backend_rfkill 28
-#define BLOG_CHANNEL_ncd_net_up 29
-#define BLOG_CHANNEL_ncd_net_dns 30
-#define BLOG_CHANNEL_ncd_net_iptables 31
-#define BLOG_CHANNEL_ncd_net_ipv4_addr 32
-#define BLOG_CHANNEL_ncd_net_ipv4_route 33
-#define BLOG_CHANNEL_ncd_net_ipv4_dhcp 34
-#define BLOG_CHANNEL_ncd_net_watch_interfaces 35
-#define BLOG_CHANNEL_ncd_sys_watch_input 36
-#define BLOG_CHANNEL_ncd_sys_evdev 37
-#define BLOG_CHANNEL_ncd_sys_watch_directory 38
-#define BLOG_CHANNEL_StreamPeerIO 39
-#define BLOG_CHANNEL_DatagramPeerIO 40
-#define BLOG_CHANNEL_BReactor 41
-#define BLOG_CHANNEL_BSignal 42
-#define BLOG_CHANNEL_FragmentProtoAssembler 43
-#define BLOG_CHANNEL_BPredicate 44
-#define BLOG_CHANNEL_ServerConnection 45
-#define BLOG_CHANNEL_Listener 46
-#define BLOG_CHANNEL_DataProto 47
-#define BLOG_CHANNEL_FrameDecider 48
-#define BLOG_CHANNEL_BSocksClient 49
-#define BLOG_CHANNEL_BDHCPClientCore 50
-#define BLOG_CHANNEL_BDHCPClient 51
-#define BLOG_CHANNEL_NCDIfConfig 52
-#define BLOG_CHANNEL_BUnixSignal 53
-#define BLOG_CHANNEL_BProcess 54
-#define BLOG_CHANNEL_PRStreamSink 55
-#define BLOG_CHANNEL_PRStreamSource 56
-#define BLOG_CHANNEL_PacketProtoDecoder 57
-#define BLOG_CHANNEL_DPRelay 58
-#define BLOG_CHANNEL_BThreadWork 59
-#define BLOG_CHANNEL_DPReceive 60
-#define BLOG_CHANNEL_BInputProcess 61
-#define BLOG_CHANNEL_NCDUdevMonitorParser 62
-#define BLOG_CHANNEL_NCDUdevMonitor 63
-#define BLOG_CHANNEL_NCDUdevCache 64
-#define BLOG_CHANNEL_NCDUdevManager 65
-#define BLOG_CHANNEL_BTime 66
-#define BLOG_CHANNEL_BEncryption 67
-#define BLOG_CHANNEL_SPProtoDecoder 68
-#define BLOG_CHANNEL_LineBuffer 69
-#define BLOG_CHANNEL_BTap 70
-#define BLOG_CHANNEL_lwip 71
-#define BLOG_CHANNEL_NCDConfigParser 72
-#define BLOG_CHANNEL_nsskey 73
-#define BLOG_CHANNEL_addr 74
-#define BLOG_CHANNEL_PasswordListener 75
-#define BLOG_CHANNEL_NCDInterfaceMonitor 76
-#define BLOG_CHANNEL_NCDRfkillMonitor 77
-#define BLOG_CHANNEL_udpgw 78
-#define BLOG_CHANNEL_UdpGwClient 79
-#define BLOG_CHANNEL_SocksUdpGwClient 80
-#define BLOG_CHANNEL_BNetwork 81
-#define BLOG_CHANNEL_BConnection 82
-#define BLOG_CHANNEL_BSSLConnection 83
-#define BLOG_CHANNEL_BDatagram 84
-#define BLOG_CHANNEL_PeerChat 85
-#define BLOG_NUM_CHANNELS 86
+#define BLOG_CHANNEL_ncd_call 23
+#define BLOG_CHANNEL_ncd_process_manager 24
+#define BLOG_CHANNEL_ncd_net_backend_waitdevice 25
+#define BLOG_CHANNEL_ncd_net_backend_waitlink 26
+#define BLOG_CHANNEL_ncd_net_backend_badvpn 27
+#define BLOG_CHANNEL_ncd_net_backend_wpa_supplicant 28
+#define BLOG_CHANNEL_ncd_net_backend_rfkill 29
+#define BLOG_CHANNEL_ncd_net_up 30
+#define BLOG_CHANNEL_ncd_net_dns 31
+#define BLOG_CHANNEL_ncd_net_iptables 32
+#define BLOG_CHANNEL_ncd_net_ipv4_addr 33
+#define BLOG_CHANNEL_ncd_net_ipv4_route 34
+#define BLOG_CHANNEL_ncd_net_ipv4_dhcp 35
+#define BLOG_CHANNEL_ncd_net_watch_interfaces 36
+#define BLOG_CHANNEL_ncd_sys_watch_input 37
+#define BLOG_CHANNEL_ncd_sys_evdev 38
+#define BLOG_CHANNEL_ncd_sys_watch_directory 39
+#define BLOG_CHANNEL_StreamPeerIO 40
+#define BLOG_CHANNEL_DatagramPeerIO 41
+#define BLOG_CHANNEL_BReactor 42
+#define BLOG_CHANNEL_BSignal 43
+#define BLOG_CHANNEL_FragmentProtoAssembler 44
+#define BLOG_CHANNEL_BPredicate 45
+#define BLOG_CHANNEL_ServerConnection 46
+#define BLOG_CHANNEL_Listener 47
+#define BLOG_CHANNEL_DataProto 48
+#define BLOG_CHANNEL_FrameDecider 49
+#define BLOG_CHANNEL_BSocksClient 50
+#define BLOG_CHANNEL_BDHCPClientCore 51
+#define BLOG_CHANNEL_BDHCPClient 52
+#define BLOG_CHANNEL_NCDIfConfig 53
+#define BLOG_CHANNEL_BUnixSignal 54
+#define BLOG_CHANNEL_BProcess 55
+#define BLOG_CHANNEL_PRStreamSink 56
+#define BLOG_CHANNEL_PRStreamSource 57
+#define BLOG_CHANNEL_PacketProtoDecoder 58
+#define BLOG_CHANNEL_DPRelay 59
+#define BLOG_CHANNEL_BThreadWork 60
+#define BLOG_CHANNEL_DPReceive 61
+#define BLOG_CHANNEL_BInputProcess 62
+#define BLOG_CHANNEL_NCDUdevMonitorParser 63
+#define BLOG_CHANNEL_NCDUdevMonitor 64
+#define BLOG_CHANNEL_NCDUdevCache 65
+#define BLOG_CHANNEL_NCDUdevManager 66
+#define BLOG_CHANNEL_BTime 67
+#define BLOG_CHANNEL_BEncryption 68
+#define BLOG_CHANNEL_SPProtoDecoder 69
+#define BLOG_CHANNEL_LineBuffer 70
+#define BLOG_CHANNEL_BTap 71
+#define BLOG_CHANNEL_lwip 72
+#define BLOG_CHANNEL_NCDConfigParser 73
+#define BLOG_CHANNEL_nsskey 74
+#define BLOG_CHANNEL_addr 75
+#define BLOG_CHANNEL_PasswordListener 76
+#define BLOG_CHANNEL_NCDInterfaceMonitor 77
+#define BLOG_CHANNEL_NCDRfkillMonitor 78
+#define BLOG_CHANNEL_udpgw 79
+#define BLOG_CHANNEL_UdpGwClient 80
+#define BLOG_CHANNEL_SocksUdpGwClient 81
+#define BLOG_CHANNEL_BNetwork 82
+#define BLOG_CHANNEL_BConnection 83
+#define BLOG_CHANNEL_BSSLConnection 84
+#define BLOG_CHANNEL_BDatagram 85
+#define BLOG_CHANNEL_PeerChat 86
+#define BLOG_NUM_CHANNELS 87

+ 1 - 0
generated/blog_channels_list.h

@@ -21,6 +21,7 @@
 {.name = "ncd_run", .loglevel = 4},
 {.name = "ncd_run", .loglevel = 4},
 {.name = "ncd_runonce", .loglevel = 4},
 {.name = "ncd_runonce", .loglevel = 4},
 {.name = "ncd_synchronous_process", .loglevel = 4},
 {.name = "ncd_synchronous_process", .loglevel = 4},
+{.name = "ncd_call", .loglevel = 4},
 {.name = "ncd_process_manager", .loglevel = 4},
 {.name = "ncd_process_manager", .loglevel = 4},
 {.name = "ncd_net_backend_waitdevice", .loglevel = 4},
 {.name = "ncd_net_backend_waitdevice", .loglevel = 4},
 {.name = "ncd_net_backend_waitlink", .loglevel = 4},
 {.name = "ncd_net_backend_waitlink", .loglevel = 4},

+ 1 - 0
ncd/CMakeLists.txt

@@ -55,6 +55,7 @@ add_executable(badvpn-ncd
     modules/run.c
     modules/run.c
     modules/runonce.c
     modules/runonce.c
     modules/synchronous_process.c
     modules/synchronous_process.c
+    modules/call.c
     modules/process_manager.c
     modules/process_manager.c
     modules/net_backend_waitdevice.c
     modules/net_backend_waitdevice.c
     modules/net_backend_waitlink.c
     modules/net_backend_waitlink.c

+ 198 - 0
ncd/modules/call.c

@@ -0,0 +1,198 @@
+/**
+ * @file call.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.
+ * 
+ * @section DESCRIPTION
+ * 
+ * Synopsis: call(string template_name, list args)
+ * Description:
+ *   Module which allows using a single statement to represent multiple statements
+ *   in a process template, allowing reuse of repetitive code.
+ * 
+ *   Behavior in detail:
+ *   - On initialization, creates a new process from the template named
+ *     template_name, with arguments args.
+ *   - When all the statements in the created process go UP, transitions UP.
+ *   - When one of the statements is no longer UP, transitions DOWN. The
+ *     created process remais paused until the call statement receives the
+ *     clean signal, to wait for following statements to deinitialize.
+ *   - On deinitialization, initiates termination of the created process and waits
+ *     for all its statements to deinitialize.
+ */
+
+#include <stdlib.h>
+
+#include <ncd/NCDModule.h>
+
+#include <generated/blog_channel_ncd_call.h>
+
+#define ModuleLog(i, ...) NCDModuleInst_Backend_Log((i), BLOG_CURRENT_CHANNEL, __VA_ARGS__)
+
+#define STATE_WORKING 1
+#define STATE_UP 2
+#define STATE_WAITING 3
+#define STATE_TERMINATING 4
+
+struct instance {
+    NCDModuleInst *i;
+    NCDModuleProcess process;
+    int state;
+};
+
+static void instance_free (struct instance *o);
+
+static void process_handler_event (struct instance *o, int event)
+{
+    switch (event) {
+        case NCDMODULEPROCESS_EVENT_UP: {
+            ASSERT(o->state == STATE_WORKING)
+            
+            // signal up
+            NCDModuleInst_Backend_Event(o->i, NCDMODULE_EVENT_UP);
+            
+            // set state up
+            o->state = STATE_UP;
+        } break;
+        
+        case NCDMODULEPROCESS_EVENT_DOWN: {
+            ASSERT(o->state == STATE_UP)
+            
+            // signal down
+            NCDModuleInst_Backend_Event(o->i, NCDMODULE_EVENT_DOWN);
+            
+            // set state waiting
+            o->state = STATE_WAITING;
+        } break;
+        
+        case NCDMODULEPROCESS_EVENT_TERMINATED: {
+            ASSERT(o->state == STATE_TERMINATING)
+            
+            // die finally
+            instance_free(o);
+            return;
+        } break;
+        
+        default: ASSERT(0);
+    }
+}
+
+static void func_new (NCDModuleInst *i)
+{
+    // allocate instance
+    struct instance *o = malloc(sizeof(*o));
+    if (!o) {
+        ModuleLog(i, BLOG_ERROR, "failed to allocate instance");
+        goto fail0;
+    }
+    NCDModuleInst_Backend_SetUser(i, o);
+    
+    // init arguments
+    o->i = i;
+    
+    // check arguments
+    NCDValue *template_name_arg;
+    NCDValue *args_arg;
+    if (!NCDValue_ListRead(o->i->args, 2, &template_name_arg, &args_arg)) {
+        ModuleLog(o->i, BLOG_ERROR, "wrong arity");
+        goto fail1;
+    }
+    if (NCDValue_Type(template_name_arg) != NCDVALUE_STRING || NCDValue_Type(args_arg) != NCDVALUE_LIST) {
+        ModuleLog(o->i, BLOG_ERROR, "wrong type");
+        goto fail1;
+    }
+    
+    // copy arguments
+    NCDValue args;
+    if (!NCDValue_InitCopy(&args, args_arg)) {
+        ModuleLog(o->i, BLOG_ERROR, "NCDValue_InitCopy failed");
+        goto fail1;
+    }
+    
+    // create process
+    if (!NCDModuleProcess_Init(&o->process, o->i, NCDValue_StringValue(template_name_arg), args, o, (NCDModuleProcess_handler_event)process_handler_event)) {
+        ModuleLog(o->i, BLOG_ERROR, "NCDModuleProcess_Init failed");
+        NCDValue_Free(&args);
+        goto fail1;
+    }
+    
+    // set state working
+    o->state = STATE_WORKING;
+    return;
+    
+fail1:
+    free(o);
+fail0:
+    NCDModuleInst_Backend_SetError(i);
+    NCDModuleInst_Backend_Event(i, NCDMODULE_EVENT_DEAD);
+}
+
+void instance_free (struct instance *o)
+{
+    NCDModuleInst *i = o->i;
+    
+    // free process
+    NCDModuleProcess_Free(&o->process);
+    
+    // free instance
+    free(o);
+    
+    NCDModuleInst_Backend_Event(i, NCDMODULE_EVENT_DEAD);
+}
+
+static void func_die (void *vo)
+{
+    struct instance *o = vo;
+    ASSERT(o->state != STATE_TERMINATING)
+    
+    // request process to terminate
+    NCDModuleProcess_Terminate(&o->process);
+    
+    // set state terminating
+    o->state = STATE_TERMINATING;
+}
+
+static void func_clean (void *vo)
+{
+    struct instance *o = vo;
+    if (o->state != STATE_WAITING) {
+        return;
+    }
+    
+    // allow process to continue
+    NCDModuleProcess_Continue(&o->process);
+    
+    // set state working
+    o->state = STATE_WORKING;
+}
+
+static const struct NCDModule modules[] = {
+    {
+        .type = "call",
+        .func_new = func_new,
+        .func_die = func_die,
+        .func_clean = func_clean
+    }, {
+        .type = NULL
+    }
+};
+
+const struct NCDModuleGroup ncdmodule_call = {
+    .modules = modules
+};

+ 2 - 0
ncd/modules/modules.h

@@ -45,6 +45,7 @@ extern const struct NCDModuleGroup ncdmodule_ip_in_network;
 extern const struct NCDModuleGroup ncdmodule_run;
 extern const struct NCDModuleGroup ncdmodule_run;
 extern const struct NCDModuleGroup ncdmodule_runonce;
 extern const struct NCDModuleGroup ncdmodule_runonce;
 extern const struct NCDModuleGroup ncdmodule_synchronous_process;
 extern const struct NCDModuleGroup ncdmodule_synchronous_process;
+extern const struct NCDModuleGroup ncdmodule_call;
 extern const struct NCDModuleGroup ncdmodule_process_manager;
 extern const struct NCDModuleGroup ncdmodule_process_manager;
 extern const struct NCDModuleGroup ncdmodule_net_backend_waitdevice;
 extern const struct NCDModuleGroup ncdmodule_net_backend_waitdevice;
 extern const struct NCDModuleGroup ncdmodule_net_backend_waitlink;
 extern const struct NCDModuleGroup ncdmodule_net_backend_waitlink;
@@ -87,6 +88,7 @@ static const struct NCDModuleGroup *ncd_modules[] = {
     &ncdmodule_run,
     &ncdmodule_run,
     &ncdmodule_runonce,
     &ncdmodule_runonce,
     &ncdmodule_synchronous_process,
     &ncdmodule_synchronous_process,
+    &ncdmodule_call,
     &ncdmodule_process_manager,
     &ncdmodule_process_manager,
     &ncdmodule_net_backend_waitdevice,
     &ncdmodule_net_backend_waitdevice,
     &ncdmodule_net_backend_waitlink,
     &ncdmodule_net_backend_waitlink,