--- a/libpurple/protocols/simple/simple.c Mon May 18 19:28:04 2020 -0400
+++ b/libpurple/protocols/simple/simple.c Mon May 18 19:58:19 2020 -0400
@@ -474,38 +474,26 @@
-static void simple_canwrite_cb(gpointer data, gint source, PurpleInputCondition cond) {
- PurpleConnection *gc = data;
- struct simple_account_data *sip = purple_connection_get_protocol_data(gc);
- const gchar *output = NULL;
+simple_push_bytes_cb(GObject *sender, GAsyncResult *res, gpointer data) + PurpleQueuedOutputStream *stream = PURPLE_QUEUED_OUTPUT_STREAM(sender); + struct simple_account_data *sip = data; - max_write = purple_circular_buffer_get_max_read(sip->txbuf);
- purple_input_remove(sip->tx_handler);
+ result = purple_queued_output_stream_push_bytes_finish(stream, res, &error); - output = purple_circular_buffer_get_output(sip->txbuf);
- written = write(sip->fd, output, max_write);
+ purple_queued_output_stream_clear_queue(stream); - if(written < 0 && errno == EAGAIN)
- else if (written <= 0) {
- /*TODO: do we really want to disconnect on a failure to write?*/
- gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"),
- purple_connection_error(gc,
- PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
+ if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + g_prefix_error(&error, "%s", _("Lost connection with server: ")); + purple_connection_take_error(sip->gc, error);
- purple_circular_buffer_mark_read(sip->txbuf, written);
static void simple_input_cb(gpointer data, gint source, PurpleInputCondition cond);
@@ -519,6 +507,7 @@
GSocketConnection *sockconn;
sockconn = g_socket_client_connect_to_host_finish(G_SOCKET_CLIENT(sender),
@@ -538,14 +527,25 @@
sip = purple_connection_get_protocol_data(gc);
+ sip->output = purple_queued_output_stream_new( + g_io_stream_get_output_stream(G_IO_STREAM(sockconn))); - simple_canwrite_cb(gc, sip->fd, PURPLE_INPUT_WRITE);
+ writelen = purple_circular_buffer_get_max_read(sip->txbuf); + buf = purple_circular_buffer_get_output(sip->txbuf); - /* If there is more to write now, we need to register a handler */
- if(purple_circular_buffer_get_used(sip->txbuf) > 0)
- sip->tx_handler = purple_input_add(sip->fd, PURPLE_INPUT_WRITE,
- simple_canwrite_cb, gc);
+ output = g_bytes_new(buf, writelen); + purple_queued_output_stream_push_bytes_async( + sip->output, output, G_PRIORITY_DEFAULT, sip->cancellable, + simple_push_bytes_cb, sip); + purple_circular_buffer_mark_read(sip->txbuf, writelen); conn = connection_create(sip, sockconn, fd);
conn->inputhandler = purple_input_add(sip->fd, PURPLE_INPUT_READ, simple_input_cb, gc);
@@ -591,39 +591,18 @@
purple_debug_info("simple", "could not send packet\n");
+ if (sip->output == NULL) {
- ret = write(sip->fd, buf, writelen);
- if (ret < 0 && errno == EAGAIN)
- else if(ret <= 0) { /* XXX: When does this happen legitimately? */
- sip->tx_handler = purple_input_add(sip->fd,
- PURPLE_INPUT_WRITE, simple_canwrite_cb,
- /* XXX: is it OK to do this? You might get part of a request sent
- with part of another. */
- if(purple_circular_buffer_get_used(sip->txbuf) > 0)
- purple_circular_buffer_append(sip->txbuf, "\r\n", 2);
- purple_circular_buffer_append(sip->txbuf, buf + ret,
+ output = g_bytes_new(buf, writelen); + purple_queued_output_stream_push_bytes_async( + sip->output, output, G_PRIORITY_DEFAULT, sip->cancellable, + simple_push_bytes_cb, sip); @@ -1792,8 +1771,11 @@
purple_debug_info("simple", "simple_input_cb: read error\n");
+ if (sip->fd == source) { + g_clear_object(&sip->output); connection_remove(sip, source);
- if(sip->fd == source) sip->fd = -1;
purple_connection_update_last_received(gc);
@@ -1855,6 +1837,8 @@
sip = purple_connection_get_protocol_data(gc);
+ sip->output = purple_queued_output_stream_new( + g_io_stream_get_output_stream(G_IO_STREAM(sockconn))); conn = connection_create(sip, sockconn, fd);
@@ -2128,8 +2112,6 @@
purple_input_remove(sip->listenpa);
- purple_input_remove(sip->tx_handler);
g_source_remove(sip->resendtimeout);
if (sip->registertimeout)
@@ -2146,6 +2128,7 @@
if (sip->listen_data != NULL)
purple_network_listen_cancel(sip->listen_data);
+ g_clear_object(&sip->output); --- a/libpurple/protocols/simple/simple.h Mon May 18 19:28:04 2020 -0400
+++ b/libpurple/protocols/simple/simple.h Mon May 18 19:58:19 2020 -0400
@@ -94,6 +94,7 @@
GCancellable *cancellable;
+ PurpleQueuedOutputStream *output; PurpleNetworkListenData *listen_data;
@@ -112,7 +113,6 @@
PurpleCircularBuffer *txbuf;