static void _c2s_time_checks(c2s_t c2s) { sess_t sess; time_t now; union xhashv xhv; now = time(NULL); if(xhash_iter_first(c2s->sessions)) do { xhv.sess_val = &sess; xhash_iter_get(c2s->sessions, NULL, NULL, xhv.val); if(!sess->s) continue; if(c2s->io_check_idle > 0 && now > sess->last_activity + c2s->io_check_idle) { log_write(c2s->log, LOG_NOTICE, "[%d] [%s, port=%d] timed out", sess->fd->fd, sess->ip, sess->port); sx_error(sess->s, stream_err_HOST_GONE, "connection timed out"); sx_close(sess->s); continue; } if(c2s->io_check_keepalive > 0 && now > sess->last_activity + c2s->io_check_keepalive && sess->s->state >= state_STREAM) { log_debug(ZONE, "sending keepalive for %d", sess->fd->fd); sx_raw_write(sess->s, " ", 1); } if(sess->rate != NULL && sess->rate->bad != 0 && rate_check(sess->rate) != 0) { /* read the pending bytes when rate limit is no longer in effect */ log_debug(ZONE, "reading throttled %d", sess->fd->fd); sess->s->want_read = 1; sx_can_read(sess->s); } } while(xhash_iter_next(c2s->sessions)); }
int sm_mio_callback(mio_t m, mio_action_t a, mio_fd_t fd, void *data, void *arg) { sm_t sm = (sm_t) arg; int nbytes; switch (a) { case action_READ: log_debug(ZONE, "read action on fd %d", fd->fd); ioctl(fd->fd, FIONREAD, &nbytes); if(nbytes == 0) { sx_kill(sm->router); return 0; } return sx_can_read(sm->router); case action_WRITE: log_debug(ZONE, "write action on fd %d", fd->fd); return sx_can_write(sm->router); case action_CLOSE: log_debug(ZONE, "close action on fd %d", fd->fd); log_write(sm->log, LOG_NOTICE, "connection to router closed"); sm_lost_router = 1; /* we're offline */ sm->online = 0; break; case action_ACCEPT: break; } return 0; }
int router_mio_callback(mio_t m, mio_action_t a, mio_fd_t fd, void *data, void *arg) { component_t comp = (component_t) arg; router_t r = (router_t) arg; struct sockaddr_storage sa; socklen_t namelen = sizeof(sa); int port, nbytes; switch(a) { case action_READ: log_debug(ZONE, "read action on fd %d", fd->fd); /* they did something */ comp->last_activity = time(NULL); ioctl(fd->fd, FIONREAD, &nbytes); if(nbytes == 0) { sx_kill(comp->s); return 0; } return sx_can_read(comp->s); case action_WRITE: log_debug(ZONE, "write action on fd %d", fd->fd); /* update activity timestamp */ comp->last_activity = time(NULL); return sx_can_write(comp->s); case action_CLOSE: log_debug(ZONE, "close action on fd %d", fd->fd); r = comp->r; log_write(r->log, LOG_NOTICE, "[%s, port=%d] disconnect", comp->ip, comp->port); /* unbind names */ xhash_walk(comp->routes, _router_route_unbind_walker, (void *) comp); /* deregister component */ xhash_zap(r->components, comp->ipport); xhash_free(comp->routes); if(comp->tq != NULL) /* !!! bounce packets */ jqueue_free(comp->tq); rate_free(comp->rate); jqueue_push(comp->r->dead, (void *) comp->s, 0); free(comp); break; case action_ACCEPT: log_debug(ZONE, "accept action on fd %d", fd->fd); getpeername(fd->fd, (struct sockaddr *) &sa, &namelen); port = j_inet_getport(&sa); log_write(r->log, LOG_NOTICE, "[%s, port=%d] connect", (char *) data, port); if(_router_accept_check(r, fd, (char *) data) != 0) return 1; comp = (component_t) calloc(1, sizeof(struct component_st)); comp->r = r; comp->fd = fd; snprintf(comp->ip, INET6_ADDRSTRLEN, "%s", (char *) data); comp->port = port; snprintf(comp->ipport, INET6_ADDRSTRLEN + 6, "%s:%d", comp->ip, comp->port); comp->s = sx_new(r->sx_env, fd->fd, _router_sx_callback, (void *) comp); mio_app(m, fd, router_mio_callback, (void *) comp); if(r->byte_rate_total != 0) comp->rate = rate_new(r->byte_rate_total, r->byte_rate_seconds, r->byte_rate_wait); comp->routes = xhash_new(51); /* register component */ log_debug(ZONE, "new component (%p) \"%s\"", comp, comp->ipport); xhash_put(r->components, comp->ipport, (void *) comp); #ifdef HAVE_SSL sx_server_init(comp->s, SX_SSL_STARTTLS_OFFER | SX_SASL_OFFER); #else sx_server_init(comp->s, SX_SASL_OFFER); #endif break; } return 0; }
int in_mio_callback(mio_t m, mio_action_t a, mio_fd_t fd, void *data, void *arg) { conn_t in = (conn_t) arg; s2s_t s2s = (s2s_t) arg; struct sockaddr_storage sa; int namelen = sizeof(sa), port, nbytes; char ipport[INET6_ADDRSTRLEN + 17]; switch(a) { case action_READ: log_debug(ZONE, "read action on fd %d", fd->fd); ioctl(fd->fd, FIONREAD, &nbytes); if(nbytes == 0) { sx_kill(in->s); return 0; } return sx_can_read(in->s); case action_WRITE: log_debug(ZONE, "write action on fd %d", fd->fd); return sx_can_write(in->s); case action_CLOSE: log_debug(ZONE, "close action on fd %d", fd->fd); /* !!! logging */ log_write(in->s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] disconnect, packets: %i", fd->fd, in->ip, in->port, in->packet_count); jqueue_push(in->s2s->dead, (void *) in->s, 0); /* remove from open streams hash if online, or open connections if not */ if (in->online) xhash_zap(in->s2s->in, in->key); else { snprintf(ipport, INET6_ADDRSTRLEN + 16, "%s/%d", in->ip, in->port); xhash_zap(in->s2s->in_accept, ipport); } jqueue_push(in->s2s->dead_conn, (void *) in, 0); break; case action_ACCEPT: s2s = (s2s_t) arg; log_debug(ZONE, "accept action on fd %d", fd->fd); getpeername(fd->fd, (struct sockaddr *) &sa, &namelen); port = j_inet_getport(&sa); log_write(s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] incoming connection", fd->fd, (char *) data, port); /* new conn */ in = (conn_t) calloc(1, sizeof(struct conn_st)); in->s2s = s2s; strncpy(in->ip, (char *) data, INET6_ADDRSTRLEN); in->port = port; in->states = xhash_new(101); in->states_time = xhash_new(101); in->fd = fd; in->init_time = time(NULL); in->s = sx_new(s2s->sx_env, in->fd->fd, _in_sx_callback, (void *) in); mio_app(m, in->fd, in_mio_callback, (void *) in); if(s2s->stanza_size_limit != 0) in->s->rbytesmax = s2s->stanza_size_limit; /* add to incoming connections hash */ snprintf(ipport, INET6_ADDRSTRLEN + 16, "%s/%d", in->ip, in->port); xhash_put(s2s->in_accept, pstrdup(xhash_pool(s2s->in_accept),ipport), (void *) in); #ifdef HAVE_SSL sx_server_init(in->s, S2S_DB_HEADER | ((s2s->sx_ssl != NULL) ? SX_SSL_STARTTLS_OFFER : 0) ); #else sx_server_init(in->s, S2S_DB_HEADER); #endif break; } return 0; }