#include <faim/aim.h>
+/*
+ * Clears out connection list, killing remaining connections.
+ */
void aim_connrst(struct aim_session_t *sess)
{
- int i;
- for (i = 0; i < AIM_CONN_MAX; i++) {
- aim_conn_close(&sess->conns[i]);
+ faim_mutex_init(&sess->connlistlock, NULL);
+ if (sess->connlist) {
+ struct aim_conn_t *cur = sess->connlist, *tmp;
+
+ while(cur) {
+ tmp = cur->next;
+ aim_conn_close(cur);
+ free(cur);
+ cur = tmp;
+ }
}
+ sess->connlist = NULL;
+ return;
}
+/*
+ * Gets a new connection structure.
+ */
struct aim_conn_t *aim_conn_getnext(struct aim_session_t *sess)
{
- int i;
- for (i=0;i<AIM_CONN_MAX;i++)
- if (sess->conns[i].fd == -1)
- return &(sess->conns[i]);
- return NULL;
+ struct aim_conn_t *newconn, *cur;
+
+ if (!(newconn = malloc(sizeof(struct aim_conn_t))))
+ return NULL;
+
+ memset(newconn, 0, sizeof(struct aim_conn_t));
+ aim_conn_close(newconn);
+ newconn->next = NULL;
+
+ faim_mutex_lock(&sess->connlistlock);
+ if (sess->connlist == NULL)
+ sess->connlist = newconn;
+ else {
+ for (cur = sess->connlist; cur->next; cur = cur->next)
+ ;
+ cur->next = newconn;
+ }
+ faim_mutex_unlock(&sess->connlistlock);
+
+ return newconn;
+}
+
+void aim_conn_kill(struct aim_session_t *sess, struct aim_conn_t **deadconn)
+{
+ struct aim_conn_t *cur;
+
+ if (!deadconn || !*deadconn)
+ return;
+
+ faim_mutex_lock(&sess->connlistlock);
+ if (sess->connlist == NULL)
+ ;
+ else if (sess->connlist->next == NULL) {
+ if (sess->connlist == *deadconn)
+ sess->connlist = NULL;
+ } else {
+ cur = sess->connlist;
+ while (cur->next) {
+ if (cur->next == *deadconn) {
+ cur->next = cur->next->next;
+ break;
+ }
+ cur = cur->next;
+ }
+ }
+ faim_mutex_unlock(&sess->connlistlock);
+
+ aim_conn_close(*deadconn);
+ free(*deadconn);
+ deadconn = NULL;
+
+ return;
}
void aim_conn_close(struct aim_conn_t *deadconn)
struct aim_conn_t *aim_getconn_type(struct aim_session_t *sess,
int type)
{
- int i;
- for (i=0; i<AIM_CONN_MAX; i++)
- if (sess->conns[i].type == type)
- return &(sess->conns[i]);
- return NULL;
+ struct aim_conn_t *cur;
+
+ faim_mutex_lock(&sess->connlistlock);
+ for (cur = sess->connlist; cur; cur = cur->next) {
+ if (cur->type == type)
+ break;
+ }
+ faim_mutex_unlock(&sess->connlistlock);
+ return cur;
}
/*
u_short port = FAIM_LOGIN_PORT;
char *host = NULL;
int i=0;
-
+
if ((connstruct=aim_conn_getnext(sess))==NULL)
return NULL;
+ faim_mutex_lock(&connstruct->active);
+
connstruct->type = type;
if (!dest) { /* just allocate a struct */
connstruct->fd = -1;
connstruct->status = 0;
+ faim_mutex_unlock(&connstruct->active);
return connstruct;
}
strncpy(host, dest, i);
host[i] = '\0';
- hp = gethostbyname2(host, AF_INET);
+ hp = gethostbyname(host);
free(host);
if (hp == NULL) {
connstruct->status = (h_errno | AIM_CONN_STATUS_RESOLVERR);
+ faim_mutex_unlock(&connstruct->active);
return connstruct;
}
if(ret < 0) {
connstruct->fd = -1;
connstruct->status = (errno | AIM_CONN_STATUS_CONNERR);
+ faim_mutex_unlock(&connstruct->active);
return connstruct;
}
+ faim_mutex_unlock(&connstruct->active);
+
return connstruct;
}
int aim_conngetmaxfd(struct aim_session_t *sess)
{
- int i,j;
+ int j = 0;
+ struct aim_conn_t *cur;
+
+ faim_mutex_lock(&sess->connlistlock);
+ for (cur = sess->connlist; cur; cur = cur->next) {
+ if (cur->fd > j)
+ j = cur->fd;
+ }
+ faim_mutex_unlock(&sess->connlistlock);
- for (i=0,j=0;i<AIM_CONN_MAX;i++)
- if(sess->conns[i].fd > j)
- j = sess->conns[i].fd;
return j;
}
int aim_countconn(struct aim_session_t *sess)
{
- int i,cnt;
+ int cnt = 0;
+ struct aim_conn_t *cur;
+
+ faim_mutex_lock(&sess->connlistlock);
+ for (cur = sess->connlist; cur; cur = cur->next)
+ cnt++;
+ faim_mutex_unlock(&sess->connlistlock);
- for (i=0,cnt=0;i<AIM_CONN_MAX;i++)
- if (sess->conns[i].fd > -1)
- cnt++;
return cnt;
}
* 1 outgoing data pending (NULL returned)
* 2 incoming data pending (connection with pending data returned)
*
+ * XXX: we could probably stand to do a little courser locking here.
+ *
*/
struct aim_conn_t *aim_select(struct aim_session_t *sess,
struct timeval *timeout, int *status)
{
+ struct aim_conn_t *cur;
fd_set fds;
+ int maxfd = 0;
int i;
- if (aim_countconn(sess) <= 0)
+ faim_mutex_lock(&sess->connlistlock);
+ if (sess->connlist == NULL) {
+ faim_mutex_unlock(&sess->connlistlock);
return 0;
+ }
+ faim_mutex_unlock(&sess->connlistlock);
/*
* If we have data waiting to be sent, return immediatly
}
FD_ZERO(&fds);
-
- for(i=0;i<AIM_CONN_MAX;i++)
- if (sess->conns[i].fd>-1)
- FD_SET(sess->conns[i].fd, &fds);
-
- if ((i = select(aim_conngetmaxfd(sess)+1, &fds, NULL, NULL, timeout))>=1) {
- int j;
- for (j=0;j<AIM_CONN_MAX;j++) {
- if (sess->conns[j].fd > -1) {
- if ((FD_ISSET(sess->conns[j].fd, &fds))) {
- *status = 2;
- return &(sess->conns[j]); /* return the first waiting struct */
- }
- }
- }
- /* should never get here */
+ maxfd = 0;
+
+ faim_mutex_lock(&sess->connlistlock);
+ for (cur = sess->connlist; cur; cur = cur->next) {
+ FD_SET(cur->fd, &fds);
+ if (cur->fd > maxfd)
+ maxfd = cur->fd;
+ }
+ faim_mutex_unlock(&sess->connlistlock);
+
+ if ((i = select(maxfd+1, &fds, NULL, NULL, timeout))>=1) {
+ faim_mutex_lock(&sess->connlistlock);
+ for (cur = sess->connlist; cur; cur = cur->next) {
+ if (FD_ISSET(cur->fd, &fds)) {
+ *status = 2;
+ faim_mutex_unlock(&sess->connlistlock);
+ return cur;
+ }
+ }
}
+ faim_mutex_unlock(&sess->connlistlock);
*status = i; /* may be 0 or -1 */
return NULL; /* no waiting or error, return */
}
{
if (conn)
return (conn->status & 0x0001);
- else
- return -1;
+ return -1;
}
int aim_conn_setstatus(struct aim_conn_t *conn, int status)
{
- if (conn)
- return (conn->status ^= status);
- else
+ int val;
+
+ if (!conn)
return -1;
+
+ faim_mutex_lock(&conn->active);
+ val = conn->status ^= status;
+ faim_mutex_unlock(&conn->active);
+ return val;
}
int aim_conn_setlatency(struct aim_conn_t *conn, int newval)
{
if (!conn)
return -1;
-
+
+ faim_mutex_lock(&conn->active);
conn->forcedlatency = newval;
conn->lastactivity = 0; /* reset this just to make sure */
+ faim_mutex_unlock(&conn->active);
return 0;
}
if (!sess)
return;
- memset(sess->logininfo.screen_name, 0x00, MAXSNLEN);
- sess->logininfo.BOSIP = NULL;
- memset(sess->logininfo.cookie, 0x00, AIM_COOKIELEN);
- sess->logininfo.email = NULL;
- sess->logininfo.regstatus = 0x00;
-
- memset(sess->conns, 0, sizeof(struct aim_conn_t)*AIM_CONN_MAX);
+ memset(sess, 0, sizeof(struct aim_session_t));
aim_connrst(sess);
-
sess->queue_outgoing = NULL;
sess->queue_incoming = NULL;
sess->pendingjoin = NULL;
}
else if (channel == 0x0002)
{
- int rendtype;
struct aim_tlv_t *block1;
struct aim_tlvlist_t *list2;
struct aim_tlv_t *tmptlv;
+ struct aim_tlv_t *miscinfo;
+ unsigned short reqclass = 0;
int a;
/* Class. */
* There's another block of TLVs embedded in the type 5 here.
*/
block1 = aim_gettlv(tlvlist, 0x0005, 1);
- if (!block1)
+ if (!block1) {
+ printf("faim: no tlv 0x0005 in rendezvous transaction!\n");
+ aim_freetlvchain(&tlvlist);
return 1; /* major problem */
+ }
a = 0x1a; /* skip -- not sure what this information is! */
* Its probably just an accepted invitation or something.
*
*/
- if (block1->length <= 0x1a)
- {
+ if (block1->length <= 0x1a) {
+ aim_freetlvchain(&tlvlist);
+ return 1;
+ }
+
+ list2 = aim_readtlvchain(block1->value+a, block1->length-a);
+
+ if (!(miscinfo = aim_gettlv(list2, 0x2711, 1))) {
+ struct aim_msgcookie_t *cook;
+
+ if ((cook = aim_uncachecookie(sess, cookie)) == NULL) {
+ printf("faim: no 0x2711 info TLV in rendezvous and its not in cache!\n");
+ aim_freetlvchain(&list2);
aim_freetlvchain(&tlvlist);
return 1;
}
- list2 = aim_readtlvchain(block1->value+a, block1->length-a);
+ if (cook->type == 1) {
+ struct aim_filetransfer_t *ft;
- 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 (cook->data) {
+ struct aim_tlv_t *errortlv;
+ int errorcode = -1;
+
+ ft = (struct aim_filetransfer_t *)cook->data;
+
+ if ((errortlv = aim_gettlv(list2, 0x000b, 1))) {
+ errorcode = aimutil_get16(errortlv->value);
}
+ printf("faim: transfer from %s (%s) for %s cancelled (error code %d)\n", ft->sender, ft->ip, ft->filename, errorcode);
+ free(cook->data);
+ } else {
+ printf("faim: not data attached to file transfer\n");
+ }
+
+ } else {
+ printf("faim: unknown cookie cache type %d\n", cook->type);
+ }
+
+ free(cook);
+ return 1;
+ }
+
+
+ /*
+ * Parse the first two bytes of the 0x2711 TLV.
+ *
+ * This can be interpretted in a couple ways.
+ *
+ * It could be said that its a service type or some such and
+ * that voice is 0, file transfer is 1, and chat is 4 (and 5).
+ *
+ * Or it could be said that its an exchange value. Exchanges
+ * four and five are for chat, voice is on exchange zero and
+ * file transfer is done on exchange 1.
+ *
+ * It should work out the same no how its thought of.
+ *
+ */
+ reqclass = aimutil_get16(miscinfo->value+0);
+
+ switch (reqclass) {
+ case AIM_RENDEZVOUS_VOICE: {
+
+ /* XXX: implement all this */
+
+ /*
+ * Call client.
+ */
+ userfunc = aim_callhandler(command->conn, 0x0004, 0x0007);
+ if (userfunc || (i = 0)) {
+ i = userfunc(sess,
+ command,
+ channel,
+ reqclass,
+ &userinfo);
+ }
+ break;
+ }
+ case AIM_RENDEZVOUS_FILETRANSFER: {
+ char ip[30];
+ char *desc = NULL;
+ struct aim_msgcookie_t cachedcook;
+ struct aim_filetransfer_t *ft;
+
+ memset(ip, 0, sizeof(ip));
+
+ if (aim_gettlv(list2, 0x0003, 1) && aim_gettlv(list2, 0x0003, 1)) {
+ struct aim_tlv_t *iptlv, *porttlv;
- if (aim_gettlv(list2, 0x000c, 1))
- msg = aim_gettlv_str(list2, 0x000c, 1);
+ iptlv = aim_gettlv(list2, 0x0003, 1);
+ porttlv = aim_gettlv(list2, 0x0005, 1);
+
+ snprintf(ip, sizeof(ip)-1, "%d.%d.%d.%d:%d",
+ aimutil_get8(iptlv->value+0),
+ aimutil_get8(iptlv->value+1),
+ aimutil_get8(iptlv->value+2),
+ aimutil_get8(iptlv->value+3),
+ aimutil_get16(porttlv->value));
+ }
+
+ if (aim_gettlv(list2, 0x000c, 1)) {
+ desc = aim_gettlv_str(list2, 0x000c, 1);
+ }
+
+ printf("faim: rend: file transfer request from %s for %s: %s (%s)\n",
+ userinfo.sn,
+ miscinfo->value+8,
+ desc,
+ ip);
+
+ memcpy(cachedcook.cookie, cookie, 8);
+ memcpy(cachedcook.extended, block1->value+10, 16);
+
+ ft = malloc(sizeof(struct aim_filetransfer_t));
+ strncpy(ft->sender, userinfo.sn, sizeof(ft->sender));
+ strncpy(ft->ip, ip, sizeof(ft->ip));
+ ft->filename = strdup(miscinfo->value+8);
+ cachedcook.type = 1;
+ cachedcook.data = ft;
+
+ if (aim_cachecookie(sess, &cachedcook) != 0)
+ printf("faim: ERROR caching message cookie\n");
+
+
+ aim_denytransfer(sess, command->conn, ft->sender, cookie, 0);
+
+ free(desc);
+
+ i = 1;
+ break;
+ }
+ case AIM_RENDEZVOUS_FILETRANSFER_GET: {
+ printf("faim: file get request (unsupported)\n");
+ i = 1;
+ break;
+ }
+ case AIM_RENDEZVOUS_CHAT_EX3:
+ case AIM_RENDEZVOUS_CHAT_EX4:
+ case AIM_RENDEZVOUS_CHAT_EX5: {
+ struct aim_chat_roominfo roominfo;
+ char *msg=NULL,*encoding=NULL,*lang=NULL;
+
+ aim_chat_readroominfo(miscinfo->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, 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,
- rendtype,
- &userinfo,
- &roominfo,
- msg,
- encoding?encoding+1:NULL,
- lang?lang+1:NULL);
- else
- i = 0;
+ 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 = 0))
+ i = userfunc(sess,
+ command,
+ channel,
+ reqclass, /* == roominfo->exchange */
+ &userinfo,
+ &roominfo,
+ msg,
+ encoding?encoding+1:NULL,
+ lang?lang+1:NULL);
free(roominfo.name);
free(msg);
free(encoding);
free(lang);
- }
+ break;
+ }
+ default: {
+ printf("faim: rendezvous: unknown rend class 0x%04x\n", reqclass);
+ i = 1;
+ break;
+ }
+ } /* switch */
+
aim_freetlvchain(&list2);
}
return i;
}
+/*
+ * Possible codes:
+ * AIM_TRANSFER_DENY_NOTSUPPORTED -- "client does not support"
+ * AIM_TRANSFER_DENY_DECLINE -- "client has declined transfer"
+ * AIM_TRANSFER_DENY_NOTACCEPTING -- "client is not accepting transfers"
+ *
+ */
+u_long aim_denytransfer(struct aim_session_t *sess,
+ struct aim_conn_t *conn,
+ char *sender,
+ char *cookie,
+ unsigned short code)
+{
+ struct command_tx_struct *newpacket;
+ int curbyte, i;
+
+ if(!(newpacket = aim_tx_new(0x0002, conn, 10+8+2+1+strlen(sender)+6)))
+ return -1;
+
+ newpacket->lock = 1;
+
+ curbyte = aim_putsnac(newpacket->data, 0x0004, 0x000b, 0x0000, sess->snac_nextid);
+ for (i = 0; i < 8; i++)
+ curbyte += aimutil_put8(newpacket->data+curbyte, cookie[i]);
+ curbyte += aimutil_put16(newpacket->data+curbyte, 0x0002);
+ curbyte += aimutil_put8(newpacket->data+curbyte, strlen(sender));
+ curbyte += aimutil_putstr(newpacket->data+curbyte, sender, strlen(sender));
+ curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0003, code);
+
+ newpacket->lock = 0;
+ aim_tx_enqueue(sess, newpacket);
+
+ return (sess->snac_nextid++);
+}
+
/*
* Not real sure what this does, nor does anyone I've talk to.
*
enter:
authconn = aim_newconn(&aimsess, AIM_CONN_TYPE_AUTH, server?server:FAIM_LOGIN_SERVER);
- if (authconn == NULL)
- {
- fprintf(stderr, "faimtest: internal connection error while in aim_login. bailing out.\n");
- return -1;
- }
- else if (authconn->fd == -1)
- {
- if (authconn->status & AIM_CONN_STATUS_RESOLVERR)
- fprintf(stderr, "faimtest: could not resolve authorizer name\n");
- else if (authconn->status & AIM_CONN_STATUS_CONNERR)
- fprintf(stderr, "faimtest: could not connect to authorizer\n");
- return -1;
- }
- else
- {
+ if (authconn == NULL) {
+ fprintf(stderr, "faimtest: internal connection error while in aim_login. bailing out.\n");
+ return -1;
+ } else if (authconn->fd == -1) {
+ if (authconn->status & AIM_CONN_STATUS_RESOLVERR)
+ fprintf(stderr, "faimtest: could not resolve authorizer name\n");
+ else if (authconn->status & AIM_CONN_STATUS_CONNERR)
+ fprintf(stderr, "faimtest: could not connect to authorizer\n");
+ aim_conn_kill(&aimsess, &authconn);
+ return -1;
+ } else {
#ifdef SNACLOGIN
- /* new login code -- not default -- pending new password encryption algo */
- aim_conn_addhandler(&aimsess, authconn, 0x0017, 0x0007, faimtest_parse_login, 0);
- aim_conn_addhandler(&aimsess, authconn, 0x0017, 0x0003, faimtest_parse_authresp, 0);
-
- aim_sendconnack(&aimsess, authconn);
- aim_request_login(&aimsess, authconn, FAIMTEST_SCREENNAME);
+ /* new login code -- not default -- pending new password encryption algo */
+ aim_conn_addhandler(&aimsess, authconn, 0x0017, 0x0007, faimtest_parse_login, 0);
+ aim_conn_addhandler(&aimsess, authconn, 0x0017, 0x0003, faimtest_parse_authresp, 0);
+
+ aim_sendconnack(&aimsess, authconn);
+ aim_request_login(&aimsess, authconn, FAIMTEST_SCREENNAME);
#else
- aim_conn_addhandler(&aimsess, authconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_AUTHSUCCESS, faimtest_parse_authresp, 0);
- aim_conn_addhandler(&aimsess, authconn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, faimtest_authsvrready, 0);
- aim_send_login(&aimsess, authconn, screenname, password, &info);
-
+ aim_conn_addhandler(&aimsess, authconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_AUTHSUCCESS, faimtest_parse_authresp, 0);
+ aim_conn_addhandler(&aimsess, authconn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, faimtest_authsvrready, 0);
+ aim_send_login(&aimsess, authconn, screenname, password, &info);
#endif
- }
+ }
while (keepgoing) {
waitingconn = aim_select(&aimsess, NULL, &selstat);
{
struct aim_conn_t *tstconn = NULL;
tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHATNAV, ip);
- if ( (tstconn==NULL) || (tstconn->status >= AIM_CONN_STATUS_RESOLVERR))
- {
- fprintf(stderr, "faimtest: unable to connect to chatnav server\n");
- return 1;
- }
+ if ( (tstconn==NULL) || (tstconn->status >= AIM_CONN_STATUS_RESOLVERR)) {
+ fprintf(stderr, "faimtest: unable to connect to chatnav server\n");
+ if (tstconn) aim_conn_kill(sess, &tstconn);
+ 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);
if ( (tstconn==NULL) || (tstconn->status >= AIM_CONN_STATUS_RESOLVERR))
{
fprintf(stderr, "faimtest: unable to connect to chat server\n");
+ if (tstconn) aim_conn_kill(sess, &tstconn);
return 1;
}
printf("faimtest: chat: connected\n");
{
printf("Login Error Code 0x%04x\n", sess->logininfo.errorcode);
printf("Error URL: %s\n", sess->logininfo.errorurl);
- aim_conn_close(command->conn);
+ aim_conn_kill(sess, &command->conn);
exit(0); /* XXX: should return in order to let the above things get free()'d. */
}
printf("BOS IP: %s\n", sess->logininfo.BOSIP);
printf("Closing auth connection...\n");
- aim_conn_close(command->conn);
+ aim_conn_kill(sess, &command->conn);
bosconn = aim_newconn(sess, AIM_CONN_TYPE_BOS, sess->logininfo.BOSIP);
- if (bosconn == NULL)
- {
- fprintf(stderr, "faimtest: could not connect to BOS: internal error\n");
- }
- else if (bosconn->status != 0)
- {
- fprintf(stderr, "faimtest: could not connect to BOS\n");
- }
- else
- {
- aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_ACK, AIM_CB_ACK_ACK, NULL, 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, NULL, 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_MSG, AIM_CB_MSG_MISSEDCALL, faimtest_parse_misses, 0);
- aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATECHANGE, faimtest_parse_misses, 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_LOC, AIM_CB_LOC_USERINFO, faimtest_parse_userinfo, 0);
-
- aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_CTN, AIM_CB_CTN_DEFAULT, aim_parse_unknown, 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, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, faimtest_parse_connerr, 0);
-
- aim_auth_sendcookie(sess, bosconn, sess->logininfo.cookie);
- }
+ if (bosconn == NULL) {
+ fprintf(stderr, "faimtest: could not connect to BOS: internal error\n");
+ } else if (bosconn->status != 0) {
+ fprintf(stderr, "faimtest: could not connect to BOS\n");
+ aim_conn_kill(sess, &bosconn);
+ } else {
+ aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_ACK, AIM_CB_ACK_ACK, NULL, 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, NULL, 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_MSG, AIM_CB_MSG_MISSEDCALL, faimtest_parse_misses, 0);
+ aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATECHANGE, faimtest_parse_misses, 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_LOC, AIM_CB_LOC_USERINFO, faimtest_parse_userinfo, 0);
+
+ aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_CTN, AIM_CB_CTN_DEFAULT, aim_parse_unknown, 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, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, faimtest_parse_connerr, 0);
+
+ aim_auth_sendcookie(sess, bosconn, sess->logininfo.cookie);
+ }
return 1;
}
printf("UNKNOWN_BIT4 ");
if (userinfo->class & 0x0010)
printf("FREE ");
+ if (userinfo->class & 0x0040)
+ printf("ICQ? ");
printf("\n");
printf("faimtest: userinfo: membersince: %lu\n", userinfo->membersince);
/*
* Channel 1: Standard Message
*/
- if (channel == 1)
- {
- struct aim_userinfo_s *userinfo;
- char *msg = NULL;
- u_int icbmflags = 0;
- char *tmpstr = NULL;
- u_short flag1, flag2;
-
+ if (channel == 1) {
+ struct aim_userinfo_s *userinfo;
+ char *msg = NULL;
+ u_int icbmflags = 0;
+ char *tmpstr = NULL;
+ u_short flag1, flag2;
+
+ userinfo = va_arg(ap, struct aim_userinfo_s *);
+ msg = va_arg(ap, char *);
+ icbmflags = va_arg(ap, u_int);
+ flag1 = va_arg(ap, u_short);
+ flag2 = va_arg(ap, u_short);
+ va_end(ap);
+
+ printf("faimtest: icbm: sn = \"%s\"\n", userinfo->sn);
+ printf("faimtest: icbm: warnlevel = 0x%04x\n", userinfo->warnlevel);
+ printf("faimtest: icbm: class = 0x%04x ", userinfo->class);
+ if (userinfo->class & 0x0010)
+ printf("(FREE) ");
+ if (userinfo->class & 0x0001)
+ printf("(TRIAL) ");
+ if (userinfo->class & 0x0004)
+ printf("(AOL) ");
+ printf("\n");
+ printf("faimtest: icbm: membersince = %lu\n", userinfo->membersince);
+ printf("faimtest: icbm: onlinesince = %lu\n", userinfo->onlinesince);
+ printf("faimtest: icbm: idletime = 0x%04x\n", userinfo->idletime);
+
+ printf("faimtest: icbm: icbmflags = ");
+ if (icbmflags & AIM_IMFLAGS_AWAY)
+ printf("away ");
+ if (icbmflags & AIM_IMFLAGS_ACK)
+ printf("ackrequest ");
+ printf("\n");
+
+ printf("faimtest: icbm: encoding flags = {%04x, %04x}\n", flag1, flag2);
+
+ printf("faimtest: icbm: message: %s\n", msg);
+
+ if (msg) {
+ tmpstr = index(msg, '>');
+ if (tmpstr != NULL)
+ tmpstr+=1;
+ else
+ tmpstr = msg;
+
+ if ( (strlen(tmpstr) >= 10) &&
+ (!strncmp(tmpstr, "disconnect", 10)) ) {
+ aim_send_im(sess, command->conn, "midendian", 0, "ta ta...");
+ aim_logoff(sess);
+ } else if (strstr(tmpstr, "goodday")) {
+ printf("faimtest: icbm: sending response\n");
+ aim_send_im(sess, command->conn, userinfo->sn, 0, "Good day to you too.");
+ } else if (!strncmp(tmpstr, "open chatnav", 12)) {
+ aim_bos_reqservice(sess, command->conn, AIM_CONN_TYPE_CHATNAV);
+ //aim_chat_join(sess, command->conn, "thishereisaname2_chat85");
+ } 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)) {
+ struct aim_conn_t *chatnavconn;
+ chatnavconn = aim_getconn_type(sess, AIM_CONN_TYPE_CHATNAV);
+ aim_conn_kill(sess, &chatnavconn);
+ } 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 (!strncmp(tmpstr, "getinfo", 7)) {
+ aim_getinfo(sess, command->conn, "75784102", AIM_GETINFO_GENERALINFO);
+ aim_getinfo(sess, command->conn, "15853637", AIM_GETINFO_AWAYMESSAGE);
+ } else {
+ printf("unknown command.\n");
+ }
+
+ }
+ }
+ /*
+ * Channel 2: Rendevous Request
+ */
+ else if (channel == 2) {
+ struct aim_userinfo_s *userinfo;
+ unsigned short reqclass;
+
+ reqclass = va_arg(ap, unsigned short);
+ switch (reqclass) {
+ case AIM_RENDEZVOUS_VOICE: {
userinfo = va_arg(ap, struct aim_userinfo_s *);
- msg = va_arg(ap, char *);
- icbmflags = va_arg(ap, u_int);
- flag1 = va_arg(ap, u_short);
- flag2 = va_arg(ap, u_short);
va_end(ap);
- printf("faimtest: icbm: sn = \"%s\"\n", userinfo->sn);
- printf("faimtest: icbm: warnlevel = 0x%04x\n", userinfo->warnlevel);
- printf("faimtest: icbm: class = 0x%04x ", userinfo->class);
+ 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)
if (userinfo->class & 0x0004)
printf("(AOL) ");
printf("\n");
- printf("faimtest: icbm: membersince = %lu\n", userinfo->membersince);
- printf("faimtest: icbm: onlinesince = %lu\n", userinfo->onlinesince);
- printf("faimtest: icbm: idletime = 0x%04x\n", userinfo->idletime);
+ /* 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);
- printf("faimtest: icbm: icbmflags = ");
- if (icbmflags & AIM_IMFLAGS_AWAY)
- printf("away ");
- if (icbmflags & AIM_IMFLAGS_ACK)
- printf("ackrequest ");
- printf("\n");
+ break;
+ }
+ case AIM_RENDEZVOUS_FILETRANSFER: {
+ printf("faimtset: file transfer!\n");
+ break;
+ }
+ case AIM_RENDEZVOUS_CHAT_EX3:
+ case AIM_RENDEZVOUS_CHAT_EX4:
+ case AIM_RENDEZVOUS_CHAT_EX5: {
+ char *msg,*encoding,*lang;
+ struct aim_chat_roominfo *roominfo;
- printf("faimtest: icbm: encoding flags = {%04x, %04x}\n", flag1, flag2);
+ 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: icbm: message: %s\n", msg);
+ 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);
- if (msg)
- {
- tmpstr = index(msg, '>');
- if (tmpstr != NULL)
- tmpstr+=1;
- else
- tmpstr = msg;
-
- if ( (strlen(tmpstr) >= 10) &&
- (!strncmp(tmpstr, "disconnect", 10)) )
- {
- aim_send_im(sess, command->conn, "midendian", 0, "ta ta...");
- aim_logoff(sess);
- }
- else if (strstr(tmpstr, "goodday"))
- {
- printf("faimtest: icbm: sending response\n");
- aim_send_im(sess, command->conn, userinfo->sn, 0, "Good day to you too.");
- }
- else if (!strncmp(tmpstr, "open chatnav", 12))
- {
- aim_bos_reqservice(sess, command->conn, AIM_CONN_TYPE_CHATNAV);
- //aim_chat_join(sess, command->conn, "thishereisaname2_chat85");
- }
- 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 (!strncmp(tmpstr, "getinfo", 7)) {
- aim_getinfo(sess, command->conn, "midendian", AIM_GETINFO_GENERALINFO);
- aim_getinfo(sess, command->conn, "midendian", AIM_GETINFO_AWAYMESSAGE);
- } else
- {
-#if 0
- printf("faimtest: icbm: starting chat...\n");
- aim_bos_reqservice(sess, command->conn, AIM_CONN_TYPE_CHATNAV);
-#else
- aim_bos_setidle(sess, command->conn, 0x0ffffffe);
-#endif
- }
-
- }
- }
- /*
- * Channel 2: Rendevous Request
- */
- else if (channel == 2)
- {
- struct aim_userinfo_s *userinfo;
- int rendtype = 0;
-
- 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: 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);
+ break;
+ }
+ default:
+ printf("faimtest: icbm: unknown reqclass (%d)\n", reqclass);
+ } /* switch */
+ } else
printf("faimtest does not support channels > 2 (chan = %02x)\n", channel);
printf("faimtest: icbm: done with ICBM handling\n");