6 * Purple is the legal property of its developers, whose names are too numerous
7 * to list here. Please refer to the COPYRIGHT file distributed with this
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
26 #include "glibcompat.h"
36 JingleTransport parent
;
41 GList
*local_candidates
;
42 GList
*remote_candidates
;
43 } JingleRawUdpPrivate
;
47 PROP_LOCAL_CANDIDATES
,
48 PROP_REMOTE_CANDIDATES
,
51 static GParamSpec
*properties
[PROP_LAST
];
53 G_DEFINE_DYNAMIC_TYPE_EXTENDED(
56 JINGLE_TYPE_TRANSPORT
,
58 G_ADD_PRIVATE_DYNAMIC(JingleRawUdp
)
61 /******************************************************************************
62 * JingleRawUdp Transport Implementation
63 *****************************************************************************/
65 jingle_rawudp_get_remote_candidates(JingleTransport
*transport
)
67 JingleRawUdp
*rawudp
= JINGLE_RAWUDP(transport
);
68 JingleRawUdpPrivate
*priv
= jingle_rawudp_get_instance_private(rawudp
);
69 GList
*candidates
= priv
->remote_candidates
;
72 for (; candidates
; candidates
= g_list_next(candidates
)) {
73 JingleRawUdpCandidate
*candidate
= candidates
->data
;
74 ret
= g_list_append(ret
, purple_media_candidate_new("",
76 PURPLE_MEDIA_CANDIDATE_TYPE_SRFLX
,
77 PURPLE_MEDIA_NETWORK_PROTOCOL_UDP
,
78 candidate
->ip
, candidate
->port
));
84 static JingleRawUdpCandidate
*
85 jingle_rawudp_get_remote_candidate_by_id(JingleRawUdp
*rawudp
, gchar
*id
)
87 JingleRawUdpPrivate
*priv
= jingle_rawudp_get_instance_private(rawudp
);
89 GList
*iter
= priv
->remote_candidates
;
90 for (; iter
; iter
= g_list_next(iter
)) {
91 JingleRawUdpCandidate
*candidate
= iter
->data
;
92 if (purple_strequal(candidate
->id
, id
)) {
100 jingle_rawudp_add_remote_candidate(JingleRawUdp
*rawudp
, JingleRawUdpCandidate
*candidate
)
102 JingleRawUdpPrivate
*priv
= jingle_rawudp_get_instance_private(rawudp
);
103 JingleRawUdpCandidate
*rawudp_candidate
=
104 jingle_rawudp_get_remote_candidate_by_id(rawudp
, candidate
->id
);
105 if (rawudp_candidate
!= NULL
) {
106 priv
->remote_candidates
= g_list_remove(
107 priv
->remote_candidates
, rawudp_candidate
);
108 g_boxed_free(JINGLE_TYPE_RAWUDP_CANDIDATE
, rawudp_candidate
);
110 priv
->remote_candidates
= g_list_append(priv
->remote_candidates
, candidate
);
112 g_object_notify_by_pspec(G_OBJECT(rawudp
), properties
[PROP_REMOTE_CANDIDATES
]);
115 static PurpleXmlNode
*
116 jingle_rawudp_to_xml_internal(JingleTransport
*transport
, PurpleXmlNode
*content
, JingleActionType action
)
118 PurpleXmlNode
*node
= JINGLE_TRANSPORT_CLASS(jingle_rawudp_parent_class
)->to_xml(transport
, content
, action
);
120 if (action
== JINGLE_SESSION_INITIATE
||
121 action
== JINGLE_TRANSPORT_INFO
||
122 action
== JINGLE_SESSION_ACCEPT
) {
123 JingleRawUdpPrivate
*priv
= jingle_rawudp_get_instance_private(JINGLE_RAWUDP(transport
));
124 GList
*iter
= priv
->local_candidates
;
126 for (; iter
; iter
= g_list_next(iter
)) {
127 JingleRawUdpCandidate
*candidate
= iter
->data
;
128 PurpleXmlNode
*xmltransport
;
129 gchar
*generation
, *component
, *port
;
131 if (candidate
->rem_known
== TRUE
)
133 candidate
->rem_known
= TRUE
;
135 xmltransport
= purple_xmlnode_new_child(node
, "candidate");
136 generation
= g_strdup_printf("%d", candidate
->generation
);
137 component
= g_strdup_printf("%d", candidate
->component
);
138 port
= g_strdup_printf("%d", candidate
->port
);
140 purple_xmlnode_set_attrib(xmltransport
, "generation", generation
);
141 purple_xmlnode_set_attrib(xmltransport
, "component", component
);
142 purple_xmlnode_set_attrib(xmltransport
, "id", candidate
->id
);
143 purple_xmlnode_set_attrib(xmltransport
, "ip", candidate
->ip
);
144 purple_xmlnode_set_attrib(xmltransport
, "port", port
);
154 static JingleTransport
*
155 jingle_rawudp_parse_internal(PurpleXmlNode
*rawudp
)
157 JingleTransport
*transport
= JINGLE_TRANSPORT_CLASS(jingle_rawudp_parent_class
)->parse(rawudp
);
158 JingleRawUdpPrivate
*priv
= jingle_rawudp_get_instance_private(JINGLE_RAWUDP(transport
));
159 PurpleXmlNode
*candidate
= purple_xmlnode_get_child(rawudp
, "candidate");
160 JingleRawUdpCandidate
*rawudp_candidate
= NULL
;
162 for (; candidate
; candidate
= purple_xmlnode_get_next_twin(candidate
)) {
163 const gchar
*id
= purple_xmlnode_get_attrib(candidate
, "id");
164 const gchar
*generation
= purple_xmlnode_get_attrib(candidate
, "generation");
165 const gchar
*component
= purple_xmlnode_get_attrib(candidate
, "component");
166 const gchar
*ip
= purple_xmlnode_get_attrib(candidate
, "ip");
167 const gchar
*port
= purple_xmlnode_get_attrib(candidate
, "port");
169 if (!id
|| !generation
|| !component
|| !ip
|| !port
)
172 rawudp_candidate
= jingle_rawudp_candidate_new(
178 rawudp_candidate
->rem_known
= TRUE
;
179 jingle_rawudp_add_remote_candidate(JINGLE_RAWUDP(transport
), rawudp_candidate
);
182 if (rawudp_candidate
!= NULL
&&
183 g_list_length(priv
->remote_candidates
) == 1) {
184 /* manufacture rtcp candidate */
185 rawudp_candidate
= g_boxed_copy(JINGLE_TYPE_RAWUDP_CANDIDATE
, rawudp_candidate
);
186 rawudp_candidate
->component
= 2;
187 rawudp_candidate
->port
= rawudp_candidate
->port
+ 1;
188 rawudp_candidate
->rem_known
= TRUE
;
189 jingle_rawudp_add_remote_candidate(JINGLE_RAWUDP(transport
), rawudp_candidate
);
196 jingle_rawudp_add_local_candidate(JingleTransport
*transport
, const gchar
*id
, guint generation
, PurpleMediaCandidate
*candidate
)
198 JingleRawUdp
*rawudp
= JINGLE_RAWUDP(transport
);
199 JingleRawUdpPrivate
*priv
= jingle_rawudp_get_instance_private(rawudp
);
201 JingleRawUdpCandidate
*rawudp_candidate
;
204 ip
= purple_media_candidate_get_ip(candidate
);
205 rawudp_candidate
= jingle_rawudp_candidate_new(id
, generation
,
206 purple_media_candidate_get_component_id(candidate
),
207 ip
, purple_media_candidate_get_port(candidate
));
210 for (iter
= priv
->local_candidates
; iter
; iter
= g_list_next(iter
)) {
211 JingleRawUdpCandidate
*c
= iter
->data
;
212 if (purple_strequal(c
->id
, id
)) {
213 generation
= c
->generation
+ 1;
215 g_boxed_free(JINGLE_TYPE_RAWUDP_CANDIDATE
, c
);
216 priv
->local_candidates
= g_list_delete_link(
217 priv
->local_candidates
, iter
);
219 rawudp_candidate
->generation
= generation
;
221 priv
->local_candidates
= g_list_append(
222 priv
->local_candidates
, rawudp_candidate
);
224 g_object_notify_by_pspec(G_OBJECT(rawudp
), properties
[PROP_LOCAL_CANDIDATES
]);
230 priv
->local_candidates
= g_list_append(
231 priv
->local_candidates
, rawudp_candidate
);
233 g_object_notify_by_pspec(G_OBJECT(rawudp
), properties
[PROP_LOCAL_CANDIDATES
]);
236 /******************************************************************************
237 * JingleRawUdp GObject Stuff
238 *****************************************************************************/
240 jingle_rawudp_set_property (GObject
*object
, guint prop_id
, const GValue
*value
, GParamSpec
*pspec
)
242 JingleRawUdp
*rawudp
= JINGLE_RAWUDP(object
);
243 JingleRawUdpPrivate
*priv
= jingle_rawudp_get_instance_private(rawudp
);
246 case PROP_LOCAL_CANDIDATES
:
247 priv
->local_candidates
= g_value_get_pointer(value
);
249 case PROP_REMOTE_CANDIDATES
:
250 priv
->remote_candidates
= g_value_get_pointer(value
);
253 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
259 jingle_rawudp_get_property (GObject
*object
, guint prop_id
, GValue
*value
, GParamSpec
*pspec
)
261 JingleRawUdp
*rawudp
= JINGLE_RAWUDP(object
);
262 JingleRawUdpPrivate
*priv
= jingle_rawudp_get_instance_private(rawudp
);
265 case PROP_LOCAL_CANDIDATES
:
266 g_value_set_pointer(value
, priv
->local_candidates
);
268 case PROP_REMOTE_CANDIDATES
:
269 g_value_set_pointer(value
, priv
->remote_candidates
);
272 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
278 jingle_rawudp_init (JingleRawUdp
*rawudp
)
283 jingle_rawudp_finalize (GObject
*rawudp
)
285 /* JingleRawUdpPrivate *priv = JINGLE_RAWUDP_GET_PRIVATE(rawudp); */
286 purple_debug_info("jingle","jingle_rawudp_finalize\n");
288 G_OBJECT_CLASS(jingle_rawudp_parent_class
)->finalize(rawudp
);
292 jingle_rawudp_class_finalize(JingleRawUdpClass
*klass
) {
296 jingle_rawudp_class_init (JingleRawUdpClass
*klass
)
298 GObjectClass
*obj_class
= G_OBJECT_CLASS(klass
);
299 JingleTransportClass
*transport_class
= JINGLE_TRANSPORT_CLASS(klass
);
301 obj_class
->finalize
= jingle_rawudp_finalize
;
302 obj_class
->set_property
= jingle_rawudp_set_property
;
303 obj_class
->get_property
= jingle_rawudp_get_property
;
305 transport_class
->to_xml
= jingle_rawudp_to_xml_internal
;
306 transport_class
->parse
= jingle_rawudp_parse_internal
;
307 transport_class
->transport_type
= JINGLE_TRANSPORT_RAWUDP
;
308 transport_class
->add_local_candidate
= jingle_rawudp_add_local_candidate
;
309 transport_class
->get_remote_candidates
= jingle_rawudp_get_remote_candidates
;
311 properties
[PROP_LOCAL_CANDIDATES
] = g_param_spec_pointer("local-candidates",
313 "The local candidates for this transport.",
314 G_PARAM_READABLE
| G_PARAM_STATIC_STRINGS
);
316 properties
[PROP_REMOTE_CANDIDATES
] = g_param_spec_pointer("remote-candidates",
318 "The remote candidates for this transport.",
319 G_PARAM_READABLE
| G_PARAM_STATIC_STRINGS
);
321 g_object_class_install_properties(obj_class
, PROP_LAST
, properties
);
324 /******************************************************************************
325 * JingleRawUdpCandidate Boxed Type
326 *****************************************************************************/
327 static JingleRawUdpCandidate
*
328 jingle_rawudp_candidate_copy(JingleRawUdpCandidate
*candidate
)
330 JingleRawUdpCandidate
*new_candidate
= g_new0(JingleRawUdpCandidate
, 1);
331 new_candidate
->generation
= candidate
->generation
;
332 new_candidate
->component
= candidate
->component
;
333 new_candidate
->id
= g_strdup(candidate
->id
);
334 new_candidate
->ip
= g_strdup(candidate
->ip
);
335 new_candidate
->port
= candidate
->port
;
337 new_candidate
->rem_known
= candidate
->rem_known
;
338 return new_candidate
;
342 jingle_rawudp_candidate_free(JingleRawUdpCandidate
*candidate
)
344 g_free(candidate
->id
);
345 g_free(candidate
->ip
);
348 G_DEFINE_BOXED_TYPE(JingleRawUdpCandidate
, jingle_rawudp_candidate
,
349 jingle_rawudp_candidate_copy
, jingle_rawudp_candidate_free
)
351 /******************************************************************************
353 *****************************************************************************/
355 jingle_rawudp_register(PurplePlugin
*plugin
) {
356 jingle_rawudp_register_type(G_TYPE_MODULE(plugin
));
359 JingleRawUdpCandidate
*
360 jingle_rawudp_candidate_new(const gchar
*id
, guint generation
, guint component
, const gchar
*ip
, guint port
)
362 JingleRawUdpCandidate
*candidate
= g_new0(JingleRawUdpCandidate
, 1);
363 candidate
->generation
= generation
;
364 candidate
->component
= component
;
365 candidate
->id
= g_strdup(id
);
366 candidate
->ip
= g_strdup(ip
);
367 candidate
->port
= port
;
369 candidate
->rem_known
= FALSE
;