Use a separate event structure to handle meta data writes.
authorGuus Sliepen <guus@tinc-vpn.org>
Thu, 17 May 2007 20:20:10 +0000 (20:20 +0000)
committerGuus Sliepen <guus@tinc-vpn.org>
Thu, 17 May 2007 20:20:10 +0000 (20:20 +0000)
Make meta socket events persistent.

src/connection.h
src/meta.c
src/meta.h
src/net.c
src/net_socket.c

index 8d5537b..495c38e 100644 (file)
@@ -101,6 +101,7 @@ typedef struct connection_t {
        int outbufstart;                        /* index of first meaningful byte in output buffer */
        int outbuflen;                          /* number of meaningful bytes in output buffer */
        int outbufsize;                         /* number of bytes allocated to output buffer */
+       struct event outev;                     /* events on this metadata connection */
 
        time_t last_ping_time;          /* last time we saw some activity from the other end or pinged them */
        time_t last_flushed_time;       /* last time buffer was empty. Only meaningful if outbuflen > 0 */
index a32d413..3e75045 100644 (file)
@@ -44,8 +44,13 @@ bool send_meta(connection_t *c, const char *buffer, int length)
        ifdebug(META) logger(LOG_DEBUG, _("Sending %d bytes of metadata to %s (%s)"), length,
                           c->name, c->hostname);
 
-       if(!c->outbuflen)
+       if(!c->outbuflen) {
                c->last_flushed_time = now;
+               if(event_add(&c->outev, NULL) < 0) {
+                       logger(LOG_EMERG, _("event_add failed: %s"), strerror(errno));
+                       abort();
+               }
+       }
 
        /* Find room in connection's buffer */
        if(length + c->outbuflen > c->outbufsize) {
@@ -79,8 +84,9 @@ bool send_meta(connection_t *c, const char *buffer, int length)
        return true;
 }
 
-bool flush_meta(connection_t *c)
+void flush_meta(int fd, short events, void *data)
 {
+       connection_t *c = data;
        int result;
        
        ifdebug(META) logger(LOG_DEBUG, _("Flushing %d bytes to %s (%s)"),
@@ -98,22 +104,24 @@ bool flush_meta(connection_t *c)
                        } else if(errno == EWOULDBLOCK) {
                                ifdebug(CONNECTIONS) logger(LOG_DEBUG, _("Flushing %d bytes to %s (%s) would block"),
                                                c->outbuflen, c->name, c->hostname);
-                               return true;
+                               return;
 #endif
                        } else {
                                logger(LOG_ERR, _("Flushing meta data to %s (%s) failed: %s"), c->name,
                                           c->hostname, strerror(errno));
                        }
 
-                       return false;
+                       terminate_connection(c, c->status.active);
+                       return;
                }
 
                c->outbufstart += result;
                c->outbuflen -= result;
        }
 
+       event_del(&c->outev);
+
        c->outbufstart = 0; /* avoid unnecessary memmoves */
-       return true;
 }
 
 void broadcast_meta(connection_t *from, const char *buffer, int length)
index 192bf24..f67caf4 100644 (file)
@@ -27,7 +27,7 @@
 
 extern bool send_meta(struct connection_t *, const char *, int);
 extern void broadcast_meta(struct connection_t *, const char *, int);
-extern bool flush_meta(struct connection_t *);
+extern void flush_meta(int fd, short events, void *data);
 extern bool receive_meta(struct connection_t *);
 
 #endif                                                 /* __TINC_META_H__ */
index 3a44ce6..8259a36 100644 (file)
--- a/src/net.c
+++ b/src/net.c
@@ -128,17 +128,9 @@ static int build_fdset(void)
                        connection_del(c);
                        if(!connection_tree->head)
                                purge();
-               } else {
-                       short events = EV_READ;
-                       if(c->outbuflen > 0)
-                               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;
                }
        }
+
        return 0;
 }
 
@@ -168,6 +160,8 @@ void terminate_connection(connection_t *c, bool report)
        if(c->socket)
                closesocket(c->socket);
 
+       event_del(&c->ev);
+
        if(c->edge) {
                if(report && !tunnelserver)
                        send_del_edge(broadcast, c->edge);
@@ -274,33 +268,25 @@ void handle_meta_connection_data(int fd, short events, void *data)
        if (c->status.remove)
                return;
 
-       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 (!receive_meta(c)) {
-                       terminate_connection(c, c->status.active);
+       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 (events & EV_WRITE) {
-               if(!flush_meta(c)) {
-                       terminate_connection(c, c->status.active);
-               }
+       if (!receive_meta(c)) {
+               terminate_connection(c, c->status.active);
+               return;
        }
 }
 
index 1b55c94..7fe80b2 100644 (file)
@@ -395,6 +395,14 @@ void setup_outgoing_connection(outgoing_t *outgoing)
        c->outgoing = outgoing;
        c->last_ping_time = now;
 
+       event_set(&c->ev, c->socket, EV_READ | EV_PERSIST, handle_meta_connection_data, c);
+       event_set(&c->outev, c->socket, EV_WRITE | EV_PERSIST, flush_meta, c);
+       if(event_add(&c->ev, NULL) < 0) {
+               logger(LOG_ERR, _("event_add failed: %s"), strerror(errno));
+               connection_del(c);
+               return;
+       }
+               
        connection_add(c);
 
        do_outgoing_connection(c);
@@ -416,8 +424,8 @@ void handle_new_meta_connection(int sock, short events, void *data)
        fd = accept(sock, &sa.sa, &len);
 
        if(fd < 0) {
-               logger(LOG_ERR, _("Accepting a new connection failed: %s"),
-                          strerror(errno));
+               logger(LOG_ERR, _("Accepting a new connection failed: %s"), strerror(errno));
+               return;
        }
 
        sockaddrunmap(&sa);
@@ -436,6 +444,14 @@ void handle_new_meta_connection(int sock, short events, void *data)
 
        ifdebug(CONNECTIONS) logger(LOG_NOTICE, _("Connection from %s"), c->hostname);
 
+       event_set(&c->ev, c->socket, EV_READ | EV_PERSIST, handle_meta_connection_data, c);
+       event_set(&c->outev, c->socket, EV_WRITE | EV_PERSIST, flush_meta, c);
+       if(event_add(&c->ev, NULL) < 0) {
+               logger(LOG_ERR, _("event_add failed: %s"), strerror(errno));
+               connection_del(c);
+               return;
+       }
+               
        configure_tcp(c);
 
        connection_add(c);