changeset 25669:d61b0c8aaca1

Added functions to help with the creation of Jingle packets. Also tweaked a few Jingle attribute values.
author Mike Ruprecht <maiku@soc.pidgin.im>
date Tue, 03 Jun 2008 23:35:39 +0000
parents 2ebe89114923
children 42e17cc5b6d2
files libpurple/protocols/jabber/jingle.c
diffstat 1 files changed, 170 insertions(+), 101 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/protocols/jabber/jingle.c	Tue Jun 03 02:59:48 2008 +0000
+++ b/libpurple/protocols/jabber/jingle.c	Tue Jun 03 23:35:39 2008 +0000
@@ -287,10 +287,13 @@
 		c = fs_candidate_new(xmlnode_get_attrib(candidate, "component"), 
 							atoi(xmlnode_get_attrib(candidate, "component")),
 							strcmp(type, "host") == 0 ?
-								FS_CANDIDATE_TYPE_HOST :
-								strcmp(type, "prflx") == 0 ?
-									FS_CANDIDATE_TYPE_PRFLX :
-									FS_CANDIDATE_TYPE_RELAY,
+							FS_CANDIDATE_TYPE_HOST :
+							strcmp(type, "prflx") == 0 ?
+							FS_CANDIDATE_TYPE_PRFLX :
+							strcmp(type, "relay") == 0 ?
+							FS_CANDIDATE_TYPE_RELAY :
+							strcmp(type, "srflx") == 0 ?
+							FS_CANDIDATE_TYPE_SRFLX : 0,
 							strcmp(xmlnode_get_attrib(candidate, "protocol"),
 							  "udp") == 0 ? 
 				 				FS_NETWORK_PROTOCOL_UDP :
@@ -353,31 +356,171 @@
 	return sess->is_initiator;
 }
 
+static void
+jabber_jingle_session_add_payload_types(const JingleSessionContent *jsc,
+					xmlnode *description,
+					const GList *codecs)
+{
+	for (; codecs ; codecs = codecs->next) {
+		FsCodec *codec = (FsCodec*)codecs->data;
+		char id[8], clockrate[10], channels[10];
+		xmlnode *payload = xmlnode_new_child(description, "payload-type");
+		
+		g_snprintf(id, sizeof(id), "%d", codec->id);
+		g_snprintf(clockrate, sizeof(clockrate), "%d", codec->clock_rate);
+		g_snprintf(channels, sizeof(channels), "%d",
+			   codec->channels == 0 ? 1 : codec->channels);
+		
+		xmlnode_set_attrib(payload, "name", codec->encoding_name);
+		xmlnode_set_attrib(payload, "id", id);
+		xmlnode_set_attrib(payload, "clockrate", clockrate);
+		xmlnode_set_attrib(payload, "channels", channels);
+	}
+}
+
 static xmlnode *
-jabber_jingle_session_create_jingle_element(const JingleSession *sess,
-											const char *action)
+jabber_jingle_session_add_description_vv(const JingleSessionContent *jsc,
+					 xmlnode *description)
+{
+	xmlnode_set_attrib(description, "profile", "RTP/AVP");
+	return description;
+}
+
+static xmlnode *
+jabber_jingle_session_add_description(const JingleSessionContent *jsc,
+				      xmlnode *content)
+{
+	xmlnode *description = xmlnode_new_child(content, "description");
+	const gchar *type = jabber_jingle_session_content_get_type(jsc);
+	xmlnode_set_namespace(description, type);
+
+	if (!strcmp(type, "urn:xmpp:tmp:jingle:apps:audio-rtp") ||
+			!strcmp(type, "urn:xmpp:tmp:jingle:apps:video-rtp"))
+		return jabber_jingle_session_add_description_vv(jsc, description);
+	else
+		return description;
+}
+
+static xmlnode *
+jabber_jingle_session_add_candidate_iceudp(xmlnode *transport,
+					   FsCandidate *c,
+					   FsCandidate *remote)
 {
-	xmlnode *jingle = xmlnode_new("jingle");
+	char port[8];
+	char prio[8];
+	char component[8];
+	xmlnode *candidate = xmlnode_new_child(transport, "candidate");
+	
+	g_snprintf(port, sizeof(port), "%d", c->port);
+	g_snprintf(prio, sizeof(prio), "%d", c->priority);
+	g_snprintf(component, sizeof(component), "%d", c->component_id);
+	
+	xmlnode_set_attrib(candidate, "component", component);
+	xmlnode_set_attrib(candidate, "foundation", "1"); /* what about this? */
+	xmlnode_set_attrib(candidate, "generation", "0"); /* ? */
+	xmlnode_set_attrib(candidate, "ip", c->ip);
+	xmlnode_set_attrib(candidate, "network", "0"); /* ? */
+	xmlnode_set_attrib(candidate, "port", port);
+	xmlnode_set_attrib(candidate, "priority", prio); /* Is this correct? */
+	xmlnode_set_attrib(candidate, "protocol",
+			   c->proto == FS_NETWORK_PROTOCOL_UDP ?
+			   "udp" : "tcp");
+	if (c->username)
+		xmlnode_set_attrib(transport, "ufrag", c->username);
+	if (c->password)
+		xmlnode_set_attrib(transport, "pwd", c->password);
+	
+	xmlnode_set_attrib(candidate, "type", 
+			   c->type == FS_CANDIDATE_TYPE_HOST ? 
+			   "host" :
+			   c->type == FS_CANDIDATE_TYPE_PRFLX ? 
+			   "prflx" :
+		       	   c->type == FS_CANDIDATE_TYPE_RELAY ? 
+			   "relay" :
+			   c->type == FS_CANDIDATE_TYPE_SRFLX ?
+			   "srflx" : NULL);
+
+	/* relay */
+	if (c->type == FS_CANDIDATE_TYPE_RELAY) {
+		/* set rel-addr and rel-port? How? */
+	}
+
+	if (remote) {
+		char remote_port[8];
+		g_snprintf(remote_port, sizeof(remote_port), "%d", remote->port);
+		xmlnode_set_attrib(candidate, "rem-addr", remote->ip);
+		xmlnode_set_attrib(candidate, "rem-port", remote_port);
+	}
+
+	return candidate;
+}
+
+static xmlnode *
+jabber_jingle_session_add_transport(const JingleSessionContent *jsc,
+				    xmlnode *content)
+{
+	xmlnode *transport = xmlnode_new_child(content, "transport");
+	const gchar *transport_type = jabber_jingle_session_content_get_transport_type(jsc);
+	xmlnode_set_namespace(transport, transport_type);
+	return transport;
+}
+
+static xmlnode *
+jabber_jingle_session_add_content(const JingleSessionContent *jsc,
+				  xmlnode *jingle)
+{
+	xmlnode *content = xmlnode_new_child(jingle, "content");
+	xmlnode_set_attrib(content, "creator",
+			   jabber_jingle_session_content_get_creator(jsc));
+	xmlnode_set_attrib(content, "name",
+			   jabber_jingle_session_content_get_name(jsc));
+	xmlnode_set_attrib(content, "sender",
+			   jabber_jingle_session_content_get_sender(jsc));
+	return content;
+}
+
+
+static xmlnode *
+jabber_jingle_session_add_jingle(const JingleSession *sess,
+				 JabberIq *iq, const char *action)
+{
+	xmlnode *jingle = iq ? xmlnode_new_child(iq->node, "jingle") : 
+				xmlnode_new("jingle");
 	xmlnode_set_namespace(jingle, "urn:xmpp:tmp:jingle");
 	xmlnode_set_attrib(jingle, "action", action);
 	xmlnode_set_attrib(jingle, "initiator", 
-					   jabber_jingle_session_get_initiator(sess));
+			   jabber_jingle_session_get_initiator(sess));
 	xmlnode_set_attrib(jingle, "responder", 
-					   jabber_jingle_session_is_initiator(sess) ?
-					   jabber_jingle_session_get_remote_jid(sess) :
-					   jabber_jingle_session_get_initiator(sess));
-	xmlnode_set_attrib(jingle, "sid", sess->id);
+			   jabber_jingle_session_is_initiator(sess) ?
+			   jabber_jingle_session_get_remote_jid(sess) :
+			   jabber_jingle_session_get_initiator(sess));
+	xmlnode_set_attrib(jingle, "sid", jabber_jingle_session_get_id(sess));
 	
 	return jingle;
 }
 
+static JabberIq *
+jabber_jingle_session_create_iq(const JingleSession *session)
+{
+	JabberIq *result = jabber_iq_new(jabber_jingle_session_get_js(session),
+					 JABBER_IQ_SET);
+	gchar *from = g_strdup_printf("%s@%s/%s", session->js->user->node,
+				      session->js->user->domain,
+				      session->js->user->resource);
+	xmlnode_set_attrib(result->node, "from", from);
+	g_free(from);
+	xmlnode_set_attrib(result->node, "to",
+			   jabber_jingle_session_get_remote_jid(session));
+	return result;
+}
+
 static xmlnode *
 jabber_jingle_session_create_terminate(const JingleSession *sess,
-									   const char *reasoncode,
-									   const char *reasontext)
+				       const char *reasoncode,
+				       const char *reasontext)
 {
 	xmlnode *jingle = 
-		jabber_jingle_session_create_jingle_element(sess, "session-terminate");
+		jabber_jingle_session_add_jingle(sess, NULL, "session-terminate");
 	xmlnode_set_attrib(jingle, "resoncode", reasoncode);
 	if (reasontext) {
 		xmlnode_set_attrib(jingle, "reasontext", reasontext);
@@ -414,77 +557,6 @@
     fs_codec_list_destroy(codecs);
     return description;
 }
-    
-static guint
-jabber_jingle_get_priority(guint type, guint network)
-{
-	switch (type) {
-		case FS_CANDIDATE_TYPE_HOST:
-			return network == 0 ? 4096 : network == 1 ? 2048 : 1024;
-			break;
-		case FS_CANDIDATE_TYPE_PRFLX:
-			return 126;
-			break;
-		case FS_CANDIDATE_TYPE_RELAY:
-			return 100;
-			break;
-		default:
-			return 0; /* unknown type, should not happen */
-	}
-}
-
-static xmlnode *
-jabber_jingle_session_create_candidate_info(FsCandidate *c, FsCandidate *remote)
-{
-	char port[8];
-	char prio[8];
-	char component[8];
-	xmlnode *candidate = NULL;
-	
-	candidate = xmlnode_new("candidate");
-	
-	g_snprintf(port, sizeof(port), "%d", c->port);
-	g_snprintf(prio, sizeof(prio), "%d", 
-		   jabber_jingle_get_priority(c->type, 0));
-	g_snprintf(component, sizeof(component), "%d", c->component_id);
-	
-	xmlnode_set_attrib(candidate, "component", component);
-	xmlnode_set_attrib(candidate, "foundation", "1"); /* what about this? */
-	xmlnode_set_attrib(candidate, "generation", "0"); /* ? */
-	xmlnode_set_attrib(candidate, "ip", c->ip);
-	xmlnode_set_attrib(candidate, "network", "0"); /* ? */
-	xmlnode_set_attrib(candidate, "port", port);
-	xmlnode_set_attrib(candidate, "priority", prio); /* Is this correct? */
-	xmlnode_set_attrib(candidate, "protocol",
-			   c->proto == FS_NETWORK_PROTOCOL_UDP ?
-			   "udp" : "tcp");
-	if (c->username)
-		xmlnode_set_attrib(candidate, "ufrag", c->username);
-	if (c->password)
-		xmlnode_set_attrib(candidate, "pwd", c->password);
-	
-	xmlnode_set_attrib(candidate, "type", 
-			   c->type == FS_CANDIDATE_TYPE_HOST ? 
-			   "host" :
-			   c->type == FS_CANDIDATE_TYPE_PRFLX ? 
-			   "prflx" :
-		       	   c->type == FS_CANDIDATE_TYPE_RELAY ? 
-			   "relay" : NULL);
-
-	/* relay */
-	if (c->type == FS_CANDIDATE_TYPE_RELAY) {
-		/* set rel-addr and rel-port? How? */
-	}
-
-	if (remote) {
-		char remote_port[8];
-		g_snprintf(remote_port, sizeof(remote_port), "%d", remote->port);
-		xmlnode_set_attrib(candidate, "rem-addr", remote->ip);
-		xmlnode_set_attrib(candidate, "rem-port", remote_port);
-	}
-
-	return candidate;
-}
 
 /* split into two separate methods, one to generate session-accept
 	(includes codecs) and one to generate transport-info (includes transports
@@ -492,8 +564,8 @@
 static xmlnode *
 jabber_jingle_session_create_session_accept(const JingleSession *sess)
 {
-	xmlnode *jingle = 
-		jabber_jingle_session_create_jingle_element(sess, "session-accept");
+	xmlnode *jingle =
+		jabber_jingle_session_add_jingle(sess, NULL, "session-accept");
 	xmlnode *content = NULL;
 	xmlnode *description = NULL;
 	xmlnode *transport = NULL;
@@ -510,10 +582,9 @@
 
 	transport = xmlnode_new_child(content, "transport");
 	xmlnode_set_namespace(transport, "urn:xmpp:tmp:jingle:transports:ice-udp");
-	candidate = jabber_jingle_session_create_candidate_info(
+	candidate = jabber_jingle_session_add_candidate_iceudp(transport,
 			purple_media_get_local_candidate(sess->media),
 			purple_media_get_remote_candidate(sess->media));
-	xmlnode_insert_child(transport, candidate);
 
 	return jingle;
 }
@@ -521,8 +592,8 @@
 static xmlnode *
 jabber_jingle_session_create_transport_info(const JingleSession *sess)
 {
-	xmlnode *jingle = 
-		jabber_jingle_session_create_jingle_element(sess, "transport-info");
+	xmlnode *jingle =
+		jabber_jingle_session_add_jingle(sess, NULL, "transport-info");
 	xmlnode *content = NULL;
 	xmlnode *transport = NULL;
 	GList *candidates = purple_media_get_local_audio_candidates(sess->media);
@@ -543,8 +614,7 @@
 			continue;
 		}
 
-		xmlnode_insert_child(transport,
-				     jabber_jingle_session_create_candidate_info(c, NULL));
+		jabber_jingle_session_add_candidate_iceudp(transport, c, NULL);
 	}
 	fs_candidate_list_destroy(candidates);
 	
@@ -557,7 +627,7 @@
 					     FsCandidate *remote_candidate)
 {
 	xmlnode *jingle = 
-		jabber_jingle_session_create_jingle_element(sess, "content-replace");
+		jabber_jingle_session_add_jingle(sess, NULL, "content-replace");
 	xmlnode *content = NULL;
 	xmlnode *transport = NULL;
 
@@ -577,9 +647,8 @@
 
 	transport = xmlnode_new_child(content, "transport");
 	xmlnode_set_namespace(transport, "urn:xmpp:tmp:jingle:transports:ice-udp");
-	xmlnode_insert_child(transport,
-			     jabber_jingle_session_create_candidate_info(native_candidate,
-									 remote_candidate));
+	jabber_jingle_session_add_candidate_iceudp(transport, native_candidate,
+						   remote_candidate);
 
 	purple_debug_info("jingle", "End create content modify\n");
 	
@@ -590,7 +659,7 @@
 jabber_jingle_session_create_content_accept(const JingleSession *sess)
 {
 	xmlnode *jingle = 
-		jabber_jingle_session_create_jingle_element(sess, "content-accept");
+		jabber_jingle_session_add_jingle(sess, NULL, "content-accept");
 	
     xmlnode *content = xmlnode_new_child(jingle, "content");
 	xmlnode *description = jabber_jingle_session_create_description(sess);
@@ -669,9 +738,9 @@
 	gchar sender[10] = "";
 
 	if (type & PURPLE_MEDIA_AUDIO) {
-		if (type & PURPLE_MEDIA_SEND_AUDIO)
+		if (type == PURPLE_MEDIA_SEND_AUDIO)
 			strcpy(sender, "initiator");
-		else if (type & PURPLE_MEDIA_RECV_AUDIO)
+		else if (type == PURPLE_MEDIA_RECV_AUDIO)
 			strcpy(sender, "responder");
 		else
 			strcpy(sender, "both");