Parcourir la source

BSocket: support unix pipes as a backend

ambrop7 il y a 15 ans
Parent
commit
103c403e85
3 fichiers modifiés avec 119 ajouts et 16 suppressions
  1. 2 1
      system/BAddr.h
  2. 97 15
      system/BSocket.c
  3. 20 0
      system/BSocket.h

+ 2 - 1
system/BAddr.h

@@ -51,9 +51,10 @@
 #define BADDR_TYPE_IPV6 2
 #define BADDR_TYPE_IPV6 2
 #ifndef BADVPN_USE_WINAPI
 #ifndef BADVPN_USE_WINAPI
     #define BADDR_TYPE_UNIX 3 // only a domain number for BSocket
     #define BADDR_TYPE_UNIX 3 // only a domain number for BSocket
+    #define BADDR_TYPE_UNIXPIPE 4 // only a domain number for BSocket
 #endif
 #endif
 #ifdef BADVPN_LINUX
 #ifdef BADVPN_LINUX
-    #define BADDR_TYPE_PACKET 4
+    #define BADDR_TYPE_PACKET 5
 #endif
 #endif
 
 
 #define BADDR_MAX_ADDR_LEN 128
 #define BADDR_MAX_ADDR_LEN 128

+ 97 - 15
system/BSocket.c

@@ -32,6 +32,7 @@
 #include <fcntl.h>
 #include <fcntl.h>
 #include <errno.h>
 #include <errno.h>
 #include <sys/socket.h>
 #include <sys/socket.h>
+#include <signal.h>
 #endif
 #endif
 
 
 #ifdef BADVPN_LINUX
 #ifdef BADVPN_LINUX
@@ -58,6 +59,8 @@
 #define CONNECT_STATUS_DONE 2
 #define CONNECT_STATUS_DONE 2
 #define CONNECT_STATUS_DONE_IMMEDIATELY 3
 #define CONNECT_STATUS_DONE_IMMEDIATELY 3
 
 
+int bsocket_initialized = 0;
+
 static int get_event_index (int event)
 static int get_event_index (int event)
 {
 {
     switch (event) {
     switch (event) {
@@ -590,6 +593,8 @@ static void setup_winsock_exts (int socket, int type, BSocket *bs)
 
 
 int BSocket_GlobalInit (void)
 int BSocket_GlobalInit (void)
 {
 {
+    ASSERT(!bsocket_initialized)
+    
     #ifdef BADVPN_USE_WINAPI
     #ifdef BADVPN_USE_WINAPI
     
     
     WORD requested = MAKEWORD(2, 2);
     WORD requested = MAKEWORD(2, 2);
@@ -601,18 +606,30 @@ int BSocket_GlobalInit (void)
         goto fail1;
         goto fail1;
     }
     }
     
     
-    return 0;
+    #else
     
     
-fail1:
-    WSACleanup();
-fail0:
-    return -1;
+    struct sigaction act;
+    memset(&act, 0, sizeof(act));
+    act.sa_handler = SIG_IGN;
+    sigemptyset(&act.sa_mask);
+    act.sa_flags = 0;
+    if (sigaction(SIGPIPE, &act, NULL) < 0) {
+        DEBUG("sigaction failed");
+        goto fail0;
+    }
     
     
-    #else
+    #endif
+    
+    bsocket_initialized = 1;
     
     
     return 0;
     return 0;
     
     
+    #ifdef BADVPN_USE_WINAPI
+fail1:
+    WSACleanup();
     #endif
     #endif
+fail0:
+    return -1;
 }
 }
 
 
 int BSocket_Init (BSocket *bs, BReactor *bsys, int domain, int type)
 int BSocket_Init (BSocket *bs, BReactor *bsys, int domain, int type)
@@ -716,6 +733,53 @@ fail0:
     return -1;
     return -1;
 }
 }
 
 
+#ifndef BADVPN_USE_WINAPI
+
+int BSocket_InitPipe (BSocket *bs, BReactor *bsys, int fd)
+{
+    // set socket nonblocking
+    if (set_nonblocking(fd) != 0) {
+        DEBUG("set_nonblocking failed");
+        goto fail0;
+    }
+    
+    bs->bsys = bsys;
+    bs->type = BSOCKET_TYPE_STREAM;
+    bs->domain = BADDR_TYPE_UNIXPIPE;
+    bs->socket = fd;
+    bs->error = BSOCKET_ERROR_NONE;
+    init_handlers(bs);
+    bs->waitEvents = 0;
+    bs->connecting_status = CONNECT_STATUS_NONE;
+    bs->recv_max = BSOCKET_DEFAULT_RECV_MAX;
+    bs->recv_num = 0;
+    bs->ready_events = 0; // just initialize it so we can clear them safely from BSocket_DisableEvent
+    
+    // init job
+    BPending_Init(&bs->job, BReactor_PendingGroup(bsys), (BPending_handler)job_handler, bs);
+    
+    // init connect job
+    BPending_Init(&bs->connect_job, BReactor_PendingGroup(bsys), (BPending_handler)connect_job_handler, bs);
+    
+    // initialize event backend
+    if (!init_event_backend(bs)) {
+        DEBUG("WARNING: init_event_backend failed");
+        goto fail1;
+    }
+    
+    DebugObject_Init(&bs->d_obj);
+    
+    return 0;
+    
+fail1:
+    BPending_Free(&bs->connect_job);
+    BPending_Free(&bs->job);
+fail0:
+    return -1;
+}
+
+#endif
+
 void BSocket_Free (BSocket *bs)
 void BSocket_Free (BSocket *bs)
 {
 {
     DebugObject_Free(&bs->d_obj);
     DebugObject_Free(&bs->d_obj);
@@ -730,7 +794,13 @@ void BSocket_Free (BSocket *bs)
     BPending_Free(&bs->job);
     BPending_Free(&bs->job);
     
     
     // close socket
     // close socket
-    close_socket(bs->socket);
+    #ifndef BADVPN_USE_WINAPI
+    if (bs->domain != BADDR_TYPE_UNIXPIPE) {
+    #endif
+        close_socket(bs->socket);
+    #ifndef BADVPN_USE_WINAPI
+    }
+    #endif
 }
 }
 
 
 void BSocket_SetRecvMax (BSocket *bs, int max)
 void BSocket_SetRecvMax (BSocket *bs, int max)
@@ -1119,13 +1189,16 @@ int BSocket_Send (BSocket *bs, uint8_t *data, int len)
     ASSERT(bs->type == BSOCKET_TYPE_STREAM)
     ASSERT(bs->type == BSOCKET_TYPE_STREAM)
     DebugObject_Access(&bs->d_obj);
     DebugObject_Access(&bs->d_obj);
     
     
-    #ifdef BADVPN_USE_WINAPI
-    int flags = 0;
-    #else
-    int flags = MSG_NOSIGNAL;
+    int bytes;
+    #ifndef BADVPN_USE_WINAPI
+    if (bs->domain == BADDR_TYPE_UNIXPIPE) {
+        bytes = write(bs->socket, data, len);
+    } else {
+    #endif
+        bytes = send(bs->socket, data, len, 0);
+    #ifndef BADVPN_USE_WINAPI
+    }
     #endif
     #endif
-    
-    int bytes = send(bs->socket, data, len, flags);
     if (bytes < 0) {
     if (bytes < 0) {
         int error;
         int error;
         #ifdef BADVPN_USE_WINAPI
         #ifdef BADVPN_USE_WINAPI
@@ -1164,7 +1237,16 @@ int BSocket_Recv (BSocket *bs, uint8_t *data, int len)
         return -1;
         return -1;
     }
     }
     
     
-    int bytes = recv(bs->socket, data, len, 0);
+    int bytes;
+    #ifndef BADVPN_USE_WINAPI
+    if (bs->domain == BADDR_TYPE_UNIXPIPE) {
+        bytes = read(bs->socket, data, len);
+    } else {
+    #endif
+        bytes = recv(bs->socket, data, len, 0);
+    #ifndef BADVPN_USE_WINAPI
+    }
+    #endif
     if (bytes < 0) {
     if (bytes < 0) {
         int error;
         int error;
         #ifdef BADVPN_USE_WINAPI
         #ifdef BADVPN_USE_WINAPI
@@ -1358,7 +1440,7 @@ int BSocket_SendToFrom (BSocket *bs, uint8_t *data, int len, BAddr *addr, BIPAdd
         msg.msg_control = NULL;
         msg.msg_control = NULL;
     }
     }
     
     
-    int bytes = sendmsg(bs->socket, &msg, MSG_NOSIGNAL);
+    int bytes = sendmsg(bs->socket, &msg, 0);
     if (bytes < 0) {
     if (bytes < 0) {
         int error;
         int error;
         switch ((error = errno)) {
         switch ((error = errno)) {

+ 20 - 0
system/BSocket.h

@@ -140,6 +140,9 @@ typedef struct BSocket_t {
 /**
 /**
  * Initializes global socket data.
  * Initializes global socket data.
  * This must be called once in program before sockets are used.
  * This must be called once in program before sockets are used.
+ * Must not be called again after success.
+ * 
+ * On unix-like systems, this sets the signal disposition for SIGPIPE to SIG_IGN.
  *
  *
  * @return 0 for success, -1 for failure
  * @return 0 for success, -1 for failure
  */
  */
@@ -147,6 +150,7 @@ int BSocket_GlobalInit (void) WARN_UNUSED;
 
 
 /**
 /**
  * Initializes a socket.
  * Initializes a socket.
+ * {@link BSocket_GlobalInit} must have been done.
  *
  *
  * @param bs the object
  * @param bs the object
  * @param bsys {@link BReactor} to operate in
  * @param bsys {@link BReactor} to operate in
@@ -158,6 +162,22 @@ int BSocket_GlobalInit (void) WARN_UNUSED;
  */
  */
 int BSocket_Init (BSocket *bs, BReactor *bsys, int domain, int type) WARN_UNUSED;
 int BSocket_Init (BSocket *bs, BReactor *bsys, int domain, int type) WARN_UNUSED;
 
 
+#ifndef BADVPN_USE_WINAPI
+
+/**
+ * Initializes a socket object backed by a pipe.
+ * The resulting socket has type BSOCKET_TYPE_STREAM.
+ * 
+ * @param bs the object
+ * @param bsys {@link BReactor} to operate in
+ * @param fd pipe file descriptor. Will be set to non-blocking mode. Will NOT be closed when
+ *           the socket is freed.
+ * @return 0 for success, -1 for failure
+ */
+int BSocket_InitPipe (BSocket *bs, BReactor *bsys, int fd);
+
+#endif
+
 /**
 /**
  * Frees a socket.
  * Frees a socket.
  *
  *