📄 c2s.c
字号:
rt = (rate_t) xhash_get(c2s->conn_rates, ip); if(rt == NULL) { rt = rate_new(c2s->conn_rate_total, c2s->conn_rate_seconds, c2s->conn_rate_wait); xhash_put(c2s->conn_rates, pstrdup(xhash_pool(c2s->conn_rates), ip), (void *) rt); pool_cleanup(xhash_pool(c2s->conn_rates), (void (*)(void *)) rate_free, rt); } if(rate_check(rt) == 0) { log_write(c2s->log, LOG_NOTICE, "[%d] [%s] is being rate limited", fd, ip); return 1; } rate_add(rt, 1); } return 0;}static int _c2s_client_mio_callback(mio_t m, mio_action_t a, int fd, void *data, void *arg) { sess_t sess = (sess_t) arg; c2s_t c2s = (c2s_t) arg; struct sockaddr_storage sa; int namelen = sizeof(sa), port, nbytes; switch(a) { case action_READ: log_debug(ZONE, "read action on fd %d", fd); /* they did something */ sess->last_activity = time(NULL); ioctl(fd, FIONREAD, &nbytes); if(nbytes == 0) { sx_kill(sess->s); return 0; } return sx_can_read(sess->s); case action_WRITE: log_debug(ZONE, "write action on fd %d", fd); return sx_can_write(sess->s); case action_CLOSE: log_debug(ZONE, "close action on fd %d", fd); log_write(sess->c2s->log, LOG_NOTICE, "[%d] [%s, port=%d] disconnect", sess->fd, sess->ip, sess->port); /* tell the sm to close their session */ if(sess->active) sm_end(sess); /* free their data */ if(sess->ip != NULL) free(sess->ip); if(sess->result != NULL) nad_free(sess->result); if(sess->jid != NULL) jid_free(sess->jid); jqueue_push(sess->c2s->dead, (void *) sess->s, 0); xhash_zap(sess->c2s->sessions, sess->skey); free(sess); break; case action_ACCEPT: log_debug(ZONE, "accept action on fd %d", fd); getpeername(fd, (struct sockaddr *) &sa, &namelen); port = j_inet_getport(&sa); log_write(c2s->log, LOG_NOTICE, "[%d] [%s, port=%d] connect", fd, (char *) data, port); if(_c2s_client_accept_check(c2s, fd, (char *) data) != 0) return 1; sess = (sess_t) malloc(sizeof(struct sess_st)); memset(sess, 0, sizeof(struct sess_st)); sess->c2s = c2s; sess->fd = fd; sess->ip = strdup((char *) data); sess->port = port; /* they did something */ sess->last_activity = time(NULL); sess->s = sx_new(c2s->sx_env, fd, _c2s_client_sx_callback, (void *) sess); mio_app(m, fd, _c2s_client_mio_callback, (void *) sess); if(c2s->byte_rate_total != 0) sess->rate = rate_new(c2s->byte_rate_total, c2s->byte_rate_seconds, c2s->byte_rate_wait); /* find out which port this is */ getsockname(fd, (struct sockaddr *) &sa, &namelen); port = j_inet_getport(&sa); /* remember it */ sprintf(sess->skey, "%d", fd); xhash_put(c2s->sessions, sess->skey, (void *) sess);#ifdef HAVE_SSL /* go ssl wrappermode if they're on the ssl port */ if(port == c2s->local_ssl_port) sx_server_init(sess->s, SX_SSL_WRAPPER | SX_SASL_OFFER | ((c2s->ar_mechanisms & AR_MECH_SASL_ANONYMOUS) ? SX_SASL_MECH_ANONYMOUS : 0) | ((c2s->ar_mechanisms & AR_MECH_SASL_PLAIN) ? SX_SASL_MECH_PLAIN : 0) | ((c2s->ar_mechanisms & AR_MECH_SASL_DIGESTMD5) ? SX_SASL_MECH_DIGESTMD5 : 0)); else sx_server_init(sess->s, ((c2s->local_pemfile != NULL) ? SX_SSL_STARTTLS_OFFER : 0) | SX_SASL_OFFER | ((c2s->ar_mechanisms & AR_MECH_SASL_ANONYMOUS) ? SX_SASL_MECH_ANONYMOUS : 0) | ((c2s->ar_mechanisms & AR_MECH_SASL_PLAIN) ? SX_SASL_MECH_PLAIN : 0) | ((c2s->ar_mechanisms & AR_MECH_SASL_DIGESTMD5) ? SX_SASL_MECH_DIGESTMD5 : 0) | (c2s->local_require_starttls ? SX_SSL_STARTTLS_REQUIRE : 0));#else sx_server_init(sess->s, SX_SASL_OFFER | ((c2s->ar_mechanisms & AR_MECH_SASL_ANONYMOUS) ? SX_SASL_MECH_ANONYMOUS : 0) | ((c2s->ar_mechanisms & AR_MECH_SASL_PLAIN) ? SX_SASL_MECH_PLAIN : 0) | ((c2s->ar_mechanisms & AR_MECH_SASL_DIGESTMD5) ? SX_SASL_MECH_DIGESTMD5 : 0));#endif break; } return 0;}static void _c2s_component_presence(c2s_t c2s, nad_t nad) { int attr; char from[1024]; sess_t sess; if((attr = nad_find_attr(nad, 0, -1, "from", NULL)) < 0) { nad_free(nad); return; } strncpy(from, NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr)); from[NAD_AVAL_L(nad, attr)] = '\0'; if(nad_find_attr(nad, 0, -1, "type", NULL) < 0) { log_debug(ZONE, "component available from '%s'", from); if(xhash_get(c2s->realms, from) != NULL) { log_debug(ZONE, "sm for serviced domain '%s' online", from); xhash_put(c2s->sm_avail, pstrdup(xhash_pool(c2s->realms), from), (void *) 1); } nad_free(nad); return; } if(nad_find_attr(nad, 0, -1, "type", "unavailable") < 0) { nad_free(nad); return; } log_debug(ZONE, "component unavailable from '%s'", from); if(xhash_get(c2s->sm_avail, from) != NULL) { log_debug(ZONE, "sm for serviced domain '%s' offline", from); if(xhash_iter_first(c2s->sessions)) do { xhash_iter_get(c2s->sessions, NULL, (void **) &sess); if(sess->jid != NULL && strcmp(sess->jid->domain, from) == 0) { log_debug(ZONE, "killing session %s", jid_full(sess->jid)); sess->active = 0; sx_close(sess->s); } } while(xhash_iter_next(c2s->sessions)); xhash_zap(c2s->sm_avail, from); }}int c2s_router_sx_callback(sx_t s, sx_event_t e, void *data, void *arg) { c2s_t c2s = (c2s_t) arg; sx_buf_t buf = (sx_buf_t) data; sx_error_t *sxe; nad_t nad; int len, elem, from, c2sid, smid, action, id, ns, attr, scan, replaced; char skey[10]; sess_t sess; switch(e) { case event_WANT_READ: log_debug(ZONE, "want read"); mio_read(c2s->mio, c2s->fd); break; case event_WANT_WRITE: log_debug(ZONE, "want write"); mio_write(c2s->mio, c2s->fd); break; case event_READ: log_debug(ZONE, "reading from %d", c2s->fd); /* do the read */ len = recv(c2s->fd, buf->data, buf->len, 0); if(len < 0) { if(errno == EWOULDBLOCK || errno == EINTR || errno == EAGAIN) { buf->len = 0; return 0; } log_write(c2s->log, LOG_NOTICE, "[%d] [router] read error: %s (%d)", c2s->fd, strerror(errno), errno); sx_kill(s); return -1; } else if(len == 0) { /* they went away */ sx_kill(s); return -1; } log_debug(ZONE, "read %d bytes", len); buf->len = len; return len; case event_WRITE: log_debug(ZONE, "writing to %d", c2s->fd); len = send(c2s->fd, buf->data, buf->len, 0); if(len >= 0) { log_debug(ZONE, "%d bytes written", len); return len; } if(errno == EWOULDBLOCK || errno == EINTR || errno == EAGAIN) return 0; log_write(c2s->log, LOG_NOTICE, "[%d] [router] write error: %s (%d)", c2s->fd, strerror(errno), errno); sx_kill(s); return -1; case event_ERROR: sxe = (sx_error_t *) data; log_write(c2s->log, LOG_NOTICE, "error from router: %s (%s)", sxe->generic, sxe->specific); if(sxe->code == SX_ERR_AUTH) sx_close(s); break; case event_STREAM: break; case event_OPEN: log_write(c2s->log, LOG_NOTICE, "connection to router established"); nad = nad_new(c2s->router->nad_cache); ns = nad_add_namespace(nad, uri_COMPONENT, NULL); nad_append_elem(nad, ns, "bind", 0); nad_append_attr(nad, -1, "name", c2s->id); log_debug(ZONE, "requesting component bind for '%s'", c2s->id); sx_nad_write(c2s->router, nad); return 0; case event_PACKET: nad = (nad_t) data; /* drop unqualified packets */ if(NAD_ENS(nad, 0) < 0) { nad_free(nad); return 0; } /* watch for the features packet */ if(s->state == state_STREAM) { if(NAD_NURI_L(nad, NAD_ENS(nad, 0)) != strlen(uri_STREAMS) || strncmp(uri_STREAMS, NAD_NURI(nad, NAD_ENS(nad, 0)), strlen(uri_STREAMS)) != 0 || NAD_ENAME_L(nad, 0) != 8 || strncmp("features", NAD_ENAME(nad, 0), 8) != 0) { log_debug(ZONE, "got a non-features packet on an unauth'd stream, dropping"); nad_free(nad); return 0; }#ifdef HAVE_SSL /* starttls if we can */ if(c2s->sx_ssl != NULL && c2s->router_pemfile != NULL && s->ssf == 0) { ns = nad_find_scoped_namespace(nad, uri_TLS, NULL); if(ns >= 0) { elem = nad_find_elem(nad, 0, ns, "starttls", 1); if(elem >= 0) { if(sx_ssl_client_starttls(c2s->sx_ssl, s, c2s->router_pemfile) == 0) { nad_free(nad); return 0; } log_write(c2s->log, LOG_ERR, "unable to establish encrypted session with router"); } } }#endif /* !!! pull the list of mechanisms, and choose the best one. * if there isn't an appropriate one, error and bail */ /* authenticate */ sx_sasl_auth(c2s->sx_sasl, s, "DIGEST-MD5", c2s->router_user, c2s->router_pass, NULL); nad_free(nad); return 0; } /* watch for the bind response */ if(s->state == state_OPEN && !c2s->online) { if(NAD_NURI_L(nad, NAD_ENS(nad, 0)) != strlen(uri_COMPONENT) || strncmp(uri_COMPONENT, NAD_NURI(nad, NAD_ENS(nad, 0)), strlen(uri_COMPONENT)) != 0 || NAD_ENAME_L(nad, 0) != 4 || strncmp("bind", NAD_ENAME(nad, 0), 4) != 0) { log_debug(ZONE, "got a packet from router, but we're not online, dropping"); nad_free(nad); return 0; } /* catch errors */ attr = nad_find_attr(nad, 0, -1, "error", NULL); if(attr >= 0) { log_write(c2s->log, LOG_ERR, "router refused bind request (%.*s)", NAD_AVAL_L(nad, attr), NAD_AVAL(nad, attr)); exit(1); } log_debug(ZONE, "coming online"); /* if we're coming online for the first time, setup listening sockets */#ifdef HAVE_SSL if(c2s->server_fd == 0 && c2s->server_ssl_fd == 0) {#else if(c2s->server_fd == 0) {#endif if(c2s->local_port != 0) { c2s->server_fd = mio_listen(c2s->mio, c2s->local_port, c2s->local_ip, _c2s_client_mio_callback, (void *) c2s); if(c2s->server_fd < 0) log_write(c2s->log, LOG_ERR, "[%s, port=%d] failed to listen", c2s->local_ip, c2s->local_port); else log_write(c2s->log, LOG_NOTICE, "[%s, port=%d] listening for connections", c2s->local_ip, c2s->local_port); } else c2s->server_fd = -1; #ifdef HAVE_SSL if(c2s->local_ssl_port != 0 && c2s->local_pemfile != NULL) { c2s->server_ssl_fd = mio_listen(c2s->mio, c2s->local_ssl_port, c2s->local_ip, _c2s_client_mio_callback, (void *) c2s); if(c2s->server_ssl_fd < 0) log_write(c2s->log, LOG_ERR, "[%s, port=%d] failed to listen", c2s->local_ip, c2s->local_ssl_port);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -