From 225174938751264d2d11d880ca820a66961c694c Mon Sep 17 00:00:00 2001 From: mid Date: Fri, 10 Nov 2000 08:35:06 +0000 Subject: [PATCH] - Fri Nov 10 08:24:34 UTC 2000 - Add sess->flags (replaces sess->snaclogin) - Remove odd setstatus call in chat parser - Remove aim_tx_enqueue macro, replace with a smarter one - If a connection is in progress, enqueue instead of calling the client-specified queuer - Add support for nonblocking connects through the AIM_SESS_FLAG_NONBLOCKCONNECT flag to aim_session_init() - Add AIM_CB_SPECIAL_CONNCOMPLETE callback. Not real useful. - Add AIM_CB_SPECIAL_FLAPVER callback. Can be used as an alternate way of starting the login process, or just to look like you know what you're doing. Fixed associated inconsistencies in aim_rxhandlers too. - Fix some connection status stupidities in faimtest. --- CHANGES | 15 ++++ aim_conn.c | 146 +++++++++++++++++++++++++++++++++----- aim_login.c | 15 ++-- aim_rxhandlers.c | 20 +++--- aim_rxqueue.c | 3 + aim_txqueue.c | 16 +++++ faim/aim.h | 17 +++-- faim/aim_cbtypes.h | 2 + utils/faimtest/faimtest.c | 74 +++++++++++++++---- 9 files changed, 258 insertions(+), 50 deletions(-) diff --git a/CHANGES b/CHANGES index 7b0f3d1..e261088 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,21 @@ No release numbers ------------------ + - Fri Nov 10 08:24:34 UTC 2000 + - Add sess->flags (replaces sess->snaclogin) + - Remove odd setstatus call in chat parser + - Remove aim_tx_enqueue macro, replace with a smarter one + - If a connection is in progress, enqueue instead of calling + the client-specified queuer + - Add support for nonblocking connects through the + AIM_SESS_FLAG_NONBLOCKCONNECT flag to aim_session_init() + - Add AIM_CB_SPECIAL_CONNCOMPLETE callback. Not real useful. + - Add AIM_CB_SPECIAL_FLAPVER callback. Can be used as an alternate + way of starting the login process, or just to look like you + know what you're doing. Fixed associated inconsistencies + in aim_rxhandlers too. + - Fix some connection status stupidities in faimtest. + - Wed Nov 8 13:11:18 UTC 2000 - Reenable/reimplement older login, but only use for ICQ UINs - This is a fairly ugly hack. But...eh. It works. diff --git a/aim_conn.c b/aim_conn.c index ca42aea..b630145 100644 --- a/aim_conn.c +++ b/aim_conn.c @@ -194,7 +194,7 @@ faim_internal struct aim_conn_t *aim_getconn_type(struct aim_session_t *sess, faim_mutex_lock(&sess->connlistlock); for (cur = sess->connlist; cur; cur = cur->next) { - if (cur->type == type) + if ((cur->type == type) && !(cur->status & AIM_CONN_STATUS_INPROGRESS)) break; } faim_mutex_unlock(&sess->connlistlock); @@ -344,13 +344,24 @@ static int aim_proxyconnect(struct aim_session_t *sess, return -1; } - memset(&sa.sin_zero, 0, 8); + memset(&sa, 0, sizeof(struct sockaddr_in)); sa.sin_port = htons(port); memcpy(&sa.sin_addr, hp->h_addr, hp->h_length); sa.sin_family = hp->h_addrtype; fd = socket(hp->h_addrtype, SOCK_STREAM, 0); + + if (sess->flags & AIM_SESS_FLAGS_NONBLOCKCONNECT) + fcntl(fd, F_SETFL, O_NONBLOCK); /* XXX save flags */ + if (connect(fd, (struct sockaddr *)&sa, sizeof(struct sockaddr_in)) < 0) { + if (sess->flags & AIM_SESS_FLAGS_NONBLOCKCONNECT) { + if ((errno == EINPROGRESS) || (errno == EINTR)) { + if (statusret) + *statusret |= AIM_CONN_STATUS_INPROGRESS; + return fd; + } + } close(fd); fd = -1; } @@ -518,9 +529,9 @@ faim_export struct aim_conn_t *aim_select(struct aim_session_t *sess, struct timeval *timeout, int *status) { struct aim_conn_t *cur; - fd_set fds; + fd_set fds, wfds; int maxfd = 0; - int i; + int i, haveconnecting = 0; faim_mutex_lock(&sess->connlistlock); if (sess->connlist == NULL) { @@ -530,32 +541,50 @@ faim_export struct aim_conn_t *aim_select(struct aim_session_t *sess, } faim_mutex_unlock(&sess->connlistlock); - /* - * If we have data waiting to be sent, return immediatly - */ - if (sess->queue_outgoing != NULL) { - *status = 1; - return NULL; - } - FD_ZERO(&fds); + FD_ZERO(&wfds); maxfd = 0; faim_mutex_lock(&sess->connlistlock); for (cur = sess->connlist; cur; cur = cur->next) { + if (cur->status & AIM_CONN_STATUS_INPROGRESS) { + FD_SET(cur->fd, &wfds); + haveconnecting++; + } 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) { + /* + * If we have data waiting to be sent, return + * + * We have to not do this if theres at least one + * connection thats still connecting, since that connection + * may have queued data and this return would prevent + * the connection from ever completing! This is a major + * inadequacy of the libfaim way of doing things. It means + * that nothing can transmit as long as there's connecting + * sockets. Evil. + * + * But its still better than having blocking connects. + * + */ + if (!haveconnecting && (sess->queue_outgoing != NULL)) { + *status = 1; + return NULL; + } + + if ((i = select(maxfd+1, &fds, &wfds, NULL, timeout))>=1) { faim_mutex_lock(&sess->connlistlock); for (cur = sess->connlist; cur; cur = cur->next) { - if (FD_ISSET(cur->fd, &fds)) { + if ((FD_ISSET(cur->fd, &fds)) || + ((cur->status & AIM_CONN_STATUS_INPROGRESS) && + FD_ISSET(cur->fd, &wfds))) { *status = 2; faim_mutex_unlock(&sess->connlistlock); - return cur; + return cur; /* XXX race condition here -- shouldnt unlock connlist */ } } *status = 0; /* shouldn't happen */ @@ -593,6 +622,8 @@ faim_export int aim_conn_isready(struct aim_conn_t *conn) * @newstatus is %XOR'd with the previous value of the connection * status and returned. Returns -1 if the connection is invalid. * + * This isn't real useful. + * */ faim_export int aim_conn_setstatus(struct aim_conn_t *conn, int status) { @@ -669,11 +700,12 @@ faim_export void aim_setupproxy(struct aim_session_t *sess, char *server, char * /** * aim_session_init - Initializes a session structure * @sess: Session to initialize + * @flags: Flags to use. Any of %AIM_SESS_FLAGS %OR'd together. * * Sets up the initial values for a session. * */ -faim_export void aim_session_init(struct aim_session_t *sess) +faim_export void aim_session_init(struct aim_session_t *sess, unsigned long flags) { if (!sess) return; @@ -685,7 +717,15 @@ faim_export void aim_session_init(struct aim_session_t *sess) sess->pendingjoin = NULL; aim_initsnachash(sess); sess->snac_nextid = 0x00000001; - sess->snaclogin = 1; /* default to yes, oh gods yes. */ + + sess->flags = 0; + + /* + * Default to SNAC login unless XORLOGIN is explicitly set. + */ + if (!(flags & AIM_SESS_FLAGS_XORLOGIN)) + sess->flags |= AIM_SESS_FLAGS_SNACLOGIN; + sess->flags |= flags; /* * This must always be set. Default to the queue-based @@ -695,3 +735,75 @@ faim_export void aim_session_init(struct aim_session_t *sess) return; } + +/** + * aim_conn_isconnecting - Determine if a connection is connecting + * @conn: Connection to examine + * + * Returns nonzero if the connection is in the process of + * connecting (or if it just completed and aim_conn_completeconnect() + * has yet to be called on it). + * + */ +faim_export int aim_conn_isconnecting(struct aim_conn_t *conn) +{ + if (!conn) + return 0; + return (conn->status & AIM_CONN_STATUS_INPROGRESS)?1:0; +} + +faim_export int aim_conn_completeconnect(struct aim_session_t *sess, struct aim_conn_t *conn) +{ + fd_set fds, wfds; + struct timeval tv; + int res, error = ETIMEDOUT; + rxcallback_t userfunc; + + if (!conn || (conn->fd == -1)) + return -1; + + if (!(conn->status & AIM_CONN_STATUS_INPROGRESS)) + return -1; + + FD_ZERO(&fds); + FD_SET(conn->fd, &fds); + FD_ZERO(&wfds); + FD_SET(conn->fd, &wfds); + tv.tv_sec = 0; + tv.tv_usec = 0; + + if ((res = select(conn->fd+1, &fds, &wfds, NULL, &tv)) == -1) { + error = errno; + aim_conn_close(conn); + errno = error; + return -1; + } else if (res == 0) { + printf("faim: aim_conn_completeconnect: false alarm on %d\n", conn->fd); + return 0; /* hasn't really completed yet... */ + } + + if (FD_ISSET(conn->fd, &fds) || FD_ISSET(conn->fd, &wfds)) { + int len = sizeof(error); + + if (getsockopt(conn->fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) + error = errno; + } + + if (error) { + aim_conn_close(conn); + errno = error; + return -1; + } + + fcntl(conn->fd, F_SETFL, 0); /* XXX should restore original flags */ + + conn->status &= ~AIM_CONN_STATUS_INPROGRESS; + + if ((userfunc = aim_callhandler(conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE))) + userfunc(sess, NULL, conn); + + /* Flush out the queues if there was something waiting for this conn */ + aim_tx_flushqueue(sess); + + return 0; +} diff --git a/aim_login.c b/aim_login.c index 49cf7f8..51aedd4 100644 --- a/aim_login.c +++ b/aim_login.c @@ -100,11 +100,12 @@ faim_export int aim_request_login(struct aim_session_t *sess, newrx->lock = 0; - sess->snaclogin = 0; + sess->flags &= ~AIM_SESS_FLAGS_SNACLOGIN; + return 0; } - sess->snaclogin = 1; + sess->flags |= AIM_SESS_FLAGS_SNACLOGIN; aim_sendconnack(sess, conn); @@ -149,9 +150,9 @@ faim_export int aim_send_login (struct aim_session_t *sess, newpacket->lock = 1; - newpacket->hdr.oscar.type = sess->snaclogin?0x02:0x01; + newpacket->hdr.oscar.type = (sess->flags & AIM_SESS_FLAGS_SNACLOGIN)?0x02:0x01; - if (sess->snaclogin) + if (sess->flags & AIM_SESS_FLAGS_SNACLOGIN) curbyte = aim_putsnac(newpacket->data, 0x0017, 0x0002, 0x0000, 0x00010000); else { curbyte = aimutil_put16(newpacket->data, 0x0000); @@ -160,7 +161,7 @@ faim_export int aim_send_login (struct aim_session_t *sess, curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x0001, strlen(sn), sn); - if (sess->snaclogin) { + if (sess->flags & AIM_SESS_FLAGS_SNACLOGIN) { md5_byte_t digest[16]; aim_encode_password_md5(password, key, digest); @@ -178,7 +179,7 @@ faim_export int aim_send_login (struct aim_session_t *sess, if (strlen(clientinfo->clientstring)) curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x0003, strlen(clientinfo->clientstring), clientinfo->clientstring); - if (sess->snaclogin) { + if (sess->flags & AIM_SESS_FLAGS_SNACLOGIN) { curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0016, (unsigned short)clientinfo->major2); curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0017, (unsigned short)clientinfo->major); curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0018, (unsigned short)clientinfo->minor); @@ -292,7 +293,7 @@ faim_internal int aim_authparse(struct aim_session_t *sess, * For SNAC login, there's a 17/3 SNAC header in front. * */ - if (sess->snaclogin) + if (sess->flags & AIM_SESS_FLAGS_SNACLOGIN) tlvlist = aim_readtlvchain(command->data+10, command->commandlen-10); else tlvlist = aim_readtlvchain(command->data, command->commandlen); diff --git a/aim_rxhandlers.c b/aim_rxhandlers.c index 220394f..bc67cbf 100644 --- a/aim_rxhandlers.c +++ b/aim_rxhandlers.c @@ -348,7 +348,7 @@ faim_export int aim_rxdispatch(struct aim_session_t *sess) head = aimutil_get32(workingPtr->data); if ((head == 0x00000001) && (workingPtr->commandlen == 4)) { faimdprintf(1, "got connection ack on auth line\n"); - workingPtr->handled = 1; + workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, workingPtr); } else if (workingPtr->hdr.oscar.type == 0x04) { /* Used only by the older login protocol */ workingPtr->handled = aim_authparse(sess, workingPtr); @@ -405,7 +405,7 @@ faim_export int aim_rxdispatch(struct aim_session_t *sess) switch (family) { case 0x0000: /* not really a family, but it works */ if (subtype == 0x0001) - workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0000, 0x0001, workingPtr); + workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, workingPtr); else workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr); break; @@ -541,10 +541,9 @@ faim_export int aim_rxdispatch(struct aim_session_t *sess) u_short subtype; family = aimutil_get16(workingPtr->data); subtype= aimutil_get16(workingPtr->data+2); - - if ((family == 0x0002) && (subtype == 0x0006)) { - workingPtr->handled = 1; - aim_conn_setstatus(workingPtr->conn, AIM_CONN_STATUS_READY); + + if ((family == 0x0000) && (subtype == 0x00001)) { + workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, workingPtr); } else if ((family == 0x000d) && (subtype == 0x0009)) { workingPtr->handled = aim_chatnav_parse_info(sess, workingPtr); } else { @@ -558,9 +557,9 @@ faim_export int aim_rxdispatch(struct aim_session_t *sess) 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 ((family == 0x0000) && (subtype == 0x00001)) { + workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, workingPtr); + } else if (family == 0x0001) { if (subtype == 0x0001) workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0001, workingPtr); else if (subtype == 0x0003) @@ -804,6 +803,9 @@ faim_internal int aim_parse_unknown(struct aim_session_t *sess, { u_int i = 0; + if (!sess || !command) + return 1; + faimdprintf(1, "\nRecieved unknown packet:"); for (i = 0; i < command->commandlen; i++) diff --git a/aim_rxqueue.c b/aim_rxqueue.c index c625bc2..a26648a 100644 --- a/aim_rxqueue.c +++ b/aim_rxqueue.c @@ -60,6 +60,9 @@ faim_export int aim_get_command(struct aim_session_t *sess, struct aim_conn_t *c if (conn->fd < 3) /* can happen when people abuse the interface */ return 0; + if (conn->status & AIM_CONN_STATUS_INPROGRESS) + return aim_conn_completeconnect(sess, conn); + /* * Rendezvous (client-client) connections do not speak * FLAP, so this function will break on them. diff --git a/aim_txqueue.c b/aim_txqueue.c index 6f6b3c1..9871f93 100644 --- a/aim_txqueue.c +++ b/aim_txqueue.c @@ -151,6 +151,19 @@ faim_internal int aim_tx_enqueue__immediate(struct aim_session_t *sess, struct c return 0; } +faim_internal int aim_tx_enqueue(struct aim_session_t *sess, struct command_tx_struct *command) +{ + /* + * If we want to send a connection thats inprogress, we have to force + * them to use the queue based version. Otherwise, use whatever they + * want. + */ + if (command && command->conn && (command->conn->status & AIM_CONN_STATUS_INPROGRESS)) { + return aim_tx_enqueue__queuebased(sess, command); + } + return (*sess->tx_enqueue)(sess, command); +} + /* * aim_get_next_txseqnum() * @@ -347,6 +360,9 @@ faim_export int aim_tx_flushqueue(struct aim_session_t *sess) /* only process if its unlocked and unsent */ if (!cur->lock && !cur->sent) { + if (cur->conn && (cur->conn->status & AIM_CONN_STATUS_INPROGRESS)) + continue; + /* * And now for the meager attempt to force transmit * latency and avoid missed messages. diff --git a/faim/aim.h b/faim/aim.h index 645b06b..46e2e8f 100644 --- a/faim/aim.h +++ b/faim/aim.h @@ -208,8 +208,9 @@ struct client_info_s { */ #define AIM_CONN_STATUS_READY 0x0001 #define AIM_CONN_STATUS_INTERNALERR 0x0002 -#define AIM_CONN_STATUS_RESOLVERR 0x0080 -#define AIM_CONN_STATUS_CONNERR 0x0040 +#define AIM_CONN_STATUS_RESOLVERR 0x0040 +#define AIM_CONN_STATUS_CONNERR 0x0080 +#define AIM_CONN_STATUS_INPROGRESS 0x0100 #define AIM_FRAMETYPE_OSCAR 0x0000 #define AIM_FRAMETYPE_OFT 0x0001 @@ -350,11 +351,15 @@ struct aim_session_t { char password[128]; } socksproxy; - int snaclogin; + unsigned long flags; struct aim_msgcookie_t *msgcookies; }; +/* Values for sess->flags */ +#define AIM_SESS_FLAGS_SNACLOGIN 0x00000001 +#define AIM_SESS_FLAGS_XORLOGIN 0x00000002 +#define AIM_SESS_FLAGS_NONBLOCKCONNECT 0x00000004 /* * AIM User Info, Standard Form. @@ -468,7 +473,7 @@ faim_internal int aim_get_command_rendezvous(struct aim_session_t *sess, struct faim_internal struct command_tx_struct *aim_tx_new(unsigned char framing, int chan, struct aim_conn_t *conn, int datalen); faim_internal int aim_tx_enqueue__queuebased(struct aim_session_t *, struct command_tx_struct *); faim_internal int aim_tx_enqueue__immediate(struct aim_session_t *, struct command_tx_struct *); -#define aim_tx_enqueue(x, y) ((*(x->tx_enqueue))(x, y)) +faim_internal int aim_tx_enqueue(struct aim_session_t *, struct command_tx_struct *); faim_internal int aim_tx_sendframe(struct aim_session_t *sess, struct command_tx_struct *cur); faim_internal unsigned int aim_get_next_txseqnum(struct aim_conn_t *); faim_export int aim_tx_flushqueue(struct aim_session_t *); @@ -517,7 +522,9 @@ faim_export int aim_conngetmaxfd(struct aim_session_t *); faim_export struct aim_conn_t *aim_select(struct aim_session_t *, struct timeval *, int *); faim_export int aim_conn_isready(struct aim_conn_t *); faim_export int aim_conn_setstatus(struct aim_conn_t *, int); -faim_export void aim_session_init(struct aim_session_t *); +faim_export int aim_conn_completeconnect(struct aim_session_t *sess, struct aim_conn_t *conn); +faim_export int aim_conn_isconnecting(struct aim_conn_t *conn); +faim_export void aim_session_init(struct aim_session_t *, unsigned long flags); faim_export void aim_setupproxy(struct aim_session_t *sess, char *server, char *username, char *password); /* aim_misc.c */ diff --git a/faim/aim_cbtypes.h b/faim/aim_cbtypes.h index 6e8fa74..c0705ba 100644 --- a/faim/aim_cbtypes.h +++ b/faim/aim_cbtypes.h @@ -214,6 +214,8 @@ #define AIM_CB_SPECIAL_AUTHSUCCESS 0x0001 #define AIM_CB_SPECIAL_AUTHOTHER 0x0002 #define AIM_CB_SPECIAL_CONNERR 0x0003 +#define AIM_CB_SPECIAL_CONNCOMPLETE 0x0004 +#define AIM_CB_SPECIAL_FLAPVER 0x0005 #define AIM_CB_SPECIAL_DEBUGCONN_CONNECT 0xe001 #define AIM_CB_SPECIAL_UNKNOWN 0xffff #define AIM_CB_SPECIAL_DEFAULT AIM_CB_SPECIAL_UNKNOWN diff --git a/utils/faimtest/faimtest.c b/utils/faimtest/faimtest.c index cfd6c64..687ca7c 100644 --- a/utils/faimtest/faimtest.c +++ b/utils/faimtest/faimtest.c @@ -116,6 +116,8 @@ static char *msgerrreasons[] = { "Not while on AOL"}; static int msgerrreasonslen = 25; +static char *screenname,*password,*server=NULL; + int faimtest_reportinterval(struct aim_session_t *sess, struct command_rx_struct *command, ...) { if (command->data) { @@ -125,6 +127,49 @@ int faimtest_reportinterval(struct aim_session_t *sess, struct command_rx_struct return 1; } +int faimtest_flapversion(struct aim_session_t *sess, struct command_rx_struct *command, ...) +{ + + printf("faimtest: using FLAP version %u\n", aimutil_get32(command->data)); + +#if 0 + /* + * This is an alternate location for starting the login process. + */ + /* XXX should do more checking to make sure its really the right AUTH conn */ + if (command->conn->type == AIM_CONN_TYPE_AUTH) { + /* do NOT send a connack/flapversion, request_login will send it if needed */ + aim_request_login(sess, command->conn, screenname); + printf("faimtest: login request sent\n"); + } +#endif + + return 1; +} + +/* + * This is a frivilous callback. You don't need it. I only used it for + * debugging non-blocking connects. + * + * If packets are sent to a conn before its fully connected, they + * will be queued and then transmitted when the connection completes. + * + */ +int faimtest_conncomplete(struct aim_session_t *sess, struct command_rx_struct *command, ...) +{ + va_list ap; + struct aim_conn_t *conn; + + va_start(ap, command); + conn = va_arg(ap, struct aim_conn_t *); + va_end(ap); + + if (conn) + printf("faimtest: connection on %d completed\n", conn->fd); + + return 1; +} + #ifdef _WIN32 /* * This is really all thats needed to link against libfaim on win32. @@ -142,8 +187,6 @@ int initwsa(void) } #endif /* _WIN32 */ -static char *screenname,*password,*server=NULL; - int main(void) { struct aim_session_t aimsess; @@ -183,7 +226,8 @@ int main(void) } #endif /* _WIN32 */ - aim_session_init(&aimsess); + /* Pass zero as flags if you want blocking connects */ + aim_session_init(&aimsess, AIM_SESS_FLAGS_NONBLOCKCONNECT); #ifdef FILESUPPORT if(listingpath) { @@ -221,14 +265,15 @@ int main(void) return -1; } + aim_conn_addhandler(&aimsess, authconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, faimtest_flapversion, 0); + aim_conn_addhandler(&aimsess, authconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0); aim_conn_addhandler(&aimsess, authconn, 0x0017, 0x0007, faimtest_parse_login, 0); - aim_conn_addhandler(&aimsess, authconn, 0x0017, 0x0003, faimtest_parse_authresp, 0); - - /* do NOT send a connack/flapversion, request_login will send it if needed */ - aim_request_login(&aimsess, authconn, screenname); + aim_conn_addhandler(&aimsess, authconn, 0x0017, 0x0003, faimtest_parse_authresp, 0); aim_conn_addhandler(&aimsess, authconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_DEBUGCONN_CONNECT, faimtest_debugconn_connect, 0); + /* If the connection is in progress, this will just be queued */ + aim_request_login(&aimsess, authconn, screenname); printf("faimtest: login request sent\n"); while (keepgoing) { @@ -432,11 +477,13 @@ int faimtest_handleredirect(struct aim_session_t *sess, struct command_rx_struct struct aim_conn_t *tstconn; /* Open a connection to the Auth */ tstconn = aim_newconn(sess, AIM_CONN_TYPE_AUTH, ip); - if ( (tstconn==NULL) || (tstconn->status >= AIM_CONN_STATUS_RESOLVERR) ) + if ( (tstconn==NULL) || (tstconn->status & AIM_CONN_STATUS_RESOLVERR) ) fprintf(stderr, "faimtest: unable to reconnect with authorizer\n"); - else + else { + 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); + } } break; @@ -444,7 +491,7 @@ int faimtest_handleredirect(struct aim_session_t *sess, struct command_rx_struct { struct aim_conn_t *tstconn = NULL; tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHATNAV, ip); - if ( (tstconn==NULL) || (tstconn->status >= AIM_CONN_STATUS_RESOLVERR)) { + 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; @@ -454,6 +501,7 @@ int faimtest_handleredirect(struct aim_session_t *sess, struct command_rx_struct 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_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0); aim_auth_sendcookie(sess, tstconn, cookie); fprintf(stderr, "\achatnav: connected\n"); } @@ -466,7 +514,7 @@ int faimtest_handleredirect(struct aim_session_t *sess, struct command_rx_struct roomname = va_arg(ap, char *); tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHAT, ip); - if ( (tstconn==NULL) || (tstconn->status >= AIM_CONN_STATUS_RESOLVERR)) + 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); @@ -480,6 +528,7 @@ int faimtest_handleredirect(struct aim_session_t *sess, struct command_rx_struct aim_chat_attachname(tstconn, roomname); aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, faimtest_serverready, 0); + aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0); aim_auth_sendcookie(sess, tstconn, cookie); } break; @@ -520,10 +569,11 @@ int faimtest_parse_authresp(struct aim_session_t *sess, struct command_rx_struct 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) { + } else if (bosconn->status & AIM_CONN_STATUS_CONNERR) { fprintf(stderr, "faimtest: could not connect to BOS\n"); aim_conn_kill(sess, &bosconn); } else { + 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, 0); /* rate info */ aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_ACK, AIM_CB_ACK_ACK, NULL, 0); -- 2.45.1