changeset 7288:ff9127038a5a

[gaim-migrate @ 7869] It doesn't completely work yet, but this is the beginnings of the MSN HTTP port 80 connect method. I don't have it set so it can be enabled, so it's harmless to commit this now, but I want a second set of eyes, and I also want to do other MSN work without dealing with hand-merging patches. committer: Tailor Script <tailor@pidgin.im>
author Christian Hammond <chipx86@chipx86.com>
date Fri, 17 Oct 2003 14:57:59 +0000
parents 3a41c3f80228
children ab2085024a29
files src/protocols/msn/Makefile.am src/protocols/msn/httpmethod.c src/protocols/msn/httpmethod.h src/protocols/msn/msn.c src/protocols/msn/notification.c src/protocols/msn/servconn.c src/protocols/msn/servconn.h src/protocols/msn/session.c src/protocols/msn/session.h src/protocols/msn/switchboard.c
diffstat 10 files changed, 665 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/src/protocols/msn/Makefile.am	Fri Oct 17 05:58:16 2003 +0000
+++ b/src/protocols/msn/Makefile.am	Fri Oct 17 14:57:59 2003 +0000
@@ -11,6 +11,8 @@
 	error.h \
 	group.c \
 	group.h \
+	httpmethod.c \
+	httpmethod.h \
 	msg.c \
 	msg.h \
 	msn.c \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/protocols/msn/httpmethod.c	Fri Oct 17 14:57:59 2003 +0000
@@ -0,0 +1,406 @@
+/**
+ * @file httpmethod.c HTTP connection method
+ *
+ * gaim
+ *
+ * Copyright (C) 2003 Christian Hammond <chipx86@gnupdate.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include "debug.h"
+#include "httpmethod.h"
+
+#define GET_NEXT(tmp) \
+	while (*(tmp) && *(tmp) != ' ' && *(tmp) != '\r') \
+		(tmp)++; \
+	if (*(tmp) != '\0') *(tmp)++ = '\0'; \
+	if (*(tmp) == '\n') (tmp)++; \
+	while (*(tmp) && *(tmp) == ' ') \
+		(tmp)++
+
+#define GET_NEXT_LINE(tmp) \
+	while (*(tmp) && *(tmp) != '\r') \
+		(tmp)++; \
+	if (*(tmp) != '\0') *(tmp)++ = '\0'; \
+	if (*(tmp) == '\n') (tmp)++
+
+typedef struct
+{
+	MsnServConn *servconn;
+	char *buffer;
+	size_t size;
+	const char *server_type;
+
+} MsnHttpQueueData;
+
+static gboolean
+http_poll(gpointer data)
+{
+	MsnServConn *servconn = data;
+
+	gaim_debug_info("msn", "Polling server %s.\n",
+					servconn->http_data->gateway_ip);
+
+	msn_http_servconn_poll(servconn);
+
+	servconn->http_data->timer = 0;
+
+	return FALSE;
+}
+
+static void
+stop_timer(MsnServConn *servconn)
+{
+	if (servconn->http_data->timer)
+	{
+		g_source_remove(servconn->http_data->timer);
+		servconn->http_data->timer = 0;
+	}
+}
+
+static void
+start_timer(MsnServConn *servconn)
+{
+	stop_timer(servconn);
+
+	servconn->http_data->timer = g_timeout_add(5000, http_poll, servconn);
+}
+
+size_t
+msn_http_servconn_write(MsnServConn *servconn, const char *buf, size_t size,
+						const char *server_type)
+{
+	size_t s;
+	char *params;
+	char *temp;
+	gboolean first;
+
+	g_return_val_if_fail(servconn != NULL, 0);
+	g_return_val_if_fail(buf      != NULL, 0);
+	g_return_val_if_fail(size      > 0,    0);
+	g_return_val_if_fail(servconn->http_data != NULL, 0);
+
+	if (servconn->http_data->waiting_response ||
+		servconn->http_data->queue != NULL)
+	{
+		MsnHttpQueueData *queue_data = g_new0(MsnHttpQueueData, 1);
+
+		queue_data->servconn    = servconn;
+		queue_data->buffer      = g_strdup(buf);
+		queue_data->size        = size;
+		queue_data->server_type = server_type;
+
+		servconn->http_data->queue =
+			g_list_append(servconn->http_data->queue, queue_data);
+
+		return size;
+	}
+
+	first = servconn->http_data->virgin;
+
+	if (first)
+	{
+		if (server_type)
+		{
+			params = g_strdup_printf("Action=open&Server=%s&IP=%s",
+									 server_type,
+									 servconn->http_data->gateway_ip);
+		}
+		else
+		{
+			params = g_strdup_printf("Action=open&IP=%s",
+									 servconn->http_data->gateway_ip);
+		}
+	}
+	else
+	{
+		params = g_strdup_printf("SessionID=%s",
+								 servconn->http_data->session_id);
+	}
+
+	temp = g_strdup_printf(
+		"POST http://%s/gateway/gateway.dll?%s HTTP/1.1\r\n"
+		"Accept: */*\r\n"
+		"Accept-Language: en-us\r\n"
+		"User-Agent: MSMSGS\r\n"
+		"Host: %s\r\n"
+		"Proxy-Connection: Keep-Alive\r\n"
+		"Connection: Keep-Alive\r\n"
+		"Pragma: no-cache\r\n"
+		"Content-Type: application/x-msn-messenger\r\n"
+		"Content-Length: %d\r\n"
+		"\r\n"
+		"%s",
+		servconn->http_data->gateway_ip,
+		params,
+		servconn->http_data->gateway_ip,
+		size,
+		buf);
+
+	g_free(params);
+
+#if 0
+	gaim_debug_misc("msn", "Writing to HTTP: {%s}\n", temp);
+#endif
+
+	s = write(servconn->fd, temp, strlen(temp));
+
+	g_free(temp);
+
+	servconn->http_data->waiting_response = TRUE;
+
+	servconn->http_data->virgin = FALSE;
+
+	stop_timer(servconn);
+
+	return s;
+}
+
+void
+msn_http_servconn_poll(MsnServConn *servconn)
+{
+	size_t s;
+	char *temp;
+
+	g_return_if_fail(servconn != NULL);
+	g_return_if_fail(servconn->http_data != NULL);
+
+	if (servconn->http_data->waiting_response ||
+		servconn->http_data->queue != NULL)
+	{
+		return;
+	}
+
+	temp = g_strdup_printf(
+		"POST http://%s/gateway/gateway.dll?Action=poll&SessionID=%s HTTP/1.1\r\n"
+		"Accept: */*\r\n"
+		"Accept-Language: en-us\r\n"
+		"User-Agent: MSMSGS\r\n"
+		"Host: %s\r\n"
+		"Proxy-Connection: Keep-Alive\r\n"
+		"Connection: Keep-Alive\r\n"
+		"Pragma: no-cache\r\n"
+		"Content-Type: application/x-msn-messenger\r\n"
+		"Content-Length: 0\r\n"
+		"\r\n",
+		servconn->http_data->gateway_ip,
+		servconn->http_data->session_id,
+		servconn->http_data->gateway_ip);
+
+#if 0
+	gaim_debug_misc("msn", "Writing to HTTP: {%s}\n", temp);
+#endif
+
+	s = write(servconn->fd, temp, strlen(temp));
+
+	g_free(temp);
+
+	servconn->http_data->waiting_response = TRUE;
+
+	stop_timer(servconn);
+
+	if (s <= 0)
+		gaim_connection_error(servconn->session->account->gc,
+							  _("Write error"));
+}
+
+gboolean
+msn_http_servconn_parse_data(MsnServConn *servconn, const char *buf,
+							 size_t size, char **ret_buf, size_t *ret_size,
+							 gboolean *error)
+{
+	GaimConnection *gc;
+	const char *s, *c;
+	char *headers, *body;
+	char *tmp;
+	size_t len = 0;
+
+	g_return_val_if_fail(servconn != NULL, FALSE);
+	g_return_val_if_fail(buf      != NULL, FALSE);
+	g_return_val_if_fail(size      > 0,    FALSE);
+	g_return_val_if_fail(ret_buf  != NULL, FALSE);
+	g_return_val_if_fail(ret_size != NULL, FALSE);
+	g_return_val_if_fail(error    != NULL, FALSE);
+
+	servconn->http_data->waiting_response = FALSE;
+
+	gc = gaim_account_get_connection(servconn->session->account);
+
+	/* Healthy defaults. */
+	*ret_buf  = NULL;
+	*ret_size = 0;
+	*error    = FALSE;
+
+	/* First, some tests to see if we have a full block of stuff. */
+
+	if (strncmp(buf, "HTTP/1.1 200 OK\r\n", 17) != 0 &&
+		strncmp(buf, "HTTP/1.1 100 Continue\r\n", 23) != 0)
+	{
+		*error = TRUE;
+
+		return FALSE;
+	}
+
+	if (strncmp(buf, "HTTP/1.1 100 Continue\r\n", 23) == 0)
+	{
+		if ((s = strstr(buf, "\r\n\r\n")) == NULL)
+			return FALSE;
+
+		s += 4;
+
+		if (*s == '\0')
+		{
+			*ret_buf = g_strdup("");
+			*ret_size = 0;
+
+			return TRUE;
+		}
+
+		buf = s;
+		size -= (s - buf);
+	}
+
+	if ((s = strstr(buf, "\r\n\r\n")) == NULL)
+		return FALSE;
+
+	headers = g_strndup(buf, s - buf);
+	s += 4; /* Skip \r\n */
+	body = g_strndup(s, size - (s - buf));
+
+#if 0
+	gaim_debug_misc("msn", "Incoming HTTP buffer: {%s\r\n%s}", headers, body);
+#endif
+
+	if ((s = strstr(headers, "Content-Length: ")) != NULL)
+	{
+		s += strlen("Content-Length: ");
+
+		if ((c = strchr(s, '\r')) == NULL)
+		{
+			g_free(headers);
+			g_free(body);
+
+			return FALSE;
+		}
+
+		tmp = g_strndup(s, c - s);
+		len = atoi(tmp);
+		g_free(tmp);
+
+		if (strlen(body) != len)
+		{
+			g_free(headers);
+			g_free(body);
+
+			gaim_debug_warning("msn",
+							   "body length (%d) != content length (%d)\n",
+							   strlen(body), len);
+			return FALSE;
+		}
+	}
+
+	/* Now we should be able to process the data. */
+	if ((s = strstr(headers, "X-MSN-Messenger: ")) != NULL)
+	{
+		char *session_id, *gw_ip;
+		char *c2, *s2;
+
+		s += strlen("X-MSN-Messenger: ");
+
+		if ((c = strchr(s, '\r')) == NULL)
+		{
+			gaim_connection_error(gc, "Malformed X-MSN-Messenger field.");
+			return FALSE;
+		}
+
+		tmp = g_strndup(s, c - s);
+
+		/* Find the value for the Session ID */
+		if ((s2 = strchr(tmp, '=')) == NULL)
+		{
+			gaim_connection_error(gc, "Malformed X-MSN-Messenger field.");
+			return FALSE;
+		}
+
+		s2++;
+
+		/* Terminate the ; so we can g_strdup it. */
+		if ((c2 = strchr(s2, ';')) == NULL)
+		{
+			gaim_connection_error(gc, "Malformed X-MSN-Messenger field.");
+			return FALSE;
+		}
+
+		*c2 = '\0';
+		c2++;
+
+		/* Now grab that session ID. */
+		session_id = g_strdup(s2);
+
+		/* Continue to the gateway IP */
+		if ((s2 = strchr(c2, '=')) == NULL)
+		{
+			gaim_connection_error(gc, "Malformed X-MSN-Messenger field.");
+			return FALSE;
+		}
+
+		s2++;
+
+		/* Grab the gateway IP */
+		gw_ip = g_strdup(s2);
+
+		g_free(tmp);
+
+		/* Set the new data. */
+		if (servconn->http_data->session_id != NULL)
+			g_free(servconn->http_data->session_id);
+
+		if (servconn->http_data->old_gateway_ip != NULL)
+			g_free(servconn->http_data->old_gateway_ip);
+
+		servconn->http_data->old_gateway_ip = servconn->http_data->gateway_ip;
+
+		servconn->http_data->session_id = session_id;
+		servconn->http_data->gateway_ip = gw_ip;
+	}
+
+	g_free(headers);
+
+	*ret_buf  = body;
+	*ret_size = len;
+
+	if (servconn->http_data->queue != NULL)
+	{
+		MsnHttpQueueData *queue_data;
+
+		queue_data = (MsnHttpQueueData *)servconn->http_data->queue->data;
+
+		servconn->http_data->queue =
+			g_list_remove(servconn->http_data->queue, queue_data);
+
+		msn_http_servconn_write(queue_data->servconn,
+								queue_data->buffer,
+								queue_data->size,
+								queue_data->server_type);
+
+		g_free(queue_data->buffer);
+		g_free(queue_data);
+	}
+	else
+		start_timer(servconn);
+
+	return TRUE;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/protocols/msn/httpmethod.h	Fri Oct 17 14:57:59 2003 +0000
@@ -0,0 +1,83 @@
+/**
+ * @file httpmethod.h HTTP connection method
+ *
+ * gaim
+ *
+ * Copyright (C) 2003 Christian Hammond <chipx86@gnupdate.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef _MSN_HTTP_METHOD_H_
+#define _MSN_HTTP_METHOD_H_
+
+typedef struct _MsnHttpMethodData MsnHttpMethodData;
+
+#include "servconn.h"
+
+struct _MsnHttpMethodData
+{
+	char *session_id;
+	char *old_gateway_ip;
+	char *gateway_ip;
+	const char *server_type;
+
+	int timer;
+
+	gboolean virgin;
+	gboolean waiting_response;
+
+	GList *queue;
+};
+
+/**
+ * Writes data to the server using the HTTP connection method.
+ *
+ * @param servconn    The server connection.
+ * @param buf         The data to write.
+ * @param size        The size of the data to write.
+ * @param server_type The optional server type.
+ *
+ * @return The number of bytes written.
+ */
+size_t msn_http_servconn_write(MsnServConn *servconn, const char *buf,
+							   size_t size, const char *server_type);
+
+/**
+ * Polls the server for data.
+ *
+ * @param servconn The server connection.
+ */
+void msn_http_servconn_poll(MsnServConn *servconn);
+
+/**
+ * Processes an incoming message and returns a string the rest of MSN
+ * can deal with.
+ *
+ * @param servconn The server connection.
+ * @param buf      The incoming buffer.
+ * @param size     The incoming size.
+ * @param ret_buf  The returned buffer.
+ * @param ret_len  The returned length.
+ * @param error    TRUE if there was an HTTP error.
+ *
+ * @return TRUE if the returned buffer is ready to be processed.
+ *         FALSE otherwise.
+ */
+gboolean msn_http_servconn_parse_data(MsnServConn *servconn,
+									  const char *buf, size_t size,
+									  char **ret_buf, size_t *ret_size,
+									  gboolean *error);
+
+#endif /* _MSN_HTTP_METHOD_H_ */
--- a/src/protocols/msn/msn.c	Fri Oct 17 05:58:16 2003 +0000
+++ b/src/protocols/msn/msn.c	Fri Oct 17 14:57:59 2003 +0000
@@ -446,6 +446,7 @@
 	MsnSession *session;
 	const char *username;
 	const char *server;
+	gboolean http_method = FALSE;
 	int port;
 
 	gc = gaim_account_get_connection(account);
@@ -458,10 +459,21 @@
 		return;
 	}
 
-	server = gaim_account_get_string(account, "server", MSN_SERVER);
-	port   = gaim_account_get_int(account,    "port",   MSN_PORT);
+	if (gaim_account_get_bool(account, "http_method", FALSE))
+	{
+		http_method = TRUE;
+
+		server = "gateway.messenger.hotmail.com";
+		port   = 80;
+	}
+	else
+	{
+		server = gaim_account_get_string(account, "server", MSN_SERVER);
+		port   = gaim_account_get_int(account,    "port",   MSN_PORT);
+	}
 
 	session = msn_session_new(account, server, port);
+	session->http_method = http_method;
 	session->prpl = my_protocol;
 
 	gc->proto_data = session;
@@ -1624,6 +1636,13 @@
 	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
 											   option);
 
+#if 0
+	option = gaim_account_option_bool_new(_("Use HTTP Method"), "http_method",
+										  FALSE);
+	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
+											   option);
+#endif
+
 	my_protocol = plugin;
 
 	gaim_prefs_add_none("/plugins/prpl/msn");
--- a/src/protocols/msn/notification.c	Fri Oct 17 05:58:16 2003 +0000
+++ b/src/protocols/msn/notification.c	Fri Oct 17 14:57:59 2003 +0000
@@ -1863,6 +1863,9 @@
 	else
 		port = 1863;
 
+	if (session->http_method)
+		port = 80;
+
 	swboard = msn_switchboard_new(session);
 
 	user = msn_user_new(session, params[4], NULL);
@@ -1925,6 +1928,9 @@
 
 		msn_switchboard_set_auth_key(swboard, params[4]);
 
+		if (session->http_method)
+			port = 80;
+
 		if (!msn_switchboard_connect(swboard, host, port)) {
 			gaim_debug(GAIM_DEBUG_ERROR, "msn",
 					   "Unable to connect to switchboard on %s, port %d\n",
@@ -2183,6 +2189,9 @@
 	msn_servconn_set_connect_cb(notification, connect_cb);
 	msn_servconn_set_failed_read_cb(notification, failed_read_cb);
 
+	if (session->http_method)
+		notification->http_data->server_type = "NS";
+
 	if (notification_commands == NULL) {
 		/* Register the command callbacks. */
 		msn_servconn_register_command(notification, "ADD",       add_cmd);
--- a/src/protocols/msn/servconn.c	Fri Oct 17 05:58:16 2003 +0000
+++ b/src/protocols/msn/servconn.c	Fri Oct 17 14:57:59 2003 +0000
@@ -186,6 +186,7 @@
 {
 	MsnServConn *servconn = data;
 
+	gaim_debug_info("msn", "In servconn's connect_cb\n");
 	if (servconn->connect_cb(data, source, cond))
 		servconn->inpa = gaim_input_add(servconn->fd, GAIM_INPUT_READ,
 										servconn->login_cb, data);
@@ -203,6 +204,12 @@
 	servconn->login_cb = msn_servconn_parse_data;
 	servconn->session = session;
 
+	if (session->http_method)
+	{
+		servconn->http_data = g_new0(MsnHttpMethodData, 1);
+		servconn->http_data->virgin = TRUE;
+	}
+
 	servconn->commands = g_hash_table_new_full(g_str_hash, g_str_equal,
 											   g_free, NULL);
 
@@ -217,14 +224,23 @@
 gboolean
 msn_servconn_connect(MsnServConn *servconn)
 {
+	MsnSession *session;
 	int i;
 
-	g_return_val_if_fail(servconn != NULL, FALSE);
+	g_return_val_if_fail(servconn         != NULL, FALSE);
 	g_return_val_if_fail(servconn->server != NULL, FALSE);
-	g_return_val_if_fail(!servconn->connected, TRUE);
+	g_return_val_if_fail(!servconn->connected,     TRUE);
+
+	session = servconn->session;
 
-	i = gaim_proxy_connect(servconn->session->account, servconn->server,
-					  servconn->port, connect_cb, servconn);
+	if (session->http_method)
+	{
+		servconn->http_data->gateway_ip = g_strdup(servconn->server);
+		servconn->port = 80;
+	}
+
+	i = gaim_proxy_connect(session->account, servconn->server,
+						   servconn->port, connect_cb, servconn);
 
 	if (i == 0)
 		servconn->connected = TRUE;
@@ -235,14 +251,35 @@
 void
 msn_servconn_disconnect(MsnServConn *servconn)
 {
+	MsnSession *session;
+
 	g_return_if_fail(servconn != NULL);
 	g_return_if_fail(servconn->connected);
 
+	session = servconn->session;
+
 	if (servconn->inpa)
 		gaim_input_remove(servconn->inpa);
 
 	close(servconn->fd);
 
+	if (servconn->http_data != NULL)
+	{
+		if (servconn->http_data->session_id != NULL)
+			g_free(servconn->http_data->session_id);
+
+		if (servconn->http_data->old_gateway_ip != NULL)
+			g_free(servconn->http_data->old_gateway_ip);
+
+		if (servconn->http_data->gateway_ip != NULL)
+			g_free(servconn->http_data->gateway_ip);
+
+		if (servconn->http_data->timer)
+			g_source_remove(servconn->http_data->timer);
+
+		g_free(servconn->http_data);
+	}
+
 	if (servconn->rxqueue != NULL)
 		g_free(servconn->rxqueue);
 
@@ -340,7 +377,11 @@
 	gaim_debug(GAIM_DEBUG_MISC, "msn", "C: %s%s", buf,
 			   (*(buf + size - 1) == '\n' ? "" : "\n"));
 
-	return write(servconn->fd, buf, size);
+	if (servconn->session->http_method)
+		return msn_http_servconn_write(servconn, buf, size,
+									   servconn->http_data->server_type);
+	else
+		return write(servconn->fd, buf, size);
 }
 
 gboolean
@@ -389,7 +430,8 @@
 	g_return_if_fail(servconn != NULL);
 	g_return_if_fail(msg != NULL);
 
-	for (l = servconn->msg_queue; l != NULL; l = l->next) {
+	for (l = servconn->msg_queue; l != NULL; l = l->next)
+	{
 		entry = l->data;
 
 		if (entry->msg == msg)
@@ -448,7 +490,8 @@
 
 	len = read(servconn->fd, buf, sizeof(buf));
 
-	if (len <= 0) {
+	if (len <= 0)
+	{
 		if (servconn->failed_read_cb != NULL)
 			servconn->failed_read_cb(data, source, cond);
 
@@ -459,8 +502,75 @@
 	memcpy(servconn->rxqueue + servconn->rxlen, buf, len);
 	servconn->rxlen += len;
 
-	while (cont) {
-		if (servconn->parsing_multiline) {
+	if (session->http_method)
+	{
+		char *result_msg = NULL;
+		size_t result_len = 0;
+		gboolean error;
+		char *tmp;
+
+		tmp = g_strndup(servconn->rxqueue, servconn->rxlen);
+
+		if (!msn_http_servconn_parse_data(servconn, tmp,
+										  servconn->rxlen, &result_msg,
+										  &result_len, &error))
+		{
+			g_free(tmp);
+			return;
+		}
+
+		g_free(tmp);
+
+		if (error)
+		{
+			gaim_connection_error(
+				gaim_account_get_connection(session->account),
+				_("Received HTTP error. Please report this."));
+
+			return;
+		}
+
+		if (servconn->http_data->session_id != NULL &&
+			!strcmp(servconn->http_data->session_id, "close"))
+		{
+			msn_servconn_destroy(servconn);
+
+			return;
+		}
+
+#if 0
+		if (strcmp(servconn->http_data->gateway_ip,
+				   msn_servconn_get_server(servconn)) != 0)
+		{
+			int i;
+
+			/* Evil hackery. I promise to remove it, even though I can't. */
+
+			servconn->connected = FALSE;
+
+			if (servconn->inpa)
+				gaim_input_remove(servconn->inpa);
+
+			close(servconn->fd);
+
+			i = gaim_proxy_connect(session->account, servconn->server,
+								   servconn->port, servconn->login_cb,
+								   servconn);
+
+			if (i == 0)
+				servconn->connected = TRUE;
+		}
+#endif
+
+		g_free(servconn->rxqueue);
+		servconn->rxqueue = result_msg;
+		servconn->rxlen   = result_len;
+	}
+
+	while (cont)
+	{
+		if (servconn->parsing_multiline)
+		{
 			char *msg;
 
 			if (servconn->rxlen == 0)
@@ -539,4 +649,3 @@
 		}
 	}
 }
-
--- a/src/protocols/msn/servconn.h	Fri Oct 17 05:58:16 2003 +0000
+++ b/src/protocols/msn/servconn.h	Fri Oct 17 14:57:59 2003 +0000
@@ -27,6 +27,7 @@
 typedef struct _MsnServConn MsnServConn;
 
 #include "msg.h"
+#include "httpmethod.h"
 
 typedef gboolean (*MsnServConnCommandCb)(MsnServConn *servconn,
 										 const char *cmd, const char **params,
@@ -50,6 +51,8 @@
 
 	gboolean connected;
 
+	MsnHttpMethodData *http_data;
+
 	char *server;
 	int port;
 
--- a/src/protocols/msn/session.c	Fri Oct 17 05:58:16 2003 +0000
+++ b/src/protocols/msn/session.c	Fri Oct 17 14:57:59 2003 +0000
@@ -22,6 +22,7 @@
 #include "msn.h"
 #include "session.h"
 #include "dispatch.h"
+#include "notification.h"
 
 MsnSession *
 msn_session_new(GaimAccount *account, const char *server, int port)
@@ -103,12 +104,23 @@
 
 	session->connected = TRUE;
 
-	session->dispatch_conn = msn_dispatch_new(session,
-											  session->dispatch_server,
-											  session->dispatch_port);
+	if (session->http_method)
+	{
+		session->notification_conn =
+			msn_notification_new(session, "gateway.messenger.hotmail.com", 80);
 
-	if (msn_servconn_connect(session->dispatch_conn))
-		return TRUE;
+		if (msn_servconn_connect(session->notification_conn))
+			return TRUE;
+	}
+	else
+	{
+		session->dispatch_conn = msn_dispatch_new(session,
+												  session->dispatch_server,
+												  session->dispatch_port);
+
+		if (msn_servconn_connect(session->dispatch_conn))
+			return TRUE;
+	}
 
 	return FALSE;
 }
--- a/src/protocols/msn/session.h	Fri Oct 17 05:58:16 2003 +0000
+++ b/src/protocols/msn/session.h	Fri Oct 17 14:57:59 2003 +0000
@@ -48,6 +48,8 @@
 
 	unsigned int trId;
 
+	gboolean http_method;
+
 	char *ssl_url;
 	char *ssl_login_host;
 	char *ssl_login_path;
--- a/src/protocols/msn/switchboard.c	Fri Oct 17 05:58:16 2003 +0000
+++ b/src/protocols/msn/switchboard.c	Fri Oct 17 14:57:59 2003 +0000
@@ -459,6 +459,9 @@
 	msn_servconn_set_connect_cb(servconn, connect_cb);
 	msn_servconn_set_failed_read_cb(servconn, failed_read_cb);
 
+	if (session->http_method)
+		swboard->servconn->http_data->server_type = "SB";
+
 	servconn->data = swboard;
 
 	session->switches = g_list_append(session->switches, swboard);