changeset 23788:9f36ed35615e

Add the new jingle.c/h files.
author Sadrul Habib Chowdhury <imadil@gmail.com>
date Sat, 22 Mar 2008 04:48:36 +0000
parents 92e71f6e10d4
children 128f6cb57829
files libpurple/protocols/jabber/jingle.c libpurple/protocols/jabber/jingle.h po/POTFILES.in
diffstat 3 files changed, 686 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/protocols/jabber/jingle.c	Sat Mar 22 04:48:36 2008 +0000
@@ -0,0 +1,579 @@
+/*
+ * purple - Jabber Protocol Plugin
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
+ *
+ */
+
+#include "config.h"
+#include "purple.h"
+#include "jingle.h"
+#include "xmlnode.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+
+#ifdef USE_FARSIGHT
+
+#include <farsight/farsight.h>
+#include <farsight/farsight-transport.h>
+
+/* keep a hash table of JingleSessions */
+static GHashTable *sessions = NULL;
+
+static gboolean
+jabber_jingle_session_equal(gconstpointer a, gconstpointer b)
+{
+	purple_debug_info("jingle", 
+					  "jabber_jingle_session_equal, comparing %s and %s\n",
+					  ((JingleSession *)a)->id,
+					  ((JingleSession *)b)->id);
+	return !strcmp(((JingleSession *) a)->id, ((JingleSession *) b)->id);
+}
+
+static JingleSession *
+jabber_jingle_session_create_internal(JabberStream *js,
+									  const char *id)
+{
+    JingleSession *sess = g_new0(JingleSession, 1);
+	sess->js = js;
+		
+	if (id) {
+		sess->id = g_strdup(id);
+	} else if (js) {
+		/* init the session ID... */
+		sess->id = jabber_get_next_id(js);
+	}
+	
+	/* insert it into the hash table */
+	if (!sessions) {
+		purple_debug_info("jingle", "Creating hash table for sessions\n");
+		sessions = g_hash_table_new(g_str_hash, g_str_equal);
+	}
+	purple_debug_info("jingle", "inserting session with key: %s into table\n",
+					  sess->id);
+	g_hash_table_insert(sessions, sess->id, sess);
+	
+	sess->remote_candidates = NULL;
+    sess->remote_codecs = NULL;
+	
+	return sess;
+}
+
+JabberStream *
+jabber_jingle_session_get_js(const JingleSession *sess)
+{
+	return sess->js;
+}
+
+JingleSession *
+jabber_jingle_session_create(JabberStream *js)
+{
+	JingleSession *sess = jabber_jingle_session_create_internal(js, NULL);
+	sess->is_initiator = TRUE;	
+	return sess;
+}
+
+JingleSession *
+jabber_jingle_session_create_by_id(JabberStream *js, const char *id)
+{
+	JingleSession *sess = jabber_jingle_session_create_internal(js, id);
+	sess->is_initiator = FALSE;
+	return sess;
+}
+
+const char *
+jabber_jingle_session_get_id(const JingleSession *sess)
+{
+	return sess->id;
+}
+
+void
+jabber_jingle_session_destroy(JingleSession *sess)
+{
+	g_hash_table_remove(sessions, sess->id);
+	g_free(sess->id);
+    farsight_codec_list_destroy(sess->remote_codecs);
+    g_list_free(sess->remote_candidates);
+	g_free(sess);
+}
+
+JingleSession *
+jabber_jingle_session_find_by_id(const char *id)
+{
+	purple_debug_info("jingle", "find_by_id %s\n", id);
+	purple_debug_info("jingle", "hash table: %lx\n", sessions);
+	purple_debug_info("jingle", "hash table size %d\n",
+					  g_hash_table_size(sessions));
+	purple_debug_info("jingle", "lookup: %lx\n", g_hash_table_lookup(sessions, id));  
+	return (JingleSession *) g_hash_table_lookup(sessions, id);
+}
+
+GList *
+jabber_jingle_get_codecs(const xmlnode *description)
+{
+	GList *codecs = NULL;
+	xmlnode *codec_element = NULL;
+	const char *encoding_name,*id, *clock_rate;
+	FarsightCodec *codec;
+	
+	for (codec_element = xmlnode_get_child(description, "payload-type") ;
+		 codec_element ;
+		 codec_element = xmlnode_get_next_twin(codec_element)) {
+		encoding_name = xmlnode_get_attrib(codec_element, "name");
+		id = xmlnode_get_attrib(codec_element, "id");
+		clock_rate = xmlnode_get_attrib(codec_element, "clockrate");
+
+		codec = g_new0(FarsightCodec, 1);
+		farsight_codec_init(codec, atoi(id), encoding_name, 
+							FARSIGHT_MEDIA_TYPE_AUDIO, 
+							clock_rate ? atoi(clock_rate) : 0);
+		codecs = g_list_append(codecs, codec);		 
+	}
+	return codecs;
+}
+
+GList *
+jabber_jingle_get_candidates(const xmlnode *transport)
+{
+	GList *candidates = NULL;
+	xmlnode *candidate = NULL;
+	FarsightTransportInfo *ti;
+	
+	for (candidate = xmlnode_get_child(transport, "candidate") ;
+		 candidate ;
+		 candidate = xmlnode_get_next_twin(candidate)) {
+		const char *type = xmlnode_get_attrib(candidate, "type");
+		ti = g_new0(FarsightTransportInfo, 1);
+		ti->component = atoi(xmlnode_get_attrib(candidate, "component"));
+		ti->ip = xmlnode_get_attrib(candidate, "ip");
+		ti->port = atoi(xmlnode_get_attrib(candidate, "port"));
+		ti->proto = strcmp(xmlnode_get_attrib(candidate, "protocol"),
+							  "udp") == 0 ? 
+				 				FARSIGHT_NETWORK_PROTOCOL_UDP :
+				 				FARSIGHT_NETWORK_PROTOCOL_TCP;
+		/* it seems Farsight RTP doesn't handle this correctly right now */
+		ti->username = xmlnode_get_attrib(candidate, "ufrag");
+		ti->password = xmlnode_get_attrib(candidate, "pwd");
+		/* not quite sure about this */
+		ti->type = strcmp(type, "host") == 0 ?
+					FARSIGHT_CANDIDATE_TYPE_LOCAL :
+					strcmp(type, "prflx") == 0 ?
+					 FARSIGHT_CANDIDATE_TYPE_DERIVED :
+					 FARSIGHT_CANDIDATE_TYPE_RELAY;
+			 
+		candidates = g_list_append(candidates, ti);
+	}
+	
+	return candidates;
+}
+
+FarsightStream *
+jabber_jingle_session_get_stream(const JingleSession *sess)
+{
+	return sess->stream;
+}
+
+void
+jabber_jingle_session_set_stream(JingleSession *sess, FarsightStream *stream)
+{
+	sess->stream = stream;
+}
+
+PurpleMedia *
+jabber_jingle_session_get_media(const JingleSession *sess)
+{
+	return sess->media;
+}
+
+void
+jabber_jingle_session_set_media(JingleSession *sess, PurpleMedia *media)
+{
+	sess->media = media;
+}
+
+const char *
+jabber_jingle_session_get_remote_jid(const JingleSession *sess)
+{
+	return sess->remote_jid;
+}
+
+void
+jabber_jingle_session_set_remote_jid(JingleSession *sess, 
+									 const char *remote_jid)
+{
+	sess->remote_jid = strdup(remote_jid);
+}
+
+const char *
+jabber_jingle_session_get_initiator(const JingleSession *sess)
+{
+	return sess->initiator;
+}
+
+void
+jabber_jingle_session_set_initiator(JingleSession *sess,
+									const char *initiator)
+{
+	sess->initiator = g_strdup(initiator);
+}
+
+gboolean
+jabber_jingle_session_is_initiator(const JingleSession *sess)
+{
+	return sess->is_initiator;
+}
+
+void
+jabber_jingle_session_add_remote_candidate(JingleSession *sess,
+										   const GList *candidate)
+{
+	/* the length of the candidate list should be 1... */
+	GList *cand = candidate;
+	for (; cand ; cand = cand->next) {
+		purple_debug_info("jingle", "Adding remote candidate with id = %s\n",
+						  ((FarsightTransportInfo *) cand->data)->candidate_id);
+		sess->remote_candidates = g_list_append(sess->remote_candidates, 
+												cand->data);
+	}
+}
+
+static GList *
+jabber_jingle_session_get_remote_candidate(const JingleSession *sess,
+										   const gchar *id)
+{
+	GList *candidates = NULL;
+	GList *find = sess->remote_candidates;
+	for (; find ; find = find->next) {
+		const FarsightTransportInfo *candidate =
+			(FarsightTransportInfo *) find->data;
+		if (!strcmp(candidate->candidate_id, id)) {
+			candidates = g_list_append(candidates, (void *) candidate);
+		}
+	}
+	return candidates;
+}
+
+static xmlnode *
+jabber_jingle_session_create_jingle_element(const JingleSession *sess,
+											const char *action)
+{
+	xmlnode *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));
+	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);
+	
+	return jingle;
+}
+
+xmlnode *
+jabber_jingle_session_create_terminate(const JingleSession *sess,
+									   const char *reasoncode,
+									   const char *reasontext)
+{
+	xmlnode *jingle = 
+		jabber_jingle_session_create_jingle_element(sess, "session-terminate");
+	xmlnode_set_attrib(jingle, "resoncode", reasoncode);
+	if (reasontext) {
+		xmlnode_set_attrib(jingle, "reasontext", reasontext);
+	}
+	xmlnode_set_attrib(jingle, "sid", sess->id);
+	
+	return jingle;
+}
+
+static xmlnode *
+jabber_jingle_session_create_description(const JingleSession *sess)
+{
+    GList *codecs =
+		farsight_stream_get_local_codecs(jabber_jingle_session_get_stream(sess));
+    
+    xmlnode *description = xmlnode_new("description");
+	xmlnode_set_namespace(description, "urn:xmpp:tmp:jingle:apps:audio-rtp");
+	
+	/* get codecs */
+	for (; codecs ; codecs = codecs->next) {
+		FarsightCodec *codec = (FarsightCodec*)codecs->data;
+		char id[8], clockrate[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);
+		
+		xmlnode_set_attrib(payload, "name", codec->encoding_name);
+		xmlnode_set_attrib(payload, "id", id);
+		xmlnode_set_attrib(payload, "clockrate", clockrate);
+    }
+    
+    return description;
+}
+    
+/* split into two separate methods, one to generate session-accept
+	(includes codecs) and one to generate transport-info (includes transports
+	candidates) */
+xmlnode *
+jabber_jingle_session_create_session_accept(const JingleSession *sess)
+{
+	xmlnode *jingle = 
+		jabber_jingle_session_create_jingle_element(sess, "session-accept");
+	xmlnode *content = NULL;
+	xmlnode *description = NULL;
+	
+	
+	content = xmlnode_new_child(jingle, "content");
+	xmlnode_set_attrib(content, "creator", "initiator");
+	xmlnode_set_attrib(content, "name", "audio-content");
+	xmlnode_set_attrib(content, "profile", "RTP/AVP");
+	
+	description = jabber_jingle_session_create_description(sess);
+    xmlnode_insert_child(jingle, description);
+	
+	return jingle;
+}
+
+static guint
+jabber_jingle_get_priority(guint type, guint network)
+{
+	switch (type) {
+		case FARSIGHT_CANDIDATE_TYPE_LOCAL:
+			return network == 0 ? 4096 : network == 1 ? 2048 : 1024;
+			break;
+		case FARSIGHT_CANDIDATE_TYPE_DERIVED:
+			return 126;
+			break;
+		case FARSIGHT_CANDIDATE_TYPE_RELAY:
+			return 100;
+			break;
+		default:
+			return 0; /* unknown type, should not happen */
+	}
+}
+
+xmlnode *
+jabber_jingle_session_create_transport_info(const JingleSession *sess,
+											gchar *candidate_id)
+{
+	xmlnode *jingle = 
+		jabber_jingle_session_create_jingle_element(sess, "transport-info");
+	xmlnode *content = NULL;
+	xmlnode *transport = NULL;
+	GList *candidates =
+		farsight_stream_get_native_candidate(
+			jabber_jingle_session_get_stream(sess), candidate_id);
+	
+	content = xmlnode_new_child(jingle, "content");
+	xmlnode_set_attrib(content, "creator", "initiator");
+	xmlnode_set_attrib(content, "name", "audio-content");
+	xmlnode_set_attrib(content, "profile", "RTP/AVP");
+		
+	transport = xmlnode_new_child(content, "transport");
+	xmlnode_set_namespace(transport, "urn:xmpp:tmp:jingle:transports:ice-tcp");
+	
+	/* get transport candidate */
+	for (; candidates ; candidates = candidates->next) {
+		FarsightTransportInfo *transport_info = 
+			(FarsightTransportInfo *) candidates->data;
+		char port[8];
+		char prio[8];
+		char component[8];
+		xmlnode *candidate = NULL;
+		
+		if (!strcmp(transport_info->ip, "127.0.0.1")) {
+			continue;
+		}
+		
+		candidate = xmlnode_new_child(transport, "candidate");
+		
+		g_snprintf(port, sizeof(port), "%d", transport_info->port);
+		g_snprintf(prio, sizeof(prio), "%d", 
+				   jabber_jingle_get_priority(transport_info->type, 0));
+		g_snprintf(component, sizeof(component), "%d", transport_info->component);
+		
+		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", transport_info->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",
+						   transport_info->proto == FARSIGHT_NETWORK_PROTOCOL_UDP ?
+						   "udp" : "tcp");
+		if (transport_info->username)
+			xmlnode_set_attrib(candidate, "ufrag", transport_info->username);
+		if (transport_info->password)
+			xmlnode_set_attrib(candidate, "pwd", transport_info->password);
+		
+		xmlnode_set_attrib(candidate, "type", 
+						   transport_info->type == FARSIGHT_CANDIDATE_TYPE_LOCAL ? 
+						   "host" :
+						   transport_info->type == FARSIGHT_CANDIDATE_TYPE_DERIVED ? 
+						   "prflx" :
+					       transport_info->type == FARSIGHT_CANDIDATE_TYPE_RELAY ? 
+						   "relay" : NULL);
+		
+	}
+	farsight_transport_list_destroy(candidates);
+	
+	return jingle;
+}
+
+xmlnode *
+jabber_jingle_session_create_content_replace(const JingleSession *sess,
+											 gchar *native_candidate_id,
+											 gchar *remote_candidate_id)
+{
+	xmlnode *jingle = 
+		jabber_jingle_session_create_jingle_element(sess, "content-replace");
+	xmlnode *content = NULL;
+	xmlnode *transport = NULL;
+	xmlnode *candidate = NULL;
+	xmlnode *description = NULL;
+	xmlnode *payload_type = NULL;
+	char local_port[8];
+	char remote_port[8];
+	char prio[8];
+	char component[8];
+	
+	purple_debug_info("jingle", "creating content-modify for native candidate %s " \
+					  ", remote candidate %s\n", native_candidate_id,
+					  remote_candidate_id);
+	
+	/* It seems the ID's we get from the Farsight callback is phony... */
+	/*
+	GList *native_candidates = 
+		farsight_stream_get_native_candidate(jabber_jingle_session_get_stream(sess),
+											 native_candidate_id);
+	purple_debug_info("jingle", "found %d native candidates with id %s\n",
+					  g_list_length(native_candidates), native_candidate_id);
+	GList *remote_candidates =
+		jabber_jingle_session_get_remote_candidate(sess, remote_candidate_id);
+	*/
+	
+	/* we assume lists have length == 1, I think they must... */
+	/*
+	FarsightTransportInfo *native = 
+		(FarsightTransportInfo *) native_candidates->data;
+	FarsightTransportInfo *remote =
+		(FarsightTransportInfo *) remote_candidates->data;
+	*/
+	
+	content = xmlnode_new_child(jingle, "content");
+	xmlnode_set_attrib(content, "creator", "initiator");
+	xmlnode_set_attrib(content, "name", "audio-content");
+	xmlnode_set_attrib(content, "profile", "RTP/AVP");
+	
+	description = xmlnode_new_child(content, "description");
+	xmlnode_set_namespace(description, "urn:xmpp:tmp:jingle:apps:audio-rtp");
+	
+	payload_type = xmlnode_new_child(description, "payload-type");
+	/* get top codec from codec_intersection to put here... */
+	/* later on this should probably handle changing codec */
+	
+	/* Skip creating the actual "content" element for now, since we don't
+		get enough info in the Farsight callback */
+#if 0
+	transport = xmlnode_new_child(content, "transport");
+	xmlnode_set_namespace(transport, "urn:xmpp:tmp:jingle:transports:ice-tcp");
+	
+	candidate = xmlnode_new_child(transport, "candidate");
+	
+	g_snprintf(local_port, sizeof(local_port), "%d", native->port);
+	g_snprintf(remote_port, sizeof(remote_port), "%d", remote->port);
+	g_snprintf(prio, sizeof(prio), "%d",
+			   jabber_jingle_get_priority(native->type, 0));
+	g_snprintf(component, sizeof(component), "%d", native->component);
+
+	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", native->ip);
+	xmlnode_set_attrib(candidate, "network", "1"); /* ? */
+	xmlnode_set_attrib(candidate, "port", local_port);
+	xmlnode_set_attrib(candidate, "priority", prio); /* Is this correct? */
+	xmlnode_set_attrib(candidate, "protocol", 
+					   native->proto == FARSIGHT_NETWORK_PROTOCOL_UDP ? 
+					   "udp" : "tcp");
+	if (native->username)
+		xmlnode_set_attrib(candidate, "ufrag", native->username);
+	if (native->password)
+		xmlnode_set_attrib(candidate, "pwd", native->password);
+		
+	xmlnode_set_attrib(candidate, "type", 
+					   native->type == FARSIGHT_CANDIDATE_TYPE_LOCAL ? 
+					   "host" : 
+					   native->type == FARSIGHT_CANDIDATE_TYPE_DERIVED ? 
+					   "prflx" : 
+					   native->type == FARSIGHT_CANDIDATE_TYPE_RELAY ? 
+					   "relay" : NULL);
+	/* relay */
+	if (native->type == FARSIGHT_CANDIDATE_TYPE_RELAY) {
+		/* set rel-addr and rel-port? How? */
+	}
+	
+	xmlnode_set_attrib(candidate, "rem-addr", remote->ip);
+	xmlnode_set_attrib(candidate, "rem-port", remote_port);
+	
+	farsight_transport_list_destroy(native_candidates);
+	farsight_transport_list_destroy(remote_candidates);
+	
+#endif /* 0 */
+	
+	purple_debug_info("jingle", "End create content modify\n");
+	
+	return jingle;
+}
+
+xmlnode *
+jabber_jingle_session_create_content_accept(const JingleSession *sess)
+{
+	xmlnode *jingle = 
+		jabber_jingle_session_create_jingle_element(sess, "content-accept");
+	
+    xmlnode *content = xmlnode_new_child(jingle, "content");
+	xmlnode *description = jabber_jingle_session_create_description(sess);
+    
+    xmlnode_set_attrib(content, "creator", "initiator");
+	xmlnode_set_attrib(content, "name", "audio-content");
+	xmlnode_set_attrib(content, "profile", "RTP/AVP");
+	
+    xmlnode_insert_child(jingle, description);
+    
+	return jingle;
+}
+
+void
+jabber_jingle_session_set_remote_codecs(JingleSession *sess, GList *codecs)
+{
+    if (sess->remote_codecs) {
+        farsight_codec_list_destroy(sess->remote_codecs);
+    }
+    sess->remote_codecs = codecs;
+}
+
+GList *
+jabber_jingle_session_get_remote_codecs(const JingleSession *sess)
+{
+    return sess->remote_codecs;
+}
+
+#endif /* USE_FARSIGHT */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/protocols/jabber/jingle.h	Sat Mar 22 04:48:36 2008 +0000
@@ -0,0 +1,106 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Library General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301,  USA
+ */
+ 
+#ifndef JINGLE_H
+#define JINGLE_H
+
+#include "config.h"
+#include "jabber.h"
+#include "media.h"
+
+#include <glib.h>
+#include <glib-object.h>
+
+#ifdef USE_FARSIGHT
+
+#include <farsight/farsight.h>
+
+G_BEGIN_DECLS
+
+typedef struct {
+	char *id;
+	JabberStream *js;
+	FarsightStream *stream;
+	PurpleMedia *media;
+	char *remote_jid;
+	char *initiator;
+	gboolean is_initiator;
+	GList *remote_candidates;
+    GList *remote_codecs;
+} JingleSession;
+
+JingleSession *jabber_jingle_session_create(JabberStream *js);
+JingleSession *jabber_jingle_session_create_by_id(JabberStream *js, 
+												  const char *id);
+
+const char *jabber_jingle_session_get_id(const JingleSession *sess);
+JabberStream *jabber_jingle_session_get_js(const JingleSession *sess);
+
+void jabber_jingle_session_destroy(JingleSession *sess);
+
+JingleSession *jabber_jingle_session_find_by_id(const char *id);
+
+FarsightStream *jabber_jingle_session_get_stream(const JingleSession *sess);
+void jabber_jingle_session_set_stream(JingleSession *sess, FarsightStream *stream);
+
+PurpleMedia *jabber_jingle_session_get_media(const JingleSession *sess);
+void jabber_jingle_session_set_media(JingleSession *sess, PurpleMedia *media);
+
+const char *jabber_jingle_session_get_remote_jid(const JingleSession *sess);
+
+gboolean jabber_jingle_session_is_initiator(const JingleSession *sess);
+
+void jabber_jingle_session_set_remote_jid(JingleSession *sess, 
+										  const char *remote_jid);
+
+const char *jabber_jingle_session_get_initiator(const JingleSession *sess);
+void jabber_jingle_session_set_initiator(JingleSession *sess, 
+										 const char *initiator);
+
+void jabber_jingle_session_add_remote_candidate(JingleSession *sess,
+												const GList *candidate);
+
+xmlnode *jabber_jingle_session_create_terminate(const JingleSession *sess,
+												const char *reasoncode,
+												const char *reasontext);
+
+xmlnode *jabber_jingle_session_create_session_accept(const JingleSession *sess);
+xmlnode *jabber_jingle_session_create_transport_info(const JingleSession *sess,
+													 gchar *candidate_id);
+xmlnode *jabber_jingle_session_create_content_replace(const JingleSession *sess,
+													  gchar *native_candidate_id,
+													  gchar *remote_candidate_id);
+xmlnode *jabber_jingle_session_create_content_accept(const JingleSession *sess);
+
+/**
+ * Gets a list of Farsight codecs from a Jingle <description> tag
+ *
+ * @param description
+ * @return A GList of FarsightCodecS
+*/
+GList *jabber_jingle_get_codecs(const xmlnode *description);
+
+GList *jabber_jingle_get_candidates(const xmlnode *transport);
+
+void jabber_jingle_session_set_remote_codecs(JingleSession *sess,
+                                             GList *codecs);
+GList *jabber_jingle_session_get_remote_codecs(const JingleSession *sess);
+
+G_END_DECLS
+
+#endif /* USE_FARSIGHT */
+
+#endif /* JINGLE_H */
--- a/po/POTFILES.in	Sat Mar 22 04:45:46 2008 +0000
+++ b/po/POTFILES.in	Sat Mar 22 04:48:36 2008 +0000
@@ -86,6 +86,7 @@
 libpurple/protocols/jabber/buddy.c
 libpurple/protocols/jabber/chat.c
 libpurple/protocols/jabber/jabber.c
+libpurple/protocols/jabber/jingle.c
 libpurple/protocols/jabber/libxmpp.c
 libpurple/protocols/jabber/message.c
 libpurple/protocols/jabber/parser.c