forked from pool/pidgin
488 lines
15 KiB
Diff
488 lines
15 KiB
Diff
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);
|
|
}
|
|
}
|
|
|