]> git.meshlink.io Git - meshlink/commitdiff
Convert to libevent.
authorScott Lamb <slamb@slamb.org>
Tue, 27 Feb 2007 01:57:01 +0000 (01:57 +0000)
committerScott Lamb <slamb@slamb.org>
Tue, 27 Feb 2007 01:57:01 +0000 (01:57 +0000)
This is a quick initial conversion that doesn't yet show much advantage:
- We roll our own timeouts.
- We roll our own signal handling.
- We build up the meta connection fd events on each loop rather than
  on state changes.

configure.in
src/connection.c
src/connection.h
src/net.c
src/net.h
src/net_packet.c
src/net_setup.c
src/net_socket.c
src/tincd.c

index 3cb6a4de0efb1b6e8e94ad84d969fcbba0a91293..a29a88f424531baf4120056db53f9e5c3949e9ae 100644 (file)
@@ -86,6 +86,9 @@ fi
 
 dnl Checks for libraries.
 
 
 dnl Checks for libraries.
 
+AC_CHECK_LIB(event, event_init,
+  [], [AC_MSG_ERROR(libevent is required)])
+
 dnl Checks for header files.
 dnl We do this in multiple stages, because unlike Linux all the other operating systems really suck and don't include their own dependencies.
 
 dnl Checks for header files.
 dnl We do this in multiple stages, because unlike Linux all the other operating systems really suck and don't include their own dependencies.
 
index c4c9fd4861a530f8b2c3e63a950f0b43ce50cb1a..1f2f96cc0aca244fda4bf71d31e9d8f13f6a4bd4 100644 (file)
@@ -70,6 +70,7 @@ connection_t *new_connection(void)
                return NULL;
 
        gettimeofday(&c->start, NULL);
                return NULL;
 
        gettimeofday(&c->start, NULL);
+       event_set(&c->ev, -1, 0, NULL, NULL);
 
        return c;
 }
 
        return c;
 }
@@ -78,20 +79,14 @@ void free_connection(connection_t *c)
 {
        cp();
 
 {
        cp();
 
-       if(c->hostname)
+       if(c) {
                free(c->hostname);
                free(c->hostname);
-
-       if(c->inkey)
                free(c->inkey);
                free(c->inkey);
-
-       if(c->outkey)
                free(c->outkey);
                free(c->outkey);
-
-       if(c->mychallenge)
                free(c->mychallenge);
                free(c->mychallenge);
-
-       if(c->hischallenge)
                free(c->hischallenge);
                free(c->hischallenge);
+               event_del(&c->ev);
+       }
 
        free(c);
 }
 
        free(c);
 }
index 087d8f0023086c58f047c687415b51762e92d62c..8d5537b2b95823f947aa5f730616b75c150748f8 100644 (file)
@@ -26,6 +26,8 @@
 #include <openssl/rsa.h>
 #include <openssl/evp.h>
 
 #include <openssl/rsa.h>
 #include <openssl/evp.h>
 
+#include <event.h>
+
 #include "avl_tree.h"
 
 #define OPTION_INDIRECT                0x0001
 #include "avl_tree.h"
 
 #define OPTION_INDIRECT                0x0001
@@ -60,6 +62,7 @@ typedef struct connection_t {
        char *hostname;                         /* the hostname of its real ip */
        int protocol_version;           /* used protocol */
 
        char *hostname;                         /* the hostname of its real ip */
        int protocol_version;           /* used protocol */
 
+       struct event ev;                        /* events on this metadata connection */
        int socket;                                     /* socket used for this connection */
        long int options;                       /* options for this connection */
        connection_status_t status;     /* status info */
        int socket;                                     /* socket used for this connection */
        long int options;                       /* options for this connection */
        connection_status_t status;     /* status info */
index e9c7020a488cf3ac83b0843b845118165e894e4f..3a44ce66b61d151dd42329e1118a2d5c00c54f43 100644 (file)
--- a/src/net.c
+++ b/src/net.c
@@ -109,10 +109,10 @@ static void purge(void)
 }
 
 /*
 }
 
 /*
-  put all file descriptors in an fd_set array
-  While we're at it, purge stuff that needs to be removed.
+  put all file descriptors into events
+  While we're at it, purge stuf that needs to be removed.
 */
 */
-static int build_fdset(fd_set *readset, fd_set *writeset)
+static int build_fdset(void)
 {
        avl_node_t *node, *next;
        connection_t *c;
 {
        avl_node_t *node, *next;
        connection_t *c;
@@ -120,9 +120,6 @@ static int build_fdset(fd_set *readset, fd_set *writeset)
 
        cp();
 
 
        cp();
 
-       FD_ZERO(readset);
-       FD_ZERO(writeset);
-
        for(node = connection_tree->head; node; node = next) {
                next = node->next;
                c = node->data;
        for(node = connection_tree->head; node; node = next) {
                next = node->next;
                c = node->data;
@@ -132,28 +129,17 @@ static int build_fdset(fd_set *readset, fd_set *writeset)
                        if(!connection_tree->head)
                                purge();
                } else {
                        if(!connection_tree->head)
                                purge();
                } else {
-                       FD_SET(c->socket, readset);
+                       short events = EV_READ;
                        if(c->outbuflen > 0)
                        if(c->outbuflen > 0)
-                               FD_SET(c->socket, writeset);
-                       if(c->socket > max)
-                               max = c->socket;
+                               events |= EV_WRITE;
+                       event_del(&c->ev);
+                       event_set(&c->ev, c->socket, events,
+                                         handle_meta_connection_data, c);
+                       if (event_add(&c->ev, NULL) < 0)
+                               return -1;
                }
        }
                }
        }
-
-       for(i = 0; i < listen_sockets; i++) {
-               FD_SET(listen_socket[i].tcp, readset);
-               if(listen_socket[i].tcp > max)
-                       max = listen_socket[i].tcp;
-               FD_SET(listen_socket[i].udp, readset);
-               if(listen_socket[i].udp > max)
-                       max = listen_socket[i].udp;
-       }
-
-       FD_SET(device_fd, readset);
-       if(device_fd > max)
-               max = device_fd;
-       
-       return max;
+       return 0;
 }
 
 /*
 }
 
 /*
@@ -279,83 +265,59 @@ static void check_dead_connections(void)
        }
 }
 
        }
 }
 
-/*
-  check all connections to see if anything
-  happened on their sockets
-*/
-static void check_network_activity(fd_set * readset, fd_set * writeset)
+void handle_meta_connection_data(int fd, short events, void *data)
 {
 {
-       connection_t *c;
-       avl_node_t *node;
-       int result, i;
+       connection_t *c = data;
+       int result;
        socklen_t len = sizeof(result);
        socklen_t len = sizeof(result);
-       vpn_packet_t packet;
 
 
-       cp();
-
-       /* check input from kernel */
-       if(FD_ISSET(device_fd, readset)) {
-               if(read_packet(&packet))
-                       route(myself, &packet);
-       }
-
-       /* check meta connections */
-       for(node = connection_tree->head; node; node = node->next) {
-               c = node->data;
-
-               if(c->status.remove)
-                       continue;
-
-               if(FD_ISSET(c->socket, readset)) {
-                       if(c->status.connecting) {
-                               c->status.connecting = false;
-                               getsockopt(c->socket, SOL_SOCKET, SO_ERROR, &result, &len);
-
-                               if(!result)
-                                       finish_connecting(c);
-                               else {
-                                       ifdebug(CONNECTIONS) logger(LOG_DEBUG,
-                                                          _("Error while connecting to %s (%s): %s"),
-                                                          c->name, c->hostname, strerror(result));
-                                       closesocket(c->socket);
-                                       do_outgoing_connection(c);
-                                       continue;
-                               }
-                       }
+       if (c->status.remove)
+               return;
 
 
-                       if(!receive_meta(c)) {
-                               terminate_connection(c, c->status.active);
-                               continue;
+       if (events & EV_READ) {
+               if(c->status.connecting) {
+                       c->status.connecting = false;
+                       getsockopt(c->socket, SOL_SOCKET, SO_ERROR, &result, &len);
+
+                       if(!result)
+                               finish_connecting(c);
+                       else {
+                               ifdebug(CONNECTIONS) logger(LOG_DEBUG,
+                                                  _("Error while connecting to %s (%s): %s"),
+                                                  c->name, c->hostname, strerror(result));
+                               closesocket(c->socket);
+                               do_outgoing_connection(c);
+                               return;
                        }
                }
 
                        }
                }
 
-               if(FD_ISSET(c->socket, writeset)) {
-                       if(!flush_meta(c)) {
-                               terminate_connection(c, c->status.active);
-                               continue;
-                       }
+               if (!receive_meta(c)) {
+                       terminate_connection(c, c->status.active);
+                       return;
                }
        }
 
                }
        }
 
-       for(i = 0; i < listen_sockets; i++) {
-               if(FD_ISSET(listen_socket[i].udp, readset))
-                       handle_incoming_vpn_data(listen_socket[i].udp);
-
-               if(FD_ISSET(listen_socket[i].tcp, readset))
-                       handle_new_meta_connection(listen_socket[i].tcp);
+       if (events & EV_WRITE) {
+               if(!flush_meta(c)) {
+                       terminate_connection(c, c->status.active);
+               }
        }
 }
 
        }
 }
 
+static void dummy(int a, short b, void *c)
+{
+}
+
 /*
   this is where it all happens...
 */
 int main_loop(void)
 {
 /*
   this is where it all happens...
 */
 int main_loop(void)
 {
-       fd_set readset, writeset;
        struct timeval tv;
        struct timeval tv;
-       int r, maxfd;
+       int r;
        time_t last_ping_check, last_config_check, last_graph_dump;
        tevent_t *event;
        time_t last_ping_check, last_config_check, last_graph_dump;
        tevent_t *event;
+       struct event timeout;
 
        cp();
 
 
        cp();
 
@@ -374,23 +336,30 @@ int main_loop(void)
                tv.tv_sec = 1;
                tv.tv_usec = 0;
 
                tv.tv_sec = 1;
                tv.tv_usec = 0;
 
-               maxfd = build_fdset(&readset, &writeset);
-
-               r = select(maxfd + 1, &readset, &writeset, NULL, &tv);
+               /* XXX: libevent transition: old timeout code in this loop */
+               timeout_set(&timeout, dummy, NULL);
+               timeout_add(&timeout, &tv);
 
 
+               r = build_fdset();
                if(r < 0) {
                if(r < 0) {
-                       if(errno != EINTR && errno != EAGAIN) {
-                               logger(LOG_ERR, _("Error while waiting for input: %s"),
-                                          strerror(errno));
-                               cp_trace();
-                               dump_connections();
-                               return 1;
-                       }
+                       logger(LOG_ERR, _("Error building fdset: %s"), strerror(errno));
+                       cp_trace();
+                       dump_connections();
+                       return 1;
+               }
 
 
-                       continue;
+               r = event_loop(EVLOOP_ONCE);
+               now = time(NULL);
+               if(r < 0) {
+                       logger(LOG_ERR, _("Error while waiting for input: %s"),
+                                  strerror(errno));
+                       cp_trace();
+                       dump_connections();
+                       return 1;
                }
 
                }
 
-               check_network_activity(&readset, &writeset);
+               /* XXX: more libevent transition */
+               timeout_del(&timeout);
 
                if(do_purge) {
                        purge();
 
                if(do_purge) {
                        purge();
index d63c0522172071fb36b2fc4b95f1db8a60c59785..d66a1c7add4f7427e1285bd6cd5ae94e61dd316a 100644 (file)
--- a/src/net.h
+++ b/src/net.h
@@ -24,6 +24,7 @@
 #define __TINC_NET_H__
 
 #include <openssl/evp.h>
 #define __TINC_NET_H__
 
 #include <openssl/evp.h>
+#include <event.h>
 
 #include "ipv6.h"
 
 
 #include "ipv6.h"
 
@@ -99,6 +100,8 @@ typedef struct packet_queue_t {
 } packet_queue_t;
 
 typedef struct listen_socket_t {
 } packet_queue_t;
 
 typedef struct listen_socket_t {
+       struct event ev_tcp;
+       struct event ev_udp;
        int tcp;
        int udp;
        sockaddr_t sa;
        int tcp;
        int udp;
        sockaddr_t sa;
@@ -133,10 +136,10 @@ extern EVP_CIPHER_CTX packet_ctx;
 #include "node.h"
 
 extern void retry_outgoing(outgoing_t *);
 #include "node.h"
 
 extern void retry_outgoing(outgoing_t *);
-extern void handle_incoming_vpn_data(int);
+extern void handle_incoming_vpn_data(int, short, void *);
 extern void finish_connecting(struct connection_t *);
 extern void do_outgoing_connection(struct connection_t *);
 extern void finish_connecting(struct connection_t *);
 extern void do_outgoing_connection(struct connection_t *);
-extern bool handle_new_meta_connection(int);
+extern void handle_new_meta_connection(int, short, void *);
 extern int setup_listen_socket(const sockaddr_t *);
 extern int setup_vpn_in_socket(const sockaddr_t *);
 extern void send_packet(const struct node_t *, vpn_packet_t *);
 extern int setup_listen_socket(const sockaddr_t *);
 extern int setup_vpn_in_socket(const sockaddr_t *);
 extern void send_packet(const struct node_t *, vpn_packet_t *);
@@ -151,6 +154,8 @@ extern void terminate_connection(struct connection_t *, bool);
 extern void flush_queue(struct node_t *);
 extern bool read_rsa_public_key(struct connection_t *);
 extern void send_mtu_probe(struct node_t *);
 extern void flush_queue(struct node_t *);
 extern bool read_rsa_public_key(struct connection_t *);
 extern void send_mtu_probe(struct node_t *);
+extern void handle_device_data(int, short, void *);
+extern void handle_meta_connection_data(int, short, void *);
 
 #ifndef HAVE_MINGW
 #define closesocket(s) close(s)
 
 #ifndef HAVE_MINGW
 #define closesocket(s) close(s)
index 9e0ba2e893fc688c898f5ba15ffc15c1bb2171f6..bb81081d25fafc3089beb320da9d44da2e6b4947 100644 (file)
@@ -484,7 +484,7 @@ void flush_queue(node_t *n)
        }
 }
 
        }
 }
 
-void handle_incoming_vpn_data(int sock)
+void handle_incoming_vpn_data(int sock, short events, void *data)
 {
        vpn_packet_t pkt;
        char *hostname;
 {
        vpn_packet_t pkt;
        char *hostname;
@@ -515,3 +515,11 @@ void handle_incoming_vpn_data(int sock)
 
        receive_udppacket(n, &pkt);
 }
 
        receive_udppacket(n, &pkt);
 }
+
+void handle_device_data(int sock, short events, void *data)
+{
+       vpn_packet_t packet;
+
+       if(read_packet(&packet))
+               route(myself, &packet);
+}
index 0c399bb6cecba5802af1f2363ec6f7f594341156..65965908002540ab94340526771bb5d62cafc8bd 100644 (file)
@@ -45,6 +45,7 @@
 #include "xalloc.h"
 
 char *myport;
 #include "xalloc.h"
 
 char *myport;
+static struct event device_ev;
 
 bool read_rsa_public_key(connection_t *c)
 {
 
 bool read_rsa_public_key(connection_t *c)
 {
@@ -447,6 +448,14 @@ bool setup_myself(void)
        if(!setup_device())
                return false;
 
        if(!setup_device())
                return false;
 
+       event_set(&device_ev, device_fd, EV_READ|EV_PERSIST,
+                         handle_device_data, NULL);
+       if (event_add(&device_ev, NULL) < 0) {
+               logger(LOG_ERR, _("event_add failed: %s"), strerror(errno));
+               close_device();
+               return false;
+       }
+
        /* Run tinc-up script to further initialize the tap interface */
        asprintf(&envp[0], "NETNAME=%s", netname ? : "");
        asprintf(&envp[1], "DEVICE=%s", device ? : "");
        /* Run tinc-up script to further initialize the tap interface */
        asprintf(&envp[0], "NETNAME=%s", netname ? : "");
        asprintf(&envp[1], "DEVICE=%s", device ? : "");
@@ -492,8 +501,33 @@ bool setup_myself(void)
                listen_socket[listen_sockets].udp =
                        setup_vpn_in_socket((sockaddr_t *) aip->ai_addr);
 
                listen_socket[listen_sockets].udp =
                        setup_vpn_in_socket((sockaddr_t *) aip->ai_addr);
 
-               if(listen_socket[listen_sockets].udp < 0)
+               if(listen_socket[listen_sockets].udp < 0) {
+                       close(listen_socket[listen_sockets].tcp);
+                       continue;
+               }
+
+               event_set(&listen_socket[listen_sockets].ev_tcp,
+                                 listen_socket[listen_sockets].tcp,
+                                 EV_READ|EV_PERSIST,
+                                 handle_new_meta_connection, NULL);
+               if(event_add(&listen_socket[listen_sockets].ev_tcp, NULL) < 0) {
+                       logger(LOG_WARNING, _("event_add failed: %s"), strerror(errno));
+                       close(listen_socket[listen_sockets].tcp);
+                       close(listen_socket[listen_sockets].udp);
                        continue;
                        continue;
+               }
+
+               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_WARNING, _("event_add failed: %s"), strerror(errno));
+                       close(listen_socket[listen_sockets].tcp);
+                       close(listen_socket[listen_sockets].udp);
+                       event_del(&listen_socket[listen_sockets].ev_tcp);
+                       continue;
+               }
 
                ifdebug(CONNECTIONS) {
                        hostname = sockaddr2hostname((sockaddr_t *) aip->ai_addr);
 
                ifdebug(CONNECTIONS) {
                        hostname = sockaddr2hostname((sockaddr_t *) aip->ai_addr);
index 1db1949c1676fd824f8d8aff6129fb44d8a3fe1c..c727d7b2086da9a12aebba6df2651cab5281164a 100644 (file)
@@ -384,7 +384,7 @@ void setup_outgoing_connection(outgoing_t *outgoing)
   accept a new tcp connect and create a
   new connection
 */
   accept a new tcp connect and create a
   new connection
 */
-bool handle_new_meta_connection(int sock)
+void handle_new_meta_connection(int sock, short events, void *data)
 {
        connection_t *c;
        sockaddr_t sa;
 {
        connection_t *c;
        sockaddr_t sa;
@@ -398,7 +398,6 @@ bool handle_new_meta_connection(int sock)
        if(fd < 0) {
                logger(LOG_ERR, _("Accepting a new connection failed: %s"),
                           strerror(errno));
        if(fd < 0) {
                logger(LOG_ERR, _("Accepting a new connection failed: %s"),
                           strerror(errno));
-               return false;
        }
 
        sockaddrunmap(&sa);
        }
 
        sockaddrunmap(&sa);
@@ -423,8 +422,6 @@ bool handle_new_meta_connection(int sock)
 
        c->allow_request = ID;
        send_id(c);
 
        c->allow_request = ID;
        send_id(c);
-
-       return true;
 }
 
 void try_outgoing_connections(void)
 }
 
 void try_outgoing_connections(void)
index ed967629975c5ab9a883804a3cd776f6c50b0ff1..3a359087f22954a4ba1c0be11d74ac78b9377d86 100644 (file)
@@ -462,6 +462,11 @@ int main(int argc, char **argv)
        if(!read_server_config())
                return 1;
 
        if(!read_server_config())
                return 1;
 
+       if(event_init() < 0) {
+               logger(LOG_ERR, _("Error initializing libevent!"));
+               return 1;
+       }
+
        if(lzo_init() != LZO_E_OK) {
                logger(LOG_ERR, _("Error initializing LZO compressor!"));
                return 1;
        if(lzo_init() != LZO_E_OK) {
                logger(LOG_ERR, _("Error initializing LZO compressor!"));
                return 1;