diff src/protocols/msn/servconn.c @ 13200:33bef17125c2

[gaim-migrate @ 15563] This is the soon-to-be-infamous nonblocking network activity patch that I've been working on. Feel free to yell at me if this makes you unhappy. committer: Tailor Script <tailor@pidgin.im>
author Daniel Atallah <daniel.atallah@gmail.com>
date Thu, 09 Feb 2006 04:17:56 +0000
parents 4e7ba55a1db2
children 8754a0fe2297
line wrap: on
line diff
--- a/src/protocols/msn/servconn.c	Thu Feb 09 04:14:54 2006 +0000
+++ b/src/protocols/msn/servconn.c	Thu Feb 09 04:17:56 2006 +0000
@@ -50,6 +50,9 @@
 
 	servconn->num = session->servconns_count++;
 
+	servconn->tx_buf = gaim_circ_buffer_new(MSN_BUF_LEN);
+	servconn->tx_handler = -1;
+
 	return servconn;
 }
 
@@ -73,8 +76,11 @@
 	if (servconn->httpconn != NULL)
 		msn_httpconn_destroy(servconn->httpconn);
 
-	if (servconn->host != NULL)
-		g_free(servconn->host);
+	g_free(servconn->host);
+
+	gaim_circ_buffer_destroy(servconn->tx_buf);
+	if (servconn->tx_handler > 0)
+		gaim_input_remove(servconn->tx_handler);
 
 	msn_cmdproc_destroy(servconn->cmdproc);
 	g_free(servconn);
@@ -181,7 +187,7 @@
 		/* Someone wants to know we connected. */
 		servconn->connect_cb(servconn);
 		servconn->inpa = gaim_input_add(servconn->fd, GAIM_INPUT_READ,
-										read_cb, data);
+			read_cb, data);
 	}
 	else
 	{
@@ -227,7 +233,7 @@
 	}
 
 	r = gaim_proxy_connect(session->account, host, port, connect_cb,
-						   servconn);
+		servconn);
 
 	if (r == 0)
 	{
@@ -279,30 +285,72 @@
 		servconn->disconnect_cb(servconn);
 }
 
+static void
+servconn_write_cb(gpointer data, gint source, GaimInputCondition cond)
+{
+	MsnServConn *servconn = data;
+	int ret, writelen;
+
+	writelen = gaim_circ_buffer_get_max_read(servconn->tx_buf);
+
+	if (writelen == 0) {
+		gaim_input_remove(servconn->tx_handler);
+		servconn->tx_handler = -1;
+		return;
+	}
+
+	ret = write(servconn->fd, servconn->tx_buf->outptr, writelen);
+
+	if (ret < 0 && errno == EAGAIN)
+		return;
+	else if (ret <= 0) {
+		msn_servconn_got_error(servconn, MSN_SERVCONN_ERROR_WRITE);
+		return;
+	}
+
+	gaim_circ_buffer_mark_read(servconn->tx_buf, ret);
+}
+
 size_t
 msn_servconn_write(MsnServConn *servconn, const char *buf, size_t len)
 {
-	size_t ret = FALSE;
+	size_t ret = 0;
 
 	g_return_val_if_fail(servconn != NULL, 0);
 
 	if (!servconn->session->http_method)
 	{
-		switch (servconn->type)
-		{
-			case MSN_SERVCONN_NS:
-			case MSN_SERVCONN_SB:
-				ret = write(servconn->fd, buf, len);
-				break;
+		if (servconn->tx_handler == -1) {
+			switch (servconn->type)
+			{
+				case MSN_SERVCONN_NS:
+				case MSN_SERVCONN_SB:
+					ret = write(servconn->fd, buf, len);
+					break;
 #if 0
-			case MSN_SERVCONN_DC:
-				ret = write(servconn->fd, &buf, sizeof(len));
-				ret = write(servconn->fd, buf, len);
-				break;
+				case MSN_SERVCONN_DC:
+					ret = write(servconn->fd, &buf, sizeof(len));
+					ret = write(servconn->fd, buf, len);
+					break;
 #endif
-			default:
-				ret = write(servconn->fd, buf, len);
-				break;
+				default:
+					ret = write(servconn->fd, buf, len);
+					break;
+			}
+		} else {
+			ret = -1;
+			errno = EAGAIN;
+		}
+
+		if (ret < 0 && errno == EAGAIN)
+			ret = 0;
+		if (ret < len) {
+			if (servconn->tx_handler == -1)
+				servconn->tx_handler = gaim_input_add(
+					servconn->fd, GAIM_INPUT_WRITE,
+					servconn_write_cb, servconn);
+			gaim_circ_buffer_append(servconn->tx_buf, buf + ret,
+				len - ret);
 		}
 	}
 	else
@@ -332,7 +380,9 @@
 
 	len = read(servconn->fd, buf, sizeof(buf) - 1);
 
-	if (len <= 0)
+	if (len < 0 && errno == EAGAIN)
+		return;
+	else if (len <= 0)
 	{
 		gaim_debug_error("msn", "servconn read error, len: %d error: %s\n", len, strerror(errno));
 		msn_servconn_got_error(servconn, MSN_SERVCONN_ERROR_READ);