diff -upr gaim-1.5.0/libgaim/protocols/oscar/aim.h gaim-1.5.0-new/libgaim/protocols/oscar/aim.h --- gaim-1.5.0/libpurple/protocols/oscar/aim.h 2005-08-07 23:36:16.000000000 -0500 +++ gaim-1.5.0-new/libpurple/protocols/oscar/aim.h 2005-09-28 11:29:23.000000000 -0500 @@ -35,6 +35,8 @@ #include "libc_interface.h" #endif +#include "gaim-io.h" + #ifdef __cplusplus extern "C" { #endif @@ -310,8 +312,13 @@ struct client_info_s { #define AIM_FRAMETYPE_FLAP 0x0000 #define AIM_FRAMETYPE_OFT 0x0001 +typedef struct aim_frame_s aim_frame_t; + typedef struct aim_conn_s { int fd; + GaimIO *io; + aim_frame_t *current_frame; + int current_payload_len; fu16_t type; fu16_t subtype; flap_seqnum_t seqnum; @@ -346,7 +353,7 @@ typedef struct aim_bstream_s { fu32_t offset; } aim_bstream_t; -typedef struct aim_frame_s { +struct aim_frame_s { fu8_t hdrtype; /* defines which piece of the union to use */ union { struct { @@ -363,7 +370,7 @@ typedef struct aim_frame_s { aim_conn_t *conn; /* the connection it came in on/is going out on */ fu8_t handled; /* 0 = new, !0 = been handled */ struct aim_frame_s *next; -} aim_frame_t; +}; typedef struct aim_msgcookie_s { fu8_t cookie[8]; diff -upr gaim-1.5.0/libgaim/protocols/oscar/aim_internal.h gaim-1.5.0-new/libgaim/protocols/oscar/aim_internal.h --- gaim-1.5.0/libgaim/protocols/oscar/aim_internal.h 2005-03-06 22:51:56.000000000 -0600 +++ gaim-1.5.0-new/libgaim/protocols/oscar/aim_internal.h 2005-09-28 11:29:23.000000000 -0500 @@ -102,8 +102,8 @@ faim_internal int aim_parse_unknown(aim_ faim_internal void aim_clonehandlers(aim_session_t *sess, aim_conn_t *dest, aim_conn_t *libgaim); /* rxqueue.c */ -faim_internal int aim_recv(int fd, void *buf, size_t count); -faim_internal int aim_bstream_recv(aim_bstream_t *bs, int fd, size_t count); +faim_internal int aim_recv(aim_conn_t *conn, void *buf, size_t count); +faim_internal int aim_bstream_recv(aim_bstream_t *bs, aim_conn_t *conn, size_t count); faim_internal void aim_rxqueue_cleanbyconn(aim_session_t *sess, aim_conn_t *conn); faim_internal void aim_frame_destroy(aim_frame_t *); diff -upr gaim-1.5.0/libgaim/protocols/oscar/conn.c gaim-1.5.0-new/libgaim/protocols/oscar/conn.c --- gaim-1.5.0/libgaim/protocols/oscar/conn.c 2005-07-09 14:26:51.000000000 -0500 +++ gaim-1.5.0-new/libgaim/protocols/oscar/conn.c 2005-09-28 11:29:23.000000000 -0500 @@ -161,6 +161,9 @@ static void connkill_real(aim_session_t if ((*deadconn)->fd != -1) aim_conn_close(*deadconn); + if ((*deadconn)->io) + gaim_io_destroy ((*deadconn)->io); + /* * This will free ->internal if it necessary... */ @@ -218,6 +221,7 @@ static void aim_conn_init(aim_conn_t *de return; deadconn->fd = -1; + deadconn->io = NULL; deadconn->subtype = -1; deadconn->type = -1; deadconn->seqnum = 0; @@ -304,8 +308,12 @@ faim_export void aim_conn_close(aim_conn { aim_rxcallback_t userfunc; - if (deadconn->fd >= 3) + if (deadconn->io) { + gaim_io_destroy (deadconn->io); + deadconn->io = NULL; + } else if (deadconn->fd >= 3) { close(deadconn->fd); + } deadconn->fd = -1; @@ -559,6 +567,7 @@ faim_internal aim_conn_t *aim_cloneconn( return NULL; conn->fd = libgaim->fd; + conn->io = gaim_io_new (conn->fd); conn->type = libgaim->type; conn->subtype = libgaim->subtype; conn->seqnum = libgaim->seqnum; @@ -606,6 +615,7 @@ faim_export aim_conn_t *aim_newconn(aim_ connstruct->sessv = (void *)sess; connstruct->type = type; + connstruct->io = NULL; if (!dest) { /* just allocate a struct */ connstruct->fd = -1; diff -upr gaim-1.5.0/libgaim/protocols/oscar/ft.c gaim-1.5.0-new/libgaim/protocols/oscar/ft.c --- gaim-1.5.0/libgaim/protocols/oscar/ft.c 2005-08-07 23:36:17.000000000 -0500 +++ gaim-1.5.0-new/libgaim/protocols/oscar/ft.c 2005-09-28 11:29:23.000000000 -0500 @@ -630,9 +630,9 @@ static int handlehdr_odc(aim_session_t * while (payloadlength - recvd) { if (payloadlength - recvd >= 1024) - i = aim_recv(conn->fd, &msg[recvd], 1024); + i = aim_recv(conn, &msg[recvd], 1024); else - i = aim_recv(conn->fd, &msg[recvd], payloadlength - recvd); + i = aim_recv(conn, &msg[recvd], payloadlength - recvd); if (i <= 0) { free(msg); free(snptr); diff -upr gaim-1.5.0/libgaim/protocols/oscar/oscar.c gaim-1.5.0-new/libgaim/protocols/oscar/oscar.c --- gaim-1.5.0/libgaim/protocols/oscar/oscar.c 2005-08-11 19:57:27.000000000 -0500 +++ gaim-1.5.0-new/libgaim/protocols/oscar/oscar.c 2005-09-28 11:29:24.000000000 -0500 @@ -1580,7 +1580,7 @@ static void oscar_callback(gpointer data gaim_debug_error("oscar", "Waiting to be destroyed\n"); return; } - } else { + } else if (!conn->io || !gaim_io_is_connected (conn->io)) { if ((conn->type == AIM_CONN_TYPE_BOS) || !(aim_getconn_type(od->sess, AIM_CONN_TYPE_BOS))) { gaim_debug_error("oscar", @@ -3243,6 +3243,11 @@ static void oscar_sendfile_connected(gpo return; } +static void oscar_sendfile_ready_to_xfer (GaimIO *io, GaimXfer *xfer) +{ + gaim_xfer_start(xfer, xfer->fd, NULL, 0); +} + /* * This is called when a buddy sends us some file info. This happens when they * are sending a file to you, and you have just established a connection to them. @@ -3285,7 +3290,12 @@ static int oscar_sendfile_prompt(aim_ses /* XXX - convert the name from UTF-8 to UCS-2 if necessary, and pass the encoding to the call below */ aim_oft_sendheader(oft_info->sess, AIM_CB_OFT_ACK, oft_info); - gaim_xfer_start(xfer, xfer->fd, NULL, 0); + + if (xfer->fd == conn->fd && conn->io && gaim_io_get_pending_write (conn->io)) { + gaim_io_set_flushed_func (conn->io, (GaimIOFunc) oscar_sendfile_ready_to_xfer, xfer); + } else { + oscar_sendfile_ready_to_xfer (conn->io, xfer); + } return 0; } @@ -3317,7 +3327,11 @@ static int oscar_sendfile_ack(aim_sessio gaim_input_remove(xfer->watcher); xfer->watcher = 0; - gaim_xfer_start(xfer, xfer->fd, NULL, 0); + if (xfer->fd == conn->fd && conn->io && gaim_io_get_pending_write (conn->io)) { + gaim_io_set_flushed_func (conn->io, (GaimIOFunc) oscar_sendfile_ready_to_xfer, xfer); + } else { + oscar_sendfile_ready_to_xfer (conn->io, xfer); + } return 0; } diff -upr gaim-1.5.0/libgaim/protocols/oscar/rxqueue.c gaim-1.5.0-new/libgaim/protocols/oscar/rxqueue.c --- gaim-1.5.0/libgaim/protocols/oscar/rxqueue.c 2004-05-05 23:41:24.000000000 -0500 +++ gaim-1.5.0-new/libgaim/protocols/oscar/rxqueue.c 2005-09-28 11:29:24.000000000 -0500 @@ -5,7 +5,7 @@ */ #define FAIM_INTERNAL -#include +#include #ifndef _WIN32 #include @@ -14,43 +14,44 @@ /* * */ -faim_internal int aim_recv(int fd, void *buf, size_t count) +faim_internal int aim_recv(aim_conn_t *conn, void *buf, size_t count) { - int left, cur; + int left, cur; - for (cur = 0, left = count; left; ) { - int ret; - - ret = recv(fd, ((unsigned char *)buf)+cur, left, 0); + if (!conn->io) + conn->io = gaim_io_new (conn->fd); - /* Of course EOF is an error, only morons disagree with that. */ - if (ret <= 0) - return -1; - - cur += ret; - left -= ret; + if (gaim_io_get_fd (conn->io) != conn->fd) { + gaim_io_destroy (conn->io); + conn->io = gaim_io_new (conn->fd); } - return cur; + if (!gaim_io_is_connected (conn->io)) + return -1; + + if (!gaim_io_read_bytes (conn->io, buf, count)) + return gaim_io_is_connected (conn->io) ? 0 : -1; + + return count; } /* * Read into a byte stream. Will not read more than count, but may read * less if there is not enough room in the stream buffer. */ -faim_internal int aim_bstream_recv(aim_bstream_t *bs, int fd, size_t count) +faim_internal int aim_bstream_recv(aim_bstream_t *bs, aim_conn_t *conn, size_t count) { int red = 0; - if (!bs || (fd < 0) || (count < 0)) + if (!bs || (conn->fd < 0) || (count < 0)) return -1; - + if (count > (bs->len - bs->offset)) count = bs->len - bs->offset; /* truncate to remaining space */ if (count) { - red = aim_recv(fd, bs->data + bs->offset, count); + red = aim_recv(conn, bs->data + bs->offset, count); if (red <= 0) return -1; @@ -86,7 +87,7 @@ static int aim_get_command_flap(aim_sess { fu8_t hdr_raw[6]; aim_bstream_t hdr; - + fr->hdrtype = AIM_FRAMETYPE_FLAP; /* @@ -101,8 +102,7 @@ static int aim_get_command_flap(aim_sess * 0x04 | Number of data bytes that follow, 2 bytes. */ aim_bstream_init(&hdr, hdr_raw, sizeof(hdr_raw)); - if (aim_bstream_recv(&hdr, conn->fd, 6) < 6) { - aim_conn_close(conn); + if (aim_bstream_recv(&hdr, conn, 6) < 6) { return -1; } @@ -113,10 +113,10 @@ static int aim_get_command_flap(aim_sess * or we break. We must handle it just in case. */ if (aimbs_get8(&hdr) != 0x2a) { - faimdprintf(sess, 0, "Invalid FLAP frame received on FLAP connection!"); + gaim_debug_misc("oscar", "Invalid FLAP frame received on FLAP connection!"); aim_conn_close(conn); return -1; - } + } fr->hdr.flap.channel = aimbs_get8(&hdr); fr->hdr.flap.seqnum = aimbs_get16(&hdr); @@ -141,8 +141,7 @@ static int aim_get_command_rendezvous(ai * Read rendezvous header */ aim_bstream_init(&hdr, hdr_raw, sizeof(hdr_raw)); - if (aim_bstream_recv(&hdr, conn->fd, 8) < 8) { - aim_conn_close(conn); + if (aim_bstream_recv(&hdr, conn, 8) < 8) { return -1; } @@ -163,7 +162,6 @@ static int aim_get_command_rendezvous(ai */ faim_export int aim_get_command(aim_session_t *sess, aim_conn_t *conn) { - aim_frame_t *fr; int payloadlen; if (!sess || !conn) @@ -172,69 +170,81 @@ faim_export int aim_get_command(aim_sess if (conn->fd == -1) return -1; /* it's an aim_conn_close()'d connection */ - if (conn->fd < 3) /* can happen when people abuse the interface */ + /* If stdin is closed, then zero becomes a valid fd + if (conn->fd < 3) return -1; + */ if (conn->status & AIM_CONN_STATUS_INPROGRESS) return aim_conn_completeconnect(sess, conn); - if (!(fr = (aim_frame_t *)calloc(sizeof(aim_frame_t), 1))) - return -ENOMEM; + if (!conn->current_frame) { + if (!(conn->current_frame = (aim_frame_t *)calloc(sizeof(aim_frame_t), 1))) + return -ENOMEM; + + /* + * Rendezvous (client to client) connections do not speak FLAP, so this + * function will break on them. + */ + if (conn->type == AIM_CONN_TYPE_RENDEZVOUS) + payloadlen = aim_get_command_rendezvous(sess, conn, conn->current_frame); + else if (conn->type == AIM_CONN_TYPE_LISTENER) { + gaim_debug_misc("oscar", "AIM_CONN_TYPE_LISTENER on fd %d\n", conn->fd); + free(conn->current_frame); + conn->current_frame = NULL; + return -1; + } else + payloadlen = aim_get_command_flap(sess, conn, conn->current_frame); - /* - * Rendezvous (client to client) connections do not speak FLAP, so this - * function will break on them. - */ - if (conn->type == AIM_CONN_TYPE_RENDEZVOUS) - payloadlen = aim_get_command_rendezvous(sess, conn, fr); - else if (conn->type == AIM_CONN_TYPE_LISTENER) { - faimdprintf(sess, 0, "AIM_CONN_TYPE_LISTENER on fd %d\n", conn->fd); - free(fr); - return -1; - } else - payloadlen = aim_get_command_flap(sess, conn, fr); + if (payloadlen < 0) { + free(conn->current_frame); + conn->current_frame = NULL; + return -1; + } - if (payloadlen < 0) { - free(fr); - return -1; - } + conn->current_payload_len = payloadlen; + } else + payloadlen = conn->current_payload_len; - if (payloadlen > 0) { + if (conn->current_payload_len > 0) { fu8_t *payload = NULL; if (!(payload = (fu8_t *) malloc(payloadlen))) { - aim_frame_destroy(fr); return -1; } - aim_bstream_init(&fr->data, payload, payloadlen); + aim_bstream_init(&conn->current_frame->data, payload, payloadlen); /* read the payload */ - if (aim_bstream_recv(&fr->data, conn->fd, payloadlen) < payloadlen) { - aim_frame_destroy(fr); /* free's payload */ - aim_conn_close(conn); + if (aim_bstream_recv(&conn->current_frame->data, conn, payloadlen) < payloadlen) { + free (payload); return -1; } - } else - aim_bstream_init(&fr->data, NULL, 0); + } else if (conn->current_payload_len == 0) + aim_bstream_init(&conn->current_frame->data, NULL, 0); - aim_bstream_rewind(&fr->data); + if (conn->current_payload_len >= 0) { + aim_bstream_rewind(&conn->current_frame->data); - fr->conn = conn; + conn->current_frame->conn = conn; - /* Enqueue this puppy */ - fr->next = NULL; /* this will always be at the bottom */ - if (sess->queue_incoming == NULL) - sess->queue_incoming = fr; - else { - aim_frame_t *cur; - for (cur = sess->queue_incoming; cur->next; cur = cur->next); - cur->next = fr; - } + /* Enqueue this puppy */ + conn->current_frame->next = NULL; /* this will always be at the bottom */ + if (sess->queue_incoming == NULL) + sess->queue_incoming = conn->current_frame; + else { + aim_frame_t *cur; + for (cur = sess->queue_incoming; cur->next; cur = cur->next); + cur->next = conn->current_frame; + } - fr->conn->lastactivity = time(NULL); + conn->current_frame->conn->lastactivity = time(NULL); - return 0; + conn->current_frame = NULL; + return 0; + } + + return -1; } /* @@ -270,7 +280,7 @@ faim_internal void aim_rxqueue_cleanbyco for (currx = sess->queue_incoming; currx; currx = currx->next) { if ((!currx->handled) && (currx->conn == conn)) currx->handled = 1; - } + } return; } diff -upr gaim-1.5.0/libgaim/protocols/oscar/txqueue.c gaim-1.5.0-new/libgaim/protocols/oscar/txqueue.c --- gaim-1.5.0/libgaim/protocols/oscar/txqueue.c 2004-07-06 02:00:32.000000000 -0500 +++ gaim-1.5.0-new/libgaim/protocols/oscar/txqueue.c 2005-09-28 11:29:24.000000000 -0500 @@ -192,25 +192,22 @@ faim_internal int aim_tx_enqueue(aim_ses return (*sess->tx_enqueue)(sess, fr); } -static int aim_send(int fd, const void *buf, size_t count) +static int aim_send(aim_conn_t *conn, const void *buf, size_t count) { int left, cur; - for (cur = 0, left = count; left; ) { - int ret; + if (!conn->io) + conn->io = gaim_io_new (conn->fd); - ret = send(fd, ((unsigned char *)buf)+cur, left, 0); - - if (ret == -1) - return -1; - else if (ret == 0) - return cur; - - cur += ret; - left -= ret; + if (gaim_io_get_fd (conn->io) != conn->fd) { + gaim_io_destroy (conn->io); + conn->io = gaim_io_new (conn->fd); } - return cur; + if (!gaim_io_write_bytes (conn->io, buf, count)) + return -1; + + return count; } static int aim_bstream_send(aim_bstream_t *bs, aim_conn_t *conn, size_t count) @@ -239,7 +236,7 @@ static int aim_bstream_send(aim_bstream_ while (count - wrote > 1024) { int ret; - ret = aim_send(conn->fd, bs->data + bs->offset + wrote, 1024); + ret = aim_send(conn, bs->data + bs->offset + wrote, 1024); if (ret > 0) wrote += ret; if (ret < 0) @@ -250,7 +247,7 @@ static int aim_bstream_send(aim_bstream_ } if (count - wrote) { - wrote = wrote + aim_send(conn->fd, bs->data + bs->offset + wrote, count - wrote); + wrote = wrote + aim_send(conn, bs->data + bs->offset + wrote, count - wrote); } }