Procházet zdrojové kódy

system/BConnection: Code reduction.

Ambroz Bizjak před 11 roky
rodič
revize
9c4888e2a3

+ 1 - 0
compile-tun2sock.sh

@@ -49,6 +49,7 @@ base/BLog_syslog.c
 system/BReactor_badvpn.c
 system/BSignal.c
 system/BConnection_unix.c
+system/BConnection_common.c
 system/BTime.c
 system/BUnixSignal.c
 system/BNetwork.c

+ 1 - 0
compile-udpgw.sh

@@ -49,6 +49,7 @@ base/BLog_syslog.c
 system/BReactor_badvpn.c
 system/BSignal.c
 system/BConnection_unix.c
+system/BConnection_common.c
 system/BDatagram_unix.c
 system/BTime.c
 system/BUnixSignal.c

+ 54 - 2
system/BConnection.h

@@ -49,6 +49,41 @@
 int BConnection_AddressSupported (BAddr addr);
 
 
+#define BLISCON_FROM_ADDR 1
+#define BLISCON_FROM_UNIX 2
+
+struct BLisCon_from {
+    int type;
+    union {
+        struct {
+            BAddr addr;
+        } from_addr;
+#ifndef BADVPN_USE_WINAPI
+        struct {
+            char const *socket_path;
+        } from_unix;
+#endif
+    } u;
+};
+
+static struct BLisCon_from BLisCon_from_addr (BAddr addr)
+{
+    struct BLisCon_from res;
+    res.type = BLISCON_FROM_ADDR;
+    res.u.from_addr.addr = addr;
+    return res;
+}
+
+#ifndef BADVPN_USE_WINAPI
+static struct BLisCon_from BLisCon_from_unix (char const *socket_path)
+{
+    struct BLisCon_from res;
+    res.type = BLISCON_FROM_UNIX;
+    res.u.from_unix.socket_path = socket_path;
+    return res;
+}
+#endif
+
 
 struct BListener_s;
 
@@ -71,7 +106,16 @@ typedef struct BListener_s BListener;
 typedef void (*BListener_handler) (void *user);
 
 /**
- * Initializes the object.
+ * Common listener initialization function.
+ * 
+ * The other type-specific init functions are wrappers around this one.
+ */
+int BListener_InitFrom (BListener *o, struct BLisCon_from from,
+                        BReactor *reactor, void *user,
+                        BListener_handler handler) WARN_UNUSED;
+
+/**
+ * Initializes the object for listening on an address.
  * {@link BNetwork_GlobalInit} must have been done.
  * 
  * @param o the object
@@ -131,7 +175,15 @@ typedef struct BConnector_s BConnector;
 typedef void (*BConnector_handler) (void *user, int is_error);
 
 /**
- * Initializes the object.
+ * Common connector initialization function.
+ * 
+ * The other type-specific init functions are wrappers around this one.
+ */
+int BConnector_InitFrom (BConnector *o, struct BLisCon_from from, BReactor *reactor, void *user,
+                         BConnector_handler handler) WARN_UNUSED;
+
+/**
+ * Initializes the object for connecting to an address.
  * {@link BNetwork_GlobalInit} must have been done.
  * 
  * @param o the object

+ 58 - 0
system/BConnection_common.c

@@ -0,0 +1,58 @@
+/**
+ * @file BConnection_common.c
+ * @author Ambroz Bizjak <ambrop7@gmail.com>
+ * 
+ * @section LICENSE
+ * 
+ * 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.
+ * 3. Neither the name of the author nor the
+ *    names of its contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
+ * 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 AUTHOR 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 "BConnection.h"
+
+int BListener_Init (BListener *o, BAddr addr, BReactor *reactor, void *user,
+                    BListener_handler handler)
+{
+    return BListener_InitFrom(o, BLisCon_from_addr(addr), reactor, user, handler);
+}
+
+#ifndef BADVPN_USE_WINAPI
+int BListener_InitUnix (BListener *o, const char *socket_path, BReactor *reactor, void *user,
+                        BListener_handler handler)
+{
+    return BListener_InitFrom(o, BLisCon_from_unix(socket_path), reactor, user, handler);
+}
+#endif
+
+int BConnector_Init (BConnector *o, BAddr addr, BReactor *reactor, void *user,
+                     BConnector_handler handler)
+{
+    return BConnector_InitFrom(o, BLisCon_from_addr(addr), reactor, user, handler);
+}
+
+#ifndef BADVPN_USE_WINAPI
+int BConnector_InitUnix (BConnector *o, const char *socket_path, BReactor *reactor, void *user,
+                         BConnector_handler handler)
+{
+    return BConnector_InitFrom(o, BLisCon_from_unix(socket_path), reactor, user, handler);
+}
+#endif

+ 105 - 195
system/BConnection_unix.c

@@ -438,9 +438,12 @@ int BConnection_AddressSupported (BAddr addr)
     return (addr.type == BADDR_TYPE_IPV4 || addr.type == BADDR_TYPE_IPV6);
 }
 
-int BListener_Init (BListener *o, BAddr addr, BReactor *reactor, void *user,
-                    BListener_handler handler)
+int BListener_InitFrom (BListener *o, struct BLisCon_from from,
+                        BReactor *reactor, void *user,
+                        BListener_handler handler)
 {
+    ASSERT(from.type == BLISCON_FROM_ADDR || from.type == BLISCON_FROM_UNIX)
+    ASSERT(from.type != BLISCON_FROM_UNIX || from.u.from_unix.socket_path)
     ASSERT(handler)
     BNetwork_Assert();
     
@@ -449,101 +452,46 @@ int BListener_Init (BListener *o, BAddr addr, BReactor *reactor, void *user,
     o->user = user;
     o->handler = handler;
     
-    // set no unix socket path
+    // init socket path
     o->unix_socket_path = NULL;
-    
-    // check address
-    if (!BConnection_AddressSupported(addr)) {
-        BLog(BLOG_ERROR, "address not supported");
-        goto fail0;
+    if (from.type == BLISCON_FROM_UNIX) {
+        o->unix_socket_path = b_strdup(from.u.from_unix.socket_path);
+        if (!o->unix_socket_path) {
+            BLog(BLOG_ERROR, "b_strdup failed");
+            goto fail0;
+        }
     }
     
-    // convert address
+    struct unix_addr unixaddr;
     struct sys_addr sysaddr;
-    addr_socket_to_sys(&sysaddr, addr);
     
-    // init fd
-    if ((o->fd = socket(sysaddr.addr.generic.sa_family, SOCK_STREAM, 0)) < 0) {
-        BLog(BLOG_ERROR, "socket failed");
-        goto fail0;
-    }
-    
-    // set non-blocking
-    if (!badvpn_set_nonblocking(o->fd)) {
-        BLog(BLOG_ERROR, "badvpn_set_nonblocking failed");
-        goto fail1;
-    }
-    
-    // set SO_REUSEADDR
-    int optval = 1;
-    if (setsockopt(o->fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0) {
-        BLog(BLOG_ERROR, "setsockopt(SO_REUSEADDR) failed");
-    }
-    
-    // bind
-    if (bind(o->fd, &sysaddr.addr.generic, sysaddr.len) < 0) {
-        BLog(BLOG_ERROR, "bind failed");
-        goto fail1;
-    }
-    
-    // listen
-    if (listen(o->fd, BCONNECTION_LISTEN_BACKLOG) < 0) {
-        BLog(BLOG_ERROR, "listen failed");
-        goto fail1;
-    }
-    
-    // init BFileDescriptor
-    BFileDescriptor_Init(&o->bfd, o->fd, (BFileDescriptor_handler)listener_fd_handler, o);
-    if (!BReactor_AddFileDescriptor(o->reactor, &o->bfd)) {
-        BLog(BLOG_ERROR, "BReactor_AddFileDescriptor failed");
-        goto fail1;
-    }
-    BReactor_SetFileDescriptorEvents(o->reactor, &o->bfd, BREACTOR_READ);
-    
-    // init default job
-    BPending_Init(&o->default_job, BReactor_PendingGroup(o->reactor), (BPending_handler)listener_default_job_handler, o);
-    
-    DebugObject_Init(&o->d_obj);
-    return 1;
-    
-fail1:
-    if (close(o->fd) < 0) {
-        BLog(BLOG_ERROR, "close failed");
-    }
-fail0:
-    return 0;
-}
-
-int BListener_InitUnix (BListener *o, const char *socket_path, BReactor *reactor, void *user,
-                        BListener_handler handler)
-{
-    ASSERT(socket_path)
-    ASSERT(handler)
-    BNetwork_Assert();
-    
-    // init arguments
-    o->reactor = reactor;
-    o->user = user;
-    o->handler = handler;
-    
-    // copy socket path
-    o->unix_socket_path = b_strdup(socket_path);
-    if (!o->unix_socket_path) {
-        BLog(BLOG_ERROR, "b_strdup failed");
-        goto fail0;
-    }
-    
-    // build address
-    struct unix_addr addr;
-    if (!build_unix_address(&addr, socket_path)) {
-        BLog(BLOG_ERROR, "build_unix_address failed");
-        goto fail1;
-    }
-    
-    // init fd
-    if ((o->fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
-        BLog(BLOG_ERROR, "socket failed");
-        goto fail1;
+    if (from.type == BLISCON_FROM_UNIX) {
+        // build address
+        if (!build_unix_address(&unixaddr, o->unix_socket_path)) {
+            BLog(BLOG_ERROR, "build_unix_address failed");
+            goto fail1;
+        }
+        
+        // init fd
+        if ((o->fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
+            BLog(BLOG_ERROR, "socket failed");
+            goto fail1;
+        }
+    } else {
+        // check address
+        if (!BConnection_AddressSupported(from.u.from_addr.addr)) {
+            BLog(BLOG_ERROR, "address not supported");
+            goto fail1;
+        }
+        
+        // convert address
+        addr_socket_to_sys(&sysaddr, from.u.from_addr.addr);
+        
+        // init fd
+        if ((o->fd = socket(sysaddr.addr.generic.sa_family, SOCK_STREAM, 0)) < 0) {
+            BLog(BLOG_ERROR, "socket failed");
+            goto fail1;
+        }
     }
     
     // set non-blocking
@@ -552,16 +500,30 @@ int BListener_InitUnix (BListener *o, const char *socket_path, BReactor *reactor
         goto fail2;
     }
     
-    // unlink existing socket
-    if (unlink(o->unix_socket_path) < 0 && errno != ENOENT) {
-        BLog(BLOG_ERROR, "unlink existing socket failed");
-        goto fail2;
-    }
-    
-    // bind
-    if (bind(o->fd, (struct sockaddr *)&addr.u.addr, addr.len) < 0) {
-        BLog(BLOG_ERROR, "bind failed");
-        goto fail2;
+    if (from.type == BLISCON_FROM_UNIX) {
+        // unlink existing socket
+        if (unlink(o->unix_socket_path) < 0 && errno != ENOENT) {
+            BLog(BLOG_ERROR, "unlink existing socket failed");
+            goto fail2;
+        }
+        
+        // bind
+        if (bind(o->fd, (struct sockaddr *)&unixaddr.u.addr, unixaddr.len) < 0) {
+            BLog(BLOG_ERROR, "bind failed");
+            goto fail2;
+        }
+    } else {
+        // set SO_REUSEADDR
+        int optval = 1;
+        if (setsockopt(o->fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0) {
+            BLog(BLOG_ERROR, "setsockopt(SO_REUSEADDR) failed");
+        }
+        
+        // bind
+        if (bind(o->fd, &sysaddr.addr.generic, sysaddr.len) < 0) {
+            BLog(BLOG_ERROR, "bind failed");
+            goto fail2;
+        }
     }
     
     // listen
@@ -585,8 +547,10 @@ int BListener_InitUnix (BListener *o, const char *socket_path, BReactor *reactor
     return 1;
     
 fail3:
-    if (unlink(o->unix_socket_path) < 0) {
-        BLog(BLOG_ERROR, "unlink socket failed");
+    if (from.type == BLISCON_FROM_UNIX) {
+        if (unlink(o->unix_socket_path) < 0) {
+            BLog(BLOG_ERROR, "unlink socket failed");
+        }
     }
 fail2:
     if (close(o->fd) < 0) {
@@ -626,9 +590,11 @@ void BListener_Free (BListener *o)
     }
 }
 
-int BConnector_Init (BConnector *o, BAddr addr, BReactor *reactor, void *user,
-                     BConnector_handler handler)
+int BConnector_InitFrom (BConnector *o, struct BLisCon_from from, BReactor *reactor, void *user,
+                         BConnector_handler handler)
 {
+    ASSERT(from.type == BLISCON_FROM_ADDR || from.type == BLISCON_FROM_UNIX)
+    ASSERT(from.type != BLISCON_FROM_UNIX || from.u.from_unix.socket_path)
     ASSERT(handler)
     BNetwork_Assert();
     
@@ -637,102 +603,41 @@ int BConnector_Init (BConnector *o, BAddr addr, BReactor *reactor, void *user,
     o->user = user;
     o->handler = handler;
     
-    // check address
-    if (!BConnection_AddressSupported(addr)) {
-        BLog(BLOG_ERROR, "address not supported");
-        goto fail0;
-    }
-    
-    // convert address
+    struct unix_addr unixaddr;
     struct sys_addr sysaddr;
-    addr_socket_to_sys(&sysaddr, addr);
-    
-    // init job
-    BPending_Init(&o->job, BReactor_PendingGroup(o->reactor), (BPending_handler)connector_job_handler, o);
-    
-    // init fd
-    if ((o->fd = socket(sysaddr.addr.generic.sa_family, SOCK_STREAM, 0)) < 0) {
-        BLog(BLOG_ERROR, "socket failed");
-        goto fail1;
-    }
-    
-    // set fd non-blocking
-    if (!badvpn_set_nonblocking(o->fd)) {
-        BLog(BLOG_ERROR, "badvpn_set_nonblocking failed");
-        goto fail2;
-    }
-    
-    // connect fd
-    int res = connect(o->fd, &sysaddr.addr.generic, sysaddr.len);
-    if (res < 0 && errno != EINPROGRESS) {
-        BLog(BLOG_ERROR, "connect failed");
-        goto fail2;
-    }
-    
-    // set not connected
-    o->connected = 0;
     
-    // set have no BFileDescriptor
-    o->have_bfd = 0;
-    
-    if (res < 0) {
-        // init BFileDescriptor
-        BFileDescriptor_Init(&o->bfd, o->fd, (BFileDescriptor_handler)connector_fd_handler, o);
-        if (!BReactor_AddFileDescriptor(o->reactor, &o->bfd)) {
-            BLog(BLOG_ERROR, "BReactor_AddFileDescriptor failed");
-            goto fail2;
+    if (from.type == BLISCON_FROM_UNIX) {
+        // build address
+        if (!build_unix_address(&unixaddr, from.u.from_unix.socket_path)) {
+            BLog(BLOG_ERROR, "build_unix_address failed");
+            goto fail0;
         }
-        BReactor_SetFileDescriptorEvents(o->reactor, &o->bfd, BREACTOR_WRITE);
-        
-        // set have BFileDescriptor
-        o->have_bfd = 1;
     } else {
-        // set connected
-        o->connected = 1;
+        // check address
+        if (!BConnection_AddressSupported(from.u.from_addr.addr)) {
+            BLog(BLOG_ERROR, "address not supported");
+            goto fail0;
+        }
         
-        // set job
-        BPending_Set(&o->job);
-    }
-    
-    DebugObject_Init(&o->d_obj);
-    return 1;
-    
-fail2:
-    if (close(o->fd) < 0) {
-        BLog(BLOG_ERROR, "close failed");
-    }
-fail1:
-    BPending_Free(&o->job);
-fail0:
-    return 0;
-}
-
-int BConnector_InitUnix (BConnector *o, const char *socket_path, BReactor *reactor, void *user,
-                         BConnector_handler handler)
-{
-    ASSERT(socket_path)
-    ASSERT(handler)
-    BNetwork_Assert();
-    
-    // init arguments
-    o->reactor = reactor;
-    o->user = user;
-    o->handler = handler;
-    
-    // build address
-    struct unix_addr addr;
-    if (!build_unix_address(&addr, socket_path)) {
-        BLog(BLOG_ERROR, "build_unix_address failed");
-        goto fail0;
+        // convert address
+        addr_socket_to_sys(&sysaddr, from.u.from_addr.addr);
     }
     
     // init job
     BPending_Init(&o->job, BReactor_PendingGroup(o->reactor), (BPending_handler)connector_job_handler, o);
     
-    // init fd
-    if ((o->fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
-        BLog(BLOG_ERROR, "socket failed");
-        goto fail1;
+    if (from.type == BLISCON_FROM_UNIX) {
+        // init fd
+        if ((o->fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
+            BLog(BLOG_ERROR, "socket failed");
+            goto fail1;
+        }
+    } else {
+        // init fd
+        if ((o->fd = socket(sysaddr.addr.generic.sa_family, SOCK_STREAM, 0)) < 0) {
+            BLog(BLOG_ERROR, "socket failed");
+            goto fail1;
+        }
     }
     
     // set fd non-blocking
@@ -742,8 +647,13 @@ int BConnector_InitUnix (BConnector *o, const char *socket_path, BReactor *react
     }
     
     // connect fd
-    int res = connect(o->fd, (struct sockaddr *)&addr.u.addr, addr.len);
-    if (res < 0 && errno != EINPROGRESS) {
+    int connect_res;
+    if (from.type == BLISCON_FROM_UNIX) {
+        connect_res = connect(o->fd, (struct sockaddr *)&unixaddr.u.addr, unixaddr.len);
+    } else {
+        connect_res = connect(o->fd, &sysaddr.addr.generic, sysaddr.len);
+    }
+    if (connect_res < 0 && errno != EINPROGRESS) {
         BLog(BLOG_ERROR, "connect failed");
         goto fail2;
     }
@@ -754,7 +664,7 @@ int BConnector_InitUnix (BConnector *o, const char *socket_path, BReactor *react
     // set have no BFileDescriptor
     o->have_bfd = 0;
     
-    if (res < 0) {
+    if (connect_res < 0) {
         // init BFileDescriptor
         BFileDescriptor_Init(&o->bfd, o->fd, (BFileDescriptor_handler)connector_fd_handler, o);
         if (!BReactor_AddFileDescriptor(o->reactor, &o->bfd)) {

+ 12 - 9
system/BConnection_win.c

@@ -437,9 +437,11 @@ int BConnection_AddressSupported (BAddr addr)
     return (addr.type == BADDR_TYPE_IPV4 || addr.type == BADDR_TYPE_IPV6);
 }
 
-int BListener_Init (BListener *o, BAddr addr, BReactor *reactor, void *user,
-                    BListener_handler handler)
+int BListener_InitFrom (BListener *o, struct BLisCon_from from,
+                        BReactor *reactor, void *user,
+                        BListener_handler handler)
 {
+    ASSERT(from.type == BLISCON_FROM_ADDR)
     ASSERT(handler)
     BNetwork_Assert();
     
@@ -449,14 +451,14 @@ int BListener_Init (BListener *o, BAddr addr, BReactor *reactor, void *user,
     o->handler = handler;
     
     // check address
-    if (!BConnection_AddressSupported(addr)) {
+    if (!BConnection_AddressSupported(from.u.from_addr.addr)) {
         BLog(BLOG_ERROR, "address not supported");
         goto fail0;
     }
     
     // convert address
     struct sys_addr sysaddr;
-    addr_socket_to_sys(&sysaddr, addr);
+    addr_socket_to_sys(&sysaddr, from.u.from_addr.addr);
     
     // remember family
     o->sys_family = sysaddr.addr.generic.sa_family;
@@ -562,9 +564,10 @@ void BListener_Free (BListener *o)
     BReactorIOCPOverlapped_Free(&o->olap);
 }
 
-int BConnector_Init (BConnector *o, BAddr addr, BReactor *reactor, void *user,
-                     BConnector_handler handler)
+int BConnector_InitFrom (BConnector *o, struct BLisCon_from from, BReactor *reactor, void *user,
+                         BConnector_handler handler)
 {
+    ASSERT(from.type == BLISCON_FROM_ADDR)
     ASSERT(handler)
     BNetwork_Assert();
     
@@ -574,18 +577,18 @@ int BConnector_Init (BConnector *o, BAddr addr, BReactor *reactor, void *user,
     o->handler = handler;
     
     // check address
-    if (!BConnection_AddressSupported(addr)) {
+    if (!BConnection_AddressSupported(from.u.from_addr.addr)) {
         BLog(BLOG_ERROR, "address not supported");
         goto fail0;
     }
     
     // convert address
     struct sys_addr sysaddr;
-    addr_socket_to_sys(&sysaddr, addr);
+    addr_socket_to_sys(&sysaddr, from.u.from_addr.addr);
     
     // create local any address
     struct sys_addr local_sysaddr;
-    addr_any_to_sys(&local_sysaddr, addr.type);
+    addr_any_to_sys(&local_sysaddr, from.u.from_addr.addr.type);
     
     // init socket
     if ((o->sock = WSASocket(sysaddr.addr.generic.sa_family, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET) {

+ 1 - 0
system/CMakeLists.txt

@@ -5,6 +5,7 @@ if (NOT EMSCRIPTEN)
     list(APPEND BSYSTEM_ADDITIONAL_SOURCES
         BSignal.c
         BNetwork.c
+        BConnection_common.c
     )
 
     if (WIN32)