X-Git-Url: http://andersk.mit.edu/gitweb/libfaim.git/blobdiff_plain/9f1a40132a2c6642e3544205c31c091051127ae0..00ef5271216e3bea9b233ce26a3c0f21fbca931f:/src/chat.c diff --git a/src/chat.c b/src/chat.c index 8eb1439..51af85b 100644 --- a/src/chat.c +++ b/src/chat.c @@ -208,6 +208,164 @@ faim_internal int aim_chat_readroominfo(u_char *buf, struct aim_chat_roominfo *o return i; } +faim_export unsigned long aim_chat_clientready(struct aim_session_t *sess, + struct aim_conn_t *conn) +{ + struct command_tx_struct *newpacket; + int i; + + if (!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 0x20))) + return -1; + + newpacket->lock = 1; + + i = aim_putsnac(newpacket->data, 0x0001, 0x0002, 0x0000, sess->snac_nextid); + + i+= aimutil_put16(newpacket->data+i, 0x000e); + i+= aimutil_put16(newpacket->data+i, 0x0001); + + i+= aimutil_put16(newpacket->data+i, 0x0004); + i+= aimutil_put16(newpacket->data+i, 0x0001); + + i+= aimutil_put16(newpacket->data+i, 0x0001); + i+= aimutil_put16(newpacket->data+i, 0x0003); + + i+= aimutil_put16(newpacket->data+i, 0x0004); + i+= aimutil_put16(newpacket->data+i, 0x0686); + + newpacket->lock = 0; + aim_tx_enqueue(sess, newpacket); + + return (sess->snac_nextid++); +} + +faim_export int aim_chat_leaveroom(struct aim_session_t *sess, char *name) +{ + struct aim_conn_t *conn; + + if ((conn = aim_chat_getconn(sess, name))) + aim_conn_close(conn); + + if (!conn) + return -1; + return 0; +} + +/* + * conn must be a BOS connection! + */ +faim_export unsigned long aim_chat_invite(struct aim_session_t *sess, + struct aim_conn_t *conn, + char *sn, + char *msg, + u_short exchange, + char *roomname, + u_short instance) +{ + struct command_tx_struct *newpacket; + int i,curbyte=0; + struct aim_msgcookie_t *cookie; + struct aim_invite_priv *priv; + + if (!sess || !conn || !sn || !msg || !roomname) + return -1; + + if (conn->type != AIM_CONN_TYPE_BOS) + return -1; + + if (!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 1152+strlen(sn)+strlen(roomname)+strlen(msg)))) + return -1; + + newpacket->lock = 1; + + curbyte = aim_putsnac(newpacket->data, 0x0004, 0x0006, 0x0000, sess->snac_nextid); + + /* + * Cookie + */ + for (i=0;i<8;i++) + curbyte += aimutil_put8(newpacket->data+curbyte, (u_char)rand()); + + /* XXX this should get uncached by the unwritten 'invite accept' handler */ + if(!(priv = calloc(sizeof(struct aim_invite_priv), 1))) + return -1; + priv->sn = strdup(sn); + priv->roomname = strdup(roomname); + priv->exchange = exchange; + priv->instance = instance; + + if(!(cookie = aim_mkcookie(newpacket->data+curbyte-8, AIM_COOKIETYPE_INVITE, priv))) + return -1; + aim_cachecookie(sess, cookie); + + /* + * Channel (2) + */ + curbyte += aimutil_put16(newpacket->data+curbyte, 0x0002); + + /* + * Dest sn + */ + curbyte += aimutil_put8(newpacket->data+curbyte, strlen(sn)); + curbyte += aimutil_putstr(newpacket->data+curbyte, sn, strlen(sn)); + + /* + * TLV t(0005) + */ + curbyte += aimutil_put16(newpacket->data+curbyte, 0x0005); + curbyte += aimutil_put16(newpacket->data+curbyte, 0x28+strlen(msg)+0x04+0x03+strlen(roomname)+0x02); + + /* + * Unknown info + */ + curbyte += aimutil_put16(newpacket->data+curbyte, 0x0000); + curbyte += aimutil_put16(newpacket->data+curbyte, 0x3131); + curbyte += aimutil_put16(newpacket->data+curbyte, 0x3538); + curbyte += aimutil_put16(newpacket->data+curbyte, 0x3446); + curbyte += aimutil_put16(newpacket->data+curbyte, 0x4100); + curbyte += aimutil_put16(newpacket->data+curbyte, 0x748f); + curbyte += aimutil_put16(newpacket->data+curbyte, 0x2420); + curbyte += aimutil_put16(newpacket->data+curbyte, 0x6287); + curbyte += aimutil_put16(newpacket->data+curbyte, 0x11d1); + curbyte += aimutil_put16(newpacket->data+curbyte, 0x8222); + curbyte += aimutil_put16(newpacket->data+curbyte, 0x4445); + curbyte += aimutil_put16(newpacket->data+curbyte, 0x5354); + curbyte += aimutil_put16(newpacket->data+curbyte, 0x0000); + + /* + * TLV t(000a) -- Unknown + */ + curbyte += aimutil_put16(newpacket->data+curbyte, 0x000a); + curbyte += aimutil_put16(newpacket->data+curbyte, 0x0002); + curbyte += aimutil_put16(newpacket->data+curbyte, 0x0001); + + /* + * TLV t(000f) -- Unknown + */ + curbyte += aimutil_put16(newpacket->data+curbyte, 0x000f); + curbyte += aimutil_put16(newpacket->data+curbyte, 0x0000); + + /* + * TLV t(000c) -- Invitation message + */ + curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x000c, strlen(msg), msg); + + /* + * TLV t(2711) -- Container for room information + */ + curbyte += aimutil_put16(newpacket->data+curbyte, 0x2711); + curbyte += aimutil_put16(newpacket->data+curbyte, 3+strlen(roomname)+2); + curbyte += aimutil_put16(newpacket->data+curbyte, exchange); + curbyte += aimutil_put8(newpacket->data+curbyte, strlen(roomname)); + curbyte += aimutil_putstr(newpacket->data+curbyte, roomname, strlen(roomname)); + curbyte += aimutil_put16(newpacket->data+curbyte, instance); + + newpacket->commandlen = curbyte; + newpacket->lock = 0; + aim_tx_enqueue(sess, newpacket); + + return (sess->snac_nextid++); +} /* * General room information. Lots of stuff. @@ -218,17 +376,16 @@ faim_internal int aim_chat_readroominfo(u_char *buf, struct aim_chat_roominfo *o * * SNAC 000e/0002 */ -faim_internal int aim_chat_parse_infoupdate(struct aim_session_t *sess, - struct command_rx_struct *command) +static int infoupdate(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen) { struct aim_userinfo_s *userinfo = NULL; rxcallback_t userfunc=NULL; - int ret = 1, i = 0; + int ret = 0, i = 0; int usercount = 0; - u_char detaillevel = 0; + unsigned char detaillevel = 0; char *roomname = NULL; struct aim_chat_roominfo roominfo; - u_short tlvcount = 0; + unsigned short tlvcount = 0; struct aim_tlvlist_t *tlvlist; char *roomdesc = NULL; unsigned short unknown_c9 = 0; @@ -236,10 +393,9 @@ faim_internal int aim_chat_parse_infoupdate(struct aim_session_t *sess, unsigned short maxmsglen = 0; unsigned short unknown_d2 = 0, unknown_d5 = 0; - i = 10; - i += aim_chat_readroominfo(command->data+i, &roominfo); + i += aim_chat_readroominfo(data+i, &roominfo); - detaillevel = aimutil_get8(command->data+i); + detaillevel = aimutil_get8(data+i); i++; if (detaillevel != 0x02) { @@ -250,19 +406,19 @@ faim_internal int aim_chat_parse_infoupdate(struct aim_session_t *sess, return 1; } - tlvcount = aimutil_get16(command->data+i); + tlvcount = aimutil_get16(data+i); i += 2; /* * Everything else are TLVs. */ - tlvlist = aim_readtlvchain(command->data+i, command->commandlen-i); + tlvlist = aim_readtlvchain(data+i, datalen-i); /* * TLV type 0x006a is the room name in Human Readable Form. */ if (aim_gettlv(tlvlist, 0x006a, 1)) - roomname = aim_gettlv_str(tlvlist, 0x006a, 1); + roomname = aim_gettlv_str(tlvlist, 0x006a, 1); /* * Type 0x006f: Number of occupants. @@ -324,9 +480,9 @@ faim_internal int aim_chat_parse_infoupdate(struct aim_session_t *sess, unknown_d5 = aim_gettlv8(tlvlist, 0x00d5, 1); - if ((userfunc = aim_callhandler(sess, command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_ROOMINFOUPDATE))) { + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { ret = userfunc(sess, - command, + rx, &roominfo, roomname, usercount, @@ -337,7 +493,8 @@ faim_internal int aim_chat_parse_infoupdate(struct aim_session_t *sess, maxmsglen, unknown_d2, unknown_d5); - } + } + free(roominfo.name); free(userinfo); free(roomname); @@ -347,56 +504,25 @@ faim_internal int aim_chat_parse_infoupdate(struct aim_session_t *sess, return ret; } -faim_internal int aim_chat_parse_joined(struct aim_session_t *sess, - struct command_rx_struct *command) +static int userlistchange(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen) { struct aim_userinfo_s *userinfo = NULL; - rxcallback_t userfunc=NULL; - int i = 10, curcount = 0, ret = 1; + rxcallback_t userfunc; + int i = 0, curcount = 0, ret = 0; - while (i < command->commandlen) { + while (i < datalen) { curcount++; userinfo = realloc(userinfo, curcount * sizeof(struct aim_userinfo_s)); - i += aim_extractuserinfo(sess, command->data+i, &userinfo[curcount-1]); + i += aim_extractuserinfo(sess, data+i, &userinfo[curcount-1]); } - if ((userfunc = aim_callhandler(sess, command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERJOIN))) { - ret = userfunc(sess, - command, - curcount, - userinfo); - } + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + ret = userfunc(sess, rx, curcount, userinfo); free(userinfo); return ret; -} - -faim_internal int aim_chat_parse_leave(struct aim_session_t *sess, - struct command_rx_struct *command) -{ - - struct aim_userinfo_s *userinfo = NULL; - rxcallback_t userfunc=NULL; - int i = 10, curcount = 0, ret = 1; - - while (i < command->commandlen) { - curcount++; - userinfo = realloc(userinfo, curcount * sizeof(struct aim_userinfo_s)); - i += aim_extractuserinfo(sess, command->data+i, &userinfo[curcount-1]); - } - - if ((userfunc = aim_callhandler(sess, command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERLEAVE))) { - ret = userfunc(sess, - command, - curcount, - userinfo); - } - - free(userinfo); - - return ret; -} +} /* * We could probably include this in the normal ICBM parsing @@ -421,12 +547,11 @@ faim_internal int aim_chat_parse_leave(struct aim_session_t *sess, * possibly others * */ -faim_internal int aim_chat_parse_incoming(struct aim_session_t *sess, - struct command_rx_struct *command) +static int incomingmsg(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen) { struct aim_userinfo_s userinfo; rxcallback_t userfunc=NULL; - int ret = 1, i = 0, z = 0; + int ret = 0, i = 0; unsigned char cookie[8]; int channel; struct aim_tlvlist_t *outerlist; @@ -435,13 +560,11 @@ faim_internal int aim_chat_parse_incoming(struct aim_session_t *sess, memset(&userinfo, 0x00, sizeof(struct aim_userinfo_s)); - i = 10; /* skip snac */ - /* * ICBM Cookie. Cache it. */ - for (z=0; z<8; z++,i++) - cookie[z] = command->data[i]; + memcpy(cookie, data, 8); + i += 8; if ((ck = aim_uncachecookie(sess, cookie, AIM_COOKIETYPE_CHAT))) { if (ck->data) @@ -458,18 +581,18 @@ faim_internal int aim_chat_parse_incoming(struct aim_session_t *sess, * We only do channel 3 here. * */ - channel = aimutil_get16(command->data+i); + channel = aimutil_get16(data+i); i += 2; if (channel != 0x0003) { faimdprintf(sess, 0, "faim: chat_incoming: unknown channel! (0x%04x)\n", channel); - return 1; + return 0; } /* * Start parsing TLVs right away. */ - outerlist = aim_readtlvchain(command->data+i, command->commandlen-i); + outerlist = aim_readtlvchain(data+8+2, datalen-8-2); /* * Type 0x0003: Source User Information @@ -490,192 +613,52 @@ faim_internal int aim_chat_parse_incoming(struct aim_session_t *sess, /* * Type 0x0005: Message Block. Conains more TLVs. */ - if (aim_gettlv(outerlist, 0x0005, 1)) - { - struct aim_tlvlist_t *innerlist; - struct aim_tlv_t *msgblock; + if (aim_gettlv(outerlist, 0x0005, 1)) { + struct aim_tlvlist_t *innerlist; + struct aim_tlv_t *msgblock; - msgblock = aim_gettlv(outerlist, 0x0005, 1); - innerlist = aim_readtlvchain(msgblock->value, msgblock->length); + msgblock = aim_gettlv(outerlist, 0x0005, 1); + innerlist = aim_readtlvchain(msgblock->value, msgblock->length); - /* - * Type 0x0001: Message. - */ - if (aim_gettlv(innerlist, 0x0001, 1)) - msg = aim_gettlv_str(innerlist, 0x0001, 1); + /* + * Type 0x0001: Message. + */ + if (aim_gettlv(innerlist, 0x0001, 1)) + msg = aim_gettlv_str(innerlist, 0x0001, 1); - aim_freetlvchain(&innerlist); - } + aim_freetlvchain(&innerlist); + } + + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + ret = userfunc(sess, rx, &userinfo, msg); - userfunc = aim_callhandler(sess, command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_INCOMINGMSG); - if (userfunc) - { - ret = userfunc(sess, - command, - &userinfo, - msg); - } free(msg); aim_freetlvchain(&outerlist); return ret; -} - -faim_export unsigned long aim_chat_clientready(struct aim_session_t *sess, - struct aim_conn_t *conn) -{ - struct command_tx_struct *newpacket; - int i; - - if (!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 0x20))) - return -1; - - newpacket->lock = 1; - - i = aim_putsnac(newpacket->data, 0x0001, 0x0002, 0x0000, sess->snac_nextid); - - i+= aimutil_put16(newpacket->data+i, 0x000e); - i+= aimutil_put16(newpacket->data+i, 0x0001); - - i+= aimutil_put16(newpacket->data+i, 0x0004); - i+= aimutil_put16(newpacket->data+i, 0x0001); - - i+= aimutil_put16(newpacket->data+i, 0x0001); - i+= aimutil_put16(newpacket->data+i, 0x0003); - - i+= aimutil_put16(newpacket->data+i, 0x0004); - i+= aimutil_put16(newpacket->data+i, 0x0686); - - newpacket->lock = 0; - aim_tx_enqueue(sess, newpacket); - - return (sess->snac_nextid++); } -faim_export int aim_chat_leaveroom(struct aim_session_t *sess, char *name) +static int snachandler(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen) { - struct aim_conn_t *conn; - if ((conn = aim_chat_getconn(sess, name))) - aim_conn_close(conn); + if (snac->subtype == 0x0002) + return infoupdate(sess, mod, rx, snac, data, datalen); + else if ((snac->subtype == 0x0003) || (snac->subtype == 0x0004)) + return userlistchange(sess, mod, rx, snac, data, datalen); + else if (snac->subtype == 0x0006) + return incomingmsg(sess, mod, rx, snac, data, datalen); - if (!conn) - return -1; return 0; } -/* - * conn must be a BOS connection! - */ -faim_export unsigned long aim_chat_invite(struct aim_session_t *sess, - struct aim_conn_t *conn, - char *sn, - char *msg, - u_short exchange, - char *roomname, - u_short instance) +faim_internal int chat_modfirst(struct aim_session_t *sess, aim_module_t *mod) { - struct command_tx_struct *newpacket; - int i,curbyte=0; - struct aim_msgcookie_t *cookie; - struct aim_invite_priv *priv; - if (!sess || !conn || !sn || !msg || !roomname) - return -1; - - if (conn->type != AIM_CONN_TYPE_BOS) - return -1; + mod->family = 0x000e; + mod->version = 0x0000; + mod->flags = 0; + strncpy(mod->name, "chat", sizeof(mod->name)); + mod->snachandler = snachandler; - if (!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 1152+strlen(sn)+strlen(roomname)+strlen(msg)))) - return -1; - - newpacket->lock = 1; - - curbyte = aim_putsnac(newpacket->data, 0x0004, 0x0006, 0x0000, sess->snac_nextid); - - /* - * Cookie - */ - for (i=0;i<8;i++) - curbyte += aimutil_put8(newpacket->data+curbyte, (u_char)rand()); - - /* XXX this should get uncached by the unwritten 'invite accept' handler */ - if(!(priv = calloc(sizeof(struct aim_invite_priv), 1))) - return -1; - priv->sn = strdup(sn); - priv->roomname = strdup(roomname); - priv->exchange = exchange; - priv->instance = instance; - - if(!(cookie = aim_mkcookie(newpacket->data+curbyte-8, AIM_COOKIETYPE_INVITE, priv))) - return -1; - aim_cachecookie(sess, cookie); - - /* - * Channel (2) - */ - curbyte += aimutil_put16(newpacket->data+curbyte, 0x0002); - - /* - * Dest sn - */ - curbyte += aimutil_put8(newpacket->data+curbyte, strlen(sn)); - curbyte += aimutil_putstr(newpacket->data+curbyte, sn, strlen(sn)); - - /* - * TLV t(0005) - */ - curbyte += aimutil_put16(newpacket->data+curbyte, 0x0005); - curbyte += aimutil_put16(newpacket->data+curbyte, 0x28+strlen(msg)+0x04+0x03+strlen(roomname)+0x02); - - /* - * Unknown info - */ - curbyte += aimutil_put16(newpacket->data+curbyte, 0x0000); - curbyte += aimutil_put16(newpacket->data+curbyte, 0x3131); - curbyte += aimutil_put16(newpacket->data+curbyte, 0x3538); - curbyte += aimutil_put16(newpacket->data+curbyte, 0x3446); - curbyte += aimutil_put16(newpacket->data+curbyte, 0x4100); - curbyte += aimutil_put16(newpacket->data+curbyte, 0x748f); - curbyte += aimutil_put16(newpacket->data+curbyte, 0x2420); - curbyte += aimutil_put16(newpacket->data+curbyte, 0x6287); - curbyte += aimutil_put16(newpacket->data+curbyte, 0x11d1); - curbyte += aimutil_put16(newpacket->data+curbyte, 0x8222); - curbyte += aimutil_put16(newpacket->data+curbyte, 0x4445); - curbyte += aimutil_put16(newpacket->data+curbyte, 0x5354); - curbyte += aimutil_put16(newpacket->data+curbyte, 0x0000); - - /* - * TLV t(000a) -- Unknown - */ - curbyte += aimutil_put16(newpacket->data+curbyte, 0x000a); - curbyte += aimutil_put16(newpacket->data+curbyte, 0x0002); - curbyte += aimutil_put16(newpacket->data+curbyte, 0x0001); - - /* - * TLV t(000f) -- Unknown - */ - curbyte += aimutil_put16(newpacket->data+curbyte, 0x000f); - curbyte += aimutil_put16(newpacket->data+curbyte, 0x0000); - - /* - * TLV t(000c) -- Invitation message - */ - curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x000c, strlen(msg), msg); - - /* - * TLV t(2711) -- Container for room information - */ - curbyte += aimutil_put16(newpacket->data+curbyte, 0x2711); - curbyte += aimutil_put16(newpacket->data+curbyte, 3+strlen(roomname)+2); - curbyte += aimutil_put16(newpacket->data+curbyte, exchange); - curbyte += aimutil_put8(newpacket->data+curbyte, strlen(roomname)); - curbyte += aimutil_putstr(newpacket->data+curbyte, roomname, strlen(roomname)); - curbyte += aimutil_put16(newpacket->data+curbyte, instance); - - newpacket->commandlen = curbyte; - newpacket->lock = 0; - aim_tx_enqueue(sess, newpacket); - - return (sess->snac_nextid++); + return 0; }