No release numbers
------------------
+ - Sun Jan 2 10:31:19 UTC 2000
+ - Cleanups in aim_info.c
+ - Can compile with -Ddebug=100 again
+ - Implemented chat: Joining/Leaving, info parsing, IM parsing/sending
+ - Implemented some chatnav: rights req/parsing, room creation
+
+ - Thu Dec 30 10:08:42 UTC 1999
+ - Fixed bug in aim_im.c when (encoding == NULL) || (lang == NULL)
+ - Added detection of voice chat requests
+ - Added AIM_CLASS_* defines, including new Away flag
+ - Added awaymsg parameter to bos_setprofile.
+ - If awaymsg is nonnull, you will be advertised as being away (your
+ class will be ORed with AIM_CLASS_AWAY), otherwise you'll show
+ up normal.
+
- Wed Dec 29 10:06:35 UTC 1999
- Fixed small bug in IM parser
- Added stubs for the capability TLVs in userinfo.
- Wed Dec 29 09:14:45 UTC 1999
- - Added a capability block to aim_bos_setprofile. Can now get chat invites again.
+ - Added a capability block to aim_bos_setprofile. Can now get chat
+ invites again.
- Extended ICBM parser to support channel 2 messages (chat invites)
- - A channel parameter has been prepended to the varargs -- REQUIRES CLIENT CHANGES.
+ - A channel parameter has been prepended to the varargs -- REQUIRES
+ CLIENT CHANGES.
- Extended faimtest to support chat invites.
- Changed faimtest to get sn/password from environment
#include <faim/aim.h>
+char *aim_chat_getname(struct aim_conn_t *conn)
+{
+ if (!conn)
+ return NULL;
+ if (conn->type != AIM_CONN_TYPE_CHAT)
+ return NULL;
+
+ return (char *)conn->priv; /* yuck ! */
+}
+
+struct aim_conn_t *aim_chat_getconn(struct aim_session_t *sess, char *name)
+{
+ int i;
+
+ for (i=0;i<AIM_CONN_MAX;i++)
+ {
+ if (sess->conns[i].type == AIM_CONN_TYPE_CHAT)
+ {
+ if (sess->conns[i].priv)
+ if (!strcmp((char *)sess->conns[i].priv, name))
+ {
+ return &sess->conns[i];
+ }
+ }
+ }
+ return NULL;
+}
+
+int aim_chat_attachname(struct aim_conn_t *conn, char *roomname)
+{
+ if (!conn || !roomname)
+ return -1;
+
+ conn->priv = malloc(strlen(roomname)+1);
+ strcpy(conn->priv, roomname);
+
+ return 0;
+}
+
+u_long aim_chat_send_im(struct aim_session_t *sess,
+ struct aim_conn_t *conn,
+ char *msg)
+{
+
+ int curbyte,i;
+ struct command_tx_struct newpacket;
+
+ if (!sess || !conn || !msg)
+ return 0;
+
+ newpacket.lock = 1; /* lock struct */
+ newpacket.type = 0x02; /* IMs are always family 0x02 */
+
+ /*
+ * Since we must have a specific connection, then theres
+ * no use in going on if we don't have one...
+ */
+ if (!conn)
+ return sess->snac_nextid;
+ newpacket.conn = conn;
+
+ /*
+ * Its simplest to set this arbitrarily large and waste
+ * space. Precalculating is costly here.
+ */
+ newpacket.commandlen = 1152;
+
+ newpacket.data = (u_char *) calloc(1, newpacket.commandlen);
+
+ curbyte = 0;
+ curbyte += aim_putsnac(newpacket.data+curbyte,
+ 0x000e, 0x0005, 0x0000, sess->snac_nextid);
+
+ /*
+ * Generate a random message cookie
+ *
+ */
+ for (i=0;i<8;i++)
+ curbyte += aimutil_put8(newpacket.data+curbyte, (u_char) random());
+
+ /*
+ * metaTLV start. -- i assume this is a metaTLV. it could be the
+ * channel ID though.
+ */
+ curbyte += aimutil_put16(newpacket.data+curbyte, 0x0003);
+
+ /*
+ * Type 1: Unknown. Blank.
+ */
+ curbyte += aimutil_put16(newpacket.data+curbyte, 0x0001);
+ curbyte += aimutil_put16(newpacket.data+curbyte, 0x0000);
+
+ /*
+ * Type 6: Unknown. Blank.
+ */
+ curbyte += aimutil_put16(newpacket.data+curbyte, 0x0006);
+ curbyte += aimutil_put16(newpacket.data+curbyte, 0x0000);
+
+ /*
+ * Type 5: Message block. Contains more TLVs.
+ *
+ * This could include other information... We just
+ * put in a message TLV however.
+ *
+ */
+ curbyte += aimutil_put16(newpacket.data+curbyte, 0x0005);
+ curbyte += aimutil_put16(newpacket.data+curbyte, strlen(msg)+4);
+
+ /*
+ * SubTLV: Type 1: Message
+ */
+ curbyte += aim_puttlv_str(newpacket.data+curbyte, 0x0001, strlen(msg), msg);
+
+ newpacket.commandlen = curbyte;
+
+ newpacket.lock = 0;
+ aim_tx_enqueue(sess, &newpacket);
+
+ return (sess->snac_nextid++);
+}
+
/*
- * FIXME: Doesn't work.
+ * Join a room of name roomname. This is the first
+ * step to joining an already created room. It's
+ * basically a Service Request for family 0x000e,
+ * with a little added on to specify the exchange
+ * and room name.
*
*/
u_long aim_chat_join(struct aim_session_t *sess,
struct aim_conn_t *conn,
+ u_short exchange,
const char *roomname)
{
struct command_tx_struct newpacket;
+ int i;
+
+ if (!sess || !conn || !roomname)
+ return 0;
newpacket.lock = 1;
if (conn)
else
newpacket.conn = aim_getconn_type(sess, AIM_CONN_TYPE_BOS);
- newpacket.type = 0x0002;
+ newpacket.type = 0x02;
- newpacket.commandlen = 12+7+strlen(roomname)+6;
+ newpacket.commandlen = 10 + 9 + strlen(roomname) + 2;
newpacket.data = (char *) malloc(newpacket.commandlen);
memset(newpacket.data, 0x00, newpacket.commandlen);
- aim_putsnac(newpacket.data, 0x0001, 0x0004, 0x0000, sess->snac_nextid);
+ i = aim_putsnac(newpacket.data, 0x0001, 0x0004, 0x0000, sess->snac_nextid);
- newpacket.data[10] = 0x00;
- newpacket.data[11] = 0x0e;
- newpacket.data[12] = 0x00;
- newpacket.data[13] = 0x01;
- newpacket.data[14] = 0x00;
- newpacket.data[15] = 0x0c;
- newpacket.data[16] = 0x00;
- newpacket.data[17] = 0x04;
- newpacket.data[18] = strlen(roomname) & 0x00ff;
- memcpy(&(newpacket.data[19]), roomname, strlen(roomname));
-
- {
- u_int i = 0;
- printf("\n\n\n");
- for (i = 0;i < newpacket.commandlen; i++)
- printf("0x%02x ", newpacket.data[i]);
- printf("\n\n\n");
- }
+ i+= aimutil_put16(newpacket.data+i, 0x000e);
+
+ /*
+ * this is techinally a TLV, but we can't use normal functions
+ * because we need the extraneous nulls and other weird things.
+ */
+ i+= aimutil_put16(newpacket.data+i, 0x0001);
+ i+= aimutil_put16(newpacket.data+i, 2+1+strlen(roomname)+2);
+ i+= aimutil_put16(newpacket.data+i, exchange);
+ i+= aimutil_put8(newpacket.data+i, strlen(roomname));
+ memcpy(newpacket.data+i, roomname, strlen(roomname));
+ i+= strlen(roomname);
+ //i+= aimutil_putstr(newpacket.data+i, roomname, strlen(roomname));
+ i+= aimutil_put16(newpacket.data+i, 0x0000);
+ /*
+ * Chat hack.
+ *
+ * XXX: A problem occurs here if we request a channel
+ * join but it fails....pendingjoin will be nonnull
+ * even though the channel is never going to get a
+ * redirect!
+ *
+ */
+ sess->pendingjoin = (char *)malloc(strlen(roomname)+1);
+ strcpy(sess->pendingjoin, roomname);
+
+ newpacket.lock = 0;
aim_tx_enqueue(sess, &newpacket);
+#if 0
{
struct aim_snac_t snac;
snac.type = 0x0004;
snac.flags = 0x0000;
- snac.data = malloc(strlen(roomname));
- memcpy(snac.data, roomname, strlen(roomname));
+ snac.data = malloc(strlen(roomname)+1);
+ strcpy(snac.data, roomname);
aim_newsnac(sess, &snac);
}
+#endif
+ return (sess->snac_nextid++);
+}
+
+int aim_chat_readroominfo(u_char *buf, struct aim_chat_roominfo *outinfo)
+{
+ int namelen = 0;
+ int i = 0;
+
+ if (!buf || !outinfo)
+ return 0;
+
+ outinfo->exchange = aimutil_get16(buf+i);
+ i += 2;
+
+ namelen = aimutil_get8(buf+i);
+ i += 1;
+
+ outinfo->name = (char *)malloc(namelen+1);
+ memcpy(outinfo->name, buf+i, namelen);
+ outinfo->name[namelen] = '\0';
+ i += namelen;
+
+ outinfo->instance = aimutil_get16(buf+i);
+ i += 2;
+
+ return i;
+};
+
+
+/*
+ * General room information. Lots of stuff.
+ *
+ * Values I know are in here but I havent attached
+ * them to any of the 'Unknown's:
+ * - Language (English)
+ *
+ */
+int aim_chat_parse_infoupdate(struct aim_session_t *sess,
+ struct command_rx_struct *command)
+{
+ struct aim_userinfo_s *userinfo;
+ rxcallback_t userfunc=NULL;
+ int ret = 1, i = 0;
+ int usercount = 0;
+ u_char detaillevel = 0;
+ char *roomname;
+ struct aim_chat_roominfo roominfo;
+ u_short tlvcount = 0;
+ struct aim_tlvlist_t *tlvlist;
+ char *roomdesc;
+
+ i = 10;
+ i += aim_chat_readroominfo(command->data+i, &roominfo);
+
+ detaillevel = aimutil_get8(command->data+i);
+ i++;
+
+ tlvcount = aimutil_get16(command->data+i);
+ i += 2;
+
+ /*
+ * Everything else are TLVs.
+ */
+ tlvlist = aim_readtlvchain(command->data+i, command->commandlen-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);
+
+ /*
+ * Type 0x006f: Number of occupants.
+ */
+ if (aim_gettlv(tlvlist, 0x006f, 1))
+ {
+ struct aim_tlv_t *tmptlv;
+ tmptlv = aim_gettlv(tlvlist, 0x006f, 1);
+
+ usercount = aimutil_get16(tmptlv->value);
+ }
+
+ /*
+ * Type 0x0073: Occupant list.
+ */
+ if (aim_gettlv(tlvlist, 0x0073, 1))
+ {
+ int curoccupant = 0;
+ struct aim_tlv_t *tmptlv;
+
+ tmptlv = aim_gettlv(tlvlist, 0x0073, 1);
+
+ /* Allocate enough userinfo structs for all occupants */
+ userinfo = calloc(usercount, sizeof(struct aim_userinfo_s));
+
+ i = 0;
+ while (curoccupant < usercount)
+ i += aim_extractuserinfo(tmptlv->value+i, &userinfo[curoccupant++]);
+ }
+
+ /*
+ * Type 0x00c9: Unknown.
+ */
+ if (aim_gettlv(tlvlist, 0x00c9, 1))
+ ;
+
+ /*
+ * Type 0x00ca: Creation date
+ */
+ if (aim_gettlv(tlvlist, 0x00ca, 1))
+ ;
+
+ /*
+ * Type 0x00d1: Maximum Message Length
+ */
+ if (aim_gettlv(tlvlist, 0x00d1, 1))
+ ;
+
+ /*
+ * Type 0x00d2: Unknown.
+ */
+ if (aim_gettlv(tlvlist, 0x00d2, 1))
+ ;
+
+ /*
+ * Type 0x00d3: Room Description
+ */
+ if (aim_gettlv(tlvlist, 0x00d3, 1))
+ roomdesc = aim_gettlv_str(tlvlist, 0x00d3, 1);
+
+ /*
+ * Type 0x00d5: Unknown.
+ */
+ if (aim_gettlv(tlvlist, 0x00d5, 1))
+ ;
+
+
+ userfunc = aim_callhandler(command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_ROOMINFOUPDATE);
+ if (userfunc)
+ {
+ ret = userfunc(sess,
+ command,
+ &roominfo,
+ roomname,
+ usercount,
+ userinfo,
+ roomdesc);
+ }
+ free(roominfo.name);
+ free(userinfo);
+ free(roomname);
+ free(roomdesc);
+ aim_freetlvchain(&tlvlist);
+
+ return ret;
+}
+
+int aim_chat_parse_joined(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(command->data+i, &userinfo[curcount-1]);
+ }
+
+ userfunc = aim_callhandler(command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERJOIN);
+ if (userfunc)
+ {
+ ret = userfunc(sess,
+ command,
+ curcount,
+ userinfo);
+ }
+
+ free(userinfo);
+
+ return ret;
+}
+
+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(command->data+i, &userinfo[curcount-1]);
+ }
+
+ userfunc = aim_callhandler(command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERLEAVE);
+ if (userfunc)
+ {
+ ret = userfunc(sess,
+ command,
+ curcount,
+ userinfo);
+ }
+
+ free(userinfo);
+
+ return ret;
+}
+
+/*
+ * We could probably include this in the normal ICBM parsing
+ * code as channel 0x0003, however, since only the start
+ * would be the same, we might as well do it here.
+ */
+int aim_chat_parse_incoming(struct aim_session_t *sess,
+ struct command_rx_struct *command)
+{
+ struct aim_userinfo_s userinfo;
+ rxcallback_t userfunc=NULL;
+ int ret = 1, i = 0, z = 0;
+ u_char cookie[8];
+ int channel;
+ struct aim_tlvlist_t *outerlist;
+ char *msg = NULL;
+
+ memset(&userinfo, 0x00, sizeof(struct aim_userinfo_s));
+
+ i = 10; /* skip snac */
+
+ /*
+ * ICBM Cookie. Ignore it.
+ */
+ for (z=0; z<8; z++,i++)
+ cookie[z] = command->data[i];
+
+ /*
+ * Channel ID
+ *
+ * Channels 1 and 2 are implemented in the normal ICBM
+ * parser.
+ *
+ * We only do channel 3 here.
+ *
+ */
+ channel = aimutil_get16(command->data+i);
+ i += 2;
+
+ if (channel != 0x0003)
+ {
+ printf("faim: chat_incoming: unknown channel! (0x%04x)\n", channel);
+ return 1;
+ }
+
+ /*
+ * Start parsing TLVs right away.
+ */
+ outerlist = aim_readtlvchain(command->data+i, command->commandlen-i);
+
+ /*
+ * Type 0x0003: Source User Information
+ */
+ if (aim_gettlv(outerlist, 0x0003, 1))
+ {
+ struct aim_tlv_t *userinfotlv;
+
+ userinfotlv = aim_gettlv(outerlist, 0x0003, 1);
+ aim_extractuserinfo(userinfotlv->value, &userinfo);
+ }
+
+ /*
+ * Type 0x0001: Unknown.
+ */
+ if (aim_gettlv(outerlist, 0x0001, 1))
+ ;
+
+ /*
+ * Type 0x0005: Message Block. Conains more TLVs.
+ */
+ 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);
+
+ /*
+ * Type 0x0001: Message.
+ */
+ if (aim_gettlv(innerlist, 0x0001, 1))
+ msg = aim_gettlv_str(innerlist, 0x0001, 1);
+
+ aim_freetlvchain(&innerlist);
+ }
+
+ userfunc = aim_callhandler(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;
+}
+
+u_long aim_chat_clientready(struct aim_session_t *sess,
+ struct aim_conn_t *conn)
+{
+ struct command_tx_struct newpacket;
+ int i;
+
+ newpacket.lock = 1;
+ if (conn)
+ newpacket.conn = conn;
+ else
+ newpacket.conn = aim_getconn_type(sess, AIM_CONN_TYPE_CHAT);
+ newpacket.type = 0x02;
+ newpacket.commandlen = 0x20;
+
+ newpacket.data = (char *) malloc(newpacket.commandlen);
+ 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++);
+}
+
+int aim_chat_leaveroom(struct aim_session_t *sess, char *name)
+{
+ int i;
+
+ for (i=0;i<AIM_CONN_MAX;i++)
+ {
+ if (sess->conns[i].type == AIM_CONN_TYPE_CHAT)
+ {
+ if (sess->conns[i].priv)
+ if (!strcmp((char *)sess->conns[i].priv, name))
+ {
+ aim_conn_close(&sess->conns[i]);
+ return 0;
+ }
+ }
+ }
+ return -1;
+}
+
+/*
+ * conn must be a BOS connection!
+ */
+u_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;
+
+ if (!sess || !conn || !sn || !msg || !roomname)
+ return 0;
+
+ newpacket.lock = 1;
+ if (conn)
+ newpacket.conn = conn;
+ else
+ newpacket.conn = aim_getconn_type(sess, AIM_CONN_TYPE_BOS);
+ newpacket.type = 0x02;
+ newpacket.commandlen = 1152+strlen(sn)+strlen(roomname)+strlen(msg);
+
+ newpacket.data = (char *) malloc(newpacket.commandlen);
+ 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());
+
+ /*
+ * 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++);
}
#include <faim/aim.h>
+
+/*
+ * conn must be a chatnav connection!
+ */
+u_long aim_chatnav_reqrights(struct aim_session_t *sess,
+ struct aim_conn_t *conn)
+{
+ struct aim_snac_t snac;
+
+ snac.id = aim_genericreq_n(sess, conn, 0x000d, 0x0002);
+
+ snac.family = 0x000d;
+ snac.type = 0x0002;
+ snac.flags = 0x0000;
+ snac.data = NULL;
+
+ aim_newsnac(sess, &snac);
+
+ return (sess->snac_nextid); /* already incremented */
+}
+
+u_long aim_chatnav_clientready(struct aim_session_t *sess,
+ struct aim_conn_t *conn)
+{
+ struct command_tx_struct newpacket;
+ int i;
+
+ newpacket.lock = 1;
+ if (conn)
+ newpacket.conn = conn;
+ else
+ newpacket.conn = aim_getconn_type(sess, AIM_CONN_TYPE_CHATNAV);
+ newpacket.type = 0x02;
+ newpacket.commandlen = 0x20;
+
+ newpacket.data = (char *) malloc(newpacket.commandlen);
+ i = aim_putsnac(newpacket.data, 0x0001, 0x0002, 0x0000, sess->snac_nextid);
+
+ i+= aimutil_put16(newpacket.data+i, 0x000d);
+ 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);
+
+ aim_tx_enqueue(sess, &newpacket);
+
+ return (sess->snac_nextid++);
+}
+
+/*
+ * Since multiple things can trigger this callback,
+ * we must lookup the snacid to determine the original
+ * snac subtype that was called.
+ */
+int aim_chatnav_parse_info(struct aim_session_t *sess, struct command_rx_struct *command)
+{
+ struct aim_snac_t *snac;
+ u_long snacid;
+ rxcallback_t userfunc;
+
+ snacid = aimutil_get32(command->data+6);
+ snac = aim_remsnac(sess, snacid);
+
+ if (!snac)
+ {
+ printf("faim: chatnav_parse_info: received response to unknown request! (%08lx)\n", snacid);
+ return 1;
+ }
+
+ if (snac->family != 0x000d)
+ {
+ printf("faim: chatnav_parse_info: recieved response that maps to corrupt request! (fam=%04x)\n", snac->family);
+ return 1;
+ }
+
+ /*
+ * We now know what the original SNAC subtype was.
+ */
+ switch(snac->type)
+ {
+ case 0x0002: /* request chat rights */
+ {
+ struct aim_tlvlist_t *tlvlist;
+ struct aim_chat_exchangeinfo *exchanges = NULL;
+ int curexchange = 0;
+ struct aim_tlv_t *exchangetlv;
+ u_char maxrooms = 0;
+ int ret = 1;
+ struct aim_tlvlist_t *innerlist;
+
+ tlvlist = aim_readtlvchain(command->data+10, command->commandlen-10);
+
+ /*
+ * Type 0x0002: Maximum concurrent rooms.
+ */
+ if (aim_gettlv(tlvlist, 0x0002, 1))
+ {
+ struct aim_tlv_t *maxroomstlv;
+ maxroomstlv = aim_gettlv(tlvlist, 0x0002, 1);
+ maxrooms = aimutil_get8(maxroomstlv->value);
+ }
+
+ /*
+ * Type 0x0003: Exchange information
+ *
+ * There can be any number of these, each one
+ * representing another exchange.
+ *
+ */
+ curexchange = 0;
+ while ((exchangetlv = aim_gettlv(tlvlist, 0x0003, curexchange+1)))
+ {
+ curexchange++;
+ exchanges = realloc(exchanges, curexchange * sizeof(struct aim_chat_exchangeinfo));
+
+ /* exchange number */
+ exchanges[curexchange-1].number = aimutil_get16(exchangetlv->value);
+ innerlist = aim_readtlvchain(exchangetlv->value+2, exchangetlv->length-2);
+
+ /*
+ * Type 0x000d: Unknown.
+ */
+ if (aim_gettlv(innerlist, 0x000d, 1))
+ ;
+
+ /*
+ * Type 0x0004: Unknown
+ */
+ if (aim_gettlv(innerlist, 0x0004, 1))
+ ;
+
+ /*
+ * Type 0x00c9: Unknown
+ */
+ if (aim_gettlv(innerlist, 0x00c9, 1))
+ ;
+
+ /*
+ * Type 0x00ca: Creation Date
+ */
+ if (aim_gettlv(innerlist, 0x00ca, 1))
+ ;
+
+ /*
+ * Type 0x00d0: Unknown
+ */
+ if (aim_gettlv(innerlist, 0x00d0, 1))
+ ;
+
+ /*
+ * Type 0x00d1: Maximum Message length
+ */
+ if (aim_gettlv(innerlist, 0x00d1, 1))
+ ;
+
+ /*
+ * Type 0x00d2: Unknown
+ */
+ if (aim_gettlv(innerlist, 0x00d2, 1))
+ ;
+
+ /*
+ * Type 0x00d3: Exchange Name
+ */
+ if (aim_gettlv(innerlist, 0x00d3, 1))
+ exchanges[curexchange-1].name = aim_gettlv_str(innerlist, 0x00d3, 1);
+ else
+ exchanges[curexchange-1].name = NULL;
+
+ /*
+ * Type 0x00d5: Unknown
+ */
+ if (aim_gettlv(innerlist, 0x00d5, 1))
+ ;
+
+ /*
+ * Type 0x00d6: Character Set (First Time)
+ */
+ if (aim_gettlv(innerlist, 0x00d6, 1))
+ exchanges[curexchange-1].charset1 = aim_gettlv_str(innerlist, 0x00d6, 1);
+ else
+ exchanges[curexchange-1].charset1 = NULL;
+
+ /*
+ * Type 0x00d7: Language (First Time)
+ */
+ if (aim_gettlv(innerlist, 0x00d7, 1))
+ exchanges[curexchange-1].lang1 = aim_gettlv_str(innerlist, 0x00d7, 1);
+ else
+ exchanges[curexchange-1].lang1 = NULL;
+
+ /*
+ * Type 0x00d8: Character Set (Second Time)
+ */
+ if (aim_gettlv(innerlist, 0x00d8, 1))
+ exchanges[curexchange-1].charset2 = aim_gettlv_str(innerlist, 0x00d8, 1);
+ else
+ exchanges[curexchange-1].charset2 = NULL;
+
+ /*
+ * Type 0x00d9: Language (Second Time)
+ */
+ if (aim_gettlv(innerlist, 0x00d9, 1))
+ exchanges[curexchange-1].lang2 = aim_gettlv_str(innerlist, 0x00d9, 1);
+ else
+ exchanges[curexchange-1].lang2 = NULL;
+
+ }
+
+ /*
+ * Call client.
+ */
+ userfunc = aim_callhandler(command->conn, 0x000d, 0x0009);
+ if (userfunc)
+ ret = userfunc(sess,
+ command,
+ snac->type,
+ maxrooms,
+ curexchange,
+ exchanges);
+ curexchange--;
+ while(curexchange)
+ {
+ if (exchanges[curexchange].name)
+ free(exchanges[curexchange].name);
+ if (exchanges[curexchange].charset1)
+ free(exchanges[curexchange].charset1);
+ if (exchanges[curexchange].lang1)
+ free(exchanges[curexchange].lang1);
+ if (exchanges[curexchange].charset2)
+ free(exchanges[curexchange].charset2);
+ if (exchanges[curexchange].lang2)
+ free(exchanges[curexchange].lang2);
+ curexchange--;
+ }
+ free(exchanges);
+ aim_freetlvchain(&innerlist);
+ aim_freetlvchain(&tlvlist);
+ return ret;
+ }
+ case 0x0003: /* request exchange info */
+ printf("faim: chatnav_parse_info: resposne to exchange info\n");
+ return 1;
+ case 0x0004: /* request room info */
+ printf("faim: chatnav_parse_info: response to room info\n");
+ return 1;
+ case 0x0005: /* request more room info */
+ printf("faim: chatnav_parse_info: response to more room info\n");
+ return 1;
+ case 0x0006: /* request occupant list */
+ printf("faim: chatnav_parse_info: response to occupant info\n");
+ return 1;
+ case 0x0007: /* search for a room */
+ printf("faim: chatnav_parse_info: search results\n");
+ return 1;
+ case 0x0008: /* create room */
+ printf("faim: chatnav_parse_info: response to create room\n");
+ return 1;
+ default: /* unknown */
+ printf("faim: chatnav_parse_info: unknown request subtype (%04x)\n", snac->type);
+ }
+
+ return 1; /* shouldn't get here */
+}
+
+u_long aim_chatnav_createroom(struct aim_session_t *sess,
+ struct aim_conn_t *conn,
+ char *name,
+ u_short exchange)
+{
+ struct command_tx_struct newpacket;
+ int i;
+ struct aim_snac_t snac;
+
+ newpacket.lock = 1;
+ if (conn)
+ newpacket.conn = conn;
+ else
+ newpacket.conn = aim_getconn_type(sess, AIM_CONN_TYPE_CHATNAV);
+ newpacket.type = 0x02;
+
+ newpacket.commandlen = 10 + 12 + strlen("invite") + strlen(name);
+
+ newpacket.data = (char *) malloc(newpacket.commandlen);
+ i = aim_putsnac(newpacket.data, 0x000d, 0x0008, 0x0000, sess->snac_nextid);
+
+ /* exchange */
+ i+= aimutil_put16(newpacket.data+i, exchange);
+
+ /* room cookie */
+ i+= aimutil_put8(newpacket.data+i, strlen("invite"));
+ i+= aimutil_putstr(newpacket.data+i, "invite", strlen("invite"));
+
+ /* instance */
+ i+= aimutil_put16(newpacket.data+i, 0xffff);
+
+ /* detail level */
+ i+= aimutil_put8(newpacket.data+i, 0x01);
+
+ /* tlvcount */
+ i+= aimutil_put16(newpacket.data+i, 0x0001);
+
+ /* room name */
+ i+= aim_puttlv_str(newpacket.data+i, 0x00d3, strlen(name), name);
+
+ snac.id = sess->snac_nextid;
+ snac.family = 0x000d;
+ snac.type = 0x0008;
+ snac.flags = 0x0000;
+ snac.data = NULL;
+
+ aim_newsnac(sess, &snac);
+
+ aim_tx_enqueue(sess, &newpacket);
+
+ return (sess->snac_nextid++);
+}
deadconn->forcedlatency = 0;
aim_clearhandlers(deadconn);
deadconn->handlerlist = NULL;
+ if (deadconn->priv)
+ free(deadconn->priv);
+ deadconn->priv = NULL;
}
struct aim_conn_t *aim_getconn_type(struct aim_session_t *sess,
if (!sess)
return;
- sess->logininfo.screen_name[0] = '\0';
+ memset(sess->logininfo.screen_name, 0x00, MAXSNLEN);
sess->logininfo.BOSIP = NULL;
- sess->logininfo.cookie[0] = '\0';
+ memset(sess->logininfo.cookie, 0x00, AIM_COOKIELEN);
sess->logininfo.email = NULL;
sess->logininfo.regstatus = 0x00;
sess->conns[i].lastactivity = 0;
sess->conns[i].forcedlatency = 0;
sess->conns[i].handlerlist = NULL;
+ sess->conns[i].priv = NULL;
}
sess->queue_outgoing = NULL;
sess->queue_incoming = NULL;
+ sess->pendingjoin = NULL;
sess->outstanding_snacs = NULL;
sess->snac_nextid = 0x00000001;
free(msg);
}
else if (channel == 0x0002)
- {
+ {
+ int rendtype;
struct aim_tlv_t *block1;
struct aim_tlvlist_t *list2;
struct aim_tlv_t *tmptlv;
int a;
- u_short exchange,instance;
- char *roomname,*msg,*encoding,*lang;
/* Class. */
if ((tmptlv = aim_gettlv(tlvlist, 0x0001, 1)))
a = 0x1a; /* skip -- not sure what this information is! */
- list2 = aim_readtlvchain(block1->value+a, block1->length-a);
- if (aim_gettlv(list2, 0x2711, 1))
+ /*
+ * XXX: Ignore if there's no data, only cookie information.
+ *
+ * Its probably just an accepted invitation or something.
+ *
+ */
+ if (block1->length <= 0x1a)
{
- struct aim_tlv_t *name;
- int len;
-
- name = aim_gettlv(list2, 0x2711, 1);
-
- exchange = aimutil_get16(name->value+0);
-
- len = aimutil_get16(name->value+2);
- roomname = (char *)malloc(len+1);
- memcpy(roomname, name->value+3, len);
- roomname[len] = '\0';
-
- instance = aimutil_get16(name->value+3+len);
+ aim_freetlvchain(&tlvlist);
+ return 1;
}
- if (aim_gettlv(list2, 0x000c, 1))
- msg = aim_gettlv_str(list2, 0x000c, 1);
+ list2 = aim_readtlvchain(block1->value+a, block1->length-a);
- if (aim_gettlv(list2, 0x000d, 1))
- encoding = aim_gettlv_str(list2, 0x000d, 1);
-
- if (aim_gettlv(list2, 0x000e, 1))
- lang = aim_gettlv_str(list2, 0x000e, 1);
+ if (aim_gettlv(list2, 0x0004, 1) /* start connection */ ||
+ aim_gettlv(list2, 0x000b, 1) /* close conncetion */)
+ {
+ rendtype = 1; /* voice request */
+
+ /*
+ * Call client.
+ */
+ userfunc = aim_callhandler(command->conn, 0x0004, 0x0007);
+ if (userfunc)
+ i = userfunc(sess,
+ command,
+ channel,
+ rendtype,
+ &userinfo);
+ else
+ i = 0;
+ }
+ else
+ {
+ struct aim_chat_roominfo roominfo;
+ char *msg=NULL,*encoding=NULL,*lang=NULL;
+
+ rendtype = 0; /* chat invite */
+ if (aim_gettlv(list2, 0x2711, 1))
+ {
+ struct aim_tlv_t *nametlv;
+
+ nametlv = aim_gettlv(list2, 0x2711, 1);
+ aim_chat_readroominfo(nametlv->value, &roominfo);
+ }
+
+ if (aim_gettlv(list2, 0x000c, 1))
+ msg = aim_gettlv_str(list2, 0x000c, 1);
+
+ if (aim_gettlv(list2, 0x000d, 1))
+ encoding = aim_gettlv_str(list2, 0x000d, 1);
+
+ if (aim_gettlv(list2, 0x000e, 1))
+ lang = aim_gettlv_str(list2, 0x000e, 1);
- /*
- * Call client.
- */
- userfunc = aim_callhandler(command->conn, 0x0004, 0x0007);
- if (userfunc)
- i = userfunc(sess, command, channel, &userinfo, roomname, msg, encoding+1, lang+1, exchange, instance);
- else
- i = 0;
+ /*
+ * Call client.
+ */
+ userfunc = aim_callhandler(command->conn, 0x0004, 0x0007);
+ if (userfunc)
+ i = userfunc(sess,
+ command,
+ channel,
+ rendtype,
+ &userinfo,
+ &roominfo,
+ msg,
+ encoding?encoding+1:NULL,
+ lang?lang+1:NULL);
+ else
+ i = 0;
- free(roomname);
- free(msg);
- free(encoding);
- free(lang);
+ free(roominfo.name);
+ free(msg);
+ free(encoding);
+ free(lang);
+ }
aim_freetlvchain(&list2);
}
* 0x0004 AOL Main Service user
* 0x0008 Unknown bit 4
* 0x0010 Free (AIM) user
+ * 0x0020 Away
*
* In some odd cases, we can end up with more
* than one of these. We only want the first,
char *prof = NULL;
u_int i = 0;
rxcallback_t userfunc=NULL;
+ struct aim_tlvlist_t *tlvlist;
{
u_long snacid = 0x000000000;
}
i = 10;
- i += aim_extractuserinfo(command->data+i, &userinfo);
-
- if (i < command->commandlen)
- {
- if (aimutil_get16(&command->data[i]) == 0x0001)
- {
- int len = 0;
-
- len = aimutil_get16(&command->data[i+2]);
-
- prof_encoding = (char *) malloc(len+1);
- memcpy(prof_encoding, &(command->data[i+4]), len);
- prof_encoding[len] = '\0';
-
- i += (2+2+len);
- }
- else
- {
- printf("faim: userinfo: **warning: unexpected TLV after TLVblock t(%04x) l(%04x)\n", aimutil_get16(command->data+i), aimutil_get16(command->data+i+2));
- i += 2 + 2 + command->data[i+3];
- }
- }
- if (i < command->commandlen)
- {
- if (aimutil_get16(&command->data[i]) == 0x0002)
- {
- int len = 0;
- len = aimutil_get16(&command->data[i+2]);
-
- prof = (char *) malloc(len+1);
- memcpy(prof, &(command->data[i+4]), len);
- prof[len] = '\0';
- }
- else
- printf("faim:userinfo: **warning: profile not found, but still have data\n");
- }
+ /*
+ * extractuserinfo will give us the basic metaTLV information
+ */
+ i += aim_extractuserinfo(command->data+i, &userinfo);
+
+ /*
+ * However, in this command, there's usually more TLVs following...
+ */
+ tlvlist = aim_readtlvchain(command->data+i, command->commandlen-i);
+ prof_encoding = aim_gettlv_str(tlvlist, 0x0001, 1);
+ prof = aim_gettlv_str(tlvlist, 0x0002, 1);
userfunc = aim_callhandler(command->conn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO);
if (userfunc)
prof_encoding,
prof);
}
-
+
free(prof_encoding);
free(prof);
+ aim_freetlvchain(&tlvlist);
return 1;
}
*/
u_long aim_bos_setprofile(struct aim_session_t *sess,
struct aim_conn_t *conn,
- char *profile)
+ char *profile,
+ char *awaymsg)
{
struct command_tx_struct newpacket;
int i = 0;
newpacket.conn = aim_getconn_type(sess, AIM_CONN_TYPE_BOS);
newpacket.commandlen = 1152+strlen(profile)+1; /*arbitrarily large */
+ if (awaymsg)
+ newpacket.commandlen += strlen(awaymsg);
+
newpacket.data = (char *) malloc(newpacket.commandlen);
i += aim_putsnac(newpacket.data, 0x0002, 0x004, 0x0000, sess->snac_nextid);
/* why do we send this twice? */
i += aim_puttlv_str(newpacket.data+i, 0x0003, strlen("text/x-aolrtf; charset=\"us-ascii\""), "text/x-aolrtf; charset=\"us-ascii\"");
- /* a blank TLV 0x0004 --- not sure what this is either */
- i += aimutil_put16(newpacket.data+i, 0x0004);
- i += aimutil_put16(newpacket.data+i, 0x0000);
+ /* Away message -- we send this no matter what, even if its blank */
+ if (awaymsg)
+ i += aim_puttlv_str(newpacket.data+i, 0x0004, strlen(awaymsg), awaymsg);
+ else
+ i += aim_puttlv_str(newpacket.data+i, 0x0004, 0x0000, NULL);
/* Capability information. */
i += aim_puttlv_str(newpacket.data+i, 0x0005, 0x0060, funkydata);
newpacket.conn = aim_getconn_type(sess, AIM_CONN_TYPE_BOS);
newpacket.type = 0x02;
newpacket.commandlen = 18;
+ if (conn->type != AIM_CONN_TYPE_BOS)
+ newpacket.commandlen += 2;
newpacket.data = (char *) malloc(newpacket.commandlen);
aim_putsnac(newpacket.data, 0x0001, 0x0008, 0x0000, sess->snac_nextid);
newpacket.data[15] = 0x03;
newpacket.data[16] = 0x00;
newpacket.data[17] = 0x04;
+ if (conn->type != AIM_CONN_TYPE_BOS)
+ {
+ newpacket.data[16] = 0x00;
+ newpacket.data[17] = 0x05;
+ }
aim_tx_enqueue(sess, &newpacket);
struct aim_conn_t *conn)
{
struct command_tx_struct newpacket;
- int i,j;
+ int i;
newpacket.lock = 1;
if (conn)
#if 0
for (j = 0; j < 0x10; j++)
-A
{
i += aimutil_put16(newpacket.data+i, j); /* family */
i += aimutil_put16(newpacket.data+i, 0x0003); /* version */
workingPtr->handled = 1;
aim_conn_setstatus(workingPtr->conn, AIM_CONN_STATUS_READY);
}
+ else if ((family == 0x000d) && (subtype == 0x0009))
+ workingPtr->handled = aim_chatnav_parse_info(sess, workingPtr);
else
{
workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr);
}
break;
case AIM_CONN_TYPE_CHAT:
- printf("\nAHH! Dont know what to do with CHAT stuff yet!\n");
- workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_DEFAULT, workingPtr);
+ {
+ u_short family, subtype;
+
+ family = aimutil_get16(workingPtr->data);
+ subtype= aimutil_get16(workingPtr->data+2);
+
+ if ((family == 0x0000) && (subtype == 0x00001))
+ workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0000, 0x0001, workingPtr);
+ else if (family == 0x0001)
+ {
+ if (subtype == 0x0001)
+ workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0001, workingPtr);
+ else if (subtype == 0x0003)
+ workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0003, workingPtr);
+ else if (subtype == 0x0007)
+ workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0007, workingPtr);
+ else
+ printf("Chat: unknown snac %04x/%04x\n", family, subtype);
+ }
+ else if (family == 0x000e)
+ {
+ if (subtype == 0x0002)
+ workingPtr->handled = aim_chat_parse_infoupdate(sess, workingPtr);
+ else if (subtype == 0x0003)
+ workingPtr->handled = aim_chat_parse_joined(sess, workingPtr);
+ else if (subtype == 0x0004)
+ workingPtr->handled = aim_chat_parse_leave(sess, workingPtr);
+ else if (subtype == 0x0006)
+ workingPtr->handled = aim_chat_parse_incoming(sess, workingPtr);
+ else
+ printf("Chat: unknown snac %04x/%04x\n", family, subtype);
+ }
+ else
+ {
+ printf("Chat: unknown snac %04x/%04x\n", family, subtype);
+ workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_DEFAULT, workingPtr);
+ }
+ }
break;
default:
printf("\nAHHHHH! UNKNOWN CONNECTION TYPE! (0x%02x)\n\n", workingPtr->conn->type);
tmptlv = aim_gettlv(tlvlist, 0x0006, 1);
memcpy(cookie, tmptlv->value, AIM_COOKIELEN);
- userfunc = aim_callhandler(command->conn, 0x0001, 0x0005);
- if (userfunc)
- ret = userfunc(sess, command, serviceid, ip, cookie);
-
+ if (serviceid == AIM_CONN_TYPE_CHAT)
+ {
+ /*
+ * Chat hack.
+ *
+ */
+ userfunc = aim_callhandler(command->conn, 0x0001, 0x0005);
+ if (userfunc)
+ ret = userfunc(sess, command, serviceid, ip, cookie, sess->pendingjoin);
+ free(sess->pendingjoin);
+ sess->pendingjoin = NULL;
+ }
+ else
+ {
+ userfunc = aim_callhandler(command->conn, 0x0001, 0x0005);
+ if (userfunc)
+ ret = userfunc(sess, command, serviceid, ip, cookie);
+ }
aim_freetlvchain(&tlvlist);
return ret;
cur = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t));
memset(cur, 0x00, sizeof(struct aim_tlvlist_t));
- cur->tlv = aim_createtlv();
+ cur->tlv = aim_createtlv();
cur->tlv->type = type;
cur->tlv->length = length;
cur->tlv->value = (u_char *)malloc(length*sizeof(u_char));
int aim_puttlv_str(u_char *buf, u_short t, u_short l, u_char *v)
{
int curbyte;
- if (!v || !buf)
- return 0;
curbyte = 0;
curbyte += aimutil_put16(buf+curbyte, (u_short)(t&0xffff));
curbyte += aimutil_put16(buf+curbyte, (u_short)(l&0xffff));
- memcpy(buf+curbyte, v, l);
+ if (v)
+ memcpy(buf+curbyte, v, l);
curbyte += l;
return curbyte;
}
#if debug > 2
printf("calling aim_tx_printqueue()\n");
- aim_tx_printqueue();
+ aim_tx_printqueue(sess);
printf("back from aim_tx_printqueue()\n");
#endif
*
*/
#if debug > 2
-int aim_tx_printqueue(void)
+int aim_tx_printqueue(struct aim_session_t *sess)
{
struct command_tx_struct *workingPtr = NULL;
(sess->queue_outgoing->sent == 1) )
{
#if debug > 1
- printf("purgequeue(): purging seqnum 0x%04x\n", aim_queue_outgoing->seqnum);
+ printf("purgequeue(): purging seqnum 0x%04x\n", sess->queue_outgoing->seqnum);
#endif
workingPtr2 = sess->queue_outgoing;
sess->queue_outgoing = NULL;
struct command_tx_struct *queue_outgoing;
struct command_rx_struct *queue_incoming;
+ /*
+ * This is a dreadful solution to the what-room-are-we-joining
+ * problem. (There's no connection between the service
+ * request and the resulting redirect.)
+ */
+ char *pendingjoin;
+
/*
* Outstanding snac handling
*
u_long sessionlen;
};
+#define AIM_CLASS_TRIAL 0x0001
+#define AIM_CLASS_UNKNOWN2 0x0002
+#define AIM_CLASS_AOL 0x0004
+#define AIM_CLASS_UNKNOWN4 0x0008
+#define AIM_CLASS_FREE 0x0010
+#define AIM_CLASS_AWAY 0x0020
+#define AIM_CLASS_UNKNOWN40 0x0040
+#define AIM_CLASS_UNKNOWN80 0x0080
+
/*
* TLV handling
*/
u_long aim_bos_setidle(struct aim_session_t *, struct aim_conn_t *, u_long);
u_long aim_bos_changevisibility(struct aim_session_t *, struct aim_conn_t *, int, char *);
u_long aim_bos_setbuddylist(struct aim_session_t *, struct aim_conn_t *, char *);
-u_long aim_bos_setprofile(struct aim_session_t *, struct aim_conn_t *, char *);
+u_long aim_bos_setprofile(struct aim_session_t *, struct aim_conn_t *, char *, char *);
u_long aim_bos_setgroupperm(struct aim_session_t *, struct aim_conn_t *, u_long);
u_long aim_bos_clientready(struct aim_session_t *, struct aim_conn_t *);
u_long aim_bos_reqrate(struct aim_session_t *, struct aim_conn_t *);
u_long aim_bos_reqbuddyrights(struct aim_session_t *, struct aim_conn_t *);
u_long aim_bos_reqlocaterights(struct aim_session_t *, struct aim_conn_t *);
u_long aim_bos_reqicbmparaminfo(struct aim_session_t *, struct aim_conn_t *);
+u_long aim_setversions(struct aim_session_t *sess, struct aim_conn_t *conn);
/* aim_rxhandlers.c */
int aim_rxdispatch(struct aim_session_t *);
u_long aim_usersearch_address(struct aim_session_t *, struct aim_conn_t *, char *);
/* u_long aim_usersearch_name(struct aim_session_t *, struct aim_conn_t *, char *); */
+
+struct aim_chat_roominfo {
+ u_short exchange;
+ char *name;
+ u_short instance;
+};
+int aim_chat_readroominfo(u_char *buf, struct aim_chat_roominfo *outinfo);
+int aim_chat_parse_infoupdate(struct aim_session_t *sess, struct command_rx_struct *command);
+int aim_chat_parse_joined(struct aim_session_t *sess, struct command_rx_struct *command);
+int aim_chat_parse_leave(struct aim_session_t *sess, struct command_rx_struct *command);
+int aim_chat_parse_incoming(struct aim_session_t *sess, struct command_rx_struct *command);
+u_long aim_chat_send_im(struct aim_session_t *sess, struct aim_conn_t *conn, char *msg);
+u_long aim_chat_join(struct aim_session_t *sess, struct aim_conn_t *conn, u_short exchange, const char *roomname);
+u_long aim_chat_clientready(struct aim_session_t *sess, struct aim_conn_t *conn);
+int aim_chat_attachname(struct aim_conn_t *conn, char *roomname);
+char *aim_chat_getname(struct aim_conn_t *conn);
+struct aim_conn_t *aim_chat_getconn(struct aim_session_t *, char *name);
+
+u_long aim_chatnav_reqrights(struct aim_session_t *sess, struct aim_conn_t *conn);
+u_long aim_chatnav_clientready(struct aim_session_t *sess, struct aim_conn_t *conn);
+
+u_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 aim_chat_exchangeinfo {
+ u_short number;
+ char *name;
+ char *charset1;
+ char *lang1;
+ char *charset2;
+ char *lang2;
+};
+int aim_chatnav_parse_info(struct aim_session_t *sess, struct command_rx_struct *command);
+u_long aim_chatnav_createroom(struct aim_session_t *sess, struct aim_conn_t *conn, char *name, u_short exchange);
+int aim_chat_leaveroom(struct aim_session_t *sess, char *name);
+
/* aim_util.c */
int aimutil_put8(u_char *, u_char);
u_char aimutil_get8(u_char *buf);
* SNAC Family: Chat Navigation Services
*/
#define AIM_CB_CTN_ERROR 0x0001
+#define AIM_CB_CTN_CREATE 0x0008
+#define AIM_CB_CTN_INFO 0x0009
#define AIM_CB_CTN_DEFAULT 0xffff
/*
* SNAC Family: Chat Services
*/
#define AIM_CB_CHT_ERROR 0x0001
+#define AIM_CB_CHT_ROOMINFOUPDATE 0x0002
+#define AIM_CB_CHT_USERJOIN 0x0003
+#define AIM_CB_CHT_USERLEAVE 0x0004
+#define AIM_CB_CHT_OUTGOINGMSG 0x0005
+#define AIM_CB_CHT_INCOMINGMSG 0x0006
#define AIM_CB_CHT_DEFAULT 0xffff
/*
*
* Default: 0
*/
-#define debug 0
+#define debug 0
/*
* Maximum number of connections the library can simultaneously
--- /dev/null
+
+17/6 (client)
+-----
+
+0100 0010
+7468 6973 6865 7265 6973 616e 616d 6532
+ t h i s h e r e i s a n a m e 2
+
+17/7 (server)
+----
+
+0a00 3336 3831 3531 3737 3430
+ 3 6 8 1 5 1 7 7 4 0
+
+17/2 (client)
+----
+0100 0010
+7468 6973 6865 7265 6973 616e 616d 6532
+ t h i s h e r e i s a n a m e 2
+
+0025 0010
+473c 5d77 c795 1c1c 4aba 2c9c 50df 275b
+ G < ] w , P '
+
+0003 0032
+414f 4c20 496e 7374 616e 7420 4d65 7373
+ A O L I n s t a n t M e s s
+656e 6765 7220 2853 4d29 2c20 7665 7273
+ e n g e r ( S M ) , v e r s
+696f 6e20 332e 352e 3136 3730 2f57 494e
+ i o n 3 . 5 . 1 6 7 0 / W I N
+3332
+ 3 2
+
+0016 0002 0004
+0017 0002 0003
+0018 0002 0005
+0019 0002 0000
+001a 0002 0686
+000e 0002 7573
+ u s
+000f 0002 656e
+ e n
+0014 0004 0000 002a
+0009 0002 0015
+
+17/3 (server)
+----
+
+0100 0010
+5468 6973 4865 7265 4973 414e 616d 6532
+
+0005 000d
+3230 352e 3138 382e 342e 3233 36
+ 2 0 5 . 1 8 8 . 4 . 2 3 6
+
+0006 0100 c11d 7e73 30d0 db
+ 6ea7 88b7 b73d 6ad9 f73f e1e8 6359 dda0
+ 4289 7651 9a32 9a27 edca 53c3 2b57 6838
+ 5f38 4968 1b83 1ae3 db0f 47db c380 59d1
+ 0b00 8f96 42e2 3785 68d8 3547 4c41 7dc9
+ 85b0 c4e2 fc7e 63b6 248d 9c33 f899 0801
+ 6e45 f038 5ff3 ea1e 2e29 0c4d d48c c902
+ 5a1e 8417 2c81 919b fc67 5a82 e1ce 3180
+ f2b9 c3db a3cc c073 b0b2 4964 992f 1693
+ cd0d 817b 4ee6 2665 4a80 dada c301 19a8
+ 388c 11d8 1e55 f2dd 0572 43a1 459d 884c
+ 2733 0f7f 715d 8364 0c3d 13e0 e4a8 ebeb
+ a181 6b2d 278f cab1 b4ea 0bda f8b7 3d43
+ e4ec f6fb a66f b511 0009 1c1e 12ab 12fd
+ e083 f44b 38bc 7401 2a47 b739 558b 9e96
+ d365 e9ee 03d6 0e4d 3650 c9f8 c728 9c04
+ 14c3 1505 0304 abc6 78
+0011 000a
+6d69 6440 6175 6b2e 6378
+
+0013 0002 0003
+
+2a04 ce58 0000 00
+
+
+2/4 (client)
+---
+0001 001f 7465 7874 2f61 6f6c 7274 663b
+ 2063 6861 7273 6574 3d22 7573 2d61 7363
+ 6969 22
+
+0002 0001 00
+
+0003 001f 7465 7874
+ 2f61 6f6c 7274 663b 2063 6861 7273 6574
+ 3d22 7573 2d61 7363 6969 22
+
+0004 0000
+
+0005 0060
+ 09 4613 464c 7f11 d182 2244 4553
+ 5400 0009 4613 414c 7f11 d182 2244 4553
+ 5400 0009 4613 454c 7f11 d182 2244 4553
+ 5400 0074 8f24 2062 8711 d182 2244 4553
+ 5400 0009 4613 484c 7f11 d182 2244 4553
+ 5400 0009 4613 434c 7f11 d182 2244 4553
+ 5400 00
+
+
+
+2a02 3764 000a
+0003 0002 0000 0000 0000
+
+2a02 3765 005c
+
+0003 0004 0000 0000 0000
+ 06 6d69 6467 6f64
+ 07 4d69 6447 7572 75
+ 0a 7467 4161 7264 7661 726b
+ 10 5468 6973 4865 7265 4973 414e 616d 6532
+ 09 6d69 6465 6e64 6961 6e
+ 09 7661 7868 6572 6465 72
+ 0a 6d6f 7573 6574 726f 7574
+ 07 6177 7761 6969 64
+
+
+
+2a02 3766 001a
+
+0004 0002 0000 0000 8012
+ 0000 0000 0003 1f40
+ 03e7 03e7 0000 0000
+
+
+
+4/4
+---
+2a02 3767 000a
+0004 0004 0000 0000 8013
+
+9/2
+---
+2a02 3768 000a
+0009 0002 0000 0000 0000
+
+9/4
+---
+2a02 3769 000e
+0009 0004 0000 0000 0000
+ 0000 001f
+
+1/14
+----
+2a02 376a 000e
+0001 0014 0000 0000 0000
+ 0000 0001
+
+2a02 376b 00bd
+0002 0004 0000 0000 0002
+ 0001 001f 7465 7874 2f61 6f6c 7274 663b 2063 68
+ 6172 7365 743d 2275 732d 6173 6369 6922
+
+ 0002 0001 00
+
+ 0003 001f 7465 7874 2f61 6f6c 7274 663b 2063 68
+ 6172 7365 743d 2275 732d 6173 6369 6922
+
+ 0004 0000
+
+ 0005 0060
+ 0946 1346 4c7f 11d1 8222 4445 5354 0000
+ 0946 1341 4c7f 11d1 8222 4445 5354 0000
+ 0946 1345 4c7f 11d1 8222 4445 5354 0000
+ 748f 2420 6287 11d1 8222 4445 5354 0000
+ 0946 1348 4c7f 11d1 8222 4445 5354 0000
+ 0946 1343 4c7f 11d1 8222 4445 5354 0000
+
+
+
+win chat invite
+----------------
+
+4233 3731 3931 5f00 cookie
+
+0002 channel
+
+10 5468 6973 4865 7265 4973 414e 616d 6532 src sn
+
+0000 warnlevel
+0004 num of tlvs that follow
+0001 0002 0011 class
+0004 0002 0000 idletime
+000f 0004 0000 0c7a sessionlen
+0003 0004 386a e35b onsince
+
+0005 0063
+ 0000 3342 3731 3931 5f00 748f 2420 6287 11d1 8222 4445 5354 0000
+
+000a 0002 0001
+000f 0000
+000c 001b 4a6f 696e 206d 6520 696e 2074 6869 7320
+ 4275 6464 7920 4368 6174 2e
+2711 001c 0004 1774 6869 7368 6572 6569 7361 6e61
+ 6d65 325f 6368 6174 3538 0000
+
+mac chat invite
+---------------
+4252 432d 0000 0009 cookie
+
+0002 channel
+
+07 4d69 6447 7572 75 src sn
+
+0000 warnlevel
+
+0004 tlvcount
+
+0001 0002 0010 class
+0004 0002 0000 idle
+000f 0004 0000 1978 sessionlen
+0003 0004 3869 93f9 onsince
+
+0005 0071
+
+0000 5242 432d 0000 0009 748f 2420 6287 11d1 8222 4445 5354 0000
+
+000a 0002 0001
+2711 0013 0004 0e6d 6964
+ 6775 7275 5f63 6861 7434 3700 00
+000f 0000
+000c 001b 4a6f 696e 206d 6520 696e 2074 6869 7320
+ 4275 6464 7920 4368 6174 2e
+000d 0008 0875 732d 6173 6369
+000e 0007 0765 6e67 6c69 7320
+
+win voice invite
+----------------
+
+3434 4443 395f 7800 cookie
+
+0002 channel
+
+10 5468 6973 4865 7265 4973 414e 616d 6532 src sn
+
+0000 warnlevel
+
+0004 tlvcount
+
+0001 0002 0011 class
+
+0004 0002 0000
+000f 0004 0000 00d8
+0003 0004 386b 27ab
+0005 003c
+0000 3434 4443 395f 7800 0946 1341 4c7f 11d1 8222 4445 5354 0000
+000a 0002 0001
+0003 0004 c63c 9612
+000f 0000
+2711 0004 0000 0001
+0004 0004 18dd 0fac
+00
+
+win voice disconnect
+--------------------
+
+3431 3246 3237 5f00
+
+0002
+
+10 5468 6973 4865 7265 4973 414e 616d 6532
+0000
+
+0004
+
+0001 0002 0011
+0004 0002 0000
+000f 0004 0000 04ec
+0003 0004 386b 27ab
+0005 0020
+0001 3134 3246 3237 5f00 0946 1341 4c7f 11d1 8222 4445 5354 0000
+000b 0002 0001
+00
+
+
+gone away
+---------
+10 5468 6973 4865 7265 4973 414e 616d 6532
+0000 warnlevel
+0004 tlvcount
+0001 0002 0031
+0004 0002 0000
+000f 0004 0000 0817
+0003 0004 386b 27ab
+61
+
+came back
+---------
+10 5468 6973 4865 7265 4973 414e 616d 6532
+0000
+0004
+0001 0002 0011
+0004 0002 00
+ 0000 0f00 0400 0008 2600 0300 0438 6b27
+ ab61
+
+2/4 -- going away
+-----------------
+0001 001f 7465 7874 2f61 6f6c 7274 663b
+ 2063 6861 7273 6574 3d22 7573 2d61 7363
+ 6969 22
+0002 0001 00
+0003 001f 7465 7874 2f61 6f6c 7274 663b
+ 2063 6861 7273 6574 3d22 7573 2d61 7363
+ 6969 22
+
+0004 0025 49
+ 2061 6d20 6177 6179 2066 726f 6d20 6d79
+ 2063 6f6d 7075 7465 7220 7269 6768 7420
+ 6e6f 772e
+
+
+2/4 -- coming back
+------------------
+0001 001f 7465 7874 2f61 6f6c 7274 663b
+ 2063 6861 7273 6574 3d22 7573 2d61 7363
+ 6969 22
+0002 0001 00
+0003 001f 7465 7874 2f61 6f6c 7274 663b
+ 2063 6861 7273 6574 3d22 7573 2d61 7363
+ 6969 22
+0004 0000 00
+
+getuserinfo with awaymsg 2/6
+------------------------
+06 6d69 6467 6f64
+
+0000
+0005
+0001 0002 0030
+0004 0002 0000
+000f 0004 0000 0044
+0002 0004 374e 69cf
+0003 0004 386b 3aa4
+0001 0021
+ 7465 7874 2f78 2d61 6f6c 7274 663b 2063
+ 6861 7273 6574 3d22 7573 2d61 7363 6969
+ 22
+0002 003a
+ 3c70 3e6d 6661 696d 2d70 7265 322e 322d
+ 6d69 6428 3330 6465 6331 3939 3929 3b20
+ 6c69 6266 6169 6d20 302e 3935 6973 6828
+ 3330 6465 6331 3939 3929
+
+getuserinfo--parameter 3
+------------------------
+
+10 5468 6973 4865 7265 4973 414e 616d 6532
+
+0000
+0004
+0001 0002 0031
+0004 0002 0000
+000f 0004 0000 1797
+0003 0004 386b 27ab
+0003 001f 7465 7874 2f61 6f6c 7274 663b 2063 6861 72 7365 743d 2275 732d 6173
+ 6369 6922 0004 0025 4920 616d 2061 7761
+ 7920 6672 6f6d 206d 7920 636f 6d70 7574
+ 6572 2072 6967 6874 206e 6f77 2e00
+
+chat join -- 1/4
+----------
+000e
+
+0001 001c
+
+0004 17 7468 6973 6865 7265 6973 616e 616d 6532 5f63 6861 7438 3500 00
+
+0000 0000
+
+redirect -- 1/5
+---------------
+000d 0002 000e service id
+0005 000c 3230 352e 3138 382e 342e 3636 IP
+0006 0100 cookie
+ e2df 8c0b 8caf
+ adc3 3996 0883 d2a0 1af6 ea29 404c 1935
+ d364 d4cf 9c0a 0ad9 c3d7 ac7c 5f5d 2c57
+ cb3e 00a4 4deb 62e0 9d57 8dc6 9a6b 2916
+ 15b8 d496 d735 7d28 0323 c931 795e b2cf
+ 459d db9b c726 5467 7170 fd55 65ae 04df
+ fd94 979e f47a 1c9d 2c60 56bb 41a3 6778
+ 6c8c 8b97 2397 e187 0541 a5cc 9927 b707
+ 8340 3c42 e40d c070 65c4 c2c0 88c1 3af1
+ ec10 eda8 9875 89ec 2a17 eee6 e7dd 2a74
+ 82cd 6b6d cb97 af9a c541 8b1b 5c9f f4e4
+ f858 93b3 5cea ff78 b816 cc37 c721 0097
+ c204 4fbb 8e66 ec3d 94ac 964e cb1b 2c78
+ a39e 6c2b 75f2 1acd ceb2 d529 2c82 81e8
+ ef84 b382 5d7d 90d2 7f31 12ac 35b6 cf51
+ a296 28fa 2623 0997 1e1b 636b 4154 d08f
+ c900 2137 3fa4 1a09 d1bc
+
+(open new connection)
+
+(send cookie on channel one, prefixed by 0000 0001 then type 6 TLV)
+
+(get server ready -- supports services 0001 and 000e)
+
+set client versions (client -- 1/17)
+-------------------
+000e 0001
+0001 0003
+
+server versions (server 1/18)
+---------------
+0001 0003
+000e 0001
+
+(request rate info 1/6 from client)
+
+(never gets rate info?)
+
+rate info ack (client -- 1/8)
+-------------
+0001
+0002
+0003
+0004
+0005
+
+send chat invite (client 4/6 -- on BOS connection)
+----------------
+3033 4136 3445 5f00 cookie
+
+0002 channel
+
+06 6d69 6467 6f64
+0005 0063
+ 0000 3330 4136 3445 5f00 74
+ 8f24 2062 8711 d182 2244 4553 5400 00
+
+ 000a 0002 0001
+ 000f 0000
+ 000c 001b
+ 4a6f 696e 206d 6520 69 6e20 7468 6973 2042 7564
+ 6479 2043 6861 742e
+ 2711 001c
+ 0004 17 7468 6973 6865 7265 6973 616e 616d 6532
+ 5f63 6861 7438 3500 00
+
+client ready (1/2)
+------------
+000e 0001
+0004 0001
+0001 0003
+0004 0686
+
+
+users joined -- e/3
+------------
+10 5468 6973 4865 7265 4973 414e 616d 6532 joining sn
+0000 warnlevel
+0004 tlvcount
+0001 0002 0011 class
+0002 0004 3355 6800
+0003 0004 386b e770
+0004 0002 0000
+
+user joined -- e/3 --another sample
+------------------------------------
+09 7661 7868 6572 6465 72
+0000 warnlevel
+0004
+0001 0002 0011
+0002 0004 3566 7a92
+0003 0004 386c 0d5a
+0004 0002 0000
+10 5468 6973 4865 7265 4973 414e 616d 6532
+0000
+0004
+0001 0002 0011
+0002 0004 3355 6800
+0003 0004 386b e770
+0004 0002 0028
+
+info update -- e/2 --another sample
+-----------------------------------
+0004 17 7468 6973 6865 7265 6973 616e 616d 6532 5f63 6861 7438 35 0000
+02 detail level
+
+0009
+
+006a 0017 5468 6973 4865 7265 4973 414e 616d 6532 2043 6861 7438 35
+006f 0002 0002
+
+0073 005b
+ 09 7661 7868 6572 6465 72
+ 0000
+ 0004
+ 0001 0002 0011
+ 0002 0004 3566 7a92
+ 0003 0004 386c 0d5a
+ 0004 0002 0000
+ 10 5468 6973 4865 7265 4973 414e 616d 6532
+ 0000
+ 0004
+ 0001 0002 0011
+ 0002 0004 3355 6800
+ 0003 0004 386b e770
+ 0004 0002 0028
+00c9 0002 0011
+00ca 0004 386b e76f
+00d1 0002 0200
+00d2 0002 0018
+00d3 0017 5468 6973 4865 7265 4973 414e 616d 6532 2043 6861 7438 35
+00d5 0001 02
+
+room info update -- e/2
+----------------
+0004 17 7468 6973 6865 7265 6973 616e 616d 6532 5f63 6861 7438 35 0000
+02 detail level
+
+0009 tlvcount
+
+006a 0017 5468 6973 4865 7265 4973 414e 616d 6532 2043 6861 7438 35
+006f 0002 0001
+0073 0031
+ 10 5468 6973 4865 7265 4973 414e 616d 6532 sn
+ 0000 warnlevel
+ 0004 tlvcount
+ 0001 0002 0011 class
+ 0002 0004 3355 6800
+ 0003 0004 386b e770
+ 0004 0002 0000
+ 00c9 0002 0011
+ 00ca 0004 386b e76f
+ 00d1 0002 0200
+ 00d2 0002 0018
+ 00d3 0017 5468 6973 4865 7265 4973 414e 616d 6532 2043 6861 7438 35
+ 00d5 0001 02
+
+users left -- e/4
+----------
+07 4d69 6447 7572 75
+0000
+0001
+0001 0002 0000
+
+
+incoming message -- e/6
+-----------------
+
+3330 3945 3446 0000
+
+0003
+
+0003 0031
+ 10 5468 6973 4865 7265 4973 414e 616d 6532
+ 0000
+ 0004
+ 0001 0002 0011
+ 0002 0004 3355 6800
+ 0003 0004 386b e770
+ 0004 0002 0000
+0001 0000
+0005 003f
+ 0001 003b 3c48 544d 4c
+ 3e3c 424f 4459 2042 4743 4f4c 4f52 3d22
+ 2366 6666 6666 6622 3e3c 464f 4e54 3e68
+ 693c 2f46 4f4e 543e 3c2f 424f 4459 3e3c
+ 2f48 544d 4c3e
+
+outgoing message -- e/5
+----------------
+3330 3945 3446 0000
+
+0003
+
+0001 0000
+0006 0000
+0005 003f
+ 0001 003b
+ 3c48 544d 4c3e 3c42 4f44 5920 4247 434f 4c4f 523d 2223
+ 6666 6666 6666 223e 3c46 4f4e 543e 6869
+ 3c2f 464f 4e54 3e3c 2f42 4f44 593e 3c2f
+ 4854 4d4c 3e00
+
+
+
+
+CHATNAV
+--------
+
+
+
+request service: 1/4 -- data=0x000d
+
+gets normal redirect 1/5
+
+sends cookie
+
+gets server ready (supports 1, d)
+
+set client versions {{d,1}, {1,3}}
+
+gets server versions {{1,3}, {d,1}}
+
+request rate info -- 1/6
+
+rate info ack -- 1/8
+
+sets client ready -- 1/2 (supports d, 1, 4, 1, 1, 3, 4, 0686)
+
+request chat rights -- d/2 -- no data
+
+gets nav information -- d/9
+--------------------
+0002 0001 03 concurrent max rooms
+0003 006d EXCHANGE DESC -- EXCHANGE 4
+ 0004 exchange
+ 000d 0003 0001 03 unknown
+ 0004 0002 001e unknown
+ 00c9 0002 0011 unknown
+ 00ca 0004 3842 4ca3
+ 00d0 0002 0003 unknown
+ 00d1 0002 0200 maxmsglen?
+ 00d2 0002 0018 unknown
+ 00d3 0011 6169 6d20 7072 6976 6174 6520 6368 6174 73 exch name
+ aim private chats
+ 00d5 0001 02 unknown
+ 00d6 0008 7573 2d61 7363 6969 charset
+ 00d7 0002 656e lang
+ 00d8 0008 7573 2d61 7363 6969 charset
+ 00d9 0002 656e lang
+0003 006f EXCHANGE DESC -- EXCHANGE 5
+ 0005
+ 000d 0003 0001 03
+ 0004 0002 001e
+ 00c9 0002 0015
+ 00ca 0004 3842 4ca3
+ 00d0 0002 0003
+ 00d1 0002 0200
+ 00d2 0002 0018
+ 00d3 0013 616f 6c20 636f 6d6d 756e 6974 7920 6368
+ 6174 73
+ aol community chats
+ 00d5 0001 02
+ 00d6 0008 7573 2d61 7363 6969
+ 00d7 0002 656e
+ 00d8 0008 7573 2d61 7363 6969
+ 00d9 0002 656e
+0003 0075 EXCHANGE DESC -- EXCHANGE 6
+ 0006
+ 000d 0003 0001 03 unknown
+ 0004 0002 001e unknown
+ 00c9 0002 0015 unknown
+ 00ca 0004 3842 4ca3 cookie?
+ 00d0 0002 0003 mxchan?
+ 00d1 0002 0200 msgsz?
+ 00d2 0002 0018 unknown
+ 00d3 0019 6e65 7463 656e 7465 7220 636f 6d6d 756e
+ 6974 7920 6368 6174 73
+ netcenter community chats exchange name
+ 00d5 0001 02 unknown
+ 00d6 0008 7573 2d61 7363 6969 charset
+ 00d7 0002 656e lang
+ 00d8 0008 7573 2d61 7363 6969 charset
+ 00d9 0002 656e lang
+
+
+create room -- d/8
+------------------
+0004 06 69 6e76 6974 65 ffff roominfo (cookie: invite)
+01 detail level
+0001 tlvcount
+00d3 000e 6177 7761 6969 6420 4368 6174 3235
+ awwaiid Chat25
+
+new room info -- d/9 (need to identify somehow!)
+-------------
+0004 0059
+ 0004 0e 6177 7761 6969 645f 6368 6174 3235 0000 roominfo
+ 02 detail level
+ 0007
+ 006a 000e 6177 7761 6969 6420 4368 6174 3235
+ 00c9 0002 0011
+ 00ca 0004 386c 72c5
+ 00d1 0002 0200
+ 00d2 0002 0018
+ 00d3 000e 6177 7761 6969 6420 4368 6174 3235
+ 00d5 0001 02
+
+
+outgoing invitation -- 4/6
+--------------------
+3131 3538 3446 4100 cookie
+0002 channel
+07 4d69 6447 7572 75 destsn
+0005 0063
+ 0000
+ 3131 3538 3446 4100
+ 748f 2420 6287 11d1 8222 4445 5354 0000
+
+ 000a 0002 0001
+ 000f 0000
+ 000c 001b
+ 4a6f 696e 206d 6520 696e 2074 6869 7320
+ 4275 6464 7920 4368 6174 2e
+
+
+ 2711 001c
+ 0004 17
+ 7468 6973 6865 7265 6973 616e 616d 6532
+ 5f63 6861 7438 35
+ 0000
+
+
+invitation accepted
+-------------------
+3131 3538 3446 4100
+
+0002
+10 5468 6973 4865 7265 4973 414e 616d 6532
+0000
+0004
+0001 0002 0011
+0004 0002 0000
+000f 0004 0000 001e
+0003 0004 386f 2026
+0005 001a
+ 0002 3131 3538 3446 4100 748f 24 2062 8711
+ d182 2244 4553 5400 0000
int faimtest_parse_oncoming(struct aim_session_t *, struct command_rx_struct *, ...);
int faimtest_parse_offgoing(struct aim_session_t *, struct command_rx_struct *, ...);
int faimtest_parse_login_phase3d_f(struct aim_session_t *, struct command_rx_struct *, ...);
-int faimtest_auth_error(struct aim_session_t *, struct command_rx_struct *, ...);
int faimtest_parse_authresp(struct aim_session_t *, struct command_rx_struct *, ...);
int faimtest_parse_incoming_im(struct aim_session_t *, struct command_rx_struct *command, ...);
int faimtest_parse_userinfo(struct aim_session_t *, struct command_rx_struct *command, ...);
int faimtest_parse_misses(struct aim_session_t *, struct command_rx_struct *command, ...);
int faimtest_parse_motd(struct aim_session_t *, struct command_rx_struct *command, ...);
int faimtest_parse_login(struct aim_session_t *, struct command_rx_struct *command, ...);
+int faimtest_chatnav_info(struct aim_session_t *, struct command_rx_struct *command, ...);
+int faimtest_chat_incomingmsg(struct aim_session_t *sess, struct command_rx_struct *command, ...);
+int faimtest_chat_infoupdate(struct aim_session_t *sess, struct command_rx_struct *command, ...);
+int faimtest_chat_leave(struct aim_session_t *sess, struct command_rx_struct *command, ...);
+int faimtest_chat_join(struct aim_session_t *sess, struct command_rx_struct *command, ...);
static char *screenname,*password;
aim_bos_setgroupperm(sess, command->conn, 0x1f);
fprintf(stderr, "faimtest: done with BOS ServerReady\n");
break;
+
case AIM_CONN_TYPE_CHATNAV:
fprintf(stderr, "faimtest: chatnav: got server ready\n");
+ aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CTN, AIM_CB_CTN_INFO, faimtest_chatnav_info, 0);
+ aim_bos_reqrate(sess, command->conn);
+ aim_bos_ackrateresp(sess, command->conn);
+ aim_chatnav_clientready(sess, command->conn);
+ aim_chatnav_reqrights(sess, command->conn);
+
+ break;
+ case AIM_CONN_TYPE_CHAT:
+ aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERJOIN, faimtest_chat_join, 0);
+ aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERLEAVE, faimtest_chat_leave, 0);
+ aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_ROOMINFOUPDATE, faimtest_chat_infoupdate, 0);
+ aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_INCOMINGMSG, faimtest_chat_incomingmsg, 0);
+ aim_bos_reqrate(sess, command->conn);
+ aim_bos_ackrateresp(sess, command->conn);
+ aim_chat_clientready(sess, command->conn);
break;
default:
fprintf(stderr, "faimtest: unknown connection type on Server Ready\n");
char *cookie;
/* this is the new buddy list */
- char buddies[] = "Buddy1&Buddy2&";
+ char buddies[] = "Buddy1&Buddy2&ThisHereIsAName2&";
/* this is the new profile */
char profile[] = "Hello";
serviceid = va_arg(ap, int);
ip = va_arg(ap, char *);
cookie = va_arg(ap, char *);
- va_end(ap);
-
+
switch(serviceid)
{
case 0x0005: /* Advertisements */
/* send the buddy list and profile (required, even if empty) */
aim_bos_setbuddylist(sess, command->conn, buddies);
- aim_bos_setprofile(sess, command->conn, profile);
+ aim_bos_setprofile(sess, command->conn, profile, NULL);
/* send final login command (required) */
aim_bos_clientready(sess, command->conn); /* tell BOS we're ready to go live */
fprintf(stderr, "faimtest: unable to connect to chatnav server\n");
return 1;
}
+#if 0
aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_CTN, AIM_CB_SPECIAL_DEFAULT, aim_parse_unknown, 0);
aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_GEN, AIM_CB_SPECIAL_DEFAULT, aim_parse_unknown, 0);
+#endif
+ aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, faimtest_serverready, 0);
aim_auth_sendcookie(sess, tstconn, cookie);
fprintf(stderr, "\achatnav: connected\n");
}
break;
case 0x000e: /* Chat */
{
-#if 0
+ char *roomname = NULL;
struct aim_conn_t *tstconn = NULL;
+
+ roomname = va_arg(ap, char *);
+
tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHAT, ip);
if ( (tstconn==NULL) || (tstconn->status >= AIM_CONN_STATUS_RESOLVERR))
{
fprintf(stderr, "faimtest: unable to connect to chat server\n");
return 1;
- }
- aim_auth_sendcookie(sess, aim_getconn_type(sess, AIM_CONN_TYPE_CHAT), cookie);
- fprintf(stderr, "\achat: connected\n");
-#endif
+ }
+ printf("faimtest: chat: connected\n");
+
+ /*
+ * We must do this to attach the stored name to the connection!
+ */
+ aim_chat_attachname(tstconn, roomname);
+
+ aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, faimtest_serverready, 0);
+ aim_auth_sendcookie(sess, tstconn, cookie);
}
break;
default:
/* dunno */
}
- return 1;
-}
-
-#if 0
-int faimtest_auth_error(struct aim_session_t *sess, struct command_rx_struct *command, ...)
-{
- va_list ap;
- char *errorurl;
- short errorcode;
-
- va_start(ap, command);
- printf("Screen name: %s\n", sess->logininfo.screen_name);
- errorurl = va_arg(ap, char *);
- printf("Error URL: %s\n", errorurl);
- errorcode = va_arg(ap, short);
- printf("Error code: 0x%02x\n", errorcode);
va_end(ap);
- aim_conn_close(aim_getconn_type(sess, AIM_CONN_TYPE_AUTH));
- exit(0);
-
- return 0;
+ return 1;
}
-#endif
int faimtest_parse_authresp(struct aim_session_t *sess, struct command_rx_struct *command, ...)
{
printf("faimtest: icbm: sending response\n");
aim_send_im(sess, command->conn, userinfo->sn, 0, "Good day to you too.");
}
-#if 0
- else if (!strncmp(tmpstr, "joinchat", 8))
+ else if (!strncmp(tmpstr, "open chatnav", 12))
{
- aim_chat_join(sess, command->conn, "GoodDay");
+ aim_bos_reqservice(sess, command->conn, AIM_CONN_TYPE_CHATNAV);
+ //aim_chat_join(sess, command->conn, "thishereisaname2_chat85");
}
-#endif
+ else if (!strncmp(tmpstr, "create", 6))
+ {
+ aim_chatnav_createroom(sess, aim_getconn_type(sess, AIM_CONN_TYPE_CHATNAV), "WorldDomination", 0x0004);
+ }
+ else if (!strncmp(tmpstr, "close chatnav", 13))
+ aim_conn_close(aim_getconn_type(sess, AIM_CONN_TYPE_CHATNAV));
+ else if (!strncmp(tmpstr, "join", 4))
+ {
+ aim_chat_join(sess, command->conn, 0x0004, "worlddomination");
+ }
+ else if (!strncmp(tmpstr, "leave", 5))
+ aim_chat_leaveroom(sess, "worlddomination");
else
{
#if 0
}
}
/*
- * Channel 2: Chat Invitation
+ * Channel 2: Rendevous Request
*/
else if (channel == 2)
{
struct aim_userinfo_s *userinfo;
- char *roomname,*msg,*encoding,*lang;
- u_short exchange, instance;
+ int rendtype = 0;
- userinfo = va_arg(ap, struct aim_userinfo_s *);
- roomname = va_arg(ap, char *);
- msg = va_arg(ap, char *);
- encoding = va_arg(ap, char *);
- lang = va_arg(ap, char *);
- exchange = va_arg(ap, u_short);
- instance = va_arg(ap, u_short);
- va_end(ap);
-
- printf("faimtest: chat invitation: source sn = %s\n", userinfo->sn);
- printf("faimtest: chat invitation: \twarnlevel = 0x%04x\n", userinfo->warnlevel);
- printf("faimtest: chat invitation: \tclass = 0x%04x ", userinfo->class);
- if (userinfo->class & 0x0010)
- printf("(FREE) ");
- if (userinfo->class & 0x0001)
- printf("(TRIAL) ");
- if (userinfo->class & 0x0004)
- printf("(AOL) ");
- printf("\n");
- /* we dont get membersince on chat invites! */
- printf("faimtest: chat invitation: \tonlinesince = %lu\n", userinfo->onlinesince);
- printf("faimtest: chat invitation: \tidletime = 0x%04x\n", userinfo->idletime);
-
- printf("faimtest: chat invitation: message = %s\n", msg);
- printf("faimtest: chat invitation: room name = %s\n", roomname);
- printf("faimtest: chat invitation: encoding = %s\n", encoding);
- printf("faimtest: chat invitation: language = %s\n", lang);
- printf("faimtest: chat invitation: exchange = 0x%04x\n", exchange);
- printf("faimtest: chat invitation: instance = 0x%04x\n", instance);
+ rendtype = va_arg(ap, int);
+ if (rendtype == 0)
+ {
+ char *msg,*encoding,*lang;
+ struct aim_chat_roominfo *roominfo;
+
+ userinfo = va_arg(ap, struct aim_userinfo_s *);
+ roominfo = va_arg(ap, struct aim_chat_roominfo *);
+ msg = va_arg(ap, char *);
+ encoding = va_arg(ap, char *);
+ lang = va_arg(ap, char *);
+ va_end(ap);
+
+ printf("faimtest: chat invitation: source sn = %s\n", userinfo->sn);
+ printf("faimtest: chat invitation: \twarnlevel = 0x%04x\n", userinfo->warnlevel);
+ printf("faimtest: chat invitation: \tclass = 0x%04x ", userinfo->class);
+ if (userinfo->class & 0x0010)
+ printf("(FREE) ");
+ if (userinfo->class & 0x0001)
+ printf("(TRIAL) ");
+ if (userinfo->class & 0x0004)
+ printf("(AOL) ");
+ printf("\n");
+ /* we dont get membersince on chat invites! */
+ printf("faimtest: chat invitation: \tonlinesince = %lu\n", userinfo->onlinesince);
+ printf("faimtest: chat invitation: \tidletime = 0x%04x\n", userinfo->idletime);
+
+ printf("faimtest: chat invitation: message = %s\n", msg);
+ printf("faimtest: chat invitation: room name = %s\n", roominfo->name);
+ printf("faimtest: chat invitation: encoding = %s\n", encoding);
+ printf("faimtest: chat invitation: language = %s\n", lang);
+ printf("faimtest: chat invitation: exchange = 0x%04x\n", roominfo->exchange);
+ printf("faimtest: chat invitation: instance = 0x%04x\n", roominfo->instance);
+ printf("faimtest: chat invitiation: autojoining %s...\n", roominfo->name);
+ /*
+ * Automatically join room...
+ */
+ aim_chat_join(sess, command->conn, 0x0004, roominfo->name);
+ }
+ else if (rendtype == 1)
+ {
+ userinfo = va_arg(ap, struct aim_userinfo_s *);
+ va_end(ap);
+
+ printf("faimtest: voice invitation: source sn = %s\n", userinfo->sn);
+ printf("faimtest: voice invitation: \twarnlevel = 0x%04x\n", userinfo->warnlevel);
+ printf("faimtest: voice invitation: \tclass = 0x%04x ", userinfo->class);
+ if (userinfo->class & 0x0010)
+ printf("(FREE) ");
+ if (userinfo->class & 0x0001)
+ printf("(TRIAL) ");
+ if (userinfo->class & 0x0004)
+ printf("(AOL) ");
+ printf("\n");
+ /* we dont get membersince on chat invites! */
+ printf("faimtest: voice invitation: \tonlinesince = %lu\n", userinfo->onlinesince);
+ printf("faimtest: voice invitation: \tidletime = 0x%04x\n", userinfo->idletime);
+
+ }
+ else
+ printf("faimtest: icbm: unknown rendtype (%d)\n", rendtype);
}
else
printf("faimtest does not support channels > 2 (chan = %02x)\n", channel);
userinfo = va_arg(ap, struct aim_userinfo_s *);
va_end(ap);
- printf("\n%s is now online\n", userinfo->sn);
+ printf("\n%s is now online (class: %04x = %s%s%s%s%s%s%s%s)\n", userinfo->sn, userinfo->class,
+ (userinfo->class&AIM_CLASS_TRIAL)?" TRIAL":"",
+ (userinfo->class&AIM_CLASS_UNKNOWN2)?" UNKNOWN2":"",
+ (userinfo->class&AIM_CLASS_AOL)?" AOL":"",
+ (userinfo->class&AIM_CLASS_UNKNOWN4)?" UNKNOWN4":"",
+ (userinfo->class&AIM_CLASS_FREE)?" FREE":"",
+ (userinfo->class&AIM_CLASS_AWAY)?" AWAY":"",
+ (userinfo->class&AIM_CLASS_UNKNOWN40)?" UNKNOWN40":"",
+ (userinfo->class&AIM_CLASS_UNKNOWN80)?" UNKNOWN80":"");
return 1;
}
return 1;
}
#endif
+
+int faimtest_chat_join(struct aim_session_t *sess, struct command_rx_struct *command, ...)
+{
+ va_list ap;
+ struct aim_userinfo_s *userinfo;
+ int count = 0, i = 0;
+
+ va_start(ap, command);
+ count = va_arg(ap, int);
+ userinfo = va_arg(ap, struct aim_userinfo_s *);
+ va_end(ap);
+
+ printf("faimtest: chat: %s: New occupants have joined:\n", (char *)command->conn->priv);
+ while (i < count)
+ printf("faimtest: chat: %s: \t%s\n", (char *)command->conn->priv, userinfo[i++].sn);
+
+ return 1;
+}
+
+int faimtest_chat_leave(struct aim_session_t *sess, struct command_rx_struct *command, ...)
+{
+ va_list ap;
+ struct aim_userinfo_s *userinfo;
+ int count = 0, i = 0;
+
+ va_start(ap, command);
+ count = va_arg(ap, int);
+ userinfo = va_arg(ap, struct aim_userinfo_s *);
+ va_end(ap);
+
+ printf("faimtest: chat: %s: Some occupants have left:\n", (char *)command->conn->priv);
+ while (i < count)
+ printf("faimtest: chat: %s: \t%s\n", (char *)command->conn->priv, userinfo[i++].sn);
+
+ return 1;
+}
+
+int faimtest_chat_infoupdate(struct aim_session_t *sess, struct command_rx_struct *command, ...)
+{
+ va_list ap;
+ struct aim_userinfo_s *userinfo;
+ struct aim_chat_roominfo *roominfo;
+ char *roomname;
+ int usercount,i;
+ char *roomdesc;
+
+ va_start(ap, command);
+ roominfo = va_arg(ap, struct aim_chat_roominfo *);
+ roomname = va_arg(ap, char *);
+ usercount= va_arg(ap, int);
+ userinfo = va_arg(ap, struct aim_userinfo_s *);
+ roomdesc = va_arg(ap, char *);
+ va_end(ap);
+
+ printf("faimtest: chat: %s: info update:\n", (char *)command->conn->priv);
+ printf("faimtest: chat: %s: \tRoominfo: {%04x, %s, %04x}\n",
+ (char *)command->conn->priv,
+ roominfo->exchange,
+ roominfo->name,
+ roominfo->instance);
+ printf("faimtest: chat: %s: \tRoomname: %s\n", (char *)command->conn->priv, roomname);
+ printf("faimtest: chat: %s: \tRoomdesc: %s\n", (char *)command->conn->priv, roomdesc);
+ printf("faimtest: chat: %s: \tOccupants: (%d)\n", (char *)command->conn->priv, usercount);
+
+ i = 0;
+ while (i < usercount)
+ printf("faimtest: chat: %s: \t\t%s\n", (char *)command->conn->priv, userinfo[i++].sn);
+
+ return 1;
+}
+
+int faimtest_chat_incomingmsg(struct aim_session_t *sess, struct command_rx_struct *command, ...)
+{
+ va_list ap;
+ struct aim_userinfo_s *userinfo;
+ char *msg;
+ char tmpbuf[1152];
+
+ va_start(ap, command);
+ userinfo = va_arg(ap, struct aim_userinfo_s *);
+ msg = va_arg(ap, char *);
+ va_end(ap);
+
+ printf("faimtest: chat: %s: incoming msg from %s: %s\n", (char *)command->conn->priv, userinfo->sn, msg);
+
+ /*
+ * Do an echo for testing purposes. But not for ourselves ("oops!")
+ */
+ if (strcmp(userinfo->sn, sess->logininfo.screen_name) != 0)
+ {
+ sprintf(tmpbuf, "(%s said \"%s\")", userinfo->sn, msg);
+ aim_chat_send_im(sess, command->conn, tmpbuf);
+ }
+
+ return 1;
+}
+
+int faimtest_chatnav_info(struct aim_session_t *sess, struct command_rx_struct *command, ...)
+{
+ u_short type;
+ va_list ap;
+
+ ap = va_start(ap, command);
+ type = va_arg(ap, u_short);
+
+ switch(type)
+ {
+ case 0x0002:
+ {
+ int maxrooms;
+ struct aim_chat_exchangeinfo *exchanges;
+ int exchangecount,i = 0;
+
+ maxrooms = va_arg(ap, u_char);
+ exchangecount = va_arg(ap, int);
+ exchanges = va_arg(ap, struct aim_chat_exchangeinfo *);
+ va_end(ap);
+
+ printf("faimtest: chat info: Chat Rights:\n");
+ printf("faimtest: chat info: \tMax Concurrent Rooms: %d\n", maxrooms);
+
+ printf("faimtest: chat info: \tExchange List: (%d total)\n", exchangecount);
+ while (i < exchangecount)
+ {
+ printf("faimtest: chat info: \t\t%x: %s (%s/%s)\n",
+ exchanges[i].number,
+ exchanges[i].name,
+ exchanges[i].charset1,
+ exchanges[i].lang1);
+ i++;
+ }
+
+ }
+ break;
+ default:
+ va_end(ap);
+ printf("faimtest: chatnav info: unknown type (%04x)\n", type);
+ }
+ return 1;
+}