ambrop7 пре 15 година
родитељ
комит
bb81875450

+ 1 - 0
blog_channels.txt

@@ -15,6 +15,7 @@ ncd_strcmp 4
 ncd_logical 4
 ncd_sleep 4
 ncd_print 4
+ncd_blocker 4
 ncd_ip_in_network 4
 ncd_run 4
 ncd_net_backend_waitdevice 4

+ 4 - 0
generated/blog_channel_ncd_blocker.h

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

+ 43 - 42
generated/blog_channels_defines.h

@@ -15,45 +15,46 @@
 #define BLOG_CHANNEL_ncd_logical 14
 #define BLOG_CHANNEL_ncd_sleep 15
 #define BLOG_CHANNEL_ncd_print 16
-#define BLOG_CHANNEL_ncd_ip_in_network 17
-#define BLOG_CHANNEL_ncd_run 18
-#define BLOG_CHANNEL_ncd_net_backend_waitdevice 19
-#define BLOG_CHANNEL_ncd_net_backend_waitlink 20
-#define BLOG_CHANNEL_ncd_net_backend_badvpn 21
-#define BLOG_CHANNEL_ncd_net_backend_wpa_supplicant 22
-#define BLOG_CHANNEL_ncd_net_backend_rfkill 23
-#define BLOG_CHANNEL_ncd_net_up 24
-#define BLOG_CHANNEL_ncd_net_dns 25
-#define BLOG_CHANNEL_ncd_net_iptables 26
-#define BLOG_CHANNEL_ncd_net_ipv4_addr 27
-#define BLOG_CHANNEL_ncd_net_ipv4_dhcp 28
-#define BLOG_CHANNEL_ncd_net_ipv4_route 29
-#define BLOG_CHANNEL_ncd_sys_evdev 30
-#define BLOG_CHANNEL_StreamPeerIO 31
-#define BLOG_CHANNEL_DatagramPeerIO 32
-#define BLOG_CHANNEL_BReactor 33
-#define BLOG_CHANNEL_BSignal 34
-#define BLOG_CHANNEL_FragmentProtoAssembler 35
-#define BLOG_CHANNEL_BPredicate 36
-#define BLOG_CHANNEL_ServerConnection 37
-#define BLOG_CHANNEL_Listener 38
-#define BLOG_CHANNEL_DataProto 39
-#define BLOG_CHANNEL_FrameDecider 40
-#define BLOG_CHANNEL_BSocksClient 41
-#define BLOG_CHANNEL_BDHCPClientCore 42
-#define BLOG_CHANNEL_BDHCPClient 43
-#define BLOG_CHANNEL_NCDIfConfig 44
-#define BLOG_CHANNEL_BUnixSignal 45
-#define BLOG_CHANNEL_BProcess 46
-#define BLOG_CHANNEL_StreamSocketSink 47
-#define BLOG_CHANNEL_StreamSocketSource 48
-#define BLOG_CHANNEL_DatagramSocketSink 49
-#define BLOG_CHANNEL_DatagramSocketSource 50
-#define BLOG_CHANNEL_PRStreamSink 51
-#define BLOG_CHANNEL_PRStreamSource 52
-#define BLOG_CHANNEL_BSocketPRFileDesc 53
-#define BLOG_CHANNEL_PacketProtoDecoder 54
-#define BLOG_CHANNEL_DPRelay 55
-#define BLOG_CHANNEL_BThreadWork 56
-#define BLOG_CHANNEL_DPReceive 57
-#define BLOG_NUM_CHANNELS 58
+#define BLOG_CHANNEL_ncd_blocker 17
+#define BLOG_CHANNEL_ncd_ip_in_network 18
+#define BLOG_CHANNEL_ncd_run 19
+#define BLOG_CHANNEL_ncd_net_backend_waitdevice 20
+#define BLOG_CHANNEL_ncd_net_backend_waitlink 21
+#define BLOG_CHANNEL_ncd_net_backend_badvpn 22
+#define BLOG_CHANNEL_ncd_net_backend_wpa_supplicant 23
+#define BLOG_CHANNEL_ncd_net_backend_rfkill 24
+#define BLOG_CHANNEL_ncd_net_up 25
+#define BLOG_CHANNEL_ncd_net_dns 26
+#define BLOG_CHANNEL_ncd_net_iptables 27
+#define BLOG_CHANNEL_ncd_net_ipv4_addr 28
+#define BLOG_CHANNEL_ncd_net_ipv4_dhcp 29
+#define BLOG_CHANNEL_ncd_net_ipv4_route 30
+#define BLOG_CHANNEL_ncd_sys_evdev 31
+#define BLOG_CHANNEL_StreamPeerIO 32
+#define BLOG_CHANNEL_DatagramPeerIO 33
+#define BLOG_CHANNEL_BReactor 34
+#define BLOG_CHANNEL_BSignal 35
+#define BLOG_CHANNEL_FragmentProtoAssembler 36
+#define BLOG_CHANNEL_BPredicate 37
+#define BLOG_CHANNEL_ServerConnection 38
+#define BLOG_CHANNEL_Listener 39
+#define BLOG_CHANNEL_DataProto 40
+#define BLOG_CHANNEL_FrameDecider 41
+#define BLOG_CHANNEL_BSocksClient 42
+#define BLOG_CHANNEL_BDHCPClientCore 43
+#define BLOG_CHANNEL_BDHCPClient 44
+#define BLOG_CHANNEL_NCDIfConfig 45
+#define BLOG_CHANNEL_BUnixSignal 46
+#define BLOG_CHANNEL_BProcess 47
+#define BLOG_CHANNEL_StreamSocketSink 48
+#define BLOG_CHANNEL_StreamSocketSource 49
+#define BLOG_CHANNEL_DatagramSocketSink 50
+#define BLOG_CHANNEL_DatagramSocketSource 51
+#define BLOG_CHANNEL_PRStreamSink 52
+#define BLOG_CHANNEL_PRStreamSource 53
+#define BLOG_CHANNEL_BSocketPRFileDesc 54
+#define BLOG_CHANNEL_PacketProtoDecoder 55
+#define BLOG_CHANNEL_DPRelay 56
+#define BLOG_CHANNEL_BThreadWork 57
+#define BLOG_CHANNEL_DPReceive 58
+#define BLOG_NUM_CHANNELS 59

+ 1 - 0
generated/blog_channels_list.h

@@ -15,6 +15,7 @@
 {.name = "ncd_logical", .loglevel = 4},
 {.name = "ncd_sleep", .loglevel = 4},
 {.name = "ncd_print", .loglevel = 4},
+{.name = "ncd_blocker", .loglevel = 4},
 {.name = "ncd_ip_in_network", .loglevel = 4},
 {.name = "ncd_run", .loglevel = 4},
 {.name = "ncd_net_backend_waitdevice", .loglevel = 4},

+ 1 - 0
ncd/CMakeLists.txt

@@ -34,6 +34,7 @@ add_executable(badvpn-ncd
     modules/logical.c
     modules/sleep.c
     modules/print.c
+    modules/blocker.c
     modules/ip_in_network.c
     modules/run.c
     modules/net_backend_waitdevice.c

+ 288 - 0
ncd/modules/blocker.c

@@ -0,0 +1,288 @@
+/**
+ * @file blocker.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
+ * 
+ * Blocker module. Provides a statement that blocks when initialized, and which can be blocked
+ * and unblocked from outside.
+ * 
+ * Synopsis: blocker()
+ * Description: provides blocking operations. Initially the blocking state is down (but this statement
+ * does not block).
+ * 
+ * Synopsis: blocker::up()
+ * Description: sets the blocking state to up.
+ * 
+ * Synopsis: blocker::down()
+ * Description: sets the blocking state to down.
+ * 
+ * Synopsis: blocker::use()
+ * Description: blocks on the blocker. This module is in up state if and only if the blocking state of
+ * the blocker is up. Multiple use statements may be used with the same blocker.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <misc/offset.h>
+#include <misc/debug.h>
+#include <ncd/NCDModule.h>
+
+#include <generated/blog_channel_ncd_blocker.h>
+
+#define ModuleLog(i, ...) NCDModuleInst_Backend_Log((i), BLOG_CURRENT_CHANNEL, __VA_ARGS__)
+
+struct instance {
+    NCDModuleInst *i;
+    LinkedList2 users;
+    int up;
+    int dying;
+};
+
+struct updown_instance {
+    NCDModuleInst *i;
+};
+
+struct use_instance {
+    NCDModuleInst *i;
+    struct instance *blocker;
+    LinkedList2Node blocker_node;
+};
+
+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
+    if (!NCDValue_ListRead(o->i->args, 0)) {
+        ModuleLog(o->i, BLOG_ERROR, "wrong arity");
+        goto fail1;
+    }
+    
+    // init users list
+    LinkedList2_Init(&o->users);
+    
+    // set not up
+    o->up = 0;
+    
+    // set not dying
+    o->dying = 0;
+    
+    // signal up
+    NCDModuleInst_Backend_Event(o->i, NCDMODULE_EVENT_UP);
+    
+    return;
+    
+fail1:
+    free(o);
+fail0:
+    NCDModuleInst_Backend_SetError(i);
+    NCDModuleInst_Backend_Event(i, NCDMODULE_EVENT_DEAD);
+}
+
+static void instance_free (struct instance *o)
+{
+    ASSERT(LinkedList2_IsEmpty(&o->users))
+    NCDModuleInst *i = o->i;
+    
+    // free instance
+    free(o);
+    
+    NCDModuleInst_Backend_Event(i, NCDMODULE_EVENT_DEAD);
+}
+
+static void func_die (void *vo)
+{
+    struct instance *o = vo;
+    ASSERT(!o->dying)
+    
+    // if we have no users, die right away, else wait for users
+    if (LinkedList2_IsEmpty(&o->users)) {
+        instance_free(o);
+        return;
+    }
+    
+    // set dying
+    o->dying = 1;
+}
+
+static void updown_func_new_templ (NCDModuleInst *i, int up)
+{
+    // allocate instance
+    struct updown_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
+    if (!NCDValue_ListRead(o->i->args, 0)) {
+        ModuleLog(o->i, BLOG_ERROR, "wrong arity");
+        goto fail1;
+    }
+    
+    // signal up
+    NCDModuleInst_Backend_Event(o->i, NCDMODULE_EVENT_UP);
+    
+    // get method object
+    struct instance *mo = i->method_object->inst_user;
+    
+    if (mo->up != up) {
+        // change up state
+        mo->up = up;
+        
+        // signal users
+        LinkedList2Iterator it;
+        LinkedList2Iterator_InitForward(&it, &mo->users);
+        LinkedList2Node *node;
+        while (node = LinkedList2Iterator_Next(&it)) {
+            struct use_instance *user = UPPER_OBJECT(node, struct use_instance, blocker_node);
+            ASSERT(user->blocker == mo)
+            NCDModuleInst_Backend_Event(user->i, up ? NCDMODULE_EVENT_UP : NCDMODULE_EVENT_DOWN);
+        }
+    }
+    
+    return;
+    
+fail1:
+    free(o);
+fail0:
+    NCDModuleInst_Backend_SetError(i);
+    NCDModuleInst_Backend_Event(i, NCDMODULE_EVENT_DEAD);
+}
+
+static void up_func_new (NCDModuleInst *i)
+{
+    updown_func_new_templ(i, 1);
+}
+
+static void down_func_new (NCDModuleInst *i)
+{
+    updown_func_new_templ(i, 0);
+}
+
+static void updown_func_die (void *vo)
+{
+    struct updown_instance *o = vo;
+    NCDModuleInst *i = o->i;
+    
+    // free instance
+    free(o);
+    
+    NCDModuleInst_Backend_Event(i, NCDMODULE_EVENT_DEAD);
+}
+
+static void use_func_new (NCDModuleInst *i)
+{
+    // allocate instance
+    struct use_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
+    if (!NCDValue_ListRead(o->i->args, 0)) {
+        ModuleLog(o->i, BLOG_ERROR, "wrong arity");
+        goto fail1;
+    }
+    
+    // set blocker
+    o->blocker = i->method_object->inst_user;
+    
+    // add to blocker's list
+    LinkedList2_Append(&o->blocker->users, &o->blocker_node);
+    
+    // signal up if needed
+    if (o->blocker->up) {
+        NCDModuleInst_Backend_Event(o->i, NCDMODULE_EVENT_UP);
+    }
+    
+    return;
+    
+fail1:
+    free(o);
+fail0:
+    NCDModuleInst_Backend_SetError(i);
+    NCDModuleInst_Backend_Event(i, NCDMODULE_EVENT_DEAD);
+}
+
+static void use_func_die (void *vo)
+{
+    struct use_instance *o = vo;
+    NCDModuleInst *i = o->i;
+    
+    // remove from blocker's list
+    LinkedList2_Remove(&o->blocker->users, &o->blocker_node);
+    
+    // make the blocker die if needed
+    if (o->blocker->dying && LinkedList2_IsEmpty(&o->blocker->users)) {
+        instance_free(o->blocker);
+    }
+    
+    // free instance
+    free(o);
+    
+    NCDModuleInst_Backend_Event(i, NCDMODULE_EVENT_DEAD);
+}
+
+static const struct NCDModule modules[] = {
+    {
+        .type = "blocker",
+        .func_new = func_new,
+        .func_die = func_die
+    }, {
+        .type = "blocker::up",
+        .func_new = up_func_new,
+        .func_die = updown_func_die,
+    }, {
+        .type = "blocker::down",
+        .func_new = down_func_new,
+        .func_die = updown_func_die,
+    }, {
+        .type = "blocker::use",
+        .func_new = use_func_new,
+        .func_die = use_func_die,
+    }, {
+        .type = NULL
+    }
+};
+
+const struct NCDModuleGroup ncdmodule_blocker = {
+    .modules = modules
+};

+ 2 - 0
ncd/modules/modules.h

@@ -39,6 +39,7 @@ extern const struct NCDModuleGroup ncdmodule_strcmp;
 extern const struct NCDModuleGroup ncdmodule_logical;
 extern const struct NCDModuleGroup ncdmodule_sleep;
 extern const struct NCDModuleGroup ncdmodule_print;
+extern const struct NCDModuleGroup ncdmodule_blocker;
 extern const struct NCDModuleGroup ncdmodule_ip_in_network;
 extern const struct NCDModuleGroup ncdmodule_run;
 extern const struct NCDModuleGroup ncdmodule_net_backend_waitdevice;
@@ -71,6 +72,7 @@ static const struct NCDModuleGroup *ncd_modules[] = {
     &ncdmodule_logical,
     &ncdmodule_sleep,
     &ncdmodule_print,
+    &ncdmodule_blocker,
     &ncdmodule_ip_in_network,
     &ncdmodule_run,
     &ncdmodule_net_backend_waitdevice,