Index: protocols/msn/ns.c
===================================================================
--- protocols/msn/ns.c	(revision 37520198d52502d1542089b48a9a9507d3c722d6)
+++ protocols/msn/ns.c	(revision ffa5b70b1315d46a8d4a1f81a2cf8aad66d06096)
@@ -35,6 +35,4 @@
 static gboolean msn_ns_connected(gpointer data, gint source, b_input_condition cond);
 static gboolean msn_ns_callback(gpointer data, gint source, b_input_condition cond);
-static int msn_ns_command(struct msn_handler_data *handler, char **cmd, int num_parts);
-static int msn_ns_message(struct msn_handler_data *handler, char *msg, int msglen, char **cmd, int num_parts);
 
 static void msn_ns_send_adl_start(struct im_connection *ic);
@@ -54,5 +52,5 @@
 
 	if (fd < 0) {
-		fd = md->ns->fd;
+		fd = md->fd;
 	}
 
@@ -73,13 +71,12 @@
 }
 
-gboolean msn_ns_connect(struct im_connection *ic, struct msn_handler_data *handler, const char *host, int port)
-{
+gboolean msn_ns_connect(struct im_connection *ic, const char *host, int port)
+{
+	struct msn_data *handler = ic->proto_data;
+
 	if (handler->fd >= 0) {
 		closesocket(handler->fd);
 	}
 
-	handler->exec_command = msn_ns_command;
-	handler->exec_message = msn_ns_message;
-	handler->data = ic;
 	handler->fd = proxy_connect(host, port, msn_ns_connected, handler);
 	if (handler->fd < 0) {
@@ -94,13 +91,7 @@
 static gboolean msn_ns_connected(gpointer data, gint source, b_input_condition cond)
 {
-	struct msn_handler_data *handler = data;
-	struct im_connection *ic = handler->data;
-	struct msn_data *md;
-
-	if (!g_slist_find(msn_connections, ic)) {
-		return FALSE;
-	}
-
-	md = ic->proto_data;
+	struct msn_data *md = data;
+	struct msn_data *handler = md;
+	struct im_connection *ic = md->ic;
 
 	if (source == -1) {
@@ -137,5 +128,5 @@
 }
 
-void msn_ns_close(struct msn_handler_data *handler)
+void msn_ns_close(struct msn_data *handler)
 {
 	if (handler->fd >= 0) {
@@ -155,6 +146,6 @@
 static gboolean msn_ns_callback(gpointer data, gint source, b_input_condition cond)
 {
-	struct msn_handler_data *handler = data;
-	struct im_connection *ic = handler->data;
+	struct msn_data *handler = data;
+	struct im_connection *ic = handler->ic;
 
 	if (msn_handler(handler) == -1) {  /* Don't do this on ret == 0, it's already done then. */
@@ -168,8 +159,8 @@
 }
 
-static int msn_ns_command(struct msn_handler_data *handler, char **cmd, int num_parts)
-{
-	struct im_connection *ic = handler->data;
-	struct msn_data *md = ic->proto_data;
+int msn_ns_command(struct msn_data *handler, char **cmd, int num_parts)
+{
+	struct im_connection *ic = handler->ic;
+	struct msn_data *md = handler;
 
 	if (num_parts == 0) {
@@ -209,52 +200,5 @@
 
 			imcb_log(ic, "Transferring to other server");
-			return msn_ns_connect(ic, handler, server, port);
-		} else if (num_parts >= 6 && strcmp(cmd[2], "SB") == 0) {
-			struct msn_switchboard *sb;
-
-			server = strchr(cmd[3], ':');
-			if (!server) {
-				imcb_error(ic, "Syntax error");
-				imc_logout(ic, TRUE);
-				return(0);
-			}
-			*server = 0;
-			port = atoi(server + 1);
-			server = cmd[3];
-
-			if (strcmp(cmd[4], "CKI") != 0) {
-				imcb_error(ic, "Unknown authentication method for switchboard");
-				imc_logout(ic, TRUE);
-				return(0);
-			}
-
-			debug("Connecting to a new switchboard with key %s", cmd[5]);
-
-			if ((sb = msn_sb_create(ic, server, port, cmd[5], MSN_SB_NEW)) == NULL) {
-				/* Although this isn't strictly fatal for the NS connection, it's
-				   definitely something serious (we ran out of file descriptors?). */
-				imcb_error(ic, "Could not create new switchboard");
-				imc_logout(ic, TRUE);
-				return(0);
-			}
-
-			if (md->msgq) {
-				struct msn_message *m = md->msgq->data;
-				GSList *l;
-
-				sb->who = g_strdup(m->who);
-
-				/* Move all the messages to the first user in the message
-				   queue to the switchboard message queue. */
-				l = md->msgq;
-				while (l) {
-					m = l->data;
-					l = l->next;
-					if (strcmp(m->who, sb->who) == 0) {
-						sb->msgq = g_slist_append(sb->msgq, m);
-						md->msgq = g_slist_remove(md->msgq, m);
-					}
-				}
-			}
+			return msn_ns_connect(ic, server, port);
 		} else {
 			imcb_error(ic, "Syntax error");
@@ -361,5 +305,4 @@
 		                  st->name, NULL);
 
-		msn_sb_stop_keepalives(msn_sb_by_handle(ic, handle));
 	} else if (strcmp(cmd[0], "FLN") == 0) {
 		const char *handle;
@@ -371,45 +314,4 @@
 		handle = msn_normalize_handle(cmd[1]);
 		imcb_buddy_status(ic, handle, 0, NULL, NULL);
-		msn_sb_start_keepalives(msn_sb_by_handle(ic, handle), TRUE);
-	} else if (strcmp(cmd[0], "RNG") == 0) {
-		struct msn_switchboard *sb;
-		char *server;
-		int session, port;
-
-		if (num_parts < 7) {
-			imcb_error(ic, "Syntax error");
-			imc_logout(ic, TRUE);
-			return(0);
-		}
-
-		session = atoi(cmd[1]);
-
-		server = strchr(cmd[2], ':');
-		if (!server) {
-			imcb_error(ic, "Syntax error");
-			imc_logout(ic, TRUE);
-			return(0);
-		}
-		*server = 0;
-		port = atoi(server + 1);
-		server = cmd[2];
-
-		if (strcmp(cmd[3], "CKI") != 0) {
-			imcb_error(ic, "Unknown authentication method for switchboard");
-			imc_logout(ic, TRUE);
-			return(0);
-		}
-
-		debug("Got a call from %s (session %d). Key = %s", cmd[5], session, cmd[4]);
-
-		if ((sb = msn_sb_create(ic, server, port, cmd[4], session)) == NULL) {
-			/* Although this isn't strictly fatal for the NS connection, it's
-			   definitely something serious (we ran out of file descriptors?). */
-			imcb_error(ic, "Could not create new switchboard");
-			imc_logout(ic, TRUE);
-			return(0);
-		} else {
-			sb->who = g_strdup(msn_normalize_handle(cmd[5]));
-		}
 	} else if (strcmp(cmd[0], "OUT") == 0) {
 		int allow_reconnect = TRUE;
@@ -494,5 +396,5 @@
 			handler->msglen = atoi(cmd[1]);
 		}
-	} else if (strcmp(cmd[0], "NFY") == 0) {
+	} else if ((strcmp(cmd[0], "NFY") == 0) || (strcmp(cmd[0], "SDG") == 0)) {
 		if (num_parts >= 3) {
 			handler->msglen = atoi(cmd[2]);
@@ -526,7 +428,7 @@
 }
 
-static int msn_ns_message(struct msn_handler_data *handler, char *msg, int msglen, char **cmd, int num_parts)
-{
-	struct im_connection *ic = handler->data;
+int msn_ns_message(struct msn_data *handler, char *msg, int msglen, char **cmd, int num_parts)
+{
+	struct im_connection *ic = handler->ic;
 	char *body;
 	int blen = 0;
@@ -717,30 +619,27 @@
 			}
 		}
-	} else if (strcmp(cmd[0], "UBM") == 0) {
-		/* This one will give us msgs from federated networks. Technically
-		   it should also get us offline messages, but I don't know how
-		   I can signal MSN servers to use it. */
-		char *ct, *handle;
-
-		if (strcmp(cmd[1], ic->acc->user) == 0) {
-			/* With MPOP, you'll get copies of your own msgs from other
-			   sessions. Discard those at least for now. */
-			return 1;
-		}
-
-		ct = get_rfc822_header(msg, "Content-Type", msglen);
-		if (strncmp(ct, "text/plain", 10) != 0) {
-			/* Typing notification or something? */
-			g_free(ct);
-			return 1;
-		}
-		if (strcmp(cmd[2], "1") != 0) {
-			handle = g_strdup_printf("%s:%s", cmd[2], cmd[1]);
-		} else {
-			handle = g_strdup(cmd[1]);
-		}
-
-		imcb_buddy_msg(ic, handle, body, 0, 0);
-		g_free(handle);
+	} else if (strcmp(cmd[0], "SDG") == 0) {
+		char **parts = g_strsplit(msg, "\r\n\r\n", 4);
+		char *from = NULL;
+		char *mt = NULL;
+		char *who = NULL;
+		char *s = NULL;
+
+		if ((from = get_rfc822_header(parts[0], "From", 0)) &&
+		    (mt = get_rfc822_header(parts[2], "Message-Type", 0)) &&
+		    (s = strchr(from, ';'))) {
+
+			who = g_strndup(from + 2, s - from - 2);
+
+			if (strcmp(mt, "Control/Typing") == 0) {
+				imcb_buddy_typing(ic, who, OPT_TYPING);
+			} else if (strcmp(mt, "Text") == 0) {
+				imcb_buddy_msg(ic, who, parts[3], 0, 0);
+			}
+		}
+		g_free(from);
+		g_free(mt);
+		g_free(who);
+		return 1;
 	}
 
@@ -893,9 +792,10 @@
 }
 
+// TODO: typing notifications, nudges lol, etc
 int msn_ns_sendmessage(struct im_connection *ic, bee_user_t *bu, const char *text)
 {
 	struct msn_data *md = ic->proto_data;
-	int type = 0;
-	char *buf, *handle;
+	int retval = 0;
+	char *buf;
 
 	if (strncmp(text, "\r\r\r", 3) == 0) {
@@ -905,25 +805,8 @@
 	}
 
-	/* This might be a federated contact. Get its network number,
-	   prefixed to bu->handle with a colon. Default is 1. */
-	for (handle = bu->handle; g_ascii_isdigit(*handle); handle++) {
-		type = type * 10 + *handle - '0';
-	}
-	if (*handle == ':') {
-		handle++;
-	} else {
-		type = 1;
-	}
-
-	buf = g_strdup_printf("%s%s", MSN_MESSAGE_HEADERS, text);
-
-	if (msn_ns_write(ic, -1, "UUM %d %s %d %d %zd\r\n%s",
-	                 ++md->trId, handle, type,
-	                 1,          /* type == IM (not nudge/typing) */
-	                 strlen(buf), buf)) {
-		return 1;
-	} else {
-		return 0;
-	}
+	buf = g_strdup_printf(MSN_MESSAGE_HEADERS, bu->handle, ic->acc->user, md->uuid, strlen(text), text);
+	retval = msn_ns_write(ic, -1, "SDG %d %zd\r\n%s", ++md->trId, strlen(buf), buf);
+	g_free(buf);
+	return retval;
 }
 
