X-Git-Url: http://andersk.mit.edu/gitweb/libfaim.git/blobdiff_plain/68ac63c2c144fc0151820d3c6feb1e3f78bba24b..fd0b7da6fe45e0a7a9f81621cfa4293b79f17d86:/aim_rxqueue.c diff --git a/aim_rxqueue.c b/aim_rxqueue.c index 763f8ec..a26648a 100644 --- a/aim_rxqueue.c +++ b/aim_rxqueue.c @@ -8,11 +8,48 @@ #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) { unsigned char generic[6]; struct command_rx_struct *newrx = NULL; @@ -23,12 +60,17 @@ int aim_get_command(struct aim_session_t *sess, struct aim_conn_t *conn) 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 == AIM_CONN_TYPE_RENDEZVOUS) return aim_get_command_rendezvous(sess, conn); + if (conn->type == AIM_CONN_TYPE_RENDEZVOUS_OUT) + return 0; /* * Read FLAP header. Six bytes: @@ -39,8 +81,8 @@ 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){ - aim_conn_kill(sess, &conn); + if (aim_recv(conn->fd, generic, 6) < 6){ + aim_conn_close(conn); faim_mutex_unlock(&conn->active); return -1; } @@ -51,6 +93,7 @@ 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; } @@ -86,10 +129,10 @@ int aim_get_command(struct aim_session_t *sess, struct aim_conn_t *conn) } /* read the data portion of the packet */ - 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_kill(sess, &conn); + aim_conn_close(conn); faim_mutex_unlock(&conn->active); return -1; } @@ -122,82 +165,6 @@ int aim_get_command(struct aim_session_t *sess, struct aim_conn_t *conn) return 0; } -int aim_get_command_rendezvous(struct aim_session_t *sess, struct aim_conn_t *conn) -{ - unsigned char hdrbuf1[6]; - unsigned char *hdr = NULL; - int hdrlen, hdrtype; - int payloadlength = 0; - int flags = 0; - char *snptr = NULL; - - if (read(conn->fd, hdrbuf1, 6) < 6) { - perror("read"); - printf("faim: rend: read error\n"); - aim_conn_kill(sess, &conn); - return -1; - } - - hdrlen = aimutil_get16(hdrbuf1+4); - - hdrlen -= 6; - hdr = malloc(hdrlen); - - faim_mutex_lock(&conn->active); - if (read(conn->fd, hdr, hdrlen) < hdrlen) { - perror("read"); - printf("faim: rend: read2 error\n"); - free(hdr); - faim_mutex_unlock(&conn->active); - aim_conn_kill(sess, &conn); - return -1; - } - - hdrtype = aimutil_get16(hdr); - - switch (hdrtype) { - case 0x0001: { - payloadlength = aimutil_get32(hdr+22); - flags = aimutil_get16(hdr+32); - snptr = hdr+38; - - printf("OFT frame: %04x / %04x / %04x / %s\n", hdrtype, payloadlength, flags, snptr); - - if (flags == 0x000e) { - printf("directim: %s has started typing\n", snptr); - } else if ((flags == 0x0000) && payloadlength) { - unsigned char *buf; - buf = malloc(payloadlength+1); - - /* XXX theres got to be a better way */ - faim_mutex_lock(&conn->active); - if (recv(conn->fd, buf, payloadlength, MSG_WAITALL) < payloadlength) { - perror("read"); - printf("faim: rend: read3 error\n"); - free(buf); - faim_mutex_unlock(&conn->active); - aim_conn_kill(sess, &conn); - return -1; - } - faim_mutex_unlock(&conn->active); - buf[payloadlength] = '\0'; - printf("directim: %s/%04x/%04x/%s\n", snptr, payloadlength, flags, buf); - aim_send_im_direct(sess, conn, buf); - free(buf); - } - break; - } - default: - printf("OFT frame: type %04x\n", hdrtype); - /* data connection may be unreliable here */ - break; - } /* switch */ - - free(hdr); - - return 0; -} - /* * Purge recieve queue of all handled commands (->handled==1). Also * allows for selective freeing using ->nofree so that the client can @@ -209,7 +176,7 @@ int aim_get_command_rendezvous(struct aim_session_t *sess, struct aim_conn_t *co * 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; @@ -267,7 +234,7 @@ void aim_purge_rxqueue(struct aim_session_t *sess) * XXX: this is something that was handled better in the old connection * handling method, but eh. */ -void aim_rxqueue_cleanbyconn(struct aim_session_t *sess, struct aim_conn_t *conn) +faim_internal void aim_rxqueue_cleanbyconn(struct aim_session_t *sess, struct aim_conn_t *conn) { struct command_rx_struct *currx;