int faimtest_authsvrready(struct aim_session_t *, struct command_rx_struct *command, ...);
int faimtest_pwdchngdone(struct aim_session_t *, struct command_rx_struct *command, ...);
int faimtest_serverready(struct aim_session_t *, struct command_rx_struct *command, ...);
+int faimtest_hostversions(struct aim_session_t *sess, struct command_rx_struct *command, ...);
int faimtest_parse_misses(struct aim_session_t *, struct command_rx_struct *command, ...);
int faimtest_parse_msgack(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_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, ...);
+int faimtest_parse_genericerr(struct aim_session_t *sess, struct command_rx_struct *command, ...);
static char *msgerrreasons[] = {
"Invalid error",
static int msgerrreasonslen = 25;
static char *screenname,*password,*server=NULL;
+static int connected = 0;
int faimtest_reportinterval(struct aim_session_t *sess, struct command_rx_struct *command, ...)
{
switch(command->conn->type) {
case AIM_CONN_TYPE_BOS: {
/* this is the new buddy list */
- char buddies[] = "Buddy1&Buddy2&ThisHereIsAName2&";
+ char buddies[] = "Buddy1&Buddy2&ThisHereIsAName2&midendian&ewarmenhoven&";
/* this is the new profile */
char profile[] = "Hello";
aim_bos_ackrateresp(sess, command->conn); /* ack rate info response */
aim_bos_reqpersonalinfo(sess, command->conn);
aim_bos_reqlocaterights(sess, command->conn);
- aim_bos_setprofile(sess, command->conn, profile, NULL, AIM_CAPS_BUDDYICON | AIM_CAPS_CHAT | AIM_CAPS_VOICE | AIM_CAPS_GETFILE | AIM_CAPS_SENDFILE | AIM_CAPS_IMIMAGE);
+ aim_bos_setprofile(sess, command->conn, profile, NULL, AIM_CAPS_BUDDYICON | AIM_CAPS_CHAT | AIM_CAPS_VOICE | AIM_CAPS_GETFILE | AIM_CAPS_SENDFILE | AIM_CAPS_IMIMAGE | AIM_CAPS_GAMES | AIM_CAPS_SAVESTOCKS);
aim_bos_reqbuddyrights(sess, command->conn);
/* send the buddy list and profile (required, even if empty) */
return 1;
}
+int faimtest_hostversions(struct aim_session_t *sess, struct command_rx_struct *command, ...)
+{
+ int vercount, i;
+ unsigned char *versions;
+ va_list ap;
+
+ va_start(ap, command);
+ vercount = va_arg(ap, int); /* number of family/version pairs */
+ versions = va_arg(ap, unsigned char *);
+ va_end(ap);
+
+ printf("faimtest: SNAC versions supported by this host: ");
+ for (i = 0; i < vercount*4; i += 4)
+ printf("0x%04x:0x%04x ",
+ aimutil_get16(versions+i), /* SNAC family */
+ aimutil_get16(versions+i+2) /* Version number */);
+ printf("\n");
+
+ return 1;
+}
+
int faimtest_serverready(struct aim_session_t *sess, struct command_rx_struct *command, ...)
{
- switch (command->conn->type)
- {
- case AIM_CONN_TYPE_BOS:
+ int famcount, i;
+ unsigned short *families;
+ va_list ap;
- aim_setversions(sess, command->conn);
- aim_bos_reqrate(sess, command->conn); /* request rate info */
+ va_start(ap, command);
+ famcount = va_arg(ap, int);
+ families = va_arg(ap, unsigned short *);
+ va_end(ap);
- fprintf(stderr, "faimtest: done with BOS ServerReady\n");
- break;
+ printf("faimtest: SNAC families supported by this host (type %d): ", command->conn->type);
+ for (i = 0; i < famcount; i++)
+ printf("0x%04x ", families[i]);
+ printf("\n");
- 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);
+ switch (command->conn->type) {
+ case AIM_CONN_TYPE_BOS:
- 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;
+ aim_setversions(sess, command->conn);
+ aim_bos_reqrate(sess, command->conn); /* request rate info */
- case AIM_CONN_TYPE_RENDEZVOUS: /* empty */
- break;
+ 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;
+
+ case AIM_CONN_TYPE_RENDEZVOUS: /* empty */
+ break;
+
+ default:
+ fprintf(stderr, "faimtest: unknown connection type on Server Ready\n");
+ }
- default:
- fprintf(stderr, "faimtest: unknown connection type on Server Ready\n");
- }
return 1;
}
if ( (tstconn==NULL) || (tstconn->status & AIM_CONN_STATUS_RESOLVERR) )
fprintf(stderr, "faimtest: unable to reconnect with authorizer\n");
else {
+ aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, faimtest_flapversion, 0);
aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
/* Send the cookie to the Auth */
aim_auth_sendcookie(sess, tstconn, cookie);
aim_conn_addhandler(sess, bosconn, 0x0009, 0x0003, faimtest_bosrights, 0);
aim_conn_addhandler(sess, bosconn, 0x0001, 0x0007, faimtest_rateresp, 0); /* rate info */
aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_ACK, AIM_CB_ACK_ACK, NULL, 0);
+ 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_SPECIAL, AIM_CB_SPECIAL_DEFAULT, aim_parse_unknown, 0);
aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_MOTD, faimtest_parse_motd, 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);
+
aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, faimtest_parse_connerr, 0);
-
+
+
aim_auth_sendcookie(sess, bosconn, cookie);
return 1;
} else if (!strncmp(tmpstr, "open directim", 13)) {
struct aim_conn_t *newconn;
newconn = aim_directim_initiate(sess, command->conn, NULL, userinfo->sn);
+ } else if (!strncmp(tmpstr, "openauth", 8)) {
+ aim_bos_reqservice(sess, command->conn, AIM_CONN_TYPE_AUTH);
+ } else if (!strncmp(tmpstr, "auth", 4)) {
+ aim_genericreq_n(sess, aim_getconn_type(sess, AIM_CONN_TYPE_AUTH), 0x0007, 0x0002);
} else if (!strncmp(tmpstr, "reqsendmsg", 10)) {
aim_send_im(sess, command->conn, "vaxherder", 0, "sendmsg 7900");
} else if (!strncmp(tmpstr, "sendmsg", 7)) {
userinfo = va_arg(ap, struct aim_userinfo_s *);
va_end(ap);
- printf("\n%s is now online (flags: %04x = %s%s%s%s%s%s%s%s) (caps = 0x%04x)\n",
+ printf("%ld %s is now online (flags: %04x = %s%s%s%s%s%s%s%s) (caps = 0x%04x)\n",
+ time(NULL),
userinfo->sn, userinfo->flags,
(userinfo->flags&AIM_FLAG_UNCONFIRMED)?" UNCONFIRMED":"",
(userinfo->flags&AIM_FLAG_ADMINISTRATOR)?" ADMINISTRATOR":"",
printf("faimtest: motd: %s (%d / %s)\n", msg, id,
(id < codeslen)?codes[id]:"unknown");
+ if (!connected)
+ connected++;
+
+ return 1;
+}
+
+int faimtest_parse_genericerr(struct aim_session_t *sess, struct command_rx_struct *command, ...)
+{
+ va_list ap;
+ unsigned short reason;
+
+ va_start(ap, command);
+ reason = va_arg(ap, int);
+ va_end(ap);
+
+ printf("faimtest: snac threw error (reason 0x%04x: %s)\n", reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown");
+
return 1;
}
int faimtest_parse_ratechange(struct aim_session_t *sess, struct command_rx_struct *command, ...)
{
+ static char *codes[5] = {"invalid",
+ "change",
+ "warning",
+ "limit",
+ "limit cleared"};
va_list ap;
- unsigned long newrate;
-
+ int code;
+ unsigned long rateclass, windowsize, clear, alert, limit, disconnect;
+ unsigned long currentavg, maxavg;
+
va_start(ap, command);
- newrate = va_arg(ap, unsigned long);
+
+ /* See code explanations below */
+ code = va_arg(ap, int);
+
+ /*
+ * See comments above aim_parse_ratechange_middle() in aim_rxhandlers.c.
+ */
+ rateclass = va_arg(ap, unsigned long);
+
+ /*
+ * 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, unsigned long);
+
+ /* Explained below */
+ clear = va_arg(ap, unsigned long);
+ alert = va_arg(ap, unsigned long);
+ limit = va_arg(ap, unsigned long);
+ disconnect = va_arg(ap, unsigned long);
+ currentavg = va_arg(ap, unsigned long);
+ maxavg = va_arg(ap, unsigned long);
+
va_end(ap);
- printf("faimtest: ratechange: %lu\n", newrate);
+
+ printf("faimtest: rate %s (rate class 0x%04lx): 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(command->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(command->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(command->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(command->conn, 0);
+ }
return 1;
}
int faimtest_parse_evilnotify(struct aim_session_t *sess, struct command_rx_struct *command, ...)
{
va_list ap;
- char *sn;
+ int newevil;
+ struct aim_userinfo_s *userinfo;
va_start(ap, command);
- sn = va_arg(ap, char *);
+ newevil = va_arg(ap, int);
+ userinfo = va_arg(ap, struct aim_userinfo_s *);
va_end(ap);
- printf("faimtest: warning from: %s\n", sn);
+ /*
+ * 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.
+ */
+ printf("faimtest: evil level change: new value = %2.1f%% (caused by %s)\n", ((float)newevil)/10, (userinfo && strlen(userinfo->sn))?userinfo->sn:"anonymous");
return 1;
}