diff libpurple/protocols/msn/slpmsg.c @ 31292:47b6eda87723

propagate from branch 'im.pidgin.pidgin' (head 07d0765c444a097af45c2650f54323afb900a07b) to branch 'im.pidgin.soc.2010.msn-tlc' (head f3998422a4724ab424e4e2328f58fc0504856557)
author masca@cpw.pidgin.im
date Mon, 19 Jul 2010 21:11:32 +0000
parents 237e2c2874e6
children 6814678f3c63
line wrap: on
line diff
--- a/libpurple/protocols/msn/slpmsg.c	Mon Jul 19 18:25:47 2010 +0000
+++ b/libpurple/protocols/msn/slpmsg.c	Mon Jul 19 21:11:32 2010 +0000
@@ -21,8 +21,12 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
-#include "msn.h"
+
+#include "internal.h"
+#include "debug.h"
+
 #include "slpmsg.h"
+#include "slpmsg_part.h"
 #include "slplink.h"
 
 /**************************************************************************
@@ -39,10 +43,48 @@
 	if (purple_debug_is_verbose())
 		purple_debug_info("msn", "slpmsg new (%p)\n", slpmsg);
 
-	slpmsg->slplink = slplink;
+	if (slplink) 
+		msn_slpmsg_set_slplink(slpmsg, slplink);
+	else
+		slpmsg->slplink = NULL;
+
+	slpmsg->header = NULL;
+	slpmsg->footer = NULL;
+
+	return slpmsg;
+}
+
+MsnSlpMessage *msn_slpmsg_new_from_data(const char *data, size_t data_len)
+{
+	MsnSlpMessage *slpmsg;
+	MsnP2PHeader *header;
+	const char *tmp;
+	int body_len;
+
+	tmp = data;
+	slpmsg = msn_slpmsg_new(NULL);
 
-	slplink->slp_msgs =
-		g_list_append(slplink->slp_msgs, slpmsg);
+	if (data_len < sizeof(*header)) {
+		return NULL;
+	}
+
+	/* Extract the binary SLP header */
+	slpmsg->header = msn_p2p_header_from_wire((MsnP2PHeader*)tmp);
+
+	/* Extract the body */
+	body_len = data_len - (tmp - data);
+	/* msg->body_len = msg->msnslp_header.length; */
+
+	if (body_len > 0) {
+		slpmsg->size = body_len;
+		slpmsg->buffer = g_malloc(body_len);
+		memcpy(slpmsg->buffer, tmp, body_len);
+		tmp += body_len;
+	}
+
+	/* Extract the footer */
+	if (body_len >= 0) 
+		slpmsg->footer = msn_p2p_footer_from_wire((MsnP2PFooter*)tmp);
 
 	return slpmsg;
 }
@@ -67,26 +109,41 @@
 	if (slpmsg->img == NULL)
 		g_free(slpmsg->buffer);
 
-	for (cur = slpmsg->msgs; cur != NULL; cur = g_list_delete_link(cur, cur))
+	for (cur = slpmsg->parts; cur != NULL; cur = g_list_delete_link(cur, cur))
 	{
 		/* Something is pointing to this slpmsg, so we should remove that
 		 * pointer to prevent a crash. */
 		/* Ex: a user goes offline and after that we receive an ACK */
 
-		MsnMessage *msg = cur->data;
+		MsnSlpMessagePart *part = cur->data;
 
-		msg->ack_cb = NULL;
-		msg->nak_cb = NULL;
-		msg->ack_data = NULL;
-		msn_message_unref(msg);
+		part->ack_cb = NULL;
+		part->nak_cb = NULL;
+		part->ack_data = NULL;
+		msn_slpmsgpart_destroy(part);
 	}
 
 	slplink->slp_msgs = g_list_remove(slplink->slp_msgs, slpmsg);
 
+	g_free(slpmsg->header);
+	g_free(slpmsg->footer);
+
 	g_free(slpmsg);
 }
 
 void
+msn_slpmsg_set_slplink(MsnSlpMessage *slpmsg, MsnSlpLink *slplink)
+{
+	g_return_if_fail(slplink != NULL);
+
+	slpmsg->slplink = slplink;
+
+	slplink->slp_msgs =
+		g_list_append(slplink->slp_msgs, slpmsg);
+
+}
+
+void
 msn_slpmsg_set_body(MsnSlpMessage *slpmsg, const char *body,
 						 long long size)
 {
@@ -116,34 +173,6 @@
 	slpmsg->size = purple_imgstore_get_size(img);
 }
 
-void
-msn_slpmsg_show(MsnMessage *msg)
-{
-	const char *info;
-	gboolean text;
-	guint32 flags;
-
-	text = FALSE;
-
-	flags = GUINT32_TO_LE(msg->msnslp_header.flags);
-
-	switch (flags)
-	{
-		case 0x0:
-			info = "SLP CONTROL";
-			text = TRUE;
-			break;
-		case 0x2:
-			info = "SLP ACK"; break;
-		case 0x20:
-		case 0x1000030:
-			info = "SLP DATA"; break;
-		default:
-			info = "SLP UNKNOWN"; break;
-	}
-
-	msn_message_show_readable(msg, info, text);
-}
 
 MsnSlpMessage *
 msn_slpmsg_sip_new(MsnSlpCall *slpcall, int cseq,
@@ -206,3 +235,127 @@
 
 	return slpmsg;
 }
+
+MsnSlpMessage *msn_slpmsg_ack_new(MsnP2PHeader *header)
+{
+	MsnSlpMessage *slpmsg;
+
+	slpmsg = msn_slpmsg_new(NULL);
+
+	slpmsg->session_id = header->session_id;
+	slpmsg->size       = header->total_size;
+	slpmsg->flags      = P2P_ACK;
+	slpmsg->ack_id     = header->id;
+	slpmsg->ack_sub_id = header->ack_id;
+	slpmsg->ack_size   = header->total_size;
+	slpmsg->info = "SLP ACK";
+
+	return slpmsg;
+}
+
+MsnSlpMessage *msn_slpmsg_obj_new(MsnSlpCall *slpcall, PurpleStoredImage *img)
+{
+	MsnSlpMessage *slpmsg;
+
+	slpmsg = msn_slpmsg_new(NULL);
+	slpmsg->slpcall = slpcall;
+	slpmsg->flags = P2P_MSN_OBJ_DATA;
+	slpmsg->info = "SLP DATA";
+
+	msn_slpmsg_set_image(slpmsg, img);
+
+	return slpmsg;
+}
+
+MsnSlpMessage *msn_slpmsg_dataprep_new(MsnSlpCall *slpcall)
+{
+	MsnSlpMessage *slpmsg;
+
+	slpmsg = msn_slpmsg_new(NULL);
+	slpmsg->slpcall = slpcall;
+	slpmsg->session_id = slpcall->session_id;
+	msn_slpmsg_set_body(slpmsg, NULL, 4);
+	slpmsg->info = "SLP DATA PREP";
+
+	return slpmsg;
+
+}
+
+MsnSlpMessage *msn_slpmsg_file_new(MsnSlpCall *slpcall, size_t size)
+{
+	MsnSlpMessage *slpmsg;
+
+	slpmsg = msn_slpmsg_new(NULL);
+
+	slpmsg->slpcall = slpcall;
+	slpmsg->flags = P2P_FILE_DATA;
+	slpmsg->info = "SLP FILE";
+	slpmsg->size = size;
+
+	return slpmsg;
+}
+
+char *msn_slpmsg_serialize(MsnSlpMessage *slpmsg, size_t *ret_size)
+{
+	MsnP2PHeader *header;
+	MsnP2PFooter *footer;
+	char *base;
+	char *tmp;
+	size_t siz;
+
+	base = g_malloc(P2P_PACKET_HEADER_SIZE + slpmsg->size + sizeof(MsnP2PFooter));
+	tmp = base;
+
+	header = msn_p2p_header_to_wire(slpmsg->header);
+	footer = msn_p2p_footer_to_wire(slpmsg->footer);
+
+	siz = sizeof(MsnP2PHeader);
+	/* Copy header */
+	memcpy(tmp, (char*)header, siz);
+	tmp += siz;
+
+	/* Copy body */
+	memcpy(tmp, slpmsg->buffer, slpmsg->size);
+	tmp += slpmsg->size;
+
+	/* Copy footer */
+	siz = sizeof(MsnP2PFooter);
+	memcpy(tmp, (char*)footer, siz);
+	tmp += siz;
+
+	*ret_size = tmp - base;
+
+	return base;
+}
+
+void msn_slpmsg_show_readable(MsnSlpMessage *slpmsg)
+{
+	GString *str;
+
+	str = g_string_new(NULL);
+
+	g_string_append_printf(str, "Session ID: %u\r\n", slpmsg->header->session_id);
+	g_string_append_printf(str, "ID:         %u\r\n", slpmsg->header->id);
+	g_string_append_printf(str, "Offset:     %" G_GUINT64_FORMAT "\r\n", slpmsg->header->offset);
+	g_string_append_printf(str, "Total size: %" G_GUINT64_FORMAT "\r\n", slpmsg->header->total_size);
+	g_string_append_printf(str, "Length:     %u\r\n", slpmsg->header->length);
+	g_string_append_printf(str, "Flags:      0x%x\r\n", slpmsg->header->flags);
+	g_string_append_printf(str, "ACK ID:     %u\r\n", slpmsg->header->ack_id);
+	g_string_append_printf(str, "SUB ID:     %u\r\n", slpmsg->header->ack_sub_id);
+	g_string_append_printf(str, "ACK Size:   %" G_GUINT64_FORMAT "\r\n", slpmsg->header->ack_size);
+
+	if (purple_debug_is_verbose() && slpmsg->buffer != NULL) {
+		g_string_append_len(str, slpmsg->buffer, slpmsg->size);
+
+		if (slpmsg->buffer[slpmsg->size - 1] == '\0') {
+			str->len--;
+			g_string_append(str, " 0x00");
+		}
+		g_string_append(str, "\r\n");
+
+	}
+
+	g_string_append_printf(str, "Footer:     %u\r\n", slpmsg->footer->value);
+
+	purple_debug_info("msn", "SlpMessage %s:\n{%s}\n", slpmsg->info, str->str);
+}