SHA256
1
0
forked from pool/pidgin
pidgin/pidgin-nonblock-aim.patch

488 lines
15 KiB
Diff
Raw Normal View History

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 <aim.h>
+#include <aim.h>
#ifndef _WIN32
#include <sys/socket.h>
@@ -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);
}
}