Use threads for UDP sockets.
authorGuus Sliepen <guus@tinc-vpn.org>
Fri, 14 Jan 2011 15:00:22 +0000 (16:00 +0100)
committerGuus Sliepen <guus@tinc-vpn.org>
Fri, 14 Jan 2011 15:00:22 +0000 (16:00 +0100)
src/net.h
src/net_packet.c
src/net_setup.c
src/net_socket.c
src/threads.h

index 9b625a0d9873c7a32723e55210559157c9df8ffc..a6d5cb965b822749ad7a35465aad1a81ca25df00 100644 (file)
--- a/src/net.h
+++ b/src/net.h
@@ -24,6 +24,7 @@
 #include "ipv6.h"
 #include "cipher.h"
 #include "digest.h"
+#include "threads.h"
 
 #ifdef ENABLE_JUMBOGRAMS
 #define MTU 9018                               /* 9000 bytes payload + 14 bytes ethernet header + 4 bytes VLAN tag */
@@ -88,6 +89,7 @@ typedef struct listen_socket_t {
        struct event ev_udp;
        int tcp;
        int udp;
+       thread_t udp_thread;
        sockaddr_t sa;
 } listen_socket_t;
 
@@ -125,7 +127,7 @@ extern int contradicting_del_edge;
 #include "node.h"
 
 extern void retry_outgoing(outgoing_t *);
-extern void handle_incoming_vpn_data(int, short, void *);
+extern void handle_incoming_vpn_data(void *);
 extern void finish_connecting(struct connection_t *);
 extern void do_outgoing_connection(struct connection_t *);
 extern void handle_new_meta_connection(int, short, void *);
index 7be466201eae816acca0d52ab3fd6ddcff545f92..61a9f48e4677ddb099ff101dc6ac69d608dfd036 100644 (file)
@@ -576,7 +576,8 @@ static node_t *try_harder(const sockaddr_t *from, const vpn_packet_t *pkt) {
        return found;
 }
 
-void handle_incoming_vpn_data(int sock, short events, void *data) {
+void handle_incoming_vpn_data(void *arg) {
+       listen_socket_t *l = arg;
        vpn_packet_t pkt;
        char *hostname;
        sockaddr_t from;
@@ -584,35 +585,39 @@ void handle_incoming_vpn_data(int sock, short events, void *data) {
        node_t *n;
        int len;
 
-       len = recvfrom(sock, (char *) &pkt.seqno, MAXSIZE, 0, &from.sa, &fromlen);
+       while(true) {
+               len = recvfrom(l->udp, (char *) &pkt.seqno, MAXSIZE, 0, &from.sa, &fromlen);
 
-       if(len <= 0 || len > MAXSIZE) {
-               if(!sockwouldblock(sockerrno))
-                       logger(LOG_ERR, "Receiving packet failed: %s", sockstrerror(sockerrno));
-               return;
-       }
+               if(len <= 0 || len > MAXSIZE) {
+                       if(!sockwouldblock(sockerrno)) {
+                               logger(LOG_ERR, "Receiving packet failed: %s", sockstrerror(sockerrno));
+                               return;
+                       }
+                       continue;
+               }
 
-       pkt.len = len;
+               pkt.len = len;
 
-       sockaddrunmap(&from);           /* Some braindead IPv6 implementations do stupid things. */
+               sockaddrunmap(&from);           /* Some braindead IPv6 implementations do stupid things. */
 
-       n = lookup_node_udp(&from);
+               n = lookup_node_udp(&from);
 
-       if(!n) {
-               n = try_harder(&from, &pkt);
-               if(n)
-                       update_node_udp(n, &from);
-               else ifdebug(PROTOCOL) {
-                       hostname = sockaddr2hostname(&from);
-                       logger(LOG_WARNING, "Received UDP packet from unknown source %s", hostname);
-                       free(hostname);
-                       return;
+               if(!n) {
+                       n = try_harder(&from, &pkt);
+                       if(n)
+                               update_node_udp(n, &from);
+                       else ifdebug(PROTOCOL) {
+                               hostname = sockaddr2hostname(&from);
+                               logger(LOG_WARNING, "Received UDP packet from unknown source %s", hostname);
+                               free(hostname);
+                               continue;
+                       }
+                       else
+                               continue;
                }
-               else
-                       return;
-       }
 
-       receive_udppacket(n, &pkt);
+               receive_udppacket(n, &pkt);
+       }
 }
 
 void handle_device_data(int sock, short events, void *data) {
index b31bed737e0653ae0a0c8fb1a7bf130a6c6364a0..dc1d665d2c0dba1f3627d561512094d79ba6d7bd 100644 (file)
@@ -529,12 +529,8 @@ bool setup_myself(void) {
                        abort();
                }
 
-               event_set(&listen_socket[listen_sockets].ev_udp,
-                                 listen_socket[listen_sockets].udp,
-                                 EV_READ|EV_PERSIST,
-                                 handle_incoming_vpn_data, NULL);
-               if(event_add(&listen_socket[listen_sockets].ev_udp, NULL) < 0) {
-                       logger(LOG_ERR, "event_add failed: %s", strerror(errno));
+               if(!thread_create(&listen_socket[listen_sockets].udp_thread, handle_incoming_vpn_data, &listen_socket[listen_sockets])) {
+                       logger(LOG_ERR, "thread_create failed: %s", strerror(errno));
                        abort();
                }
 
@@ -625,6 +621,7 @@ void close_network_connections(void) {
                event_del(&listen_socket[i].ev_udp);
                close(listen_socket[i].tcp);
                close(listen_socket[i].udp);
+               thread_destroy(&listen_socket[i].udp_thread);
        }
 
        xasprintf(&envp[0], "NETNAME=%s", netname ? : "");
index e20076fbe00d9f97e71406f3c95c8193fddfa8c8..7c4463eaab1d28089f259dbb380bdfb829a0b504 100644 (file)
@@ -237,28 +237,6 @@ int setup_vpn_in_socket(const sockaddr_t *sa) {
                return -1;
        }
 
-#ifdef O_NONBLOCK
-       {
-               int flags = fcntl(nfd, F_GETFL);
-
-               if(fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0) {
-                       closesocket(nfd);
-                       logger(LOG_ERR, "System call `%s' failed: %s", "fcntl",
-                                  strerror(errno));
-                       return -1;
-               }
-       }
-#elif defined(WIN32)
-       {
-               unsigned long arg = 1;
-               if(ioctlsocket(nfd, FIONBIO, &arg) != 0) {
-                       closesocket(nfd);
-                       logger(LOG_ERR, "Call to `%s' failed: %s", "ioctlsocket", sockstrerror(sockerrno));
-                       return -1;
-               }
-       }
-#endif
-
        option = 1;
        setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, (void *)&option, sizeof option);
 
index 3243907d5d52c3c36114edcf75a13085584fe3b9..d2ef4a640c7766bd6d00176dd89aca108f76ca9e 100644 (file)
@@ -1,11 +1,6 @@
 #ifndef __THREADS_H__
 #define __THREADS_H__
 
-typedef struct event {
-       int foo;
-} event_t;
-       
-
 #ifdef HAVE_MINGW
 typedef HANDLE thread_t;
 typedef CRITICAL_SECTION mutex_t;
@@ -33,11 +28,11 @@ static inline void mutex_unlock(mutex_t *mutex) {
 typedef pthread_t thread_t;
 typedef pthread_mutex_t mutex_t;
 
-static inline void thread_create(thread_t *tid, void (*func)(void *), void *arg) {
+static inline bool thread_create(thread_t *tid, void (*func)(void *), void *arg) {
        return !pthread_create(tid, NULL, (void *(*)(void *))func, arg);
 }
 static inline void thread_destroy(thread_t *tid) {
-       pthread_join(tid);
+       pthread_join(*tid, NULL);
 }
 static inline void mutex_create(mutex_t *mutex) {
        pthread_mutex_init(mutex, NULL);