Mercurial > pidgin
changeset 24966:bee5ab815291
Added a Jingle ice-udp transmitter.
author | Mike Ruprecht <maiku@soc.pidgin.im> |
---|---|
date | Mon, 24 Nov 2008 10:43:38 +0000 |
parents | 70ae1029bb70 |
children | adf153852bcf ca0c9cc50e35 |
files | libpurple/protocols/jabber/Makefile.am libpurple/protocols/jabber/Makefile.mingw libpurple/protocols/jabber/disco.c libpurple/protocols/jabber/jingle/iceudp.c libpurple/protocols/jabber/jingle/iceudp.h libpurple/protocols/jabber/jingle/jingle.c libpurple/protocols/jabber/jingle/rtp.c |
diffstat | 7 files changed, 545 insertions(+), 17 deletions(-) [+] |
line wrap: on
line diff
--- a/libpurple/protocols/jabber/Makefile.am Mon Nov 17 01:09:55 2008 +0000 +++ b/libpurple/protocols/jabber/Makefile.am Mon Nov 24 10:43:38 2008 +0000 @@ -25,6 +25,8 @@ jingle/jingle.h \ jingle/content.c \ jingle/content.h \ + jingle/iceudp.c \ + jingle/iceudp.h \ jingle/rawudp.c \ jingle/rawudp.h \ jingle/rtp.c \
--- a/libpurple/protocols/jabber/Makefile.mingw Mon Nov 17 01:09:55 2008 +0000 +++ b/libpurple/protocols/jabber/Makefile.mingw Mon Nov 24 10:43:38 2008 +0000 @@ -55,6 +55,7 @@ jabber.c \ jingle/jingle.c \ jingle/content.c \ + jingle/iceudp.c \ jingle/rawudp.c \ jingle/rtp.c \ jingle/session.c \
--- a/libpurple/protocols/jabber/disco.c Mon Nov 17 01:09:55 2008 +0000 +++ b/libpurple/protocols/jabber/disco.c Mon Nov 24 10:43:38 2008 +0000 @@ -160,6 +160,7 @@ SUPPORT_FEATURE(JINGLE_APP_RTP_SUPPORT_AUDIO); SUPPORT_FEATURE(JINGLE_APP_RTP_SUPPORT_VIDEO); SUPPORT_FEATURE(JINGLE_TRANSPORT_RAWUDP); + SUPPORT_FEATURE(JINGLE_TRANSPORT_ICEUDP); #endif } else { const char *ext = NULL;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/protocols/jabber/jingle/iceudp.c Mon Nov 24 10:43:38 2008 +0000 @@ -0,0 +1,374 @@ +/** + * @file iceudp.c + * + * purple + * + * 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 "iceudp.h" +#include "jingle.h" +#include "debug.h" + +#include <string.h> + +struct _JingleIceUdpPrivate +{ + GList *local_candidates; + GList *remote_candidates; +}; + +#define JINGLE_ICEUDP_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), JINGLE_TYPE_ICEUDP, JingleIceUdpPrivate)) + +static void jingle_iceudp_class_init (JingleIceUdpClass *klass); +static void jingle_iceudp_init (JingleIceUdp *iceudp); +static void jingle_iceudp_finalize (GObject *object); +static void jingle_iceudp_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); +static void jingle_iceudp_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); +static JingleTransport *jingle_iceudp_parse_internal(xmlnode *iceudp); +static xmlnode *jingle_iceudp_to_xml_internal(JingleTransport *transport, xmlnode *content, JingleActionType action); + +static JingleTransportClass *parent_class = NULL; + +enum { + PROP_0, + PROP_LOCAL_CANDIDATES, + PROP_REMOTE_CANDIDATES, +}; + +static JingleIceUdpCandidate * +jingle_iceudp_candidate_copy(JingleIceUdpCandidate *candidate) +{ + JingleIceUdpCandidate *new_candidate = g_new0(JingleIceUdpCandidate, 1); + new_candidate->component = candidate->component; + new_candidate->foundation = g_strdup(candidate->foundation); + new_candidate->generation = candidate->generation; + new_candidate->ip = g_strdup(candidate->ip); + new_candidate->network = candidate->network; + new_candidate->port = candidate->port; + new_candidate->priority = candidate->priority; + new_candidate->protocol = g_strdup(candidate->protocol); + new_candidate->type = g_strdup(candidate->type); + + new_candidate->username = g_strdup(candidate->username); + new_candidate->password = g_strdup(candidate->password); + + return new_candidate; +} + +static void +jingle_iceudp_candidate_free(JingleIceUdpCandidate *candidate) +{ + g_free(candidate->foundation); + g_free(candidate->ip); + g_free(candidate->protocol); + g_free(candidate->type); + + g_free(candidate->username); + g_free(candidate->password); +} + +GType +jingle_iceudp_candidate_get_type() +{ + static GType type = 0; + + if (type == 0) { + type = g_boxed_type_register_static("JingleIceUdpCandidate", + (GBoxedCopyFunc)jingle_iceudp_candidate_copy, + (GBoxedFreeFunc)jingle_iceudp_candidate_free); + } + return type; +} + +JingleIceUdpCandidate * +jingle_iceudp_candidate_new(guint component, const gchar *foundation, + guint generation, const gchar *ip, guint network, + guint port, guint priority, const gchar *protocol, + const gchar *type, const gchar *username, const gchar *password) +{ + JingleIceUdpCandidate *candidate = g_new0(JingleIceUdpCandidate, 1); + candidate->component = component; + candidate->foundation = g_strdup(foundation); + candidate->generation = generation; + candidate->ip = g_strdup(ip); + candidate->network = network; + candidate->port = port; + candidate->priority = priority; + candidate->protocol = g_strdup(protocol); + candidate->type = g_strdup(type); + + candidate->username = g_strdup(username); + candidate->password = g_strdup(password); + return candidate; +} + +GType +jingle_iceudp_get_type() +{ + static GType type = 0; + + if (type == 0) { + static const GTypeInfo info = { + sizeof(JingleIceUdpClass), + NULL, + NULL, + (GClassInitFunc) jingle_iceudp_class_init, + NULL, + NULL, + sizeof(JingleIceUdp), + 0, + (GInstanceInitFunc) jingle_iceudp_init, + NULL + }; + type = g_type_register_static(JINGLE_TYPE_TRANSPORT, "JingleIceUdp", &info, 0); + } + return type; +} + +static void +jingle_iceudp_class_init (JingleIceUdpClass *klass) +{ + GObjectClass *gobject_class = (GObjectClass*)klass; + parent_class = g_type_class_peek_parent(klass); + + gobject_class->finalize = jingle_iceudp_finalize; + gobject_class->set_property = jingle_iceudp_set_property; + gobject_class->get_property = jingle_iceudp_get_property; + klass->parent_class.to_xml = jingle_iceudp_to_xml_internal; + klass->parent_class.parse = jingle_iceudp_parse_internal; + klass->parent_class.transport_type = JINGLE_TRANSPORT_ICEUDP; + + g_object_class_install_property(gobject_class, PROP_LOCAL_CANDIDATES, + g_param_spec_pointer("local-candidates", + "Local candidates", + "The local candidates for this transport.", + G_PARAM_READABLE)); + + g_object_class_install_property(gobject_class, PROP_REMOTE_CANDIDATES, + g_param_spec_pointer("remote-candidates", + "Remote candidates", + "The remote candidates for this transport.", + G_PARAM_READABLE)); + + g_type_class_add_private(klass, sizeof(JingleIceUdpPrivate)); +} + +static void +jingle_iceudp_init (JingleIceUdp *iceudp) +{ + iceudp->priv = JINGLE_ICEUDP_GET_PRIVATE(iceudp); + memset(iceudp->priv, 0, sizeof(iceudp->priv)); +} + +static void +jingle_iceudp_finalize (GObject *iceudp) +{ +/* JingleIceUdpPrivate *priv = JINGLE_ICEUDP_GET_PRIVATE(iceudp); */ + purple_debug_info("jingle","jingle_iceudp_finalize\n"); +} + +static void +jingle_iceudp_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + JingleIceUdp *iceudp; + g_return_if_fail(JINGLE_IS_ICEUDP(object)); + + iceudp = JINGLE_ICEUDP(object); + + switch (prop_id) { + case PROP_LOCAL_CANDIDATES: + iceudp->priv->local_candidates = + g_value_get_pointer(value); + break; + case PROP_REMOTE_CANDIDATES: + iceudp->priv->remote_candidates = + g_value_get_pointer(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +jingle_iceudp_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + JingleIceUdp *iceudp; + g_return_if_fail(JINGLE_IS_ICEUDP(object)); + + iceudp = JINGLE_ICEUDP(object); + + switch (prop_id) { + case PROP_LOCAL_CANDIDATES: + g_value_set_pointer(value, iceudp->priv->local_candidates); + break; + case PROP_REMOTE_CANDIDATES: + g_value_set_pointer(value, iceudp->priv->remote_candidates); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +void +jingle_iceudp_add_local_candidate(JingleIceUdp *iceudp, JingleIceUdpCandidate *candidate) +{ + GList *iter = iceudp->priv->local_candidates; + + for (; iter; iter = g_list_next(iter)) { + JingleIceUdpCandidate *c = iter->data; + if ((c->component == candidate->component) && + !strcmp(c->foundation, candidate->foundation)) { + guint generation = c->generation + 1; + + g_boxed_free(JINGLE_TYPE_ICEUDP_CANDIDATE, c); + iceudp->priv->local_candidates = g_list_delete_link( + iceudp->priv->local_candidates, iter); + + candidate->generation = generation; + + iceudp->priv->local_candidates = g_list_append( + iceudp->priv->local_candidates, candidate); + return; + } + } + + iceudp->priv->local_candidates = g_list_append( + iceudp->priv->local_candidates, candidate); +} + +GList * +jingle_iceudp_get_remote_candidates(JingleIceUdp *iceudp) +{ + return g_list_copy(iceudp->priv->remote_candidates); +} + +static JingleIceUdpCandidate * +jingle_iceudp_get_remote_candidate_by_id(JingleIceUdp *iceudp, + guint component, const gchar *foundation) +{ + GList *iter = iceudp->priv->remote_candidates; + for (; iter; iter = g_list_next(iter)) { + JingleIceUdpCandidate *candidate = iter->data; + if ((candidate->component == component) && + !strcmp(candidate->foundation, foundation)) { + return candidate; + } + } + return NULL; +} + +static void +jingle_iceudp_add_remote_candidate(JingleIceUdp *iceudp, JingleIceUdpCandidate *candidate) +{ + JingleIceUdpPrivate *priv = JINGLE_ICEUDP_GET_PRIVATE(iceudp); + JingleIceUdpCandidate *iceudp_candidate = + jingle_iceudp_get_remote_candidate_by_id(iceudp, + candidate->component, candidate->foundation); + if (iceudp_candidate != NULL) { + priv->remote_candidates = g_list_remove( + priv->remote_candidates, iceudp_candidate); + g_boxed_free(JINGLE_TYPE_ICEUDP_CANDIDATE, iceudp_candidate); + } + priv->remote_candidates = g_list_append(priv->remote_candidates, candidate); +} + +static JingleTransport * +jingle_iceudp_parse_internal(xmlnode *iceudp) +{ + JingleTransport *transport = parent_class->parse(iceudp); + xmlnode *candidate = xmlnode_get_child(iceudp, "candidate"); + JingleIceUdpCandidate *iceudp_candidate = NULL; + + const gchar *username = xmlnode_get_attrib(iceudp, "ufrag"); + const gchar *password = xmlnode_get_attrib(iceudp, "pwd"); + + for (; candidate; candidate = xmlnode_get_next_twin(candidate)) { + iceudp_candidate = jingle_iceudp_candidate_new( + atoi(xmlnode_get_attrib(candidate, "component")), + xmlnode_get_attrib(candidate, "foundation"), + atoi(xmlnode_get_attrib(candidate, "generation")), + xmlnode_get_attrib(candidate, "ip"), + atoi(xmlnode_get_attrib(candidate, "network")), + atoi(xmlnode_get_attrib(candidate, "port")), + atoi(xmlnode_get_attrib(candidate, "priority")), + xmlnode_get_attrib(candidate, "protocol"), + xmlnode_get_attrib(candidate, "type"), + username, password); + jingle_iceudp_add_remote_candidate(JINGLE_ICEUDP(transport), iceudp_candidate); + } + + return transport; +} + +static xmlnode * +jingle_iceudp_to_xml_internal(JingleTransport *transport, xmlnode *content, JingleActionType action) +{ + xmlnode *node = parent_class->to_xml(transport, content, action); + + if (action == JINGLE_SESSION_INITIATE || action == JINGLE_TRANSPORT_INFO || + action == JINGLE_CONTENT_ADD || action == JINGLE_TRANSPORT_REPLACE) { + JingleIceUdpCandidate *candidate = JINGLE_ICEUDP_GET_PRIVATE( + transport)->local_candidates->data; + xmlnode_set_attrib(node, "pwd", candidate->password); + xmlnode_set_attrib(node, "ufrag", candidate->username); + } + + if (action == JINGLE_TRANSPORT_INFO || action == JINGLE_SESSION_ACCEPT) { + JingleIceUdpPrivate *priv = JINGLE_ICEUDP_GET_PRIVATE(transport); + GList *iter = priv->local_candidates; + + for (; iter; iter = g_list_next(iter)) { + JingleIceUdpCandidate *candidate = iter->data; + + xmlnode *xmltransport = xmlnode_new_child(node, "candidate"); + gchar *component = g_strdup_printf("%d", candidate->component); + gchar *generation = g_strdup_printf("%d", candidate->generation); + gchar *network = g_strdup_printf("%d", candidate->network); + gchar *port = g_strdup_printf("%d", candidate->port); + gchar *priority = g_strdup_printf("%d", candidate->priority); + + xmlnode_set_attrib(xmltransport, "component", component); + xmlnode_set_attrib(xmltransport, "foundation", candidate->foundation); + xmlnode_set_attrib(xmltransport, "generation", generation); + xmlnode_set_attrib(xmltransport, "ip", candidate->ip); + xmlnode_set_attrib(xmltransport, "network", network); + xmlnode_set_attrib(xmltransport, "port", port); + xmlnode_set_attrib(xmltransport, "priority", priority); + xmlnode_set_attrib(xmltransport, "protocol", candidate->protocol); + + if (action == JINGLE_SESSION_ACCEPT) { + /* XXX: fix this, it's dummy data */ + xmlnode_set_attrib(xmltransport, "rel-addr", "10.0.1.1"); + xmlnode_set_attrib(xmltransport, "rel-port", "8998"); + xmlnode_set_attrib(xmltransport, "rem-addr", "192.0.2.1"); + xmlnode_set_attrib(xmltransport, "rem-port", "3478"); + } + + xmlnode_set_attrib(xmltransport, "type", candidate->type); + + g_free(component); + g_free(generation); + g_free(network); + g_free(port); + g_free(priority); + } + } + + return node; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/protocols/jabber/jingle/iceudp.h Mon Nov 24 10:43:38 2008 +0000 @@ -0,0 +1,107 @@ +/** + * @file iceudp.h + * + * purple + * + * 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 + */ + +#ifndef JINGLE_ICEUDP_H +#define JINGLE_ICEUDP_H + +#include <glib.h> +#include <glib-object.h> + +#include "transport.h" + +G_BEGIN_DECLS + +#define JINGLE_TYPE_ICEUDP (jingle_iceudp_get_type()) +#define JINGLE_TYPE_ICEUDP_CANDIDATE (jingle_iceudp_candidate_get_type()) +#define JINGLE_ICEUDP(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), JINGLE_TYPE_ICEUDP, JingleIceUdp)) +#define JINGLE_ICEUDP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), JINGLE_TYPE_ICEUDP, JingleIceUdpClass)) +#define JINGLE_IS_ICEUDP(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), JINGLE_TYPE_ICEUDP)) +#define JINGLE_IS_ICEUDP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), JINGLE_TYPE_ICEUDP)) +#define JINGLE_ICEUDP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), JINGLE_TYPE_ICEUDP, JingleIceUdpClass)) + +/** @copydoc _JingleIceUdp */ +typedef struct _JingleIceUdp JingleIceUdp; +/** @copydoc _JingleIceUdpClass */ +typedef struct _JingleIceUdpClass JingleIceUdpClass; +/** @copydoc _JingleIceUdpPrivate */ +typedef struct _JingleIceUdpPrivate JingleIceUdpPrivate; +/** @copydoc _JingleIceUdpCandidate */ +typedef struct _JingleIceUdpCandidate JingleIceUdpCandidate; + +/** The iceudp class */ +struct _JingleIceUdpClass +{ + JingleTransportClass parent_class; /**< The parent class. */ + + xmlnode *(*to_xml) (JingleTransport *transport, xmlnode *content, JingleActionType action); + JingleTransport *(*parse) (xmlnode *transport); +}; + +/** The iceudp class's private data */ +struct _JingleIceUdp +{ + JingleTransport parent; /**< The parent of this object. */ + JingleIceUdpPrivate *priv; /**< The private data of this object. */ +}; + +struct _JingleIceUdpCandidate +{ + guint component; + gchar *foundation; + guint generation; + gchar *ip; + guint network; + guint port; + guint priority; + gchar *protocol; + gchar *type; + + gchar *username; + gchar *password; +}; + +#ifdef __cplusplus +extern "C" { +#endif + +GType jingle_iceudp_candidate_get_type(void); + +/** + * Gets the iceudp class's GType + * + * @return The iceudp class's GType. + */ +GType jingle_iceudp_get_type(void); + +JingleIceUdpCandidate *jingle_iceudp_candidate_new(guint component, + const gchar *foundation, guint generation, const gchar *ip, + guint network, guint port, guint priority, const gchar *protocol, + const gchar *type, const gchar *username, const gchar *password); +void jingle_iceudp_add_local_candidate(JingleIceUdp *iceudp, JingleIceUdpCandidate *candidate); +GList *jingle_iceudp_get_remote_candidates(JingleIceUdp *iceudp); + +#ifdef __cplusplus +} +#endif + +G_END_DECLS + +#endif /* JINGLE_ICEUDP_H */ +
--- a/libpurple/protocols/jabber/jingle/jingle.c Mon Nov 17 01:09:55 2008 +0000 +++ b/libpurple/protocols/jabber/jingle/jingle.c Mon Nov 24 10:43:38 2008 +0000 @@ -25,6 +25,7 @@ #include "jingle.h" #include <string.h> #include "session.h" +#include "iceudp.h" #include "rawudp.h" #include "rtp.h" @@ -101,9 +102,9 @@ #endif else if (!strcmp(type, JINGLE_TRANSPORT_RAWUDP)) return JINGLE_TYPE_RAWUDP; -#if 0 else if (!strcmp(type, JINGLE_TRANSPORT_ICEUDP)) return JINGLE_TYPE_ICEUDP; +#if 0 else if (!strcmp(type, JINGLE_TRANSPORT_SOCKS)) return JINGLE_TYPE_SOCKS; else if (!strcmp(type, JINGLE_TRANSPORT_IBB))
--- a/libpurple/protocols/jabber/jingle/rtp.c Mon Nov 17 01:09:55 2008 +0000 +++ b/libpurple/protocols/jabber/jingle/rtp.c Mon Nov 24 10:43:38 2008 +0000 @@ -24,6 +24,7 @@ #include "jingle.h" #include "media.h" #include "mediamanager.h" +#include "iceudp.h" #include "rawudp.h" #include "rtp.h" #include "session.h" @@ -222,10 +223,22 @@ } g_free(id); return transport; -#if 0 } else if (type == JINGLE_TYPE_ICEUDP) { - return NULL; -#endif + JingleTransport *transport = jingle_transport_create(JINGLE_TRANSPORT_ICEUDP); + JingleIceUdpCandidate *iceudp_candidate; + for (; candidates; candidates = g_list_next(candidates)) { + FsCandidate *candidate = candidates->data; + iceudp_candidate = jingle_iceudp_candidate_new(candidate->component_id, + candidate->foundation, generation, candidate->ip, + 0, candidate->port, candidate->priority, "udp", + candidate->type == FS_CANDIDATE_TYPE_HOST ? "host" : + candidate->type == FS_CANDIDATE_TYPE_SRFLX ? "srflx" : + candidate->type == FS_CANDIDATE_TYPE_PRFLX ? "prflx" : + candidate->type == FS_CANDIDATE_TYPE_RELAY ? "relay" : "", + candidate->username, candidate->password); + jingle_iceudp_add_local_candidate(JINGLE_ICEUDP(transport), iceudp_candidate); + } + return transport; } else { return NULL; } @@ -247,10 +260,25 @@ } return ret; -#if 0 - } else if (type == JINGLE_TRANSPORT_ICEUDP) { - return NULL; -#endif + } else if (!strcmp(type, JINGLE_TRANSPORT_ICEUDP)) { + GList *candidates = jingle_iceudp_get_remote_candidates(JINGLE_ICEUDP(transport)); + + for (; candidates; candidates = g_list_delete_link(candidates, candidates)) { + JingleIceUdpCandidate *candidate = candidates->data; + FsCandidate *fscandidate = fs_candidate_new( + candidate->foundation, candidate->component, + !strcmp(candidate->type, "host") ? FS_CANDIDATE_TYPE_HOST : + !strcmp(candidate->type, "srflx") ? FS_CANDIDATE_TYPE_SRFLX : + !strcmp(candidate->type, "prflx") ? FS_CANDIDATE_TYPE_PRFLX : + !strcmp(candidate->type, "relay") ? FS_CANDIDATE_TYPE_RELAY : 0, + FS_NETWORK_PROTOCOL_UDP, candidate->ip, candidate->port); + fscandidate->username = g_strdup(candidate->username); + fscandidate->password = g_strdup(candidate->password); + fscandidate->priority = candidate->priority; + ret = g_list_append(ret, fscandidate); + } + + return ret; } else { return NULL; } @@ -287,10 +315,13 @@ jingle_rtp_candidates_prepared_cb(PurpleMedia *media, gchar *sid, gchar *name, JingleSession *session) { JingleContent *content = jingle_session_find_content(session, sid, "initiator"); + JingleTransport *oldtransport = jingle_content_get_transport(content); GList *candidates = purple_media_get_local_candidates(media, sid, name); JingleTransport *transport = JINGLE_TRANSPORT(jingle_rtp_candidates_to_transport( - session, JINGLE_TYPE_RAWUDP, 0, candidates)); + session, JINGLE_IS_RAWUDP(oldtransport) ? + JINGLE_TYPE_RAWUDP : JINGLE_TYPE_ICEUDP, + 0, candidates)); g_list_free(candidates); JINGLE_RTP_GET_PRIVATE(content)->candidates_ready = TRUE; @@ -298,8 +329,11 @@ jingle_content_set_pending_transport(content, transport); jingle_content_accept_transport(content); - if (jingle_rtp_ready_to_initiate(session, media)) + if (jingle_rtp_ready_to_initiate(session, media)) { jabber_iq_send(jingle_session_to_packet(session, JINGLE_SESSION_INITIATE)); + if (JINGLE_IS_ICEUDP(transport)) + jabber_iq_send(jingle_session_to_packet(session, JINGLE_TRANSPORT_INFO)); + } } static void @@ -320,8 +354,12 @@ JINGLE_RTP_GET_PRIVATE(content)->codecs_ready = purple_media_codecs_ready(media, sid); - if (jingle_rtp_ready_to_initiate(session, media)) + if (jingle_rtp_ready_to_initiate(session, media)) { + JingleTransport *transport = jingle_content_get_transport(content); jabber_iq_send(jingle_session_to_packet(session, JINGLE_SESSION_INITIATE)); + if (JINGLE_IS_ICEUDP(transport)) + jabber_iq_send(jingle_session_to_packet(session, JINGLE_TRANSPORT_INFO)); + } } } @@ -399,6 +437,8 @@ if (JINGLE_IS_RAWUDP(transport)) transmitter = "rawudp"; + else if (JINGLE_IS_ICEUDP(transport)) + transmitter = "nice"; else transmitter = "notransmitter"; @@ -577,10 +617,12 @@ jingle_content_get_name(content), jingle_session_get_remote_jid(session), codecs); - purple_media_add_remote_candidates(jingle_rtp_get_media(session), - jingle_content_get_name(content), - jingle_session_get_remote_jid(session), - candidates); + if (JINGLE_IS_RAWUDP(transport)) { + purple_media_add_remote_candidates(jingle_rtp_get_media(session), + jingle_content_get_name(content), + jingle_session_get_remote_jid(session), + candidates); + } /* very hacky */ if (xmlnode_get_next_twin(xmlcontent) == NULL) @@ -653,7 +695,7 @@ if (type & PURPLE_MEDIA_AUDIO) { - transport = jingle_transport_create(JINGLE_TRANSPORT_RAWUDP); + transport = jingle_transport_create(JINGLE_TRANSPORT_ICEUDP); content = jingle_content_create(JINGLE_APP_RTP, "initiator", "session", "audio-session", "both", transport); jingle_session_add_content(session, content); @@ -661,7 +703,7 @@ jingle_rtp_init_media(content); } if (type & PURPLE_MEDIA_VIDEO) { - transport = jingle_transport_create(JINGLE_TRANSPORT_RAWUDP); + transport = jingle_transport_create(JINGLE_TRANSPORT_ICEUDP); content = jingle_content_create(JINGLE_APP_RTP, "initiator", "session", "video-session", "both", transport); jingle_session_add_content(session, content);