in.c

来自「这是一个完全开放的」· C语言 代码 · 共 541 行 · 第 1/2 页

C
541
字号
/* * jabberd - Jabber Open Source Server * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney, *                    Ryan Eatmon, Robert Norris * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA */#include "s2s.h"/* * we handle incoming connections, and the packets that arrive on them. * * action points: * *   event_STREAM - new incoming connection *     - create new dbconn (key stream id) *     - DONE * *   event_PACKET: <result from='them' to='us'>key</result> - auth request *     - get dbconn for this sx *     - if dbconn state is valid *       - send result: <result to='them' from='us' type='valid'/> *       - DONE *     - out_packet(s2s, <verify to='them' from='us' id='stream id'>key</verify>) *     - DONE *    *   event_PACKET: <verify from='them' to='us' id='123'>key</verify> - validate their key *     - generate dbkey: sha1(secret+remote+id) *     - if their key matches dbkey *       - send them: <verify to='them' from='us' id='123' type='valid'/> *     - else *       - send them: <verify to='them' from='us' id='123' type='invalid'/> *     - DONE * *   event_PACKET - they're trying to send us something *     - get dbconn for this sx *     - if dbconn state is invalid *       - drop packet *       - DONE *     - write packet to router *     - DONE *//* forward decls */static int _in_sx_callback(sx_t s, sx_event_t e, void *data, void *arg);static void _in_result(conn_t in, nad_t nad);static void _in_verify(conn_t in, nad_t nad);static void _in_packet(conn_t in, nad_t nad);int in_mio_callback(mio_t m, mio_action_t a, int 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;    switch(a) {        case action_READ:            log_debug(ZONE, "read action on fd %d", fd);            ioctl(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);            return sx_can_write(in->s);        case action_CLOSE:            log_debug(ZONE, "close action on fd %d", fd);            /* !!! logging */            log_write(in->s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] disconnect", fd, in->ip, in->port);            jqueue_push(in->s2s->dead, (void *) in->s, 0);            xhash_zap(in->s2s->in, in->key);            xhash_free(in->states);            xhash_free(in->routes);            if(in->key != NULL) free(in->key);            free(in);            break;        case action_ACCEPT:            s2s = (s2s_t) arg;            log_debug(ZONE, "accept action on fd %d", fd);                        getpeername(fd, (struct sockaddr *) &sa, &namelen);            port = j_inet_getport(&sa);            log_write(s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] incoming connection", fd, (char *) data, port);            /* new conn */            in = (conn_t) malloc(sizeof(struct conn_st));            memset(in, 0, sizeof(struct conn_st));            in->s2s = s2s;            strcpy(in->ip, (char *) data);            in->port = port;            in->states = xhash_new(101);            in->fd = fd;            in->init_time = time(NULL);            in->s = sx_new(s2s->sx_env, in->fd, _in_sx_callback, (void *) in);            mio_app(m, in->fd, in_mio_callback, (void *) in);#ifdef HAVE_SSL            sx_server_init(in->s, S2S_DB_HEADER | ((s2s->local_pemfile != NULL) ? SX_SSL_STARTTLS_OFFER : 0) );#else            sx_server_init(in->s, S2S_DB_HEADER);#endif            break;    }    return 0;}static int _in_sx_callback(sx_t s, sx_event_t e, void *data, void *arg) {    conn_t in = (conn_t) arg;    sx_buf_t buf = (sx_buf_t) data;    int len;    sx_error_t *sxe;    nad_t nad;    switch(e) {        case event_WANT_READ:            log_debug(ZONE, "want read");            mio_read(in->s2s->mio, in->fd);            break;        case event_WANT_WRITE:            log_debug(ZONE, "want write");            mio_write(in->s2s->mio, in->fd);            break;        case event_READ:            log_debug(ZONE, "reading from %d", in->fd);            /* do the read */            len = recv(in->fd, buf->data, buf->len, 0);            if(len < 0) {                if(errno == EWOULDBLOCK || errno == EINTR || errno == EAGAIN) {                    buf->len = 0;                    return 0;                }                log_write(in->s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] read error: %s (%d)", in->fd, in->ip, in->port, 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", in->fd);            len = send(in->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(in->s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] write error: %s (%d)", in->fd, in->ip, in->port, strerror(errno), errno);            sx_kill(s);            return -1;        case event_ERROR:            sxe = (sx_error_t *) data;            log_write(in->s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] error: %s (%s)", in->fd, in->ip, in->port, sxe->generic, sxe->specific);            break;        case event_STREAM:        case event_OPEN:            log_debug(ZONE, "STREAM or OPEN event from %s port %d (id %s)", in->ip, in->port, s->id);            /* first time, bring them online */            if ((!in->online)||(strcmp(in->key,s->id)!=0)) {                 log_debug(ZONE, "incoming conn from %s port %d is online (id %s)", in->ip, in->port, s->id);                in->online = 1;                /* record the id */                if (in->key != NULL)                   log_debug(ZONE,"adding new SSL stream id %s for stream id %s", s->id, in->key);                in->key = strdup(s->id);                /* track it */                xhash_put(in->s2s->in, in->key, (void *) in);            }              break;        case event_PACKET:            nad = (nad_t) data;            /* dialback packets */            if(NAD_NURI_L(nad, NAD_ENS(nad, 0)) == strlen(uri_DIALBACK) && strncmp(uri_DIALBACK, NAD_NURI(nad, NAD_ENS(nad, 0)), strlen(uri_DIALBACK)) == 0) {                /* only result and verify mean anything */                if(NAD_ENAME_L(nad, 0) == 6) {                    if(strncmp("result", NAD_ENAME(nad, 0), 6) == 0) {                        _in_result(in, nad);                        return 0;                    }                    if(strncmp("verify", NAD_ENAME(nad, 0), 6) == 0) {                        _in_verify(in, nad);                        return 0;                    }                }                                log_debug(ZONE, "unknown dialback packet, dropping it");                nad_free(nad);                return 0;            }            /*             * not dialback, so it has to be a normal-ish jabber packet:             *  - jabber:client or jabber:server             *  - message, presence or iq             *  - has to and from attributes             */            if(!(                 /* must be jabber:client or jabber:server */                 NAD_ENS(nad, 0) >= 0 &&

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?