diff libpurple/protocols/msn/slplink.c @ 30735:66e7fe9f7810

propagate from branch 'im.pidgin.pidgin' (head cd770a44f05f96d1e74ea761e614d1a468ba60df) to branch 'im.pidgin.cpw.qulogic.msnp16' (head 6d2fd5bca8c2fda994d1dfbb04197ab9882d652d)
author Elliott Sales de Andrade <qulogic@pidgin.im>
date Sat, 22 May 2010 06:27:18 +0000
parents f8ec889c5bce 11e748b759a2
children 2bc54dfae627
line wrap: on
line diff
--- a/libpurple/protocols/msn/slplink.c	Mon May 10 23:21:44 2010 +0000
+++ b/libpurple/protocols/msn/slplink.c	Sat May 22 06:27:18 2010 +0000
@@ -101,10 +101,8 @@
 
 	session = slplink->session;
 
-#if 0
-	if (slplink->directconn != NULL)
-		msn_directconn_destroy(slplink->directconn);
-#endif
+	if (slplink->dc != NULL)
+		msn_dc_destroy(slplink->dc);
 
 	while (slplink->slp_calls != NULL)
 		msn_slpcall_destroy(slplink->slp_calls->data);
@@ -185,11 +183,21 @@
 		slplink->swboard->flag |= MSN_SB_FLAG_FT;
 
 	slplink->slp_calls = g_list_append(slplink->slp_calls, slpcall);
+
+	/*
+	if (slplink->dc != NULL && slplink->dc->state == DC_STATE_ESTABLISHED)
+		msn_dc_ref(slplink->dc);
+	*/
 }
 
 void
 msn_slplink_remove_slpcall(MsnSlpLink *slplink, MsnSlpCall *slpcall)
 {
+	/*
+	if (slplink->dc != NULL && slplink->dc->state == DC_STATE_ESTABLISHED)
+		msn_dc_unref(slplink->dc);
+	*/
+
 	slplink->slp_calls = g_list_remove(slplink->slp_calls, slpcall);
 
 	/* The slplink has no slpcalls in it, release it from MSN_SB_FLAG_FT.
@@ -197,6 +205,10 @@
 	 * destroyed. */
 	if (slplink->slp_calls == NULL && slplink->swboard != NULL)
 		msn_switchboard_release(slplink->swboard, MSN_SB_FLAG_FT);
+
+	/* The slplink has no slpcalls in it, release it from the DC. */
+	if (slplink->slp_calls == NULL && slplink->dc != NULL)
+		msn_dc_destroy(slplink->dc);
 }
 
 MsnSlpCall *
@@ -236,16 +248,14 @@
 	return NULL;
 }
 
-static void
+void
 msn_slplink_send_msg(MsnSlpLink *slplink, MsnMessage *msg)
 {
-#if 0
-	if (slplink->directconn != NULL)
+	if (slplink->dc != NULL && slplink->dc->state == DC_STATE_ESTABLISHED)
 	{
-		msn_directconn_send_msg(slplink->directconn, msg);
+		msn_dc_enqueue_msg(slplink->dc, msg);
 	}
 	else
-#endif
 	{
 		if (slplink->swboard == NULL)
 		{
@@ -344,6 +354,7 @@
 		if (slpmsg->slpcall->xfer && purple_xfer_get_status(slpmsg->slpcall->xfer) == PURPLE_XFER_STATUS_STARTED)
 		{
 			slpmsg->slpcall->xfer_msg = slpmsg;
+			msn_message_ref(msg);
 			purple_xfer_prpl_ready(slpmsg->slpcall->xfer);
 		}
 		else
@@ -382,6 +393,7 @@
 msn_slplink_release_slpmsg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg)
 {
 	MsnMessage *msg;
+	const char *passport;
 
 	slpmsg->msg = msg = msn_message_new_msnslp();
 
@@ -420,7 +432,8 @@
 
 	msg->msnslp_header.total_size = slpmsg->size;
 
-	msn_message_set_header(msg, "P2P-Dest", slplink->remote_user);
+	passport = purple_normalize(slplink->session->account, slplink->remote_user);
+	msn_message_set_header(msg, "P2P-Dest", passport);
 
 	msg->ack_cb = msg_ack;
 	msg->nak_cb = msg_nak;
@@ -461,21 +474,29 @@
 	}
 }
 
-static void
-msn_slplink_send_ack(MsnSlpLink *slplink, MsnMessage *msg)
+static MsnSlpMessage *
+msn_slplink_create_ack(MsnSlpLink *slplink, MsnSlpHeader *header)
 {
 	MsnSlpMessage *slpmsg;
 
 	slpmsg = msn_slpmsg_new(slplink);
 
-	slpmsg->session_id = msg->msnslp_header.session_id;
-	slpmsg->size       = msg->msnslp_header.total_size;
+	slpmsg->session_id = header->session_id;
+	slpmsg->size       = header->total_size;
 	slpmsg->flags      = 0x02;
-	slpmsg->ack_id     = msg->msnslp_header.id;
-	slpmsg->ack_sub_id = msg->msnslp_header.ack_id;
-	slpmsg->ack_size   = msg->msnslp_header.total_size;
+	slpmsg->ack_id     = header->id;
+	slpmsg->ack_sub_id = header->ack_id;
+	slpmsg->ack_size   = header->total_size;
 	slpmsg->info = "SLP ACK";
 
+	return slpmsg;
+}
+
+static void
+msn_slplink_send_ack(MsnSlpLink *slplink, MsnSlpHeader *header)
+{
+	MsnSlpMessage *slpmsg = msn_slplink_create_ack(slplink, header);
+
 	msn_slplink_send_slpmsg(slplink, slpmsg);
 	msn_slpmsg_destroy(slpmsg);
 }
@@ -487,6 +508,9 @@
 	PurpleXfer *xfer;
 
 	xfer = (PurpleXfer *)slpcall->xfer;
+	if (purple_xfer_get_status(xfer) >= PURPLE_XFER_STATUS_STARTED)
+		return;
+
 	purple_xfer_ref(xfer);
 	purple_xfer_start(xfer, -1, NULL, 0);
 	if (purple_xfer_get_status(xfer) != PURPLE_XFER_STATUS_STARTED) {
@@ -521,21 +545,12 @@
 }
 
 void
-msn_slplink_process_msg(MsnSlpLink *slplink, MsnMessage *msg)
+msn_slplink_process_msg(MsnSlpLink *slplink, MsnSlpHeader *header, const char *data, gsize len)
 {
 	MsnSlpMessage *slpmsg;
-	const char *data;
 	guint64 offset;
-	gsize len;
 
-	if (purple_debug_is_verbose())
-		msn_slpmsg_show(msg);
-
-#ifdef MSN_DEBUG_SLP_FILES
-	debug_msg_to_file(msg, FALSE);
-#endif
-
-	if (msg->msnslp_header.total_size < msg->msnslp_header.length)
+	if (header->total_size < header->length)
 	{
 		/* We seem to have received a bad header */
 		purple_debug_warning("msn", "Total size listed in SLP binary header "
@@ -544,17 +559,15 @@
 		return;
 	}
 
-	data = msn_message_get_bin_data(msg, &len);
-
-	offset = msg->msnslp_header.offset;
+	offset = header->offset;
 
 	if (offset == 0)
 	{
 		slpmsg = msn_slpmsg_new(slplink);
-		slpmsg->id = msg->msnslp_header.id;
-		slpmsg->session_id = msg->msnslp_header.session_id;
-		slpmsg->size = msg->msnslp_header.total_size;
-		slpmsg->flags = msg->msnslp_header.flags;
+		slpmsg->id = header->id;
+		slpmsg->session_id = header->session_id;
+		slpmsg->size = header->total_size;
+		slpmsg->flags = header->flags;
 
 		if (slpmsg->session_id)
 		{
@@ -597,7 +610,7 @@
 	}
 	else
 	{
-		slpmsg = msn_slplink_message_find(slplink, msg->msnslp_header.session_id, msg->msnslp_header.id);
+		slpmsg = msn_slplink_message_find(slplink, header->session_id, header->id);
 		if (slpmsg == NULL)
 		{
 			/* Probably the transfer was canceled */
@@ -644,8 +657,7 @@
 		return;
 #endif
 
-	if (msg->msnslp_header.offset + msg->msnslp_header.length
-		>= msg->msnslp_header.total_size)
+	if (header->offset + header->length >= header->total_size)
 	{
 		/* All the pieces of the slpmsg have been received */
 		MsnSlpCall *slpcall;
@@ -657,32 +669,45 @@
 			return;
 		}
 
-		if (!slpcall->wasted) {
-			if (slpmsg->flags == 0x100)
-			{
-				MsnDirectConn *directconn;
+		purple_debug_info("msn", "msn_slplink_process_msg: slpmsg complete\n");
 
-				directconn = slplink->directconn;
+		if (/* !slpcall->wasted && */ slpmsg->flags == 0x100)
+		{
 #if 0
-				if (!directconn->acked)
-					msn_directconn_send_handshake(directconn);
+			MsnDirectConn *directconn;
+
+			directconn = slplink->directconn;
+			if (!directconn->acked)
+				msn_directconn_send_handshake(directconn);
 #endif
-			}
-			else if (slpmsg->flags == 0x00 || slpmsg->flags == 0x1000000 ||  
-			         slpmsg->flags == 0x20 || slpmsg->flags == 0x1000020 ||  
-			         slpmsg->flags == 0x1000030)
-			{
-				/* Release all the messages and send the ACK */
+		}
+		else if (slpmsg->flags == 0x00 || slpmsg->flags == 0x1000000 ||
+		         slpmsg->flags == 0x20 || slpmsg->flags == 0x1000020 ||
+		         slpmsg->flags == 0x1000030)
+		{
+			/* Release all the messages and send the ACK */
 
-				msn_slplink_send_ack(slplink, msg);
+			if (slpcall->wait_for_socket) {
+				/*
+				 * Save ack for later because we have to send
+				 * a 200 OK message to the previous direct connect
+				 * invitation before ACK but the listening socket isn't
+				 * created yet.
+				 */
+				purple_debug_info("msn", "msn_slplink_process_msg: save ACK\n");
+
+				slpcall->slplink->dc->prev_ack = msn_slplink_create_ack(slplink, header);
+			} else if (!slpcall->wasted) {
+				purple_debug_info("msn", "msn_slplink_process_msg: send ACK\n");
+
+				msn_slplink_send_ack(slplink, header);
 				msn_slplink_send_queued_slpmsgs(slplink);
 			}
-
 		}
 
 		msn_slpmsg_destroy(slpmsg);
 
-		if (slpcall->wasted)
+		if (!slpcall->wait_for_socket && slpcall->wasted)
 			msn_slpcall_destroy(slpcall);
 	}
 }