Make meta socket events persistent.
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 */
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) {
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)"),
} 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)
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__ */
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;
}
if(c->socket)
closesocket(c->socket);
+ event_del(&c->ev);
+
if(c->edge) {
if(report && !tunnelserver)
send_del_edge(broadcast, c->edge);
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;
}
}
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);
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);
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);