Mercurial > pidgin
diff libfaim/aim_rxqueue.c @ 237:6ced2f1c8b24
[gaim-migrate @ 247]
How cool is this, libfaim is making a comeback. I completely redid everything,
as was necessary because of the updates to libfaim since gaim 0.9.7. You can
sign on and send/recv IMs, but there's a bad lag between display updates that
I haven't figured out how to fix yet.
committer: Tailor Script <tailor@pidgin.im>
author | Eric Warmenhoven <eric@warmenhoven.org> |
---|---|
date | Sat, 20 May 2000 00:30:53 +0000 |
parents | 68b230f8da5f |
children | 501e09c51cbc |
line wrap: on
line diff
--- a/libfaim/aim_rxqueue.c Thu May 18 18:20:18 2000 +0000 +++ b/libfaim/aim_rxqueue.c Sat May 20 00:30:53 2000 +0000 @@ -1,247 +1,165 @@ /* - 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 "aim.h" - -/* - This is a modified read() to make SURE we get the number - of bytes we are told to, otherwise block. - */ -int Read(int fd, u_char *buf, int len) -{ - int i = 0; - int j = 0; - - while ((i < len) && (!(i < 0))) - { - j = read(fd, &(buf[i]), len-i); - if ( (j < 0) && (errno != EAGAIN)) - return -errno; /* fail */ - else - i += j; /* success, continue */ - } -#if 0 - printf("\nRead Block: (%d/%04x)\n", len, len); - printf("\t"); - for (j = 0; j < len; j++) - { - if (j % 8 == 0) - printf("\n\t"); - if (buf[j] >= ' ' && buf[j] < 127) - printf("%c=%02x ",buf[j], buf[j]); - else - printf("0x%02x ", buf[j]); - } - printf("\n\n"); -#endif - return i; -} +#include <aim.h> /* - struct command_struct * - get_generic( - struct connection_info struct *, - struct command_struct * - ) - - Grab as many command sequences as we can off the socket, and enqueue - each command in the incoming event queue in a seperate struct. - -*/ -int aim_get_command(void) + * 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, 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 command_rx_struct *workingPtr = NULL; - struct aim_conn_t *conn = NULL; -#if debug > 0 - printf("Reading generic/unknown response..."); -#endif - - - /* dont wait at all (ie, never call this unless something is there) */ - tv.tv_sec = 0; - tv.tv_usec = 0; - conn = aim_select(&tv); + u_char generic[6]; + struct command_rx_struct *newrx = NULL; - if (conn==NULL) - return 0; /* nothing waiting */ - - s = conn->fd; + if (!sess || !conn) + 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; + if (conn->fd < 3) /* can happen when people abuse the interface */ + return 0; - 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 = Read(s, &(generic[i]), 1)) < 0) - { - /* error is probably not recoverable...(must be a pessimistic day) */ - aim_conn_close(conn); - return err; - } + /* + * 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; + } - if (readgood == 0) - { - if (generic[i] == 0x2a) - { - readgood = 1; -#if debug > 1 - printf("%x ", generic[i]); - fflush(stdout); -#endif - i++; - } - else - { -#if debug > 1 - printf("skipping 0x%d ", generic[i]); - fflush(stdout); -#endif - j++; - } - } - else - { -#if debug > 1 - printf("%x ", generic[i]); -#endif - i++; - } - FD_ZERO(&fds); - FD_SET(s, &fds); - tv.tv_sec= 2; - tv.tv_usec= 2; - } - - if (generic[0] != 0x2a) - { - /* this really shouldn't happen, since the main loop - select() should protect us from entering this function - without data waiting */ - printf("Bad incoming data!"); - return -1; - } - - isav = i; + /* + * 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) { + faimdprintf(1, "Bad incoming data!"); + return -1; + } /* allocate a new struct */ - workingStruct = (struct command_rx_struct *) malloc(sizeof(struct command_rx_struct)); - workingStruct->lock = 1; /* lock the struct */ + newrx = (struct command_rx_struct *)malloc(sizeof(struct command_rx_struct)); + if (!newrx) + return -1; + memset(newrx, 0x00, sizeof(struct command_rx_struct)); - /* store type -- byte 2 */ - workingStruct->type = (char) generic[1]; + newrx->lock = 1; /* lock the struct */ + + /* store channel -- byte 2 */ + newrx->type = (char) generic[1]; /* store seqnum -- bytes 3 and 4 */ - workingStruct->seqnum = ( (( (unsigned int) generic[2]) & 0xFF) << 8); - workingStruct->seqnum += ( (unsigned int) generic[3]) & 0xFF; + newrx->seqnum = aimutil_get16(generic+2); /* store commandlen -- bytes 5 and 6 */ - workingStruct->commandlen = ( (( (unsigned int) generic[4]) & 0xFF ) << 8); - workingStruct->commandlen += ( (unsigned int) generic[5]) & 0xFF; - - printf("%d\n", workingStruct->commandlen); + newrx->commandlen = aimutil_get16(generic+4); + + newrx->nofree = 0; /* free by default */ /* malloc for data portion */ - workingStruct->data = (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 */ - i = Read(s, workingStruct->data, workingStruct->commandlen); - if (i < 0) - { - aim_conn_close(conn); - return i; - } + if (read(conn->fd, newrx->data, newrx->commandlen) < newrx->commandlen){ + free(newrx->data); + free(newrx); + aim_conn_close(conn); + return -1; + } -#if debug > 0 - printf(" done. (%db+%db read, %db skipped)\n", isav, i, j); -#endif + newrx->conn = conn; - workingStruct->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 (aim_queue_incoming == NULL) - aim_queue_incoming = workingStruct; - else - { - workingPtr = aim_queue_incoming; - while (workingPtr->next != NULL) - workingPtr = workingPtr->next; - workingPtr->next = workingStruct; - } + if (sess->queue_incoming == NULL) { + sess->queue_incoming = newrx; + } else { + struct command_rx_struct *cur; + + /* + * This append operation takes a while. It might be faster + * if we maintain a pointer to the last entry in the queue + * and just update that. Need to determine if the overhead + * to maintain that is lower than the overhead for this loop. + */ + for (cur = sess->queue_incoming; cur->next; cur = cur->next) + ; + cur->next = newrx; + } + + newrx->conn->lastactivity = time(NULL); return 0; } /* - purge_rxqueue() - - This is just what it sounds. It purges the receive (rx) queue of - all handled commands. This is normally called from inside - aim_rxdispatch() after it's processed all the commands in the queue. - + * Purge recieve queue of all handled commands (->handled==1). Also + * allows for selective freeing using ->nofree so that the client can + * keep the data for various purposes. + * + * If ->nofree is nonzero, the frame will be delinked from the global list, + * but will not be free'ed. The client _must_ keep a pointer to the + * data -- libfaim will not! If the client marks ->nofree but + * does not keep a pointer, it's lost forever. + * */ -struct command_rx_struct *aim_purge_rxqueue(struct command_rx_struct *queue) +void aim_purge_rxqueue(struct aim_session_t *sess) { - int i = 0; - struct command_rx_struct *workingPtr = NULL; - struct command_rx_struct *workingPtr2 = NULL; + struct command_rx_struct *cur = NULL; + struct command_rx_struct *tmp; - workingPtr = queue; - if (queue == NULL) - { - return queue; + if (sess->queue_incoming == NULL) + return; + + if (sess->queue_incoming->next == NULL) { + if (sess->queue_incoming->handled) { + tmp = sess->queue_incoming; + sess->queue_incoming = NULL; + + if (!tmp->nofree) { + free(tmp->data); + free(tmp); + } else + tmp->next = NULL; } - else if (queue->next == NULL) - { - if (queue->handled == 1) - { - workingPtr2 = queue; - queue = NULL; - free(workingPtr2->data); - free(workingPtr2); - } - return queue; - } - else - { - for (i = 0; workingPtr != NULL; i++) - { - if (workingPtr->next->handled == 1) - { - /* save struct */ - workingPtr2 = workingPtr->next; - /* dequeue */ - workingPtr->next = workingPtr2->next; - /* free */ - free(workingPtr2->data); - free(workingPtr2); - } + return; + } - workingPtr = workingPtr->next; - } - } + for(cur = sess->queue_incoming; cur->next != NULL; ) { + if (cur->next->handled) { + tmp = cur->next; + cur->next = tmp->next; + if (!tmp->nofree) { + free(tmp->data); + free(tmp); + } else + tmp->next = NULL; + } + cur = cur->next; - return queue; + /* + * Be careful here. Because of the way we just + * manipulated the pointer, cur may be NULL and + * the for() will segfault doing the check unless + * we find this case first. + */ + if (cur == NULL) + break; + } + + return; }