Index: protocols/msn/gw.c
===================================================================
--- protocols/msn/gw.c	(revision a4be2f6df564eea09612731be194278e4fb755e0)
+++ protocols/msn/gw.c	(revision 913a663a3e383c40c644a7d0a8c8aba9d417167c)
@@ -30,4 +30,7 @@
 void msn_gw_free(struct msn_gw *gw)
 {
+	if (gw->poll_timeout != -1) {
+		b_event_remove(gw->poll_timeout);
+	}
 	g_byte_array_free(gw->in, TRUE);
 	g_byte_array_free(gw->out, TRUE);
@@ -66,7 +69,28 @@
 	struct msn_gw *gw = req->data;
 
+	gw->waiting = FALSE;
+
+	if (!gw->open) {
+		/* the user tried to logout while the request was pending
+		 * see msn_ns_close() */
+		msn_gw_free(gw);
+		return;
+	}
+
+	if (getenv("BITLBEE_DEBUG")) {
+		fprintf(stderr, "\n\x1b[90mHTTP:%s\n", req->reply_body);
+		fprintf(stderr, "\n\x1b[97m\n");
+	}
+
+	if (req->status_code != 200) {
+		gw->callback(gw->data, -1, B_EV_IO_READ);
+		return;
+	}
+
 	if ((value = get_rfc822_header(req->reply_headers, "X-MSN-Messenger", 0))) {
 		if (!msn_gw_parse_session_header(gw, value)) {
-			/* XXX handle this */
+			gw->callback(gw->data, -1, B_EV_IO_READ);
+			g_free(value);
+			return;
 		}
 		g_free(value);
@@ -78,5 +102,8 @@
 	}
 
-	/* XXX handle reply */
+	if (req->body_size) {
+		g_byte_array_append(gw->in, (const guint8 *) req->reply_body, req->body_size);
+		gw->callback(gw->data, -1, B_EV_IO_READ);
+	}
 
 	if (gw->poll_timeout != -1) {
@@ -104,4 +131,5 @@
 
 	http_dorequest(gw->last_host, gw->port, gw->ssl, request, msn_gw_callback, gw);
+	gw->open = TRUE;
 	gw->waiting = TRUE;
 
@@ -113,5 +141,4 @@
 {
 	msn_gw_dorequest(gw, "Action=open&Server=NS");
-	gw->open = TRUE;
 }
 
@@ -125,2 +152,26 @@
 	return FALSE;
 }
+
+ssize_t msn_gw_read(struct msn_gw *gw, char **buf)
+{
+	size_t bodylen;
+	if (!gw->open) {
+		return 0;
+	}
+
+	bodylen = gw->in->len;
+	g_byte_array_append(gw->in, (guint8 *) "", 1); /* nullnullnull */
+	*buf = (char *) g_byte_array_free(gw->in, FALSE);
+	gw->in = g_byte_array_new();
+	return bodylen;
+}
+
+void msn_gw_write(struct msn_gw *gw, char *buf, size_t len)
+{
+	g_byte_array_append(gw->out, (const guint8 *) buf, len);
+	if (!gw->open) {
+		msn_gw_open(gw);
+	} else if (!gw->waiting) {
+		msn_gw_dorequest(gw, NULL);
+	}
+}
Index: protocols/msn/msn.c
===================================================================
--- protocols/msn/msn.c	(revision a4be2f6df564eea09612731be194278e4fb755e0)
+++ protocols/msn/msn.c	(revision 913a663a3e383c40c644a7d0a8c8aba9d417167c)
@@ -62,9 +62,5 @@
 
 	if (!server) {
-		imcb_error(ic, "The msn protocol is disabled in this version because most servers disabled MSNP18 over port 1863.");
-		imcb_error(ic, "If you find a working server, you can change the 'server' setting of this account. Good luck!");
-		imcb_error(ic, "See also: http://ismsndeadyet.com/"); // shameless plug
-		imc_logout(ic, FALSE);
-		return;
+		server = "geo.gateway.messenger.live.com";
 	}
 
@@ -79,4 +75,5 @@
 	md->domaintree = g_tree_new(msn_domaintree_cmp);
 	md->fd = -1;
+	md->is_http = TRUE;
 
 	msn_connections = g_slist_prepend(msn_connections, ic);
Index: protocols/msn/msn.h
===================================================================
--- protocols/msn/msn.h	(revision a4be2f6df564eea09612731be194278e4fb755e0)
+++ protocols/msn/msn.h	(revision 913a663a3e383c40c644a7d0a8c8aba9d417167c)
@@ -263,3 +263,10 @@
 const struct msn_status_code *msn_status_by_number(int number);
 
+/* gw.c */
+struct msn_gw *msn_gw_new(struct msn_data *md);
+void msn_gw_free(struct msn_gw *gw);
+void msn_gw_open(struct msn_gw *gw);
+ssize_t msn_gw_read(struct msn_gw *gw, char **buf);
+void msn_gw_write(struct msn_gw *gw, char *buf, size_t len);
+
 #endif //_MSN_H
Index: protocols/msn/msn_util.c
===================================================================
--- protocols/msn/msn_util.c	(revision a4be2f6df564eea09612731be194278e4fb755e0)
+++ protocols/msn/msn_util.c	(revision 913a663a3e383c40c644a7d0a8c8aba9d417167c)
@@ -174,5 +174,5 @@
 void msn_queue_feed(struct msn_data *h, char *bytes, int st)
 {
-	h->rxq = g_renew(char, h->rxq, h->rxlen + 1024);
+	h->rxq = g_renew(char, h->rxq, h->rxlen + st);
 	memcpy(h->rxq + h->rxlen, bytes, st);
 	h->rxlen += st;
@@ -235,5 +235,5 @@
 			/* If we reached the end of the buffer, there's still an incomplete command there.
 			   Return and wait for more data. */
-			if (i == h->rxlen && h->rxq[i - 1] != '\r' && h->rxq[i - 1] != '\n') {
+			if (i && i == h->rxlen && h->rxq[i - 1] != '\r' && h->rxq[i - 1] != '\n') {
 				break;
 			}
Index: protocols/msn/ns.c
===================================================================
--- protocols/msn/ns.c	(revision a4be2f6df564eea09612731be194278e4fb755e0)
+++ protocols/msn/ns.c	(revision 913a663a3e383c40c644a7d0a8c8aba9d417167c)
@@ -60,5 +60,12 @@
 
 	len = strlen(out);
-	st = write(fd, out, len);
+
+	if (md->is_http) {
+		st = len;
+		msn_gw_write(md->gw, out, len);
+	} else {
+		st = write(fd, out, len);
+	}
+
 	g_free(out);
 	if (st != len) {
@@ -79,9 +86,15 @@
 	}
 
-	handler->fd = proxy_connect(host, port, msn_ns_connected, handler);
-	if (handler->fd < 0) {
-		imcb_error(ic, "Could not connect to server");
-		imc_logout(ic, TRUE);
-		return FALSE;
+	if (handler->is_http) {
+		handler->gw = msn_gw_new(handler);
+		handler->gw->callback = msn_ns_callback;
+		msn_ns_connected(handler, -1, B_EV_IO_READ);
+	} else {
+		handler->fd = proxy_connect(host, port, msn_ns_connected, handler);
+		if (handler->fd < 0) {
+			imcb_error(ic, "Could not connect to server");
+			imc_logout(ic, TRUE);
+			return FALSE;
+		}
 	}
 
@@ -95,5 +108,5 @@
 	struct im_connection *ic = md->ic;
 
-	if (source == -1) {
+	if (source == -1 && !md->is_http) {
 		imcb_error(ic, "Could not connect to server");
 		imc_logout(ic, TRUE);
@@ -121,5 +134,7 @@
 
 	if (msn_ns_write(ic, source, "VER %d %s CVR0\r\n", ++md->trId, MSNP_VER)) {
-		handler->inpa = b_input_add(handler->fd, B_EV_IO_READ, msn_ns_callback, handler);
+		if (!handler->is_http) {
+			handler->inpa = b_input_add(handler->fd, B_EV_IO_READ, msn_ns_callback, handler);
+		}
 		imcb_log(ic, "Connected to server, waiting for reply");
 	}
@@ -130,4 +145,12 @@
 void msn_ns_close(struct msn_data *handler)
 {
+	if (handler->gw) {
+		if (handler->gw->waiting) {
+			/* mark it as closed, let the request callback clean it */
+			handler->gw->open = FALSE;
+		} else {
+			msn_gw_free(handler->gw);
+		}
+	}
 	if (handler->fd >= 0) {
 		closesocket(handler->fd);
@@ -148,8 +171,14 @@
 	struct msn_data *handler = data;
 	struct im_connection *ic = handler->ic;
-	char bytes[1024];
+	char *bytes;
 	int st;
 
-	st = read(handler->fd, bytes, 1024);
+	if (handler->is_http) {
+		st = msn_gw_read(handler->gw, &bytes);
+	} else {
+		bytes = g_malloc(1024);
+		st = read(handler->fd, bytes, 1024);
+	}
+
 	if (st <= 0) {
 		imcb_error(ic, "Error while reading from server");
@@ -159,4 +188,6 @@
 
 	msn_queue_feed(handler, bytes, st);
+
+	g_free(bytes);
 
 	/* Ignore ret == 0, it's already disconnected then. */
