⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 c2s.c

📁 这是一个完全开放的
💻 C
📖 第 1 页 / 共 3 页
字号:
        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 + -