+
+static int faimtest_parse_ratechange(aim_session_t *sess, aim_frame_t *fr, ...)
+{
+ static char *codes[5] = {
+ "invalid",
+ "change",
+ "warning",
+ "limit",
+ "limit cleared"
+ };
+ va_list ap;
+ fu16_t code, rateclass;
+ fu32_t windowsize, clear, alert, limit, disconnect;
+ fu32_t currentavg, maxavg;
+
+ va_start(ap, fr);
+
+ /* See code explanations below */
+ code = va_arg(ap, fu16_t);
+
+ /*
+ * See comments above aim_parse_ratechange_middle() in aim_rxhandlers.c.
+ */
+ rateclass = va_arg(ap, fu16_t);
+
+ /*
+ * Not sure what this is exactly. I think its the temporal
+ * relation factor (ie, how to make the rest of the numbers
+ * make sense in the real world).
+ */
+ windowsize = va_arg(ap, fu32_t);
+
+ /* Explained below */
+ clear = va_arg(ap, fu32_t);
+ alert = va_arg(ap, fu32_t);
+ limit = va_arg(ap, fu32_t);
+ disconnect = va_arg(ap, fu32_t);
+ currentavg = va_arg(ap, fu32_t);
+ maxavg = va_arg(ap, fu32_t);
+
+ va_end(ap);
+
+
+ dvprintf("faimtest: rate %s (rate class 0x%04x): curavg = %ld, maxavg = %ld, alert at %ld, clear warning at %ld, limit at %ld, disconnect at %ld (window size = %ld)\n",
+ (code < 5)?codes[code]:"invalid",
+ rateclass,
+ currentavg, maxavg,
+ alert, clear,
+ limit, disconnect,
+ windowsize);
+
+ if (code == AIM_RATE_CODE_CHANGE) {
+ /*
+ * Not real sure when these get sent.
+ */
+ if (currentavg >= clear)
+ aim_conn_setlatency(fr->conn, 0);
+
+ } else if (code == AIM_RATE_CODE_WARNING) {
+ /*
+ * We start getting WARNINGs the first time we go below the
+ * 'alert' limit (currentavg < alert) and they stop when
+ * either we pause long enough for currentavg to go above
+ * 'clear', or until we flood it bad enough to go below
+ * 'limit' (and start getting LIMITs instead) or even further
+ * and go below 'disconnect' and get disconnected completely
+ * (and won't be able to login right away either).
+ */
+ aim_conn_setlatency(fr->conn, windowsize/4); /* XXX this is bogus! */
+
+ } else if (code == AIM_RATE_CODE_LIMIT) {
+ /*
+ * When we hit LIMIT, messages will start getting dropped.
+ */
+ aim_conn_setlatency(fr->conn, windowsize/2); /* XXX this is bogus! */
+
+ } else if (code == AIM_RATE_CODE_CLEARLIMIT) {
+ /*
+ * The limit is cleared when curavg goes above 'clear'.
+ */
+ aim_conn_setlatency(fr->conn, 0);
+ }
+
+ return 1;
+}
+
+static int faimtest_parse_evilnotify(aim_session_t *sess, aim_frame_t *fr, ...)
+{
+ va_list ap;
+ fu16_t newevil;
+ struct aim_userinfo_s *userinfo;
+
+ va_start(ap, fr);
+ newevil = va_arg(ap, fu16_t);
+ userinfo = va_arg(ap, struct aim_userinfo_s *);
+ va_end(ap);
+
+ /*
+ * Evil Notifications that are lacking userinfo->sn are anon-warns
+ * if they are an evil increases, but are not warnings at all if its
+ * a decrease (its the natural backoff happening).
+ *
+ * newevil is passed as an int representing the new evil value times
+ * ten.
+ */
+ dvprintf("faimtest: evil level change: new value = %2.1f%% (caused by %s)\n", ((float)newevil)/10, (userinfo && strlen(userinfo->sn))?userinfo->sn:"anonymous");
+
+ return 1;
+}
+
+static int faimtest_parse_searchreply(aim_session_t *sess, aim_frame_t *fr, ...)
+{
+ va_list ap;
+ char *address, *SNs;
+ int i, num;
+
+ va_start(ap, fr);
+ address = va_arg(ap, char *);
+ num = va_arg(ap, int);
+ SNs = va_arg(ap, char *);
+ va_end(ap);
+
+ dvprintf("faimtest: E-Mail Search Results for %s: ", address);
+
+ for(i = 0; i < num; i++)
+ dvinlineprintf("%s, ", &SNs[i*(MAXSNLEN+1)]);
+ dinlineprintf("\n");
+
+ return 1;
+}
+
+static int faimtest_parse_searcherror(aim_session_t *sess, aim_frame_t *fr, ...)
+{
+ va_list ap;
+ char *address;
+
+ va_start(ap, fr);
+ address = va_arg(ap, char *);
+ va_end(ap);
+
+ dvprintf("faimtest: E-Mail Search Results for %s: No Results or Invalid Email\n", address);
+
+ return 1;
+}
+
+void addcb_bos(aim_session_t *sess, aim_conn_t *bosconn)
+{
+
+ aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
+
+ aim_conn_addhandler(sess, bosconn, 0x0009, 0x0003, faimtest_bosrights, 0);
+ aim_conn_addhandler(sess, bosconn, 0x0001, 0x0007, faimtest_rateresp_bos, 0); /* rate info */
+ aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, 0x0018, faimtest_hostversions, 0);
+ aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, faimtest_serverready, 0);
+ 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_GEN, AIM_CB_GEN_MOTD, faimtest_parse_motd, 0);
+ aim_conn_addhandler(sess, bosconn, 0x0004, 0x0005, faimtest_icbmparaminfo, 0);
+ aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, faimtest_parse_connerr, 0);
+ aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_RIGHTSINFO, faimtest_locrights, 0);
+ aim_conn_addhandler(sess, bosconn, 0x0001, 0x001f, faimtest_memrequest, 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_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, 0x000a, 0x0001, faimtest_parse_searcherror, 0);
+ aim_conn_addhandler(sess, bosconn, 0x000a, 0x0003, faimtest_parse_searchreply, 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);
+
+ aim_conn_addhandler(sess, bosconn, 0x0001, 0x0001, faimtest_parse_genericerr, 0);
+ aim_conn_addhandler(sess, bosconn, 0x0003, 0x0001, faimtest_parse_genericerr, 0);
+ aim_conn_addhandler(sess, bosconn, 0x0009, 0x0001, faimtest_parse_genericerr, 0);
+
+#ifdef MID_REWROTE_ALL_THE_CRAP
+ aim_conn_addhandler(sess, bosconn, 0xffff, 0xffff, faimtest_parse_unknown, 0);
+#endif
+
+ return;
+}
+