From: mid Date: Sun, 3 Sep 2000 01:45:35 +0000 (+0000) Subject: - Sat Sep 2 23:42:37 UTC 2000 X-Git-Tag: rel_0_99_2~120 X-Git-Url: http://andersk.mit.edu/gitweb/libfaim.git/commitdiff_plain/96f8b1edd2c6bb991cb4fec0a5bef6570ceb502f - Sat Sep 2 23:42:37 UTC 2000 - Hopefully fix aim_snac.c bugs - Add Buddy List Rights parser (max buddies and max watchers) - Fix rather major problem in rxhandlers caused by missing breaks - Add reason code for msgerr (0004/0001) callback - Add BOS Rights parser (max permit / max deny) - Add locate error (0002/0001) parser - Add parser for missed calls (0004/000a) --- diff --git a/CHANGES b/CHANGES index 87eecb0..4b57c98 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,15 @@ No release numbers ------------------ + - Sat Sep 2 23:42:37 UTC 2000 + - Hopefully fix aim_snac.c bugs + - Add Buddy List Rights parser (max buddies and max watchers) + - Fix rather major problem in rxhandlers caused by missing breaks + - Add reason code for msgerr (0004/0001) callback + - Add BOS Rights parser (max permit / max deny) + - Add locate error (0002/0001) parser + - Add parser for missed calls (0004/000a) + - Fri Sep 1 23:34:28 UTC 2000 - Switched the read()s in rxqueue to use recv() - Should fix the big message problem and the big buddy list problem diff --git a/aim_buddylist.c b/aim_buddylist.c index 6947931..d043a56 100644 --- a/aim_buddylist.c +++ b/aim_buddylist.c @@ -86,3 +86,43 @@ u_long aim_remove_buddy(struct aim_session_t *sess, return( sess->snac_nextid++ ); } +int aim_parse_buddyrights(struct aim_session_t *sess, + struct command_rx_struct *command, ...) +{ + rxcallback_t userfunc = NULL; + int ret=1; + struct aim_tlvlist_t *tlvlist; + struct aim_tlv_t *tlv; + unsigned short maxbuddies = 0, maxwatchers = 0; + + /* + * TLVs follow + */ + if (!(tlvlist = aim_readtlvchain(command->data+10, command->commandlen-10))) + return ret; + + /* + * TLV type 0x0001: Maximum number of buddies. + */ + if ((tlv = aim_gettlv(tlvlist, 0x0001, 1))) { + maxbuddies = aimutil_get16(tlv->value); + } + + /* + * TLV type 0x0002: Maximum number of watchers. + * + * XXX: what the hell is a watcher? + * + */ + if ((tlv = aim_gettlv(tlvlist, 0x0002, 1))) { + maxwatchers = aimutil_get16(tlv->value); + } + + userfunc = aim_callhandler(command->conn, 0x0003, 0x0003); + if (userfunc) + ret = userfunc(sess, command, maxbuddies, maxwatchers); + + aim_freetlvchain(&tlvlist); + + return ret; +} diff --git a/aim_im.c b/aim_im.c index 531e018..f316192 100644 --- a/aim_im.c +++ b/aim_im.c @@ -856,6 +856,8 @@ int aim_parse_msgerror_middle(struct aim_session_t *sess, struct aim_snac_t *snac = NULL; int ret = 0; rxcallback_t userfunc = NULL; + char *dest; + unsigned short reason = 0; /* * Get SNAC from packet and look it up @@ -872,14 +874,18 @@ int aim_parse_msgerror_middle(struct aim_session_t *sess, if (!snac) { printf("faim: msgerr: got an ICBM-failed error on an unknown SNAC ID! (%08lx)\n", snacid); - } + dest = NULL; + } else + dest = snac->data; + + reason = aimutil_get16(command->data+10); /* * Call client. */ userfunc = aim_callhandler(command->conn, 0x0004, 0x0001); if (userfunc) - ret = userfunc(sess, command, (snac)?snac->data:"(UNKNOWN)"); + ret = userfunc(sess, command, dest, reason); else ret = 0; @@ -892,3 +898,47 @@ int aim_parse_msgerror_middle(struct aim_session_t *sess, } +int aim_parse_missedcall(struct aim_session_t *sess, + struct command_rx_struct *command) +{ + int i, ret = 1; + rxcallback_t userfunc = NULL; + unsigned short channel, nummissed, reason; + struct aim_userinfo_s userinfo; + + i = 10; /* Skip SNAC header */ + + + /* + * XXX: supposedly, this entire packet can repeat as many times + * as necessary. Should implement that. + */ + + /* + * Channel ID. + */ + channel = aimutil_get16(command->data+i); + i += 2; + + /* + * Extract the standard user info block. + */ + i += aim_extractuserinfo(command->data+i, &userinfo); + + nummissed = aimutil_get16(command->data+i); + i += 2; + + reason = aimutil_get16(command->data+i); + i += 2; + + /* + * Call client. + */ + userfunc = aim_callhandler(command->conn, 0x0004, 0x000a); + if (userfunc) + ret = userfunc(sess, command, channel, &userinfo, nummissed, reason); + else + ret = 0; + + return ret; +} diff --git a/aim_info.c b/aim_info.c index 8015916..fcf1195 100644 --- a/aim_info.c +++ b/aim_info.c @@ -57,6 +57,49 @@ u_long aim_getinfo(struct aim_session_t *sess, return (sess->snac_nextid++); } +int aim_parse_locateerr(struct aim_session_t *sess, + struct command_rx_struct *command) +{ + u_long snacid = 0x000000000; + struct aim_snac_t *snac = NULL; + int ret = 0; + rxcallback_t userfunc = NULL; + char *dest; + unsigned short reason = 0; + + /* + * Get SNAC from packet and look it up + * the list of unrepliedto/outstanding + * SNACs. + * + */ + snacid = aimutil_get32(command->data+6); + snac = aim_remsnac(sess, snacid); + + if (!snac) { + printf("faim: locerr: got an locate-failed error on an unknown SNAC ID! (%08lx)\n", snacid); + dest = NULL; + } else + dest = snac->data; + + reason = aimutil_get16(command->data+10); + + /* + * Call client. + */ + userfunc = aim_callhandler(command->conn, 0x0002, 0x0001); + if (userfunc) + ret = userfunc(sess, command, dest, reason); + else + ret = 0; + + if (snac) { + free(snac->data); + free(snac); + } + + return ret; +} /* * Capability blocks. diff --git a/aim_misc.c b/aim_misc.c index 4b38852..eddf377 100644 --- a/aim_misc.c +++ b/aim_misc.c @@ -260,6 +260,45 @@ u_long aim_bos_setgroupperm(struct aim_session_t *sess, return aim_genericreq_l(sess, conn, 0x0009, 0x0004, &mask); } +int aim_parse_bosrights(struct aim_session_t *sess, + struct command_rx_struct *command, ...) +{ + rxcallback_t userfunc = NULL; + int ret=1; + struct aim_tlvlist_t *tlvlist; + struct aim_tlv_t *tlv; + unsigned short maxpermits = 0, maxdenies = 0; + + /* + * TLVs follow + */ + if (!(tlvlist = aim_readtlvchain(command->data+10, command->commandlen-10))) + return ret; + + /* + * TLV type 0x0001: Maximum number of buddies on permit list. + */ + if ((tlv = aim_gettlv(tlvlist, 0x0001, 1))) { + maxpermits = aimutil_get16(tlv->value); + } + + /* + * TLV type 0x0002: Maximum number of buddies on deny list. + * + */ + if ((tlv = aim_gettlv(tlvlist, 0x0002, 1))) { + maxdenies = aimutil_get16(tlv->value); + } + + userfunc = aim_callhandler(command->conn, 0x0009, 0x0003); + if (userfunc) + ret = userfunc(sess, command, maxpermits, maxdenies); + + aim_freetlvchain(&tlvlist); + + return ret; +} + /* * aim_bos_clientready() * diff --git a/aim_rxhandlers.c b/aim_rxhandlers.c index aaeba3b..4e76e2a 100644 --- a/aim_rxhandlers.c +++ b/aim_rxhandlers.c @@ -431,10 +431,11 @@ int aim_rxdispatch(struct aim_session_t *sess) workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_GEN, AIM_CB_GEN_DEFAULT, workingPtr); break; } + break; case 0x0002: /* Family: Location */ switch (subtype) { case 0x0001: - workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0002, 0x0001, workingPtr); + workingPtr->handled = aim_parse_locateerr(sess, workingPtr); break; case 0x0003: workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0002, 0x0003, workingPtr); @@ -446,13 +447,14 @@ int aim_rxdispatch(struct aim_session_t *sess) workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_LOC, AIM_CB_LOC_DEFAULT, workingPtr); break; } + break; case 0x0003: /* Family: Buddy List */ switch (subtype) { case 0x0001: workingPtr->handled = aim_parse_generalerrs(sess, workingPtr); break; case 0x0003: - workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0003, 0x0003, workingPtr); + workingPtr->handled = aim_parse_buddyrights(sess, workingPtr); break; case 0x000b: /* oncoming buddy */ workingPtr->handled = aim_parse_oncoming_middle(sess, workingPtr); @@ -479,7 +481,7 @@ int aim_rxdispatch(struct aim_session_t *sess) workingPtr->handled = aim_parse_incoming_im_middle(sess, workingPtr); break; case 0x000a: - workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0004, 0x000a, workingPtr); + workingPtr->handled = aim_parse_missedcall(sess, workingPtr); break; case 0x000c: workingPtr->handled = aim_parse_msgack_middle(sess, workingPtr); @@ -492,7 +494,7 @@ int aim_rxdispatch(struct aim_session_t *sess) if (subtype == 0x0001) workingPtr->handled = aim_parse_generalerrs(sess, workingPtr); else if (subtype == 0x0003) - workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0009, 0x0003, workingPtr); + workingPtr->handled = aim_parse_bosrights(sess, workingPtr); else workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_BOS, AIM_CB_BOS_DEFAULT, workingPtr); break; @@ -508,7 +510,7 @@ int aim_rxdispatch(struct aim_session_t *sess) workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_LOK, AIM_CB_LOK_DEFAULT, workingPtr); } break; - case 0x000b: + case 0x000b: { if (subtype == 0x0001) workingPtr->handled = aim_parse_generalerrs(sess, workingPtr); else if (subtype == 0x0002) @@ -516,15 +518,16 @@ int aim_rxdispatch(struct aim_session_t *sess) else workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_STS, AIM_CB_STS_DEFAULT, workingPtr); break; - case AIM_CB_FAM_SPECIAL: - workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr); - break; + } + case AIM_CB_FAM_SPECIAL: + workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr); + break; default: workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr); break; - } + } /* switch(family) */ break; - } + } /* AIM_CONN_TYPE_BOS */ case AIM_CONN_TYPE_CHATNAV: { u_short family; u_short subtype; diff --git a/aim_rxqueue.c b/aim_rxqueue.c index 9d8dd7f..72f4481 100644 --- a/aim_rxqueue.c +++ b/aim_rxqueue.c @@ -42,7 +42,6 @@ int aim_get_command(struct aim_session_t *sess, struct aim_conn_t *conn) */ faim_mutex_lock(&conn->active); if (recv(conn->fd, generic, 6, MSG_WAITALL) < 6){ - printf("faim: flap: read underflow (header)\n"); aim_conn_close(conn); faim_mutex_unlock(&conn->active); return -1; @@ -91,7 +90,6 @@ int aim_get_command(struct aim_session_t *sess, struct aim_conn_t *conn) /* read the data portion of the packet */ if (recv(conn->fd, newrx->data, newrx->commandlen, MSG_WAITALL) < newrx->commandlen){ - printf("faim: flap: read underflow (payload)\n"); free(newrx->data); free(newrx); aim_conn_close(conn); diff --git a/aim_snac.c b/aim_snac.c index 2a44674..dd87849 100644 --- a/aim_snac.c +++ b/aim_snac.c @@ -37,7 +37,7 @@ void aim_initsnachash(struct aim_session_t *sess) u_long aim_newsnac(struct aim_session_t *sess, struct aim_snac_t *newsnac) { - struct aim_snac_t *snac = NULL, *cur = NULL; + struct aim_snac_t *snac = NULL; int index; if (!newsnac) @@ -56,6 +56,8 @@ u_long aim_newsnac(struct aim_session_t *sess, sess->snac_hash[index] = snac; faim_mutex_unlock(&sess->snac_hash_locks[index]); + printf("faim: cached snac %lx\n", snac->id); + return(snac->id); } @@ -69,7 +71,7 @@ u_long aim_newsnac(struct aim_session_t *sess, struct aim_snac_t *aim_remsnac(struct aim_session_t *sess, u_long id) { - struct aim_snac_t *cur; + struct aim_snac_t *cur = NULL; int index; index = id % FAIM_SNAC_HASH_SIZE; @@ -77,11 +79,9 @@ struct aim_snac_t *aim_remsnac(struct aim_session_t *sess, faim_mutex_lock(&sess->snac_hash_locks[index]); if (!sess->snac_hash[index]) ; - else if (!sess->snac_hash[index]->next) { - if (sess->snac_hash[index]->id == id) { - cur = sess->snac_hash[index]; - sess->snac_hash[index] = NULL; - } + else if (sess->snac_hash[index]->id == id) { + cur = sess->snac_hash[index]; + sess->snac_hash[index] = cur->next; } else { cur = sess->snac_hash[index]; while (cur->next) { @@ -111,36 +111,41 @@ struct aim_snac_t *aim_remsnac(struct aim_session_t *sess, int aim_cleansnacs(struct aim_session_t *sess, int maxage) { - struct aim_snac_t *cur; - struct aim_snac_t *remed = NULL; + struct aim_snac_t *cur, *next, *prev = NULL; time_t curtime; int i; for (i = 0; i < FAIM_SNAC_HASH_SIZE; i++) { faim_mutex_lock(&sess->snac_hash_locks[i]); - if (!sess->snac_hash[i]) - ; - else if (!sess->snac_hash[i]->next) { - if ((sess->snac_hash[i]->issuetime + maxage) >= curtime) { - remed = sess->snac_hash[i]; - if(remed->data) - free(remed->data); - free(remed); - sess->snac_hash[i] = NULL; - } - } else { - cur = sess->snac_hash[i]; - while(cur && cur->next) { - if ((cur->next->issuetime + maxage) >= curtime) { - remed = cur->next; - cur->next = cur->next->next; - if (remed->data) - free(remed->data); - free(remed); - } - cur = cur->next; + if (!sess->snac_hash[i]) { + faim_mutex_unlock(&sess->snac_hash_locks[i]); + continue; + } + + curtime = time(NULL); /* done here in case we waited for the lock */ + + cur = sess->snac_hash[i]; + while (cur) { + next = cur->next; + if ((curtime - cur->issuetime) > maxage) { + if (sess->snac_hash[i] == cur) + prev = sess->snac_hash[i] = next; + else + prev->next = next; + + printf("faim: killing ancient snac %lx (%lx)\n", cur->id, curtime - cur->issuetime); + + /* XXX should we have destructors here? */ + if (cur->data) + free(cur->data); + free(cur); + + } else { + prev = cur; } + cur = next; } + faim_mutex_unlock(&sess->snac_hash_locks[i]); } diff --git a/faim/aim.h b/faim/aim.h index f5f5603..0327561 100644 --- a/faim/aim.h +++ b/faim/aim.h @@ -544,6 +544,8 @@ int aim_parse_outgoing_im_middle(struct aim_session_t *, struct command_rx_struc u_long aim_seticbmparam(struct aim_session_t *, struct aim_conn_t *conn); int aim_parse_msgerror_middle(struct aim_session_t *, struct command_rx_struct *); int aim_negchan_middle(struct aim_session_t *sess, struct command_rx_struct *command); +int aim_parse_bosrights(struct aim_session_t *sess, struct command_rx_struct *command, ...); +int aim_parse_missedcall(struct aim_session_t *sess, struct command_rx_struct *command); struct aim_conn_t * aim_directim_initiate(struct aim_session_t *, struct aim_conn_t *, struct aim_directim_priv *, char *); int aim_send_im_direct(struct aim_session_t *, struct aim_conn_t *, char *); @@ -654,7 +656,7 @@ int aim_parse_offgoing_middle(struct aim_session_t *, struct command_rx_struct * int aim_putuserinfo(u_char *buf, int buflen, struct aim_userinfo_s *info); int aim_sendbuddyoncoming(struct aim_session_t *sess, struct aim_conn_t *conn, struct aim_userinfo_s *info); int aim_sendbuddyoffgoing(struct aim_session_t *sess, struct aim_conn_t *conn, char *sn); - +int aim_parse_locateerr(struct aim_session_t *sess, struct command_rx_struct *command); /* aim_auth.c */ int aim_auth_sendcookie(struct aim_session_t *, struct aim_conn_t *, u_char *); @@ -664,6 +666,7 @@ u_long aim_auth_changepasswd(struct aim_session_t *, struct aim_conn_t *, char * /* aim_buddylist.c */ u_long aim_add_buddy(struct aim_session_t *, struct aim_conn_t *, char *); u_long aim_remove_buddy(struct aim_session_t *, struct aim_conn_t *, char *); +int aim_parse_buddyrights(struct aim_session_t *sess, struct command_rx_struct *command, ...); /* aim_search.c */ u_long aim_usersearch_address(struct aim_session_t *, struct aim_conn_t *, char *); diff --git a/utils/faimtest/faimtest.c b/utils/faimtest/faimtest.c index 7ebb441..a6e3cbf 100644 --- a/utils/faimtest/faimtest.c +++ b/utils/faimtest/faimtest.c @@ -76,6 +76,37 @@ int faimtest_directim_disconnect(struct aim_session_t *sess, struct command_rx_s int faimtest_directim_typing(struct aim_session_t *sess, struct command_rx_struct *command, ...); int faimtest_parse_ratechange(struct aim_session_t *sess, struct command_rx_struct *command, ...); int faimtest_parse_evilnotify(struct aim_session_t *sess, struct command_rx_struct *command, ...); +int faimtest_parse_msgerr(struct aim_session_t *sess, struct command_rx_struct *command, ...); +int faimtest_parse_buddyrights(struct aim_session_t *sess, struct command_rx_struct *command, ...); +int faimtest_parse_locerr(struct aim_session_t *sess, struct command_rx_struct *command, ...); + +static char *msgerrreasons[] = { + "Invalid error", + "Invalid SNAC", + "Rate to host", + "Rate to client", + "Not logged on", + "Service unavailable", + "Service not defined", + "Obsolete SNAC", + "Not supported by host", + "Not supported by client", + "Refused by client", + "Reply too big", + "Responses lost", + "Request denied", + "Busted SNAC payload", + "Insufficient rights", + "In local permit/deny", + "Too evil (sender)", + "Too evil (receiver)", + "User temporarily unavailable", + "No match", + "List overflow", + "Request ambiguous", + "Queue full", + "Not while on AOL"}; +static int msgerrreasonslen = 25; int faimtest_reportinterval(struct aim_session_t *sess, struct command_rx_struct *command, ...) { @@ -261,8 +292,33 @@ int faimtest_serverready(struct aim_session_t *sess, struct command_rx_struct *c return 1; } +int faimtest_parse_buddyrights(struct aim_session_t *sess, struct command_rx_struct *command, ...) +{ + va_list ap; + unsigned short maxbuddies, maxwatchers; + + va_start(ap, command); + maxbuddies = va_arg(ap, unsigned short); + maxwatchers = va_arg(ap, unsigned short); + va_end(ap); + + printf("faimtest: buddy list rights: Max buddies = %d / Max watchers = %d\n", maxbuddies, maxwatchers); + + return 1; +} + int faimtest_bosrights(struct aim_session_t *sess, struct command_rx_struct *command, ...) { + unsigned short maxpermits, maxdenies; + va_list ap; + + va_start(ap, command); + maxpermits = va_arg(ap, unsigned short); + maxdenies = va_arg(ap, unsigned short); + va_end(ap); + + printf("faimtest: BOS rights: Max permit = %d / Max deny = %d\n", maxpermits, maxdenies); + aim_bos_clientready(sess, command->conn); printf("faimtest: officially connected to BOS.\n"); @@ -403,14 +459,15 @@ int faimtest_parse_authresp(struct aim_session_t *sess, struct command_rx_struct aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATEINFO, NULL, 0); aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_REDIRECT, faimtest_handleredirect, 0); aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_STS, AIM_CB_STS_SETREPORTINTERVAL, faimtest_reportinterval, 0); + aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_RIGHTSINFO, faimtest_parse_buddyrights, 0); aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_ONCOMING, faimtest_parse_oncoming, 0); aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_OFFGOING, faimtest_parse_offgoing, 0); aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING, faimtest_parse_incoming_im, 0); - aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_ERROR, faimtest_parse_misses, 0); + aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_ERROR, faimtest_parse_locerr, 0); aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_MISSEDCALL, faimtest_parse_misses, 0); aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATECHANGE, faimtest_parse_ratechange, 0); aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_EVIL, faimtest_parse_evilnotify, 0); - aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ERROR, faimtest_parse_misses, 0); + aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ERROR, faimtest_parse_msgerr, 0); aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO, faimtest_parse_userinfo, 0); aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ACK, faimtest_parse_msgack, 0); @@ -599,6 +656,8 @@ int faimtest_parse_incoming_im(struct aim_session_t *sess, struct command_rx_str struct aim_conn_t *newconn; newconn = aim_directim_initiate(sess, command->conn, NULL, userinfo->sn); //aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINITIATE, faimtest_directim_initiate, 0); + } else if (!strncmp(tmpstr, "reqsendmsg", 10)) { + aim_send_im(sess, command->conn, "vaxherder", 0, "sendmsg 7986"); } else if (!strncmp(tmpstr, "sendmsg", 7)) { int i; i = atoi(tmpstr+8); @@ -896,56 +955,84 @@ int faimtest_parse_offgoing(struct aim_session_t *sess, struct command_rx_struct int faimtest_parse_motd(struct aim_session_t *sess, struct command_rx_struct *command, ...) { + static char *codes[] = { + "Unknown", + "Mandatory upgrade", + "Advisory upgrade", + "System bulletin", + "Top o' the world!"}; + static int codeslen = 5; + char *msg; - u_short id; + unsigned short id; va_list ap; va_start(ap, command); - id = va_arg(ap, u_short); + id = va_arg(ap, unsigned short); msg = va_arg(ap, char *); va_end(ap); - printf("faimtest: motd: %s (%d)\n", msg, id); + printf("faimtest: motd: %s (%d / %s)\n", msg, id, + (id < codeslen)?codes[id]:"unknown"); + + return 1; +} + +int faimtest_parse_msgerr(struct aim_session_t *sess, struct command_rx_struct *command, ...) +{ + va_list ap; + char *destsn; + unsigned short reason; + + va_start(ap, command); + destsn = va_arg(ap, char *); + reason = va_arg(ap, unsigned short); + va_end(ap); + + printf("faimtest: message to %s bounced (reason 0x%04x: %s)\n", destsn, reason, (reasondata+0); - subtype= aimutil_get16(command->data+2); + va_list ap; + unsigned short chan, nummissed, reason; + struct aim_userinfo_s *userinfo; - switch (family) - { - case 0x0001: - if (subtype == 0x000a) /* or AIM_CB_RATECHANGE */ - printf("\n****STOP SENDING/RECIEVING MESSAGES SO FAST!****\n\n"); - break; - case 0x0002: - if (subtype == 0x0001) /* or AIM_CB_USERERROR */ - { - u_long snacid = 0x00000000; - - snacid = aimutil_get32(&command->data[6]); - - printf("Received unknown error in SNAC family 0x0002 (snacid = %08lx)\n", snacid); - } - break; - case 0x0004: - if (subtype == 0x0001) /* or AIM_CB_MISSED_IM */ - printf("\n***LAST IM DIDN\'T MAKE IT BECAUSE THE BUDDY IS NOT ONLINE***\n\n"); - else if (subtype == 0x000a) /* or AIM_CB_MISSED_CALL */ - printf("You missed some messages from %s because they were sent too fast\n", &(command->data[13])); - break; - } + va_start(ap, command); + chan = va_arg(ap, unsigned short); + userinfo = va_arg(ap, struct aim_userinfo_s *); + nummissed = va_arg(ap, unsigned short); + reason = va_arg(ap, unsigned short); + va_end(ap); + printf("faimtest: missed %d messages from %s (reason %d: %s)\n", nummissed, userinfo->sn, reason, (reason