# HG changeset patch # User Eric Warmenhoven # Date 973896542 0 # Node ID efcacae6acdbc4eb868814f55555469a6e743823 # Parent e6637ff339579c6d26bde5d9f140bb43791b4590 [gaim-migrate @ 1091] libfaim connects non-blocking committer: Tailor Script diff -r e6637ff33957 -r efcacae6acdb doc/CREDITS --- a/doc/CREDITS Fri Nov 10 05:54:04 2000 +0000 +++ b/doc/CREDITS Fri Nov 10 22:49:02 2000 +0000 @@ -47,6 +47,7 @@ G. Sumner Hayes Security Patches Brian Ryner for a little make file patch :) Ryan C. Gordon +Elliot Tobin A big thanks to the X-Chat developers, who were kind enough to license X-Chat under the GPL so that I could learn to be as cool diff -r e6637ff33957 -r efcacae6acdb libfaim/CHANGES --- a/libfaim/CHANGES Fri Nov 10 05:54:04 2000 +0000 +++ b/libfaim/CHANGES Fri Nov 10 22:49:02 2000 +0000 @@ -1,6 +1,39 @@ 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. + - You'll need to remove the aim_sendconnack() before the + call to aim_request_login. It will now do it automatically + if its needed. (hint: ***CLIENT CHANGE***) + + - Wed Nov 8 02:23:25 UTC 2000 + - I'm trying out using a modified version of the kernel-doc scripts + to help document the libfaim code a bit. See aim_conn.c and + aim_tlv.c, as well as the scripts in utils/docs. + + - Wed Oct 25 17:52:20 UTC 2000 + - Cleanup warnings from newer gcc's (RH7.0) + - Aparently newer gcc's don't let you do as strong of integer types + on va_arg as older ones... So, let me know if this breaks on your + compiler + - Tue Oct 17 02:10:13 UTC 2000 - Rearrange a few things diff -r e6637ff33957 -r efcacae6acdb libfaim/aim_conn.c --- a/libfaim/aim_conn.c Fri Nov 10 05:54:04 2000 +0000 +++ b/libfaim/aim_conn.c Fri Nov 10 22:49:02 2000 +0000 @@ -14,8 +14,12 @@ #include #endif -/* - * Clears out connection list, killing remaining connections. +/** + * aim_connrst - Clears out connection list, killing remaining connections. + * @sess: Session to be cleared + * + * Clears out the connection list and kills any connections left. + * */ faim_internal void aim_connrst(struct aim_session_t *sess) { @@ -34,8 +38,12 @@ return; } -/* - * Gets a new connection structure. +/** + * aim_conn_getnext - Gets a new connection structure. + * @sess: Session + * + * Allocate a new empty connection structure. + * */ faim_internal struct aim_conn_t *aim_conn_getnext(struct aim_session_t *sess) { @@ -61,6 +69,13 @@ return newconn; } +/** + * aim_conn_init - Reset a connection to default values. + * @deadconn: Connection to be reset + * + * Initializes and/or resets a connection structure. + * + */ static void aim_conn_init(struct aim_conn_t *deadconn) { if (!deadconn) @@ -80,6 +95,14 @@ return; } +/** + * aim_conn_kill - Close and free a connection. + * @sess: Session for the connection + * @deadconn: Connection to be freed + * + * Close, clear, and free a connection structure. + * + */ faim_export void aim_conn_kill(struct aim_session_t *sess, struct aim_conn_t **deadconn) { struct aim_conn_t *cur; @@ -117,6 +140,13 @@ return; } +/** + * aim_conn_close - Close a connection + * @deadconn: Connection to close + * + * Close (but not free) a connection. + * + */ faim_export void aim_conn_close(struct aim_conn_t *deadconn) { int typesav = -1, subtypesav = -1; @@ -147,6 +177,16 @@ return; } +/** + * aim_getconn_type - Find a connection of a specific type + * @sess: Session to search + * @type: Type of connection to look for + * + * Searches for a connection of the specified type in the + * specified session. Returns the first connection of that + * type found. + * + */ faim_internal struct aim_conn_t *aim_getconn_type(struct aim_session_t *sess, int type) { @@ -154,15 +194,24 @@ 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); return cur; } -/* - * An extrememly quick and dirty SOCKS5 interface. +/** + * aim_proxyconnect - An extrememly quick and dirty SOCKS5 interface. + * @sess: Session to connect + * @host: Host to connect to + * @port: Port to connect to + * @statusret: Return value of the connection + * + * Attempts to connect to the specified host via the configured + * proxy settings, if present. If no proxy is configured for + * this session, the connection is done directly. + * */ static int aim_proxyconnect(struct aim_session_t *sess, char *host, unsigned short port, @@ -295,13 +344,24 @@ 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; } @@ -309,10 +369,16 @@ return fd; } -/* - * aim_newconn(type, dest) +/** + * aim_newconn - Open a new connection + * @sess: Session to create connection in + * @type: Type of connection to create + * @dest: Host to connect to (in "host:port" syntax) * - * Opens a new connection to the specified dest host of type type. + * Opens a new connection to the specified dest host of specified + * type, using the proxy settings if available. If @host is %NULL, + * the connection is allocated and returned, but no connection + * is made. * * FIXME: Return errors in a more sane way. * @@ -375,6 +441,14 @@ return connstruct; } +/** + * aim_conngetmaxfd - Return the highest valued file discriptor in session + * @sess: Session to search + * + * Returns the highest valued filed descriptor of all open + * connections in @sess. + * + */ faim_export int aim_conngetmaxfd(struct aim_session_t *sess) { int j = 0; @@ -390,6 +464,13 @@ return j; } +/** + * aim_countconn - Return the number of open connections in the session + * @sess: Session to look at + * + * Returns the number of number connections in @sess. + * + */ static int aim_countconn(struct aim_session_t *sess) { int cnt = 0; @@ -403,6 +484,15 @@ return cnt; } +/** + * aim_conn_in_sess - Predicate to test the precense of a connection in a sess + * @sess: Session to look in + * @conn: Connection to look for + * + * Searches @sess for the passed connection. Returns 1 if its present, + * zero otherwise. + * + */ faim_export int aim_conn_in_sess(struct aim_session_t *sess, struct aim_conn_t *conn) { struct aim_conn_t *cur; @@ -417,16 +507,19 @@ return 0; } -/* - * aim_select(timeout) +/** + * aim_select - Wait for a socket with data or timeout + * @sess: Session to wait on + * @timeout: How long to wait + * @status: Return status * * Waits for a socket with data or for timeout, whichever comes first. - * See select(2). + * See select(). * * Return codes in *status: - * -1 error in select() (NULL returned) - * 0 no events pending (NULL returned) - * 1 outgoing data pending (NULL returned) + * -1 error in select() (%NULL returned) + * 0 no events pending (%NULL returned) + * 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. @@ -436,9 +529,9 @@ 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) { @@ -448,32 +541,50 @@ } 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 */ @@ -486,6 +597,16 @@ return NULL; /* no waiting or error, return */ } +/** + * aim_conn_isready - Test if a connection is marked ready + * @conn: Connection to test + * + * Returns true if the connection is ready, false otherwise. + * Returns -1 if the connection is invalid. + * + * XXX: This is deprecated. + * + */ faim_export int aim_conn_isready(struct aim_conn_t *conn) { if (conn) @@ -493,6 +614,17 @@ return -1; } +/** + * aim_conn_setstatus - Set the status of a connection + * @conn: Connection + * @status: New status + * + * @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) { int val; @@ -506,6 +638,20 @@ return val; } +/** + * aim_conn_setlatency - Set a forced latency value for connection + * @conn: Conn to set latency for + * @newval: Number of seconds to force between transmits + * + * Causes @newval seconds to be spent between transmits on a connection. + * + * This is my lame attempt at overcoming not understanding the rate + * limiting. + * + * XXX: This should really be replaced with something that scales and + * backs off like the real rate limiting does. + * + */ faim_export int aim_conn_setlatency(struct aim_conn_t *conn, int newval) { if (!conn) @@ -519,12 +665,18 @@ return 0; } -/* +/** + * aim_setupproxy - Configure a proxy for this session + * @sess: Session to set proxy for + * @server: SOCKS server + * @username: SOCKS username + * @password: SOCKS password + * * Call this with your SOCKS5 proxy server parameters before - * the first call to aim_newconn(). If called with all NULL + * the first call to aim_newconn(). If called with all %NULL * args, it will clear out a previously set proxy. * - * Set username and password to NULL if not applicable. + * Set username and password to %NULL if not applicable. * */ faim_export void aim_setupproxy(struct aim_session_t *sess, char *server, char *username, char *password) @@ -545,7 +697,15 @@ return; } -faim_export void aim_session_init(struct aim_session_t *sess) +/** + * 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, unsigned long flags) { if (!sess) return; @@ -558,6 +718,15 @@ aim_initsnachash(sess); sess->snac_nextid = 0x00000001; + 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 * version for back-compatibility. @@ -566,3 +735,75 @@ 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 -r e6637ff33957 -r efcacae6acdb libfaim/aim_login.c --- a/libfaim/aim_login.c Fri Nov 10 05:54:04 2000 +0000 +++ b/libfaim/aim_login.c Fri Nov 10 22:49:02 2000 +0000 @@ -10,6 +10,7 @@ #include "md5.h" static int aim_encode_password_md5(const char *password, const char *key, md5_byte_t *digest); +static int aim_encode_password(const char *password, unsigned char *encoded); /* * FIXME: Reimplement the TIS stuff. @@ -49,19 +50,76 @@ struct aim_conn_t *conn, char *sn) { - int curbyte=0; - + int curbyte; struct command_tx_struct *newpacket; + if (!sess || !conn || !sn) + return -1; + + /* + * For ICQ, we enable the ancient horrible login and stuff + * a key packet into the queue to make it look like we got + * a reply back. This is so the client doesn't know we're + * really not doing MD5 login. + * + * This may sound stupid, but I'm not in the best of moods and + * I don't plan to keep support for this crap around much longer. + * Its all AOL's fault anyway, really. I hate AOL. Really. They + * always seem to be able to piss me off by doing the dumbest little + * things. Like disabling MD5 logins for ICQ UINs, or adding purposefully + * wrong TLV lengths, or adding superfluous information to host strings, + * or... I'll stop. + * + */ + if ((sn[0] >= '0') && (sn[0] <= '9')) { + struct command_rx_struct *newrx; + int i; + + if (!(newrx = (struct command_rx_struct *)malloc(sizeof(struct command_rx_struct)))) + return -1; + memset(newrx, 0x00, sizeof(struct command_rx_struct)); + newrx->lock = 1; + newrx->hdrtype = AIM_FRAMETYPE_OSCAR; + newrx->hdr.oscar.type = 0x02; + newrx->hdr.oscar.seqnum = 0; + newrx->commandlen = 10+2+1; + newrx->nofree = 0; + if (!(newrx->data = malloc(newrx->commandlen))) { + free(newrx); + return -1; + } + + i = aim_putsnac(newrx->data, 0x0017, 0x0007, 0x0000, 0x0000); + i += aimutil_put16(newrx->data+i, 0x01); + i += aimutil_putstr(newrx->data+i, "0", 1); + + newrx->conn = conn; + + newrx->next = sess->queue_incoming; + sess->queue_incoming = newrx; + + newrx->lock = 0; + + sess->flags &= ~AIM_SESS_FLAGS_SNACLOGIN; + + return 0; + } + + sess->flags |= AIM_SESS_FLAGS_SNACLOGIN; + + aim_sendconnack(sess, conn); + if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, 10+2+2+strlen(sn)))) return -1; newpacket->lock = 1; - curbyte += aim_putsnac(newpacket->data+curbyte, 0x0017, 0x0006, 0x0000, 0x00010000); + curbyte = aim_putsnac(newpacket->data, 0x0017, 0x0006, 0x0000, 0x00010000); curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x0001, strlen(sn), sn); + newpacket->commandlen = curbyte; newpacket->lock = 0; + return aim_tx_enqueue(sess, newpacket); } @@ -82,8 +140,6 @@ char *key) { int curbyte=0; - md5_byte_t digest[16]; - struct command_tx_struct *newpacket; if (!clientinfo || !sn || !password) @@ -94,27 +150,52 @@ newpacket->lock = 1; - newpacket->hdr.oscar.type = 0x02; + newpacket->hdr.oscar.type = (sess->flags & AIM_SESS_FLAGS_SNACLOGIN)?0x02:0x01; - curbyte = aim_putsnac(newpacket->data+curbyte, 0x0017, 0x0002, 0x0000, 0x00010000); + if (sess->flags & AIM_SESS_FLAGS_SNACLOGIN) + curbyte = aim_putsnac(newpacket->data, 0x0017, 0x0002, 0x0000, 0x00010000); + else { + curbyte = aimutil_put16(newpacket->data, 0x0000); + curbyte += aimutil_put16(newpacket->data+curbyte, 0x0001); + } - curbyte+= aim_puttlv_str(newpacket->data+curbyte, 0x0001, strlen(sn), sn); + curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x0001, strlen(sn), sn); - aim_encode_password_md5(password, key, digest); - curbyte+= aim_puttlv_str(newpacket->data+curbyte, 0x0025, 16, (char *)digest); - + if (sess->flags & AIM_SESS_FLAGS_SNACLOGIN) { + md5_byte_t digest[16]; + + aim_encode_password_md5(password, key, digest); + curbyte+= aim_puttlv_str(newpacket->data+curbyte, 0x0025, 16, (char *)digest); + } else { + char *password_encoded; + + password_encoded = (char *) malloc(strlen(password)); + aim_encode_password(password, password_encoded); + curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x0002, strlen(password), password_encoded); + free(password_encoded); + } + /* XXX is clientstring required by oscar? */ if (strlen(clientinfo->clientstring)) curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x0003, strlen(clientinfo->clientstring), clientinfo->clientstring); - 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); - curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0019, (unsigned short)clientinfo->minor2); - curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x001a, (unsigned short)clientinfo->build); + 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); + curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0019, (unsigned short)clientinfo->minor2); + curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x001a, (unsigned short)clientinfo->build); - curbyte += aim_puttlv_32(newpacket->data+curbyte, 0x0014, clientinfo->unknown); - curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0009, 0x0015); + curbyte += aim_puttlv_32(newpacket->data+curbyte, 0x0014, clientinfo->unknown); + curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0009, 0x0015); + } else { + curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0016, 0x010a); + curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0017, 0x0004); + curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0018, 0x003c); + curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0019, 0x0001); + curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x001a, 0x0cce); + curbyte += aim_puttlv_32(newpacket->data+curbyte, 0x0014, 0x00000055); + } if (strlen(clientinfo->country)) curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x000e, strlen(clientinfo->country), clientinfo->country); @@ -145,25 +226,23 @@ return 0; } -/* - * int encode_password( - * const char *password, - * char *encoded - * ); +/** + * aim_encode_password - Encode a password using old XOR method + * @password: incoming password + * @encoded: buffer to put encoded password * * This takes a const pointer to a (null terminated) string * containing the unencoded password. It also gets passed * an already allocated buffer to store the encoded password. * This buffer should be the exact length of the password without - * the null. The encoded password buffer IS NOT NULL TERMINATED. + * the null. The encoded password buffer /is not %NULL terminated/. * * The encoding_table seems to be a fixed set of values. We'll * hope it doesn't change over time! * - * NOTE: This is no longer used. Its here for historical reference. + * This is only used for the XOR method, not the better MD5 method. * */ -#if 0 static int aim_encode_password(const char *password, unsigned char *encoded) { u_char encoding_table[] = { @@ -187,7 +266,6 @@ return 0; } -#endif /* * This is sent back as a general response to the login command. @@ -215,7 +293,10 @@ * For SNAC login, there's a 17/3 SNAC header in front. * */ - tlvlist = aim_readtlvchain(command->data+10, command->commandlen-10); + if (sess->flags & AIM_SESS_FLAGS_SNACLOGIN) + tlvlist = aim_readtlvchain(command->data+10, command->commandlen-10); + else + tlvlist = aim_readtlvchain(command->data, command->commandlen); /* * No matter what, we should have a screen name. diff -r e6637ff33957 -r efcacae6acdb libfaim/aim_rxhandlers.c --- a/libfaim/aim_rxhandlers.c Fri Nov 10 05:54:04 2000 +0000 +++ b/libfaim/aim_rxhandlers.c Fri Nov 10 22:49:02 2000 +0000 @@ -343,16 +343,17 @@ workingPtr->handled = 1; break; case AIM_CONN_TYPE_AUTH: { - u_long head; + unsigned long head; head = aimutil_get32(workingPtr->data); - if (head == 0x00000001) { + if ((head == 0x00000001) && (workingPtr->commandlen == 4)) { faimdprintf(1, "got connection ack on auth line\n"); - workingPtr->handled = 1; - } else if (workingPtr->hdr.oscar.type == 0x0004) { + 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); } else { - u_short family,subtype; + unsigned short family,subtype; family = aimutil_get16(workingPtr->data); subtype = aimutil_get16(workingPtr->data+2); @@ -404,7 +405,7 @@ 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; @@ -540,10 +541,9 @@ 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 { @@ -557,9 +557,9 @@ 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) @@ -803,6 +803,9 @@ { u_int i = 0; + if (!sess || !command) + return 1; + faimdprintf(1, "\nRecieved unknown packet:"); for (i = 0; i < command->commandlen; i++) diff -r e6637ff33957 -r efcacae6acdb libfaim/aim_rxqueue.c --- a/libfaim/aim_rxqueue.c Fri Nov 10 05:54:04 2000 +0000 +++ b/libfaim/aim_rxqueue.c Fri Nov 10 22:49:02 2000 +0000 @@ -60,6 +60,9 @@ 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 -r e6637ff33957 -r efcacae6acdb libfaim/aim_tlv.c --- a/libfaim/aim_tlv.c Fri Nov 10 05:54:04 2000 +0000 +++ b/libfaim/aim_tlv.c Fri Nov 10 22:49:02 2000 +0000 @@ -1,6 +1,17 @@ #include -faim_internal struct aim_tlvlist_t *aim_readtlvchain(u_char *buf, int maxlen) +/** + * aim_readtlvchain - Read a TLV chain from a buffer. + * @buf: Input buffer + * @maxlen: Length of input buffer + * + * Reads and parses a series of TLV patterns from a data buffer; the + * returned structure is manipulatable with the rest of the TLV + * routines. When done with a TLV chain, aim_freetlvchain() should + * be called to free the dynamic substructures. + * + */ +faim_export struct aim_tlvlist_t *aim_readtlvchain(u_char *buf, int maxlen) { int pos; struct aim_tlvlist_t *list; @@ -62,7 +73,16 @@ return list; } -faim_internal void aim_freetlvchain(struct aim_tlvlist_t **list) +/** + * aim_freetlvchain - Free a TLV chain structure + * @list: Chain to be freed + * + * Walks the list of TLVs in the passed TLV chain and + * frees each one. Note that any references to this data + * should be removed before calling this. + * + */ +faim_export void aim_freetlvchain(struct aim_tlvlist_t **list) { struct aim_tlvlist_t *cur, *cur2; @@ -81,7 +101,14 @@ return; } -faim_internal int aim_counttlvchain(struct aim_tlvlist_t **list) +/** + * aim_counttlvchain - Count the number of TLVs in a chain + * @list: Chain to be counted + * + * Returns the number of TLVs stored in the passed chain. + * + */ +faim_export int aim_counttlvchain(struct aim_tlvlist_t **list) { struct aim_tlvlist_t *cur; int count = 0; @@ -95,6 +122,14 @@ return count; } +/** + * aim_sizetlvchain - Count the number of bytes in a TLV chain + * @list: Chain to be sized + * + * Returns the number of bytes that would be needed to + * write the passed TLV chain to a data buffer. + * + */ faim_export int aim_sizetlvchain(struct aim_tlvlist_t **list) { struct aim_tlvlist_t *cur; @@ -109,8 +144,18 @@ return size; } - -faim_internal int aim_addtlvtochain_str(struct aim_tlvlist_t **list, unsigned short type, char *str, int len) +/** + * aim_addtlvtochain_str - Add a string to a TLV chain + * @list: Desination chain (%NULL pointer if empty) + * @type: TLV type + * @str: String to add + * @len: Length of string to add (not including %NULL) + * + * Adds the passed string as a TLV element of the passed type + * to the TLV chain. + * + */ +faim_export int aim_addtlvtochain_str(struct aim_tlvlist_t **list, unsigned short type, char *str, int len) { struct aim_tlvlist_t *newtlv; struct aim_tlvlist_t *cur; @@ -141,7 +186,16 @@ return newtlv->tlv->length; } -faim_internal int aim_addtlvtochain16(struct aim_tlvlist_t **list, unsigned short type, unsigned short val) +/** + * aim_addtlvtochain16 - Add a 16bit integer to a TLV chain + * @list: Destination chain + * @type: TLV type to add + * @val: Value to add + * + * Adds a two-byte unsigned integer to a TLV chain. + * + */ +faim_export int aim_addtlvtochain16(struct aim_tlvlist_t **list, unsigned short type, unsigned short val) { struct aim_tlvlist_t *newtl; struct aim_tlvlist_t *cur; @@ -172,7 +226,16 @@ return 2; } -faim_internal int aim_addtlvtochain32(struct aim_tlvlist_t **list, unsigned short type, unsigned long val) +/** + * aim_addtlvtochain32 - Add a 32bit integer to a TLV chain + * @list: Destination chain + * @type: TLV type to add + * @val: Value to add + * + * Adds a four-byte unsigned integer to a TLV chain. + * + */ +faim_export int aim_addtlvtochain32(struct aim_tlvlist_t **list, unsigned short type, unsigned long val) { struct aim_tlvlist_t *newtl; struct aim_tlvlist_t *cur; @@ -203,7 +266,29 @@ return 4; } -faim_internal int aim_addtlvtochain_caps(struct aim_tlvlist_t **list, unsigned short type, unsigned short caps) +/** + * aim_addtlvtochain_caps - Add a capability block to a TLV chain + * @list: Destination chain + * @type: TLV type to add + * @caps: Bitfield of capability flags to send + * + * Adds a block of capability blocks to a TLV chain. The bitfield + * passed in should be a bitwise %OR of any of the %AIM_CAPS constants: + * + * %AIM_CAPS_BUDDYICON Supports Buddy Icons + * + * %AIM_CAPS_VOICE Supports Voice Chat + * + * %AIM_CAPS_IMIMAGE Supports DirectIM/IMImage + * + * %AIM_CAPS_CHAT Supports Chat + * + * %AIM_CAPS_GETFILE Supports Get File functions + * + * %AIM_CAPS_SENDFILE Supports Send File functions + * + */ +faim_export int aim_addtlvtochain_caps(struct aim_tlvlist_t **list, unsigned short type, unsigned short caps) { unsigned char buf[128]; /* icky fixed length buffer */ struct aim_tlvlist_t *newtl; @@ -236,7 +321,19 @@ return newtl->tlv->length; } -faim_internal int aim_writetlvchain(u_char *buf, int buflen, struct aim_tlvlist_t **list) +/** + * aim_writetlvchain - Write a TLV chain into a data buffer. + * @buf: Destination buffer + * @buflen: Maximum number of bytes that will be written to buffer + * @list: Source TLV chain + * + * Copies a TLV chain into a raw data buffer, writing only the number + * of bytes specified. This operation does not free the chain; + * aim_freetlvchain() must still be called to free up the memory used + * by the chain structures. + * + */ +faim_export int aim_writetlvchain(u_char *buf, int buflen, struct aim_tlvlist_t **list) { int goodbuflen = 0; int i = 0; @@ -266,10 +363,19 @@ } -/* - * Grab the Nth TLV of type type in the TLV list list. +/** + * aim_gettlv - Grab the Nth TLV of type type in the TLV list list. + * @list: Source chain + * @type: Requested TLV type + * @nth: Index of TLV of type to get + * + * Returns a pointer to an aim_tlv_t of the specified type; + * %NULL on error. The @nth parameter is specified starting at %1. + * In most cases, there will be no more than one TLV of any type + * in a chain. + * */ -faim_internal struct aim_tlv_t *aim_gettlv(struct aim_tlvlist_t *list, u_short type, int nth) +faim_export struct aim_tlv_t *aim_gettlv(struct aim_tlvlist_t *list, u_short type, int nth) { int i; struct aim_tlvlist_t *cur; @@ -288,7 +394,18 @@ return NULL; } -faim_internal char *aim_gettlv_str(struct aim_tlvlist_t *list, u_short type, int nth) +/** + * aim_gettlv_str - Retrieve the Nth TLV in chain as a string. + * @list: Source TLV chain + * @type: TLV type to search for + * @nth: Index of TLV to return + * + * Same as aim_gettlv(), except that the return value is a %NULL- + * terminated string instead of an aim_tlv_t. This is a + * dynamic buffer and must be freed by the caller. + * + */ +faim_export char *aim_gettlv_str(struct aim_tlvlist_t *list, u_short type, int nth) { struct aim_tlv_t *tlv; char *newstr; @@ -303,7 +420,19 @@ return newstr; } -faim_internal struct aim_tlv_t *aim_grabtlv(u_char *src) +/** + * aim_grabtlv - Grab a single TLV from a data buffer + * @src: Source data buffer (must be at least 4 bytes long) + * + * Creates a TLV structure aim_tlv_t and returns it + * filled with values from a buffer, possibly including a + * dynamically allocated buffer for the value portion. + * + * Both the aim_tlv_t and the tlv->value pointer + * must be freed by the caller if non-%NULL. + * + */ +faim_export struct aim_tlv_t *aim_grabtlv(u_char *src) { struct aim_tlv_t *dest = NULL; @@ -323,7 +452,20 @@ return dest; } -faim_internal struct aim_tlv_t *aim_grabtlvstr(u_char *src) +/** + * aim_grabtlvstr - Grab a single TLV from a data buffer as string + * @src: Source data buffer (must be at least 4 bytes long) + * + * Creates a TLV structure aim_tlv_t and returns it + * filled with values from a buffer, possibly including a + * dynamically allocated buffer for the value portion, which + * is %NULL-terminated as a string. + * + * Both the aim_tlv_t and the tlv->value pointer + * must be freed by the caller if non-%NULL. + * + */ +faim_export struct aim_tlv_t *aim_grabtlvstr(u_char *src) { struct aim_tlv_t *dest = NULL; @@ -344,7 +486,19 @@ return dest; } -faim_internal int aim_puttlv(u_char *dest, struct aim_tlv_t *newtlv) +/** + * aim_puttlv - Write a aim_tlv_t into a data buffer + * @dest: Destination data buffer + * @newtlv: Source TLV structure + * + * Writes out the passed TLV structure into the buffer. No bounds + * checking is done on the output buffer. + * + * The passed aim_tlv_t is not freed. aim_freetlv() should + * still be called by the caller to free the structure. + * + */ +faim_export int aim_puttlv(u_char *dest, struct aim_tlv_t *newtlv) { int i=0; @@ -357,15 +511,31 @@ return i; } -faim_internal struct aim_tlv_t *aim_createtlv(void) +/** + * aim_createtlv - Generate an aim_tlv_t structure. + * + * Allocates an empty TLV structure and returns a pointer + * to it; %NULL on error. + * + */ +faim_export struct aim_tlv_t *aim_createtlv(void) { - struct aim_tlv_t *newtlv = NULL; - newtlv = (struct aim_tlv_t *)malloc(sizeof(struct aim_tlv_t)); + struct aim_tlv_t *newtlv; + + if (!(newtlv = (struct aim_tlv_t *)malloc(sizeof(struct aim_tlv_t)))) + return NULL; memset(newtlv, 0, sizeof(struct aim_tlv_t)); return newtlv; } -faim_internal int aim_freetlv(struct aim_tlv_t **oldtlv) +/** + * aim_freetlv - Free a aim_tlv_t structure + * @oldtlv: TLV to be destroyed + * + * Frees both the TLV structure and the value portion. + * + */ +faim_export int aim_freetlv(struct aim_tlv_t **oldtlv) { if (!oldtlv) return -1; @@ -379,7 +549,16 @@ return 0; } -faim_internal int aim_puttlv_16(u_char *buf, u_short t, u_short v) +/** + * aim_puttlv_16 - Write a two-byte TLV. + * @buf: Destination buffer + * @t: TLV type + * @v: Value + * + * Writes a TLV with a two-byte integer value portion. + * + */ +faim_export int aim_puttlv_16(u_char *buf, u_short t, u_short v) { int curbyte=0; curbyte += aimutil_put16(buf+curbyte, (u_short)(t&0xffff)); @@ -388,7 +567,16 @@ return curbyte; } -faim_internal int aim_puttlv_32(u_char *buf, u_short t, u_long v) +/** + * aim_puttlv_32 - Write a four-byte TLV. + * @buf: Destination buffer + * @t: TLV type + * @v: Value + * + * Writes a TLV with a four-byte integer value portion. + * + */ +faim_export int aim_puttlv_32(u_char *buf, u_short t, u_long v) { int curbyte=0; curbyte += aimutil_put16(buf+curbyte, (u_short)(t&0xffff)); @@ -397,7 +585,19 @@ return curbyte; } -faim_internal int aim_puttlv_str(u_char *buf, u_short t, int l, char *v) +/** + * aim_puttlv_str - Write a string TLV. + * @buf: Destination buffer + * @t: TLV type + * @l: Length of string + * @v: String to write + * + * Writes a TLV with a string value portion. (Only the first @l + * bytes of the passed string will be written, which should not + * include the terminating NULL.) + * + */ +faim_export int aim_puttlv_str(u_char *buf, u_short t, int l, char *v) { int curbyte; diff -r e6637ff33957 -r efcacae6acdb libfaim/aim_txqueue.c --- a/libfaim/aim_txqueue.c Fri Nov 10 05:54:04 2000 +0000 +++ b/libfaim/aim_txqueue.c Fri Nov 10 22:49:02 2000 +0000 @@ -151,6 +151,19 @@ 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 @@ /* 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 -r e6637ff33957 -r efcacae6acdb libfaim/faim/aim.h --- a/libfaim/faim/aim.h Fri Nov 10 05:54:04 2000 +0000 +++ b/libfaim/faim/aim.h Fri Nov 10 22:49:02 2000 +0000 @@ -208,8 +208,9 @@ */ #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,9 +351,15 @@ char password[128]; } socksproxy; + 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. @@ -466,7 +473,7 @@ 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 *); @@ -515,7 +522,9 @@ 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 -r e6637ff33957 -r efcacae6acdb libfaim/faim/aim_cbtypes.h --- a/libfaim/faim/aim_cbtypes.h Fri Nov 10 05:54:04 2000 +0000 +++ b/libfaim/faim/aim_cbtypes.h Fri Nov 10 22:49:02 2000 +0000 @@ -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 -r e6637ff33957 -r efcacae6acdb plugins/spellchk.c --- a/plugins/spellchk.c Fri Nov 10 05:54:04 2000 +0000 +++ b/plugins/spellchk.c Fri Nov 10 22:49:02 2000 +0000 @@ -26,12 +26,12 @@ GList *words = NULL; -int num_words(char *); -int get_word(char *, int); -char *have_word(char *, int); -void substitute(char **, int, int, char *); +static int num_words(char *); +static int get_word(char *, int); +static char *have_word(char *, int); +static void substitute(char **, int, int, char *); -void substitute_words(struct gaim_connection *gc, char *who, char **message, void *m) { +static void substitute_words(struct gaim_connection *gc, char *who, char **message, void *m) { int i, l; int word; GList *w; @@ -60,7 +60,7 @@ } } -int buf_get_line(char *ibuf, char **buf, int *position, int len) { +static int buf_get_line(char *ibuf, char **buf, int *position, int len) { int pos = *position, spos = pos; if (pos == len) @@ -78,7 +78,7 @@ return 1; } -void load_conf() { +static void load_conf() { char *defaultconf = "BAD r\nGOOD are\n\n" "BAD u\nGOOD you\n\n" "BAD teh\nGOOD the\n\n"; @@ -155,7 +155,7 @@ return "Watches outgoing IM text and corrects common spelling errors."; } -int num_words(char *m) { +static int num_words(char *m) { int count = 0; int pos; int state = 0; @@ -184,7 +184,7 @@ return count; } -int get_word(char *m, int word) { +static int get_word(char *m, int word) { int count = 0; int pos = 0; int state = 0; @@ -213,7 +213,7 @@ return pos - 1; } -char *have_word(char *m, int pos) { +static char *have_word(char *m, int pos) { char *tmp = strpbrk(&m[pos], "' \t\f\r\n\".?!-,"); int len = (int)(tmp - &m[pos]); @@ -229,7 +229,7 @@ return tmp; } -void substitute(char **mes, int pos, int m, char *text) { +static void substitute(char **mes, int pos, int m, char *text) { char *new = g_malloc(strlen(*mes) + strlen(text) + 1); char *tmp; new[0] = 0; @@ -243,17 +243,17 @@ g_free(tmp); } -GtkWidget *configwin = NULL; -GtkWidget *list; -GtkWidget *bad_entry; -GtkWidget *good_entry; +static GtkWidget *configwin = NULL; +static GtkWidget *list; +static GtkWidget *bad_entry; +static GtkWidget *good_entry; -void row_unselect() { +static void row_unselect() { gtk_entry_set_text(GTK_ENTRY(bad_entry), ""); gtk_entry_set_text(GTK_ENTRY(good_entry), ""); } -void row_select() { +static void row_select() { char *badwrd, *goodwrd; int row; @@ -271,7 +271,7 @@ } } -void list_add_new() { +static void list_add_new() { int i; gchar *item[2] = {"*NEW*", "EDIT ME"}; @@ -280,7 +280,7 @@ gtk_clist_moveto(GTK_CLIST(list), i, 0, 0.5, 0); } -void list_delete() { +static void list_delete() { int row; if (GTK_CLIST(list)->selection) @@ -293,13 +293,13 @@ } } -void close_config() { +static void close_config() { if (configwin) gtk_widget_destroy(configwin); configwin = NULL; } -void save_list() { +static void save_list() { int fh, i = 0; char buf[512]; char *a, *b; @@ -319,7 +319,7 @@ load_conf(); } -void bad_changed() { +static void bad_changed() { int row; char *m; @@ -333,7 +333,7 @@ } } -void good_changed() { +static void good_changed() { int row; char *m; diff -r e6637ff33957 -r efcacae6acdb src/buddy.c --- a/src/buddy.c Fri Nov 10 05:54:04 2000 +0000 +++ b/src/buddy.c Fri Nov 10 22:49:02 2000 +0000 @@ -262,9 +262,10 @@ struct group_show *g; GSList *m; struct buddy_show *b; + gboolean remove_group; while (s) { - gboolean remove_group = FALSE; + remove_group = FALSE; g = (struct group_show *)s->data; m = g->members; while (m) { @@ -287,10 +288,11 @@ g_free(b->name); g_free(b->show); g_free(b); - } else { + } else if (g_slist_find(b->connlist, gc)) { b->connlist = g_slist_remove(b->connlist, gc); m = g_slist_next(m); - } + } else + m = g_slist_next(m); } if (remove_group) s = shows; @@ -316,13 +318,13 @@ { destroy_buddies(gc); plugin_event(event_signoff, gc, 0, 0, 0); + update_keepalive(gc, FALSE); serv_close(gc); if (connections) return; sprintf(debug_buff, "date: %s\n", full_date()); debug_print(debug_buff); - update_keepalive(gc, FALSE); destroy_all_dialogs(); destroy_buddy(); #ifdef USE_APPLET diff -r e6637ff33957 -r efcacae6acdb src/oscar.c --- a/src/oscar.c Fri Nov 10 05:54:04 2000 +0000 +++ b/src/oscar.c Fri Nov 10 22:49:02 2000 +0000 @@ -311,7 +311,7 @@ debug_print(debug_buff); sess = g_new0(struct aim_session_t, 1); - aim_session_init(sess); + aim_session_init(sess, AIM_SESS_FLAGS_NONBLOCKCONNECT); /* we need an immediate queue because we don't use a while-loop to * see if things need to be sent. */ sess->tx_enqueue = &aim_tx_enqueue__immediate; @@ -347,7 +347,6 @@ aim_conn_addhandler(sess, conn, 0x0017, 0x0007, gaim_parse_login, 0); aim_conn_addhandler(sess, conn, 0x0017, 0x0003, gaim_parse_auth_resp, 0); - aim_sendconnack(sess, conn); aim_request_login(sess, conn, gc->username); gc->inpa = gdk_input_add(conn->fd, GDK_INPUT_READ | GDK_INPUT_EXCEPTION, @@ -446,7 +445,7 @@ hide_login_progress(gc, _("Internal Error")); destroy_gaim_conn(gc); return -1; - } else if (bosconn->status != 0) { + } else if (bosconn->status & AIM_CONN_STATUS_CONNERR) { #ifdef USE_APPLET set_user_state(offline); #endif @@ -558,7 +557,7 @@ debug_print("Reconnecting with authorizor...\n"); { struct aim_conn_t *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) debug_print("unable to reconnect with authorizer\n"); else { odata->paspa = gdk_input_add(tstconn->fd, @@ -571,7 +570,7 @@ case 0xd: /* ChatNav */ { struct aim_conn_t *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) { debug_print("unable to connect to chatnav server\n"); return 1; }