X-Git-Url: http://andersk.mit.edu/gitweb/libfaim.git/blobdiff_plain/040457cc47af3fd2ed743bda700e28a603d39eb6..64c78745f1e1ef7ecd8166b3af5b80d0d142cfb9:/aim_rxqueue.c diff --git a/aim_rxqueue.c b/aim_rxqueue.c index 481e49b..6cc1806 100644 --- a/aim_rxqueue.c +++ b/aim_rxqueue.c @@ -6,29 +6,77 @@ * aim_rxhandlers.c. */ +#define FAIM_INTERNAL #include +#ifndef _WIN32 +#include +#endif + +/* + * Since not all implementations support MSG_WAITALL, define + * an alternate guarenteed read function... + * + * We keep recv() for systems that can do it because it means + * a single system call for the entire packet, where read may + * take more for a badly fragmented packet. + * + */ +faim_internal int aim_recv(int fd, void *buf, size_t count) +{ +#ifdef MSG_WAITALL + return recv(fd, buf, count, MSG_WAITALL); +#else + int left, ret, cur = 0; + + left = count; + + while (left) { + ret = recv(fd, ((unsigned char *)buf)+cur, left, 0); + if (ret == -1) + return -1; + if (ret == 0) + return cur; + + cur += ret; + left -= ret; + } + + return cur; +#endif +} + /* * 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) +faim_export int aim_get_command(struct aim_session_t *sess, struct aim_conn_t *conn) { - u_char generic[6]; + unsigned char generic[6]; struct command_rx_struct *newrx = NULL; if (!sess || !conn) return 0; + if (conn->fd == -1) + return -1; /* its a aim_conn_close()'d connection */ + 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. */ - if (conn->type > 0x01000) - return 0; + if (conn->type == AIM_CONN_TYPE_RENDEZVOUS) + return aim_get_command_rendezvous(sess, conn); + if (conn->type == AIM_CONN_TYPE_RENDEZVOUS_OUT) { + printf("out on fd %d\n", conn->fd); + return 0; + } /* * Read FLAP header. Six bytes: @@ -39,12 +87,11 @@ int aim_get_command(struct aim_session_t *sess, struct aim_conn_t *conn) * 4 short -- Number of data bytes that follow. */ faim_mutex_lock(&conn->active); - if (read(conn->fd, generic, 6) < 6){ + if (aim_recv(conn->fd, generic, 6) < 6){ aim_conn_close(conn); faim_mutex_unlock(&conn->active); return -1; } - faim_mutex_unlock(&conn->active); /* * This shouldn't happen unless the socket breaks, the server breaks, @@ -52,22 +99,28 @@ int aim_get_command(struct aim_session_t *sess, struct aim_conn_t *conn) */ if (generic[0] != 0x2a) { faimdprintf(1, "Bad incoming data!"); + aim_conn_close(conn); + faim_mutex_unlock(&conn->active); return -1; } /* allocate a new struct */ - newrx = (struct command_rx_struct *)malloc(sizeof(struct command_rx_struct)); - if (!newrx) + if (!(newrx = (struct command_rx_struct *)malloc(sizeof(struct command_rx_struct)))) { + faim_mutex_unlock(&conn->active); return -1; + } memset(newrx, 0x00, sizeof(struct command_rx_struct)); newrx->lock = 1; /* lock the struct */ + /* we're doing OSCAR if we're here */ + newrx->hdrtype = AIM_FRAMETYPE_OSCAR; + /* store channel -- byte 2 */ - newrx->type = (char) generic[1]; + newrx->hdr.oscar.type = (char) generic[1]; /* store seqnum -- bytes 3 and 4 */ - newrx->seqnum = aimutil_get16(generic+2); + newrx->hdr.oscar.seqnum = aimutil_get16(generic+2); /* store commandlen -- bytes 5 and 6 */ newrx->commandlen = aimutil_get16(generic+4); @@ -75,15 +128,14 @@ int aim_get_command(struct aim_session_t *sess, struct aim_conn_t *conn) newrx->nofree = 0; /* free by default */ /* malloc for data portion */ - newrx->data = (u_char *) malloc(newrx->commandlen); - if (!newrx->data) { + if (!(newrx->data = (u_char *) malloc(newrx->commandlen))) { free(newrx); + faim_mutex_unlock(&conn->active); return -1; } /* read the data portion of the packet */ - faim_mutex_lock(&conn->active); - if (read(conn->fd, newrx->data, newrx->commandlen) < newrx->commandlen){ + if (aim_recv(conn->fd, newrx->data, newrx->commandlen) < newrx->commandlen){ free(newrx->data); free(newrx); aim_conn_close(conn); @@ -130,7 +182,7 @@ int aim_get_command(struct aim_session_t *sess, struct aim_conn_t *conn) * does not keep a pointer, it's lost forever. * */ -void aim_purge_rxqueue(struct aim_session_t *sess) +faim_export void aim_purge_rxqueue(struct aim_session_t *sess) { struct command_rx_struct *cur = NULL; struct command_rx_struct *tmp; @@ -144,6 +196,8 @@ void aim_purge_rxqueue(struct aim_session_t *sess) sess->queue_incoming = NULL; if (!tmp->nofree) { + if (tmp->hdrtype == AIM_FRAMETYPE_OFT) + free(tmp->hdr.oft.hdr2); free(tmp->data); free(tmp); } else @@ -157,6 +211,8 @@ void aim_purge_rxqueue(struct aim_session_t *sess) tmp = cur->next; cur->next = tmp->next; if (!tmp->nofree) { + if (tmp->hdrtype == AIM_FRAMETYPE_OFT) + free(tmp->hdr.oft.hdr2); free(tmp->data); free(tmp); } else @@ -176,3 +232,21 @@ void aim_purge_rxqueue(struct aim_session_t *sess) return; } + +/* + * Since aim_get_command will aim_conn_kill dead connections, we need + * to clean up the rxqueue of unprocessed connections on that socket. + * + * XXX: this is something that was handled better in the old connection + * handling method, but eh. + */ +faim_internal void aim_rxqueue_cleanbyconn(struct aim_session_t *sess, struct aim_conn_t *conn) +{ + struct command_rx_struct *currx; + + for (currx = sess->queue_incoming; currx; currx = currx->next) { + if ((!currx->handled) && (currx->conn == conn)) + currx->handled = 1; + } + return; +}