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

📄 chat.c

📁 AnyQ服务端源代码(2004/10/28)源码
💻 C
字号:
/* -------------------------------------------------------------------------- * * License * * The contents of this file are subject to the Jabber Open Source License * Version 1.0 (the "License").  You may not copy or use this file, in either * source code or executable form, except in compliance with the License.  You * may obtain a copy of the License at http://www.jabber.com/license/ or at * http://www.opensource.org/. * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the License * for the specific language governing rights and limitations under the * License. * * Copyright (c) 2000-2001 Schuyler Heath <sheath@jabber.org> * * Acknowledgements * * Special thanks to the Jabber Open Source Contributors for their * suggestions and support of Jabber. * * -------------------------------------------------------------------------- */#include "sb.h"result mt_chat_closed(mpacket mp, void *arg);void mt_chat_free(sbchat sc){    session s = sc->s;    jpacket jp;    log_debug(ZONE,"freeing SB chat %X",sc);    mt_free(sc->thread);    while ((jp = mt_jpbuf_de(sc->buff)) != NULL)    {        jutil_error(jp->x,TERROR_EXTERNAL);        mt_deliver(s->ti,jp->x);    }    pool_free(sc->p);    SREF_DEC(s);}void mt_chat_remove(sbchat sc){    session s = sc->s;    sbc_user cur;    log_debug(ZONE,"removing SB chat %X",sc);    assert(sc->state != sb_CLOSE);    sc->state = sb_CLOSE;    for (cur = sc->users; cur != NULL; cur = cur->next)        xhash_zap(s->chats,cur->mid);    if (sc->invite_id)        xhash_zap(s->invites,sc->invite_id);}void mt_chat_end(sbchat sc){    mt_chat_remove(sc);    if (sc->st != NULL)    {        sc->st->cb = &mt_chat_closed;        mt_stream_close(sc->st);    }}sbc_user mt_chat_add(sbchat sc, char *mid){    sbc_user su;    pool p = sc->p;    su = pmalloc(p,sizeof(_sbc_user));    su->mid = pstrdup(p,mid);    su->next = sc->users;    sc->users = su;    xhash_put(sc->s->chats,su->mid,(void *) sc);    return su;}void mt_chat_bye(sbchat sc, mpacket mp){    char *mid = mt_packet_data(mp,1);    log_debug(ZONE,"User '%s' left, %d",mid,sc->count);    if (--sc->count != 0)    {        sbc_user cur, prev;        for (prev = NULL, cur = sc->users; cur != NULL; prev = cur, cur = cur->next)        {            if (j_strcmp(cur->mid,mid) == 0)            {                if (prev)                    prev->next = cur->next;                else                    sc->users = cur->next;                break;            }        }        xhash_zap(sc->s->chats,mid);    }    else        mt_chat_end(sc);}void mt_chat_invite(sbchat sc, char *user){    session s = sc->s;    xmlnode msg, x;    char buf[40];    snprintf(buf,40,"%X",sc);    lowercase(buf);    sc->invite_id = pstrdup(sc->p,buf);    log_debug(ZONE,"SB invite %s",sc->invite_id);    xhash_put(s->invites,sc->invite_id,(void *) sc);    msg = xmlnode_new_tag("message");    xmlnode_put_attrib(msg,"to",jid_full(s->id));    xmlnode_put_attrib(msg,"from",mt_mid2jid_full(msg->p,user,s->host));    xmlnode_insert_cdata(xmlnode_insert_tag(msg,"body"),s->ti->invite_msg,-1);    x = xmlnode_insert_tag(msg,"x");    xmlnode_put_attrib(x,"jid",spools(msg->p,sc->invite_id,"@",s->ti->con_id,msg->p));    xmlnode_put_attrib(x,"xmlns","jabber:x:conference");    mt_deliver(s->ti,msg);}void mt_chat_joied(sbchat sc, char *user){    sbchat old;    ++sc->count;    if ((old = xhash_get(sc->s->chats,user)) != NULL)    {        if (old != sc)        {            mt_chat_end(old);  /* leave the other session */            mt_chat_add(sc,user);        }    }    else        mt_chat_add(sc,user);    if (sc->count == 2 && !sc->invite_id && sc->s->invites)        mt_chat_invite(sc,user);}void mt_chat_joi(sbchat sc, mpacket mp){    mt_chat_joied(sc,mt_packet_data(mp,1));    if (sc->state != sb_READY)    { /* make sure the other users joins before we start send messages */        sc->state = sb_READY;        mt_jpbuf_flush(sc->buff);    }}void mt_chat_text(sbchat sc, mpacket mp){    session s = sc->s;    xmlnode x, msg;    char *user = mt_mid2jid_full(mp->p,mt_packet_data(mp,1),s->host);    char *body = mt_packet_data(mp,mp->count - 1);    char *fmt = mt_packet_data(mp,mp->count - 2);    if (strncmp(fmt,"X-MMS-IM-Format",15))    {        log_debug(ZONE,"Unknown format '%s'",fmt);        fmt = NULL;    }    msg = xmlnode_new_tag("message");    xmlnode_put_attrib(msg,"to",jid_full(s->id));    xmlnode_put_attrib(msg,"from",user);    xmlnode_put_attrib(msg,"type","chat");    xmlnode_insert_cdata(xmlnode_insert_tag(msg,"thread"),sc->thread,-1);    xmlnode_insert_cdata(xmlnode_insert_tag(msg,"body"),body,-1);    if (sc->xhtml == 1 && fmt != NULL)        mt_xhtml_message(msg,fmt,body);    x = xmlnode_insert_tag(msg,"x");    xmlnode_put_attrib(x,"xmlns","jabber:x:event");    xmlnode_insert_tag(x,"composing");    mt_deliver(s->ti,msg);}void mt_chat_comp(sbchat sc, mpacket mp){    if (sc->comp)    {        session s = sc->s;        xmlnode x, msg;        char *user = mt_mid2jid_full(mp->p,mt_packet_data(mp,1),s->host);        msg = xmlnode_new_tag("message");        xmlnode_put_attrib(msg,"to",jid_full(s->id));        xmlnode_put_attrib(msg,"from",user);        xmlnode_put_attrib(msg,"type","chat");        xmlnode_insert_cdata(xmlnode_insert_tag(msg,"thread"),sc->thread,-1);        x = xmlnode_insert_tag(msg,"x");        xmlnode_put_attrib(x,"xmlns","jabber:x:event");        xmlnode_insert_tag(x,"composing");        xmlnode_insert_cdata(xmlnode_insert_tag(x,"id"),sc->thread,-1);        mt_deliver(s->ti,msg);    }}void mt_chat_msg(sbchat sc, mpacket mp){    char *ctype;    /* I've seen some MSGs sent without a MIME header... */    if (strncmp(mt_packet_data(mp,5),"Content-Type: ",14) == 0)        ctype = mt_packet_data(mp,5);    else if (strncmp(mt_packet_data(mp,4),"Content-Type: ",14) == 0)        ctype = mt_packet_data(mp,4);    else    {        log_debug(ZONE,"Invalid message sent from '%s: couldn't find Content-Type",mt_packet_data(mp,1));        return;    }    ctype += 14;    if (j_strcmp(ctype,"text/x-msmsgscontrol") == 0)    {        mt_chat_comp(sc,mp);    }    else if (j_strcmp(ctype,"text/plain; charset=UTF-8") == 0)    {        mt_chat_text(sc,mp);    }    else    {        log_debug(ZONE,"Unknown content-type: %s",ctype);    }}result mt_chat_closed(mpacket mp, void *arg){    if (mp == NULL)        mt_chat_free((sbchat) arg);    else if (j_strcmp(mt_packet_data(mp,0),"MSG") == 0)        mt_chat_msg((sbchat) arg,mp);    return r_DONE;}result mt_chat_packets(mpacket mp, void *arg){    sbchat sc = (sbchat) arg;    if (mp != NULL)    {        char *cmd;        cmd = mt_packet_data(mp,0);        if (j_strcmp(cmd,"MSG") == 0)            mt_chat_msg(sc,mp);        else if (j_strcmp(cmd,"JOI") == 0)            mt_chat_joi(sc,mp);        else if (j_strcmp(cmd,"BYE") == 0)            mt_chat_bye(sc,mp);        else if (j_atoi(cmd,0) != 0)            mt_chat_end(sc);        else            return r_ERR;    }    else    {        mt_chat_remove(sc);        mt_chat_free(sc);    }    return r_DONE;}void mt_chat_write(sbchat sc, jpacket jp){    xmlnode cur;    char *body = NULL, *name;    for_each_node(cur,jp->x)    {        if (xmlnode_get_type(cur) != NTYPE_TAG) continue;        name = xmlnode_get_name(cur);        if (strcmp(name,"thread") == 0)        {            char *thread = xmlnode_get_data(cur);            if (thread != NULL)            {                mt_free(sc->thread);                sc->thread = mt_strdup(thread);            }        }        else if (strcmp(name,"body") == 0)        {            char *data;            if (body == NULL && (data = xmlnode_get_data(cur)) != NULL)            {                spool sp = spool_new(jp->p);                spool_add(sp,MIME_MSG);                mt_replace_newline(sp,data);                body = spool_print(sp);            }        }        else        {            char *xmlns = xmlnode_get_attrib(cur,"xmlns");            if (xmlns != NULL)            {                if (strcmp(xmlns,NS_XHTML) == 0)                {                    char *tmp = mt_xhtml_format(cur);                    if (tmp != NULL)                        body = tmp;                }                else if (strcmp(xmlns,"jabber:x:event") == 0)                    sc->comp = 1;            }        }    }    if (body == NULL)    {        char buf[512];        snprintf(buf,512,MIME_TYPE,sc->s->user);        mt_cmd_msg(sc->st,"U",buf);    }    else        mt_cmd_msg(sc->st,"U",body);    xmlnode_free(jp->x);}result mt_chat_cal(mpacket mp, void *arg){    if (j_strcmp(mt_packet_data(mp,0),"CAL"))    {        sbchat sc = (sbchat) arg;        if (j_atoi(mt_packet_data(mp,0),0) == 217)        {            jpacket jp;            while ((jp = mt_jpbuf_de(sc->buff)) != NULL)            {                jutil_error(jp->x,(terror){405,"User is offline"});                mt_deliver(sc->s->ti,jp->x);            }        }        mt_chat_end(sc);    }    return r_DONE;}result mt_chat_usr(mpacket mp, void *arg){    sbchat sc = (sbchat) arg;    if (j_strcmp(mt_packet_data(mp,0),"USR") == 0)    { /* send the initial invite */        mt_stream_register(sc->st,&mt_chat_cal,(void *) sc);        mt_cmd_cal(sc->st,sc->users->mid);    }    else if (j_atoi(mt_packet_data(mp,0),0))        mt_chat_end(sc);    else        return r_ERR;    return r_DONE;}result mt_chat_xfr(mpacket mp, void *arg){    sbchat sc = (sbchat) arg;    if (sc->state == sb_CLOSE)    {        mt_chat_free(sc);        return r_DONE;    }    if (j_strcmp(mt_packet_data(mp,0),"XFR") == 0 && j_strcmp(mt_packet_data(mp,2),"SB") == 0)    {        session s = sc->s;        mpstream st;        char *host, *port;        host = mt_packet_data(mp,3);        port = strchr(host,':');        if (port != NULL)        {            *port = '\0';            ++port;        }        st = sc->st = mt_stream_connect(host,j_atoi(port,1863),&mt_chat_packets,(void *) sc);        mt_stream_register(st,&mt_chat_usr,(void *) sc);        mt_cmd_usr(st,s->user,mt_packet_data(mp,5));    }    else    {        mt_chat_remove(sc);        mt_chat_free(sc);    }    return r_DONE;}result mt_chat_ans(mpacket mp, void *arg){    sbchat sc = (sbchat) arg;    char *cmd;    cmd = mt_packet_data(mp,0);    if (j_strcmp(cmd,"IRO") == 0)    {        mt_chat_joied(sc,mt_packet_data(mp,4));        return r_PASS;    }    if (j_strcmp(cmd,"ANS") == 0 && sc->users != NULL)    {        sc->state = sb_READY;        mt_jpbuf_flush(sc->buff);    }    else    {        log_debug(ZONE,"SB session, ANS error, %s",cmd);        mt_chat_end(sc);    }    return r_DONE;}sbchat mt_chat_new(session s, char *user){    sbchat sc;    pool p;    SREF_INC(s);    p = pool_new();    sc = pmalloc(p,sizeof(_sbchat));    sc->p = p;    sc->s = s;    sc->st = NULL;    sc->state = sb_START;    sc->buff = mt_jpbuf_new(p);    sc->thread = mt_strdup(shahash(user)); /* make a default thread */    sc->invite_id = NULL;    sc->comp = 0;    sc->xhtml = 1;    sc->count = sc->count = 0;    sc->users = NULL;    mt_chat_add(sc,user);    return sc;}void mt_chat_join(session s, char *user, char *host, int port, char *chal, char *sid){    sbchat sc;    mpstream st;    sc = mt_chat_new(s,user);    st = sc->st = mt_stream_connect(host,port,&mt_chat_packets,(void *) sc);    mt_stream_register(st,&mt_chat_ans,(void *) sc);    mt_cmd_ans(st,sc->s->user,chal,sid);}void mt_chat_send_flush(jpacket jp, void *arg){    sbchat sc = (sbchat) arg;    mt_chat_write(sc,jp);}void mt_chat_send(session s, jpacket jp, char *to){    sbchat sc;    sc = (sbchat) xhash_get(s->chats,to);    if (sc == NULL)    {        sc = mt_chat_new(s,to);        mt_stream_register(s->st,&mt_chat_xfr,(void *) sc);        mt_cmd_xfr_sb(s->st);        mt_jpbuf_en(sc->buff,jp,&mt_chat_send_flush,(void *) sc);    }    else if (sc->state == sb_READY)        mt_chat_write(sc,jp);    else        mt_jpbuf_en(sc->buff,jp,&mt_chat_send_flush,(void *) sc);}void mt_chat_message_flush(jpacket jp, void *arg){    session s = (session) arg;    char *user = (char *) jp->aux1;    mt_chat_send(s,jp,user);}void mt_chat_message(session s, jpacket jp, char *to){    if (s->connected == 0)    {        jp->aux1 = (void *) to;        mt_jpbuf_en(s->buff,jp,&mt_chat_message_flush,(void *) s);    }    else        mt_chat_send(s,jp,to);}void mt_message(session s, jpacket jp){    if (jp->to->user != NULL)    {        char *to = mt_jid2mid(jp->p,jp->to);        if (to == NULL || strcmp(to,s->user) == 0)        {            jutil_error(jp->x,TERROR_BAD);            mt_deliver(s->ti,jp->x);        }        else        {            lowercase(to);            if (xmlnode_get_tag(jp->x,"x?xmlns=jabber:x:conference"))                mt_con_invite(s,jp,to);            else                mt_chat_message(s,jp,to);        }    }    else    {        jutil_error(jp->x,TERROR_NOTALLOWED);        mt_deliver(s->ti,jp->x);    }}

⌨️ 快捷键说明

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