From: mid Date: Sun, 2 Apr 2000 03:34:12 +0000 (+0000) Subject: - Sun Apr 2 01:45:15 UTC 2000 X-Git-Tag: rel_0_99_2~165 X-Git-Url: http://andersk.mit.edu/gitweb/libfaim.git/commitdiff_plain/f1a5efe0f353b6c28d4d962b3416329024771cef - Sun Apr 2 01:45:15 UTC 2000 - Increased AIM_CONN_MAX from 5 to 7. Precausionary only - Removed deprecated TIS_TELNET_PROXY from faim/faimconfig.h - Added macros for the simple integer functions in aim_util.c - Removed usage of aim_failsaferead() - Still not sure why I had it to begin with. I think it was a remament from when we used non-blocking sockets (which I don't know why I did either) - Removed some of the oddities in aim_get_command() - gprof showed this taking 20kns on my k6-300. Should be faster now. - Added conn parameter. This should prevent aim_select() from getting called too many times in a row. --- diff --git a/CHANGES b/CHANGES index e10031f..47e82b6 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,19 @@ No release numbers ------------------ + - Sun Apr 2 01:45:15 UTC 2000 + - Increased AIM_CONN_MAX from 5 to 7. Precausionary only + - Removed deprecated TIS_TELNET_PROXY from faim/faimconfig.h + - Added macros for the simple integer functions in aim_util.c + - Removed usage of aim_failsaferead() + - Still not sure why I had it to begin with. I think it + was a remament from when we used non-blocking sockets + (which I don't know why I did either) + - Removed some of the oddities in aim_get_command() + - gprof showed this taking 20kns on my k6-300. Should be faster now. + - Added conn parameter. This should prevent aim_select() from + getting called too many times in a row. + - Thu Mar 23 08:45:40 UTC 2000 - Removed aim_countconn() > 0 check in aim_select(), its logically redundent - Added aim_putuserinfo() (inverse of aim_extractuserinfo()) diff --git a/aim_chat.c b/aim_chat.c index 6ce4b69..83256f0 100644 --- a/aim_chat.c +++ b/aim_chat.c @@ -247,16 +247,16 @@ int aim_chat_readroominfo(u_char *buf, struct aim_chat_roominfo *outinfo) int aim_chat_parse_infoupdate(struct aim_session_t *sess, struct command_rx_struct *command) { - struct aim_userinfo_s *userinfo; + struct aim_userinfo_s *userinfo = NULL; rxcallback_t userfunc=NULL; int ret = 1, i = 0; int usercount = 0; u_char detaillevel = 0; - char *roomname; + char *roomname = NULL; struct aim_chat_roominfo roominfo; u_short tlvcount = 0; struct aim_tlvlist_t *tlvlist; - char *roomdesc; + char *roomdesc = NULL; i = 10; i += aim_chat_readroominfo(command->data+i, &roominfo); diff --git a/aim_conn.c b/aim_conn.c index cb4d1b2..5cb4a79 100644 --- a/aim_conn.c +++ b/aim_conn.c @@ -176,6 +176,9 @@ struct aim_conn_t *aim_select(struct aim_session_t *sess, fd_set fds; int i; + if (aim_countconn(sess) <= 0) + return 0; + /* * If we have data waiting to be sent, return immediatly */ diff --git a/aim_rxqueue.c b/aim_rxqueue.c index 7ec7e13..4298b47 100644 --- a/aim_rxqueue.c +++ b/aim_rxqueue.c @@ -1,175 +1,92 @@ /* - aim_rxqueue.c - - This file contains the management routines for the receive - (incoming packet) queue. The actual packet handlers are in - aim_rxhandlers.c. - + * aim_rxqueue.c + * + * This file contains the management routines for the receive + * (incoming packet) queue. The actual packet handlers are in + * aim_rxhandlers.c. */ #include - /* - * This is a modified read() to make SURE we get the number - * of bytes we are told to, otherwise block. - * - * Modified to count errno (Sébastien Carpe ) - * -*/ -int aim_failsaferead(int fd, u_char *buf, int len) -{ - int i = 0; - int j = 0; - int err_count=0; - - while ((i < len) && (!(i < 0))) - { - j = read(fd, &(buf[i]), len-i); - if ( (j < 0) && (errno != EAGAIN)) - return -errno; /* fail */ - else if (j==0) - { - err_count++; - if (err_count> MAX_READ_ERROR) { - /* - * Reached maximum number of allowed read errors. - * - * Lets suppose the connection is lost and errno didn't - * know it. - * - */ - return (-1); - } - } - else - i += j; /* success, continue */ - } - return i; -} - -/* - * Grab as many command sequences as we can off the socket, and enqueue - * each command in the incoming event queue in a seperate struct. + * Grab a single command sequence off the socket, and enqueue + * it in the incoming event queue in a seperate struct. */ -int aim_get_command(struct aim_session_t *sess) +int aim_get_command(struct aim_session_t *sess, struct aim_conn_t *conn) { - int i, readgood, j, isav, err; - int s; - fd_set fds; - struct timeval tv; - char generic[6]; - struct command_rx_struct *workingStruct = NULL; - struct aim_conn_t *conn = NULL; - int selstat = 0; - - faimdprintf(1, "Reading generic/unknown response..."); - - /* dont wait at all (ie, never call this unless something is there) */ - tv.tv_sec = 0; - tv.tv_usec = 0; - conn = aim_select(sess, &tv, &selstat); - - if (conn==NULL) - return 0; /* nothing waiting */ + u_char generic[6]; + struct command_rx_struct *newrx = NULL; - s = conn->fd; + if (!sess || !conn) + return 0; - if (s < 3) + if (conn->fd < 3) /* can happen when people abuse the interface */ return 0; - FD_ZERO(&fds); - FD_SET(s, &fds); - tv.tv_sec = 0; /* wait, but only for 10us */ - tv.tv_usec = 10; - - generic[0] = 0x00; - - readgood = 0; - i = 0; - j = 0; - /* read first 6 bytes (the FLAP header only) off the socket */ - while ( (select(s+1, &fds, NULL, NULL, &tv) == 1) && (i < 6)) - { - if ((err = aim_failsaferead(s, &(generic[i]), 1)) < 0) - { - /* error is probably not recoverable...(must be a pessimistic day) */ - /* aim_conn_close(conn); */ - return err; - } - - if (readgood == 0) - { - if (generic[i] == 0x2a) - { - readgood = 1; - faimdprintf(1, "%x ", generic[i]); - i++; - } - else - { - faimdprintf(1, "skipping 0x%d ", generic[i]); - j++; - } - } - else - { - faimdprintf(1, "%x ", generic[i]); - i++; - } - FD_ZERO(&fds); - FD_SET(s, &fds); - tv.tv_sec= 2; - tv.tv_usec= 2; - } + /* + * Read FLAP header. Six bytes: + * + * 0 char -- Always 0x2a + * 1 char -- Channel ID. Usually 2 -- 1 and 4 are used during login. + * 2 short -- Sequence number + * 4 short -- Number of data bytes that follow. + */ + if (read(conn->fd, generic, 6) < 6){ + aim_conn_close(conn); + return -1; + } /* * This shouldn't happen unless the socket breaks, the server breaks, * or we break. We must handle it just in case. */ if (generic[0] != 0x2a) { - printf("Bad incoming data!"); + faimdprintf(1, "Bad incoming data!"); return -1; } - isav = i; - /* allocate a new struct */ - workingStruct = (struct command_rx_struct *) malloc(sizeof(struct command_rx_struct)); - memset(workingStruct, 0x00, sizeof(struct command_rx_struct)); + newrx = (struct command_rx_struct *)malloc(sizeof(struct command_rx_struct)); + if (!newrx) + return -1; + memset(newrx, 0x00, sizeof(struct command_rx_struct)); - workingStruct->lock = 1; /* lock the struct */ + newrx->lock = 1; /* lock the struct */ /* store channel -- byte 2 */ - workingStruct->type = (char) generic[1]; + newrx->type = (char) generic[1]; /* store seqnum -- bytes 3 and 4 */ - workingStruct->seqnum = aimutil_get16(generic+2); + newrx->seqnum = aimutil_get16(generic+2); /* store commandlen -- bytes 5 and 6 */ - workingStruct->commandlen = aimutil_get16(generic+4); + newrx->commandlen = aimutil_get16(generic+4); - workingStruct->nofree = 0; /* free by default */ + newrx->nofree = 0; /* free by default */ /* malloc for data portion */ - workingStruct->data = (u_char *) malloc(workingStruct->commandlen); + newrx->data = (u_char *) malloc(newrx->commandlen); + if (!newrx->data) { + free(newrx); + return -1; + } /* read the data portion of the packet */ - if (aim_failsaferead(s, workingStruct->data, workingStruct->commandlen) < 0){ + if (read(conn->fd, newrx->data, newrx->commandlen) < newrx->commandlen){ + free(newrx->data); + free(newrx); aim_conn_close(conn); return -1; } - faimdprintf(1, " done. (%db+%db read, %db skipped)\n", isav, i, j); - - workingStruct->conn = conn; + newrx->conn = conn; - workingStruct->next = NULL; /* this will always be at the bottom */ - workingStruct->lock = 0; /* unlock */ + newrx->next = NULL; /* this will always be at the bottom */ + newrx->lock = 0; /* unlock */ /* enqueue this packet */ if (sess->queue_incoming == NULL) { - sess->queue_incoming = workingStruct; + sess->queue_incoming = newrx; } else { struct command_rx_struct *cur; @@ -181,10 +98,10 @@ int aim_get_command(struct aim_session_t *sess) */ for (cur = sess->queue_incoming; cur->next; cur = cur->next) ; - cur->next = workingStruct; + cur->next = newrx; } - workingStruct->conn->lastactivity = time(NULL); + newrx->conn->lastactivity = time(NULL); return 0; } diff --git a/aim_txqueue.c b/aim_txqueue.c index 8a42e33..a21481f 100644 --- a/aim_txqueue.c +++ b/aim_txqueue.c @@ -7,6 +7,23 @@ #include +/* + * Allocate a new tx frame. + * + * This is more for looks than anything else. + */ +struct command_tx_struct *aim_tx_new(void) +{ + struct command_tx_struct *new; + + new = (struct command_tx_struct *)malloc(sizeof(struct command_tx_struct)); + if (!new) + return NULL; + memset(new, 0, sizeof(struct command_tx_struct)); + + return new; +} + /* * aim_tx_enqeue() * diff --git a/aim_util.c b/aim_util.c index 0fa8427..9bbf828 100644 --- a/aim_util.c +++ b/aim_util.c @@ -7,13 +7,18 @@ #include #include -int aimutil_put8(u_char *buf, u_char data) +#define AIMUTIL_USEMACROS + +#ifdef AIMUTIL_USEMACROS +/* macros in faim/aim.h */ +#else +inline int aimutil_put8(u_char *buf, u_char data) { buf[0] = (u_char)data&0xff; return 1; } -u_char aimutil_get8(u_char *buf) +inline u_char aimutil_get8(u_char *buf) { return buf[0]; } @@ -21,14 +26,14 @@ u_char aimutil_get8(u_char *buf) /* * Endian-ness issues here? */ -int aimutil_put16(u_char *buf, u_short data) +inline int aimutil_put16(u_char *buf, u_short data) { buf[0] = (u_char)(data>>8)&0xff; buf[1] = (u_char)(data)&0xff; return 2; } -u_short aimutil_get16(u_char *buf) +inline u_short aimutil_get16(u_char *buf) { u_short val; val = (buf[0] << 8) & 0xff00; @@ -36,7 +41,7 @@ u_short aimutil_get16(u_char *buf) return val; } -int aimutil_put32(u_char *buf, u_long data) +inline int aimutil_put32(u_char *buf, u_long data) { buf[0] = (u_char)(data>>24)&0xff; buf[1] = (u_char)(data>>16)&0xff; @@ -45,7 +50,7 @@ int aimutil_put32(u_char *buf, u_long data) return 4; } -u_long aimutil_get32(u_char *buf) +inline u_long aimutil_get32(u_char *buf) { u_long val; val = (buf[0] << 24) & 0xff000000; @@ -54,8 +59,9 @@ u_long aimutil_get32(u_char *buf) val+= (buf[3] ) & 0x000000ff; return val; } +#endif /* AIMUTIL_USEMACROS */ -int aimutil_putstr(u_char *dest, const u_char *src, int len) +inline int aimutil_putstr(u_char *dest, const u_char *src, int len) { memcpy(dest, src, len); return len; @@ -174,8 +180,7 @@ int aim_snlen(const char *sn) return 0; curPtr = sn; - while ( (*curPtr) != (char) NULL) - { + while ( (*curPtr) != (char) NULL) { if ((*curPtr) != ' ') i++; curPtr++; @@ -206,23 +211,19 @@ int aim_sncmp(const char *sn1, const char *sn2) curPtr1 = sn1; curPtr2 = sn2; - while ( (*curPtr1 != (char) NULL) && (*curPtr2 != (char) NULL) ) - { - if ( (*curPtr1 == ' ') || (*curPtr2 == ' ') ) - { - if (*curPtr1 == ' ') - curPtr1++; - if (*curPtr2 == ' ') - curPtr2++; - } - else - { - if ( toupper(*curPtr1) != toupper(*curPtr2)) - return 1; - curPtr1++; - curPtr2++; - } + while ( (*curPtr1 != (char) NULL) && (*curPtr2 != (char) NULL) ) { + if ( (*curPtr1 == ' ') || (*curPtr2 == ' ') ) { + if (*curPtr1 == ' ') + curPtr1++; + if (*curPtr2 == ' ') + curPtr2++; + } else { + if ( toupper(*curPtr1) != toupper(*curPtr2)) + return 1; + curPtr1++; + curPtr2++; } + } return 0; } diff --git a/faim/aim.h b/faim/aim.h index dc82d19..e230c9a 100644 --- a/faim/aim.h +++ b/faim/aim.h @@ -262,7 +262,7 @@ int aim_counttlvchain(struct aim_tlvlist_t **list); * Get command from connections / Dispatch commands * already in queue. */ -int aim_get_command(struct aim_session_t *); +int aim_get_command(struct aim_session_t *, struct aim_conn_t *); int aim_rxdispatch(struct aim_session_t *); int aim_logoff(struct aim_session_t *); @@ -299,6 +299,7 @@ int aim_parse_unknown(struct aim_session_t *, struct command_rx_struct *command, int aim_parse_missed_im(struct aim_session_t *, struct command_rx_struct *, ...); int aim_parse_last_bad(struct aim_session_t *, struct command_rx_struct *, ...); +struct command_tx_struct *aim_tx_new(void); int aim_tx_enqueue(struct aim_session_t *, struct command_tx_struct *); u_int aim_get_next_txseqnum(struct aim_conn_t *); int aim_tx_flushqueue(struct aim_session_t *); @@ -400,6 +401,7 @@ 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); + /* aim_auth.c */ int aim_auth_sendcookie(struct aim_session_t *, struct aim_conn_t *, u_char *); u_long aim_auth_clientready(struct aim_session_t *, struct aim_conn_t *); @@ -449,12 +451,37 @@ u_long aim_chatnav_createroom(struct aim_session_t *sess, struct aim_conn_t *con int aim_chat_leaveroom(struct aim_session_t *sess, char *name); /* aim_util.c */ +#ifdef AIMUTIL_USEMACROS +/* + * These are really ugly. You'd think this was LISP. I wish it was. + */ +#define aimutil_put8(buf, data) ((*(buf) = (u_char)(data)&0xff),1) +#define aimutil_get8(buf) ((*(buf))&0xff) +#define aimutil_put16(buf, data) ( \ + (*(buf) = (u_char)((data)>>8)&0xff), \ + (*((buf)+1) = (u_char)(data)&0xff), \ + 2) +#define aimutil_get16(buf) ((((*(buf))<<8)&0xff00) + ((*((buf)+1)) & 0xff)) +#define aimutil_put32(buf, data) ( \ + (*((buf)) = (u_char)((data)>>24)&0xff), \ + (*((buf)+1) = (u_char)((data)>>16)&0xff), \ + (*((buf)+2) = (u_char)((data)>>8)&0xff), \ + (*((buf)+3) = (u_char)(data)&0xff), \ + 4) +#define aimutil_get32(buf) ((((*(buf))<<24)&0xff000000) + \ + (((*((buf)+1))<<16)&0x00ff0000) + \ + (((*((buf)+2))<< 8)&0x0000ff00) + \ + (((*((buf)+3) )&0x000000ff))) +#else +#warning Not using aimutil macros. May have performance problems. int aimutil_put8(u_char *, u_char); u_char aimutil_get8(u_char *buf); int aimutil_put16(u_char *, u_short); u_short aimutil_get16(u_char *); int aimutil_put32(u_char *, u_long); u_long aimutil_get32(u_char *); +#endif + int aimutil_putstr(u_char *, const u_char *, int); int aimutil_tokslen(char *toSearch, int index, char dl); int aimutil_itemcnt(char *toSearch, char dl); diff --git a/faim/faimconfig.h b/faim/faimconfig.h index 64229c8..0184f77 100644 --- a/faim/faimconfig.h +++ b/faim/faimconfig.h @@ -1,7 +1,7 @@ /* * faimconfig.h * - * Contains various compile-time options that apply _only to libfaim. + * Contains various compile-time options that apply _only_ to libfaim. * Note that setting any of these options in a frontend header does not imply * that they'll get set here. Notably, the 'debug' of this file is _not_ * the same as the frontend 'debug'. They can be different values. @@ -23,24 +23,21 @@ /* * Maximum number of connections the library can simultaneously * handle per session structure. Five is fairly arbitrary. - * Only one client that I know of uses more than one concurrently - * anyway (which means its only lightly tested too). + * + * Normally, only one connection gets used at a time. However, if + * chat is used, its easily possible for several connections to be + * open simultaneously. * - * Default: 5 + * Normal connection list looks like this: + * 1 -- used for authentication at login (closed after login) + * 1 -- used for BOS (general messaging) (stays open for entire session) + * 1 -- used for chatnav (room creation, etc) (opened at random) + * 1n -- used for n connected chat rooms (AOL limits to three) * - */ -#define AIM_CONN_MAX 5 - -/* - * define TIS_TELNET_PROXY if you have a TIS firewall (Gauntlet) and - * you want to use FAIM through the firewall + * Default: 7 * - * XXX: The TIS firewall code hasn't existed, let alone worked, - * in many, many months. I'd be happy to take fixes. - * - * Default: undefined */ -#undef TIS_TELNET_PROXY "proxy.mydomain.com" +#define AIM_CONN_MAX 7 /* * USE_SNAC_FOR_IMS is an old feature that allowed better @@ -80,6 +77,9 @@ * AIM process. The later server addresses come from * the authorizer service. * + * This is only here for convenience. Its still up to + * the client to connect to it. + * */ #define FAIM_LOGIN_SERVER "login.oscar.aol.com" #define FAIM_LOGIN_PORT 5190 @@ -93,4 +93,14 @@ */ #define MAX_READ_ERROR 100 +/* + * The integer extraction/copying functions in aim_util.c have + * both a function version and a macro version. The macro + * version is suggested. Since the function version is more + * readable, I leave both around for reference. + * + * Default: defined. + */ +#define AIMUTIL_USEMACROS + #endif /* __FAIMCONFIG_H__ */ diff --git a/utils/faimtest/faimtest.c b/utils/faimtest/faimtest.c index fc400f5..62b049b 100644 --- a/utils/faimtest/faimtest.c +++ b/utils/faimtest/faimtest.c @@ -65,12 +65,12 @@ int faimtest_chat_infoupdate(struct aim_session_t *sess, struct command_rx_struc int faimtest_chat_leave(struct aim_session_t *sess, struct command_rx_struct *command, ...); int faimtest_chat_join(struct aim_session_t *sess, struct command_rx_struct *command, ...); -static char *screenname,*password; +static char *screenname,*password,*server=NULL; int main(void) { struct aim_session_t aimsess; - struct aim_conn_t *authconn = NULL; + struct aim_conn_t *authconn = NULL, *waitingconn = NULL; int keepgoing = 1, stayconnected = 1; struct client_info_s info = {"FAIMtest (Hi guys!)", 3, 5, 1670, "us", "en"}; int selstat = 0; @@ -84,12 +84,14 @@ int main(void) return -1; } + server = getenv("AUTHSERVER"); + /* * (I used a goto-based loop here because n wanted quick proof * that reconnecting without restarting was actually possible...) */ enter: - authconn = aim_newconn(&aimsess, AIM_CONN_TYPE_AUTH, FAIM_LOGIN_SERVER); + authconn = aim_newconn(&aimsess, AIM_CONN_TYPE_AUTH, server?server:FAIM_LOGIN_SERVER); if (authconn == NULL) { @@ -122,7 +124,7 @@ int main(void) } while (keepgoing) { - aim_select(&aimsess, NULL, &selstat); + waitingconn = aim_select(&aimsess, NULL, &selstat); switch(selstat) { case -1: /* error */ @@ -137,7 +139,7 @@ int main(void) break; case 2: /* incoming data pending */ - if (aim_get_command(&aimsess) < 0) { + if (aim_get_command(&aimsess, waitingconn) < 0) { printf("\afaimtest: connection error!\n"); } else aim_rxdispatch(&aimsess);