Procházet zdrojové kódy

system: BConnection: add BConnector_InitUnix()

ambrop7 před 14 roky
rodič
revize
4f52c90912
2 změnil soubory, kde provedl 95 přidání a 0 odebrání
  1. 16 0
      system/BConnection.h
  2. 79 0
      system/BConnection_unix.c

+ 16 - 0
system/BConnection.h

@@ -144,6 +144,22 @@ typedef void (*BConnector_handler) (void *user, int is_error);
 int BConnector_Init (BConnector *o, BAddr addr, BReactor *reactor, void *user,
                      BConnector_handler handler) WARN_UNUSED;
 
+#ifndef BADVPN_USE_WINAPI
+/**
+ * Initializes the object for connecting to a Unix socket.
+ * {@link BNetwork_GlobalInit} must have been done.
+ * 
+ * @param o the object
+ * @param socket_path socket path for connecting
+ * @param reactor reactor we live in
+ * @param user argument to handler
+ * @param handler handler called when the connection attempt finishes
+ * @return 1 on success, 0 on failure
+ */
+int BConnector_InitUnix (BConnector *o, const char *socket_path, BReactor *reactor, void *user,
+                         BConnector_handler handler) WARN_UNUSED;
+#endif
+
 /**
  * Frees the object.
  * 

+ 79 - 0
system/BConnection_unix.c

@@ -652,6 +652,85 @@ fail1:
     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;
+    }
+    
+    // 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;
+    }
+    
+    // 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, (struct sockaddr *)&addr.u.addr, addr.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;
+        }
+        BReactor_SetFileDescriptorEvents(o->reactor, &o->bfd, BREACTOR_WRITE);
+        
+        // set have BFileDescriptor
+        o->have_bfd = 1;
+    } else {
+        // set connected
+        o->connected = 1;
+        
+        // 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;
+}
+
 void BConnector_Free (BConnector *o)
 {
     DebugObject_Free(&o->d_obj);