cpw.darkrain42.xmpp.bosh: 8aa3507d: BOSH: Use a write buffer (read: basicall...
paul at darkrain42.org
paul at darkrain42.org
Sat Apr 4 19:15:41 EDT 2009
-----------------------------------------------------------------
Revision: 8aa3507dc80559098f9ac283dd24fe367f814bee
Ancestor: 06a295e020eccbf9caabb99c59a341b531098f43
Author: paul at darkrain42.org
Date: 2009-04-04T23:05:04
Branch: im.pidgin.cpw.darkrain42.xmpp.bosh
URL: http://d.pidgin.im/viewmtn/revision/info/8aa3507dc80559098f9ac283dd24fe367f814bee
Modified files:
libpurple/protocols/jabber/bosh.c
ChangeLog:
BOSH: Use a write buffer (read: basically cut-n-paste from jabber.c)
-------------- next part --------------
============================================================
--- libpurple/protocols/jabber/bosh.c 63f3731f3cb0d172094d200e4053b3c6edc9ab8c
+++ libpurple/protocols/jabber/bosh.c 9edebc2942dcbb3959bf1236249890dd1bb98a94
@@ -79,8 +79,11 @@ struct _PurpleHTTPConnection {
PurpleBOSHConnection *bosh;
PurpleSslConnection *psc;
int fd;
- int ie_handle;
+ guint readh;
+ guint writeh;
+ PurpleCircBuffer *write_buffer;
+
gboolean ready;
int requests; /* number of outstanding HTTP requests */
@@ -92,7 +95,8 @@ static void http_connection_connect(Purp
};
static void http_connection_connect(PurpleHTTPConnection *conn);
-static void http_connection_send_request(PurpleHTTPConnection *conn, const GString *req);
+static void http_connection_send_request(PurpleHTTPConnection *conn,
+ const GString *req);
void jabber_bosh_init(void)
{
@@ -127,6 +131,8 @@ jabber_bosh_http_connection_init(PurpleB
conn->fd = -1;
conn->ready = FALSE;
+ conn->write_buffer = purple_circ_buffer_new(0 /* default grow size */);
+
return conn;
}
@@ -136,8 +142,12 @@ jabber_bosh_http_connection_destroy(Purp
if (conn->buf)
g_string_free(conn->buf, TRUE);
- if (conn->ie_handle)
- purple_input_remove(conn->ie_handle);
+ if (conn->write_buffer)
+ purple_circ_buffer_destroy(conn->write_buffer);
+ if (conn->readh)
+ purple_input_remove(conn->readh);
+ if (conn->writeh)
+ purple_input_remove(conn->writeh);
if (conn->psc)
purple_ssl_close(conn->psc);
if (conn->fd >= 0)
@@ -579,11 +589,16 @@ static void http_connection_disconnected
conn->fd = -1;
}
- if (conn->ie_handle) {
- purple_input_remove(conn->ie_handle);
- conn->ie_handle = 0;
+ if (conn->readh) {
+ purple_input_remove(conn->readh);
+ conn->readh = 0;
}
+ if (conn->writeh) {
+ purple_input_remove(conn->writeh);
+ conn->writeh = 0;
+ }
+
if (conn->bosh->pipelining)
/* Hmmmm, fall back to multiple connections */
conn->bosh->pipelining = FALSE;
@@ -696,7 +711,7 @@ http_connection_read(PurpleHTTPConnectio
/*
* If the socket is closed, the processing really needs to know about
- * it. Handle that now (it will be handled again post-processing).
+ * it. Handle that now.
*/
http_connection_disconnected(conn);
@@ -762,7 +777,7 @@ connection_established_cb(gpointer data,
}
conn->fd = source;
- conn->ie_handle = purple_input_add(conn->fd, PURPLE_INPUT_READ,
+ conn->readh = purple_input_add(conn->fd, PURPLE_INPUT_READ,
http_connection_read_cb, conn);
connection_common_established_cb(conn);
}
@@ -797,13 +812,59 @@ static void http_connection_connect(Purp
}
}
+static int
+http_connection_do_send(PurpleHTTPConnection *conn, const char *data, int len)
+{
+ int ret;
+
+ if (conn->psc)
+ ret = purple_ssl_write(conn->psc, data, len);
+ else
+ ret = write(conn->fd, data, len);
+
+ return ret;
+}
+
static void
+http_connection_send_cb(gpointer data, gint source, PurpleInputCondition cond)
+{
+ PurpleHTTPConnection *conn = data;
+ int ret;
+ int writelen = purple_circ_buffer_get_max_read(conn->write_buffer);
+
+ if (writelen == 0) {
+ purple_input_remove(conn->writeh);
+ conn->writeh = 0;
+ return;
+ }
+
+ ret = http_connection_do_send(conn, conn->write_buffer->outptr, writelen);
+
+ if (ret < 0 && errno == EAGAIN)
+ return;
+ else if (ret <= 0) {
+ /*
+ * TODO: Handle this better. Probably requires a PurpleBOSHConnection
+ * buffer that stores what is "being sent" until the
+ * PurpleHTTPConnection reports it is fully sent.
+ */
+ purple_connection_error_reason(conn->bosh->js->gc,
+ PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+ _("Write error"));
+ return;
+ }
+
+ purple_circ_buffer_mark_read(conn->write_buffer, ret);
+}
+
+static void
http_connection_send_request(PurpleHTTPConnection *conn, const GString *req)
{
- char *packet;
+ char *data;
int ret;
+ size_t len;
- packet = g_strdup_printf("POST %s HTTP/1.1\r\n"
+ data = g_strdup_printf("POST %s HTTP/1.1\r\n"
"Host: %s\r\n"
"User-Agent: %s\r\n"
"Content-Encoding: text/xml; charset=utf-8\r\n"
@@ -812,25 +873,35 @@ http_connection_send_request(PurpleHTTPC
conn->bosh->path, conn->bosh->host, bosh_useragent,
req->len, req->str);
- /* TODO: Better error handling, circbuffer or possible integration with
- * low-level code in jabber.c */
- if (conn->psc)
- ret = purple_ssl_write(conn->psc, packet, strlen(packet));
- else
- ret = write(conn->fd, packet, strlen(packet));
+ len = strlen(data);
++conn->requests;
++conn->bosh->requests;
- g_free(packet);
- if (ret < 0 && errno == EAGAIN)
- purple_debug_error("jabber", "BOSH write would have blocked\n");
+ if (conn->writeh == 0)
+ ret = http_connection_do_send(conn, data, len);
+ else {
+ ret = -1;
+ errno = EAGAIN;
+ }
- if (ret <= 0) {
+ if (ret < 0 && errno != EAGAIN) {
+ /*
+ * TODO: Handle this better. Probably requires a PurpleBOSHConnection
+ * buffer that stores what is "being sent" until the
+ * PurpleHTTPConnection reports it is fully sent.
+ */
purple_connection_error_reason(conn->bosh->js->gc,
PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
_("Write error"));
return;
+ } else if (ret < len) {
+ if (ret < 0)
+ ret = 0;
+ if (conn->writeh == 0)
+ conn->writeh = purple_input_add(conn->psc ? conn->psc->fd : conn->fd,
+ PURPLE_INPUT_WRITE, http_connection_send_cb, conn);
+ purple_circ_buffer_append(conn->write_buffer, data + ret, len - ret);
}
}
More information about the Commits
mailing list