diff src/protocols/yahoo/yahoo.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 a0a4b44239e8
children 263c2db78f77
line wrap: on
line diff
--- a/src/protocols/yahoo/yahoo.c	Thu Feb 09 04:14:54 2006 +0000
+++ b/src/protocols/yahoo/yahoo.c	Thu Feb 09 04:17:56 2006 +0000
@@ -2286,19 +2286,34 @@
 	GaimConnection *gc = data;
 	GaimAccount *account = gaim_connection_get_account(gc);
 	struct yahoo_data *yd = gc->proto_data;
-	char buf[2048], *i = buf;
+	char bufread[2048], *i = bufread, *buf = bufread;
 	int len;
 	GString *s;
 
-	len = read(source, buf, sizeof(buf)-1);
-	if (len <= 0  || (strncmp(buf, "HTTP/1.0 302", strlen("HTTP/1.0 302")) &&
+	len = read(source, bufread, sizeof(bufread) - 1);
+	if (len < 0 && errno == EAGAIN)
+		return;
+	else if (len <= 0) {
+		gaim_connection_error(gc, _("Unable to read"));
+		return;
+	}
+
+	if (yd->rxlen > 0 || !g_strstr_len(buf, len, "\r\n\r\n")) {
+		yd->rxqueue = g_realloc(yd->rxqueue, yd->rxlen + len + 1);
+		memcpy(yd->rxqueue + yd->rxlen, buf, len);
+		yd->rxlen += len;
+		i = buf = yd->rxqueue;
+		len = yd->rxlen;
+	}
+	buf[len] = '\0';
+
+	if ((strncmp(buf, "HTTP/1.0 302", strlen("HTTP/1.0 302")) &&
 			  strncmp(buf, "HTTP/1.1 302", strlen("HTTP/1.1 302")))) {
 		gaim_connection_error(gc, _("Unable to read"));
 		return;
 	}
 
 	s = g_string_sized_new(len);
-	buf[sizeof(buf)-1] = '\0';
 
 	while ((i = strstr(i, "Set-Cookie: "))) {
 		i += strlen("Set-Cookie: ");
@@ -2311,6 +2326,9 @@
 	yd->auth = g_string_free(s, FALSE);
 	gaim_input_remove(gc->inpa);
 	close(source);
+	g_free(yd->rxqueue);
+	yd->rxqueue = NULL;
+	yd->rxlen = 0;
 	/* Now we have our cookies to login with.  I'll go get the milk. */
 	if (gaim_proxy_connect(account, "wcs2.msg.dcn.yahoo.com",
 			       gaim_account_get_int(account, "port", YAHOO_PAGER_PORT),
@@ -2324,12 +2342,41 @@
 {
 	GaimConnection *gc = data;
 	struct yahoo_data *yd = gc->proto_data;
+	int written, total_len;
+
 	if (source < 0) {
 		gaim_connection_error(gc, _("Unable to connect."));
 		return;
 	}
-	write(source, yd->auth, strlen(yd->auth));
+
+	total_len = strlen(yd->auth) - yd->auth_written;
+	written = write(source, yd->auth + yd->auth_written, total_len);
+
+	if (written < 0 && errno == EAGAIN)
+		written = 0;
+	else if (written <= 0) {
+		g_free(yd->auth);
+		yd->auth = NULL;
+		if (gc->inpa)
+			gaim_input_remove(gc->inpa);
+		gc->inpa = 0;
+		gaim_connection_error(gc, _("Unable to connect."));
+		return;
+	}
+
+	if (written < total_len) {
+		yd->auth_written += written;
+		if (!gc->inpa)
+			gc->inpa = gaim_input_add(source, GAIM_INPUT_WRITE,
+				yahoo_got_cookies, gc);
+		return;
+	}
+
 	g_free(yd->auth);
+	yd->auth = NULL;
+	yd->auth_written = 0;
+	if (gc->inpa)
+		gaim_input_remove(gc->inpa);
 	gc->inpa = gaim_input_add(source, GAIM_INPUT_READ, yahoo_web_pending, gc);
 }
 
@@ -2526,6 +2573,9 @@
 	gaim_connection_set_display_name(gc, gaim_account_get_username(account));
 
 	yd->fd = -1;
+	yd->txhandler = -1;
+	/* TODO: Is there a good grow size for the buffer? */
+	yd->txbuf = gaim_circ_buffer_new(0);
 	yd->friends = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, yahoo_friend_free);
 	yd->confs = NULL;
 	yd->conf_id = 2;
@@ -2579,22 +2629,23 @@
 		yahoo_c_leave(gc, 1); /* 1 = YAHOO_CHAT_ID */
 
 	g_hash_table_destroy(yd->friends);
-	if (yd->chat_name)
-		g_free(yd->chat_name);
-
-	if (yd->cookie_y)
-		g_free(yd->cookie_y);
-	if (yd->cookie_t)
-		g_free(yd->cookie_t);
+	g_free(yd->chat_name);
+
+	g_free(yd->cookie_y);
+	g_free(yd->cookie_t);
+
+	if (yd->txhandler)
+		gaim_input_remove(yd->txhandler);
+
+	gaim_circ_buffer_destroy(yd->txbuf);
 
 	if (yd->fd >= 0)
 		close(yd->fd);
 
-	if (yd->rxqueue)
-		g_free(yd->rxqueue);
+	g_free(yd->rxqueue);
 	yd->rxlen = 0;
-	if (yd->picture_url)
-		g_free(yd->picture_url);
+	g_free(yd->picture_url);
+
 	if (yd->picture_upload_todo)
 		yahoo_buddy_icon_upload_data_free(yd->picture_upload_todo);
 	if (yd->ycht)