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

📄 client.c

📁 jabber server jabber server jabber server jabber server
💻 C
📖 第 1 页 / 共 2 页
字号:
/* -------------------------------------------------------------------------- * * License * * The contents of this file are subject to the Jabber Open Source License * Version 1.0 (the "JOSL").  You may not copy or use this file, in either * source code or executable form, except in compliance with the JOSL. You * may obtain a copy of the JOSL at http://www.jabber.org/ or at * http://www.opensource.org/.   * * Software distributed under the JOSL is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the JOSL * for the specific language governing rights and limitations under the * JOSL. * * Copyrights *  * Portions created by or assigned to Jabber.com, Inc. are  * Copyright (c) 1999-2002 Jabber.com, Inc.  All Rights Reserved.  Contact * information for Jabber.com, Inc. is available at http://www.jabber.com/. * * Portions Copyright (c) 1998-1999 Jeremie Miller. *  * Acknowledgements *  * Special thanks to the Jabber Open Source Contributors for their * suggestions and support of Jabber. *  * Alternatively, the contents of this file may be used under the terms of the * GNU General Public License Version 2 or later (the "GPL"), in which case * the provisions of the GPL are applicable instead of those above.  If you * wish to allow use of your version of this file only under the terms of the * GPL and not to allow others to use your version of this file under the JOSL, * indicate your decision by deleting the provisions above and replace them * with the notice and other provisions required by the GPL.  If you do not * delete the provisions above, a recipient may use your version of this file * under either the JOSL or the GPL.  *  *  * --------------------------------------------------------------------------*//*    <service id="pthsock client">      <host>pth-csock.127.0.0.1</host> <!-- Can be anything -->      <load>	    <pthsock_client>../load/pthsock_client.so</pthsock_client>      </load>      <pthcsock xmlns='jabber:config:pth-csock'>        <alias to="main.host.com">alias.host.com</alias>        <alias to="default.host.com"/>        <listen>5222</listen>            <!-- Port to listen on -->        <!-- allow 25 connects per 5 seconts -->        <rate time="5" points="25"/>       </pthcsock>    </service>*/#include <jabberd.h>#define DEFAULT_AUTH_TIMEOUT 120#define DEFAULT_HEARTBEAT 60/* socket manager instance */typedef struct smi_st{    instance i;    int auth_timeout;    int heartbeat;    xht aliases;    xht users;    xmlnode cfg;    char *host;    int register_feature;	/**< should we advertise the register stream feature? */} *smi, _smi;typedef enum { state_UNKNOWN, state_AUTHD } user_state;typedef struct edata_st{    smi si;    int aliased;    jid session_id;    jid sending_id;    user_state state;    char *client_id, *sid, *res, *auth_id;    time_t connect_time;    time_t last_activity;    mio m;    pth_msgport_t pre_auth_mp;} _cdata,*cdata;/* makes a route packet, intelligently */xmlnode pthsock_make_route(xmlnode x, char *to, char *from, char *type){    xmlnode new;    new = x ? xmlnode_wrap(x, "route") : xmlnode_new_tag("route");    if(type != NULL)         xmlnode_put_attrib(new, "type", type);    if(to != NULL)         xmlnode_put_attrib(new, "to", to);    if(from != NULL)         xmlnode_put_attrib(new, "from", from);    return new;}/* incoming jabberd deliver()ed packets */result pthsock_client_packets(instance id, dpacket p, void *arg){    smi s__i = (smi)arg;    cdata cdcur;    mio m;    int fd = 0;    if(p->id->user != NULL)        fd = atoi(p->id->user);         if(p->type != p_ROUTE || fd == 0)    { /* we only want <route/> packets or ones with a valid connection */        log_warn(p->host, "pthsock_client bouncing invalid %s packet from %s", xmlnode_get_name(p->x), xmlnode_get_attrib(p->x,"from"));        deliver_fail(p, "invalid client packet");        return r_DONE;    }    if ((cdcur = xhash_get(s__i->users, xmlnode_get_attrib(p->x,"to"))) == NULL)    {        if (!j_strcmp(xmlnode_get_attrib(p->x, "type"),  "session"))        {            jutil_tofrom(p->x);            xmlnode_put_attrib(p->x, "type", "error");            deliver(dpacket_new(p->x), s__i->i);        } else {            xmlnode_free(p->x);        }        return r_DONE;    }    if (fd != cdcur->m->fd || cdcur->m->state != state_ACTIVE)        m = NULL;    else if (j_strcmp(p->id->resource,cdcur->res) != 0)        m = NULL;    else        m = cdcur->m;    if(m == NULL)    {         if (j_strcmp(xmlnode_get_attrib(p->x, "type"), "error") == 0)        { /* we got a 510, but no session to end */            log_debug2(ZONE, LOGT_SESSION, "[%s] received Session close for non-existant session: %s", ZONE, xmlnode_get_attrib(p->x, "from"));            xmlnode_free(p->x);            return r_DONE;        }        log_debug2(ZONE, LOGT_SESSION, "[%s] connection not found for %s, closing session", ZONE, xmlnode_get_attrib(p->x, "from"));        jutil_tofrom(p->x);        xmlnode_put_attrib(p->x, "type", "error");        deliver(dpacket_new(p->x), s__i->i);        return r_DONE;    }    log_debug2(ZONE, LOGT_DELIVER, "[%s] %s has an active session, delivering packet", ZONE, xmlnode_get_attrib(p->x, "from"));    if (j_strcmp(xmlnode_get_attrib(p->x, "type"), "error") == 0)    { /* <route type="error" means we were disconnected */        log_debug2(ZONE, LOGT_SESSION, "[%s] closing down session %s at request of session manager", ZONE, xmlnode_get_attrib(p->x, "from"));        mio_write(m, NULL, "<stream:error><conflict xmlns='urn:ietf:params:xml:ns:xmpp-streams'/><text xmlns='urn:ietf:params:xml:ns:xmpp-streams' xml:lang='en'>Disconnected</text></stream:error></stream:stream>", -1);        mio_close(m);        xmlnode_free(p->x);        return r_DONE;    }    else if(cdcur->state == state_UNKNOWN && j_strcmp(xmlnode_get_attrib(p->x, "type"), "auth") == 0)    { /* look for our auth packet back */        char *type = xmlnode_get_attrib(xmlnode_get_firstchild(p->x), "type");        char *id   = xmlnode_get_attrib(xmlnode_get_tag(p->x, "iq"), "id");        if((j_strcmp(type, "result") == 0) && j_strcmp(cdcur->auth_id, id) == 0)        { /* update the cdata status if it's a successfull auth */            xmlnode x;            log_debug2(ZONE, LOGT_AUTH|LOGT_SESSION, "[%s], auth for user successful", ZONE);            /* notify SM to start a session */            x = pthsock_make_route(NULL, jid_full(cdcur->session_id), cdcur->client_id, "session");            log_debug2(ZONE, LOGT_SESSION, "[%s] requesting Session Start for %s", ZONE, xmlnode_get_attrib(p->x, "from"));            deliver(dpacket_new(x), s__i->i);        }         else if(j_strcmp(type,"error") == 0)        {            log_record(jid_full(jid_user(cdcur->session_id)), "login", "fail", "%s %s %s", mio_ip(cdcur->m), xmlnode_get_attrib(xmlnode_get_tag(p->x, "iq/error"),"code"), cdcur->session_id->resource);        }    }     else if(cdcur->state == state_UNKNOWN && j_strcmp(xmlnode_get_attrib(p->x, "type"), "session") == 0)    { /* got a session reply from the server */        mio_wbq q;        cdcur->state = state_AUTHD;        log_record(jid_full(jid_user(cdcur->session_id)), "login", "ok", "%s %s", mio_ip(cdcur->m), cdcur->session_id->resource);        /* change the host id */        cdcur->session_id = jid_new(m->p, xmlnode_get_attrib(p->x, "from"));        xmlnode_free(p->x);        /* if we have packets in the queue, write them */        while((q = (mio_wbq)pth_msgport_get(cdcur->pre_auth_mp)) != NULL)        {            q->x = pthsock_make_route(q->x, jid_full(cdcur->session_id), cdcur->client_id, NULL);            deliver(dpacket_new(q->x), s__i->i);        }        pth_msgport_destroy(cdcur->pre_auth_mp);        cdcur->pre_auth_mp = NULL;        return r_DONE;    }    if(xmlnode_get_firstchild(p->x) == NULL || xhash_get(s__i->users, xmlnode_get_attrib(p->x, "to")) == NULL)    {        xmlnode_free(p->x);    }    else    {        /* change the to name to match what the client wants to hear 	 * jer: I have no sympathy for clients that can't handle this right, they should check the stream from="" anyway        if(cdcur->aliased)        {            jid j = jid_new(p->p, xmlnode_get_attrib(xmlnode_get_firstchild(p->x), "to"));            if(j != NULL && j_strcmp(j->server, cdcur->sending_id->server) != 0)            {                jid_set(j, cdcur->sending_id->server, JID_SERVER);                xmlnode_put_attrib(xmlnode_get_firstchild(p->x), "to", jid_full(j));            }            j = jid_new(p->p, xmlnode_get_attrib(xmlnode_get_firstchild(p->x), "from"));            if(j != NULL && j->user == NULL && j_strcmp(j->server, cdcur->session_id->server) == 0)            {                jid_set(j, cdcur->sending_id->server, JID_SERVER);                xmlnode_put_attrib(xmlnode_get_firstchild(p->x), "from", jid_full(j));            }        }*/        log_debug2(ZONE, LOGT_IO, "[%s] Writing packet to MIO: %s", ZONE, xmlnode2str(xmlnode_get_firstchild(p->x)));        mio_write(m, xmlnode_get_firstchild(p->x), NULL, 0);        cdcur->last_activity = time(NULL);    }    return r_DONE;}cdata pthsock_client_cdata(mio m, smi s__i){    cdata cd;    char *buf;    cd               = pmalloco(m->p, sizeof(_cdata));    cd->pre_auth_mp  = pth_msgport_create("pre_auth_mp");    cd->state        = state_UNKNOWN;    cd->connect_time = time(NULL);    cd->last_activity = cd->connect_time;    cd->m            = m;    cd->si           = s__i;    buf = pmalloco(m->p, 100);    /* HACK to fix race conditon */    snprintf(buf, 99, "%X", m);    cd->res = pstrdup(m->p, buf);    /* we use <fd>@host to identify connetions */    snprintf(buf, 99, "%d@%s/%s", m->fd, s__i->host, cd->res);    cd->client_id = pstrdup(m->p, buf);    return cd;}void pthsock_client_read(mio m, int flag, void *arg, xmlnode x){    cdata cd = (cdata)arg;    xmlnode h;    char *alias, *to;    int version = 0;    if(cd == NULL)         return;    log_debug2(ZONE, LOGT_IO, "[%s] pthsock_client_read called with: m:%X flag:%d arg:%X", ZONE, m, flag, arg);    switch(flag)    {    case MIO_CLOSED:        log_debug2(ZONE, LOGT_IO, "[%s] io_select Socket %d close notification", ZONE, m->fd);        xhash_zap(cd->si->users, cd->client_id);        if(cd->state == state_AUTHD)        {            h = pthsock_make_route(NULL, jid_full(cd->session_id), cd->client_id, "error");            deliver(dpacket_new(h), cd->si->i);        }        if(cd->pre_auth_mp != NULL)        { /* if there is a pre_auth queue still */            mio_wbq q;            while((q = (mio_wbq)pth_msgport_get(cd->pre_auth_mp)) != NULL)            {                log_debug2(ZONE, LOGT_IO, "[%s] freeing unsent packet due to disconnect with no auth: %s", ZONE, xmlnode2str(q->x));                xmlnode_free(q->x);            }            pth_msgport_destroy(cd->pre_auth_mp);            cd->pre_auth_mp = NULL;        }         break;    case MIO_ERROR:        while((h = mio_cleanup(m)) != NULL)            deliver_fail(dpacket_new(h), "Socket Error to Client");        break;    case MIO_XML_ROOT:        log_debug2(ZONE, LOGT_IO, "[%s] root received for %d", ZONE, m->fd);        to = xmlnode_get_attrib(x, "to");        cd->sending_id = jid_new(cd->m->p, to);	/* check for XMPP version attribute */	version = j_atoi(xmlnode_get_attrib(x, "version"), 0);        /* check for a matching alias or use default alias */        log_debug2(ZONE, LOGT_IO, "[%s] Recieved connection to: %s", ZONE, jid_full(cd->sending_id));        alias = xhash_get(cd->si->aliases, to);        alias = alias ? alias : xhash_get(cd->si->aliases, "default");        /* set host to that alias, or to the given host */        cd->session_id = alias ? jid_new(m->p, alias) : cd->sending_id;        /* if we are using an alias, set the alias flag */        if(j_strcmp(jid_full(cd->session_id), jid_full(cd->sending_id)) != 0) cd->aliased = 1;        if(cd->aliased) log_debug2(ZONE, LOGT_SESSION, "[%s] using alias %s --> %s", ZONE, jid_full(cd->sending_id), jid_full(cd->session_id));        /* write header */        h = xstream_header("jabber:client", NULL, jid_full(cd->session_id));        cd->sid = pstrdup(m->p, xmlnode_get_attrib(h, "id"));        /* XXX hack in the style that jabber.com uses for flash mode support */        if(j_strncasecmp(xmlnode_get_attrib(x, "xmlns:flash"), "http://www.jabber.com/streams/flash",35) == 0)        {            h = xmlnode_new_tag_pool(xmlnode_pool(h),"flash:stream");            xmlnode_put_attrib(h, "xmlns:flash", "http://www.jabber.com/streams/flash");             xmlnode_put_attrib(h, "xmlns:stream", "http://etherx.jabber.org/streams");             xmlnode_put_attrib(h, "xmlns", "jabber:client");             xmlnode_put_attrib(h, "id", cd->sid);             xmlnode_put_attrib(h, "from", jid_full(cd->session_id));             /* put real stream declaration on incoming root */            xmlnode_put_attrib(x, "xmlns:stream", "http://etherx.jabber.org/streams");         }	if (version>=1) {	    xmlnode_put_attrib(h, "version", "1.0");	}        mio_write(m, NULL, xstream_header_char(h), -1);        xmlnode_free(h);        if(j_strcmp(xmlnode_get_attrib(x, "xmlns"), "jabber:client") != 0)        { /* if they sent something other than jabber:client */	    mio_write(m, NULL, "<stream:error><invalid-namespace xmlns='urn:ietf:params:xml:ns:xmpp-streams'/><text xmlns='urn:ietf:params:xml:ns:xmpp-streams' xml:lang='en'>Invalid Namespace</text></stream:error></stream:stream>", -1);            mio_close(m);        }        else if(cd->session_id == NULL)

⌨️ 快捷键说明

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