comparison libpurple/protocols/jabber/jingle/rawudp.c @ 26030:365eb0b68d5f

Update Jingle raw-udp to latest spec version.
author Mike Ruprecht <maiku@soc.pidgin.im>
date Fri, 07 Nov 2008 03:00:09 +0000
parents 7252e3d0c627
children 835a7003eed3
comparison
equal deleted inserted replaced
26029:b9d4ab2c84c6 26030:365eb0b68d5f
24 24
25 #include <string.h> 25 #include <string.h>
26 26
27 struct _JingleRawUdpPrivate 27 struct _JingleRawUdpPrivate
28 { 28 {
29 guint generation; 29 GList *local_candidates;
30 gchar *id; 30 GList *remote_candidates;
31 gchar *ip;
32 guint port;
33 }; 31 };
34 32
35 #define JINGLE_RAWUDP_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), JINGLE_TYPE_RAWUDP, JingleRawUdpPrivate)) 33 #define JINGLE_RAWUDP_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), JINGLE_TYPE_RAWUDP, JingleRawUdpPrivate))
36 34
37 static void jingle_rawudp_class_init (JingleRawUdpClass *klass); 35 static void jingle_rawudp_class_init (JingleRawUdpClass *klass);
44 42
45 static JingleTransportClass *parent_class = NULL; 43 static JingleTransportClass *parent_class = NULL;
46 44
47 enum { 45 enum {
48 PROP_0, 46 PROP_0,
49 PROP_GENERATION, 47 PROP_LOCAL_CANDIDATES,
50 PROP_ID, 48 PROP_REMOTE_CANDIDATES,
51 PROP_IP,
52 PROP_PORT,
53 }; 49 };
50
51 static JingleRawUdpCandidate *
52 jingle_rawudp_candidate_copy(JingleRawUdpCandidate *candidate)
53 {
54 JingleRawUdpCandidate *new_candidate = g_new0(JingleRawUdpCandidate, 1);
55 new_candidate->generation = candidate->generation;
56 new_candidate->component = candidate->component;
57 new_candidate->id = g_strdup(candidate->id);
58 new_candidate->ip = g_strdup(candidate->ip);
59 new_candidate->port = candidate->port;
60 return new_candidate;
61 }
62
63 static void
64 jingle_rawudp_candidate_free(JingleRawUdpCandidate *candidate)
65 {
66 g_free(candidate->id);
67 g_free(candidate->ip);
68 }
69
70 GType
71 jingle_rawudp_candidate_get_type()
72 {
73 static GType type = 0;
74
75 if (type == 0) {
76 type = g_boxed_type_register_static("JingleRawUdpCandidate",
77 (GBoxedCopyFunc)jingle_rawudp_candidate_copy,
78 (GBoxedFreeFunc)jingle_rawudp_candidate_free);
79 }
80 return type;
81 }
82
83 JingleRawUdpCandidate *
84 jingle_rawudp_candidate_new(const gchar *id, guint generation, guint component, const gchar *ip, guint port)
85 {
86 JingleRawUdpCandidate *candidate = g_new0(JingleRawUdpCandidate, 1);
87 candidate->generation = generation;
88 candidate->component = component;
89 candidate->id = g_strdup(id);
90 candidate->ip = g_strdup(ip);
91 candidate->port = port;
92 return candidate;
93 }
54 94
55 GType 95 GType
56 jingle_rawudp_get_type() 96 jingle_rawudp_get_type()
57 { 97 {
58 static GType type = 0; 98 static GType type = 0;
86 gobject_class->get_property = jingle_rawudp_get_property; 126 gobject_class->get_property = jingle_rawudp_get_property;
87 klass->parent_class.to_xml = jingle_rawudp_to_xml_internal; 127 klass->parent_class.to_xml = jingle_rawudp_to_xml_internal;
88 klass->parent_class.parse = jingle_rawudp_parse_internal; 128 klass->parent_class.parse = jingle_rawudp_parse_internal;
89 klass->parent_class.transport_type = JINGLE_TRANSPORT_RAWUDP; 129 klass->parent_class.transport_type = JINGLE_TRANSPORT_RAWUDP;
90 130
91 g_object_class_install_property(gobject_class, PROP_GENERATION, 131 g_object_class_install_property(gobject_class, PROP_LOCAL_CANDIDATES,
92 g_param_spec_uint("generation", 132 g_param_spec_pointer("local-candidates",
93 "Generation", 133 "Local candidates",
94 "The generation for this transport.", 134 "The local candidates for this transport.",
95 0, 135 G_PARAM_READABLE));
96 G_MAXUINT, 136
97 0, 137 g_object_class_install_property(gobject_class, PROP_REMOTE_CANDIDATES,
98 G_PARAM_READWRITE)); 138 g_param_spec_pointer("remote-candidates",
99 139 "Remote candidates",
100 g_object_class_install_property(gobject_class, PROP_ID, 140 "The remote candidates for this transport.",
101 g_param_spec_string("id", 141 G_PARAM_READABLE));
102 "Id",
103 "The id for this transport.",
104 NULL,
105 G_PARAM_READWRITE));
106
107 g_object_class_install_property(gobject_class, PROP_IP,
108 g_param_spec_string("ip",
109 "IP Address",
110 "The IP address for this transport.",
111 NULL,
112 G_PARAM_READWRITE));
113
114 g_object_class_install_property(gobject_class, PROP_PORT,
115 g_param_spec_uint("port",
116 "Port",
117 "The port for this transport.",
118 0,
119 65535,
120 0,
121 G_PARAM_READWRITE));
122 142
123 g_type_class_add_private(klass, sizeof(JingleRawUdpPrivate)); 143 g_type_class_add_private(klass, sizeof(JingleRawUdpPrivate));
124 } 144 }
125 145
126 static void 146 static void
131 } 151 }
132 152
133 static void 153 static void
134 jingle_rawudp_finalize (GObject *rawudp) 154 jingle_rawudp_finalize (GObject *rawudp)
135 { 155 {
136 JingleRawUdpPrivate *priv = JINGLE_RAWUDP_GET_PRIVATE(rawudp); 156 /* JingleRawUdpPrivate *priv = JINGLE_RAWUDP_GET_PRIVATE(rawudp); */
137 purple_debug_info("jingle","jingle_rawudp_finalize\n"); 157 purple_debug_info("jingle","jingle_rawudp_finalize\n");
138
139 g_free(priv->id);
140 g_free(priv->ip);
141 } 158 }
142 159
143 static void 160 static void
144 jingle_rawudp_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) 161 jingle_rawudp_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
145 { 162 {
147 g_return_if_fail(JINGLE_IS_RAWUDP(object)); 164 g_return_if_fail(JINGLE_IS_RAWUDP(object));
148 165
149 rawudp = JINGLE_RAWUDP(object); 166 rawudp = JINGLE_RAWUDP(object);
150 167
151 switch (prop_id) { 168 switch (prop_id) {
152 case PROP_GENERATION: 169 case PROP_LOCAL_CANDIDATES:
153 rawudp->priv->generation = g_value_get_uint(value); 170 rawudp->priv->local_candidates =
154 break; 171 g_value_get_pointer(value);
155 case PROP_ID: 172 break;
156 g_free(rawudp->priv->id); 173 case PROP_REMOTE_CANDIDATES:
157 rawudp->priv->id = g_value_dup_string(value); 174 rawudp->priv->remote_candidates =
158 break; 175 g_value_get_pointer(value);
159 case PROP_IP:
160 g_free(rawudp->priv->ip);
161 rawudp->priv->ip = g_value_dup_string(value);
162 break;
163 case PROP_PORT:
164 rawudp->priv->port = g_value_get_uint(value);
165 break; 176 break;
166 default: 177 default:
167 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 178 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
168 break; 179 break;
169 } 180 }
176 g_return_if_fail(JINGLE_IS_RAWUDP(object)); 187 g_return_if_fail(JINGLE_IS_RAWUDP(object));
177 188
178 rawudp = JINGLE_RAWUDP(object); 189 rawudp = JINGLE_RAWUDP(object);
179 190
180 switch (prop_id) { 191 switch (prop_id) {
181 case PROP_GENERATION: 192 case PROP_LOCAL_CANDIDATES:
182 g_value_set_uint(value, rawudp->priv->generation); 193 g_value_set_pointer(value, rawudp->priv->local_candidates);
183 break; 194 break;
184 case PROP_ID: 195 case PROP_REMOTE_CANDIDATES:
185 g_value_set_string(value, rawudp->priv->id); 196 g_value_set_pointer(value, rawudp->priv->remote_candidates);
186 break;
187 case PROP_IP:
188 g_value_set_string(value, rawudp->priv->ip);
189 break;
190 case PROP_PORT:
191 g_value_set_uint(value, rawudp->priv->port);
192 break; 197 break;
193 default: 198 default:
194 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 199 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
195 break; 200 break;
196 } 201 }
197 } 202 }
198 203
199 JingleRawUdp * 204 void
200 jingle_rawudp_create(guint generation, const gchar *id, const gchar *ip, guint port) 205 jingle_rawudp_add_local_candidate(JingleRawUdp *rawudp, JingleRawUdpCandidate *candidate)
201 { 206 {
202 return g_object_new(jingle_rawudp_get_type(), 207 GList *iter = rawudp->priv->local_candidates;
203 "generation", generation, 208
204 "id", id, 209 for (; iter; iter = g_list_next(iter)) {
205 "ip", ip, 210 JingleRawUdpCandidate *c = iter->data;
206 "port", port, NULL); 211 if (!strcmp(c->id, candidate->id)) {
212 guint generation = c->generation + 1;
213
214 g_boxed_free(JINGLE_TYPE_RAWUDP_CANDIDATE, c);
215 rawudp->priv->local_candidates = g_list_delete_link(
216 rawudp->priv->local_candidates, iter);
217
218 candidate->generation = generation;
219
220 rawudp->priv->local_candidates = g_list_append(
221 rawudp->priv->local_candidates, candidate);
222 return;
223 }
224 }
225
226 rawudp->priv->local_candidates = g_list_append(
227 rawudp->priv->local_candidates, candidate);
228 }
229
230 GList *
231 jingle_rawudp_get_remote_candidates(JingleRawUdp *rawudp)
232 {
233 return g_list_copy(rawudp->priv->remote_candidates);
234 }
235
236 static JingleRawUdpCandidate *
237 jingle_rawudp_get_remote_candidate_by_id(JingleRawUdp *rawudp, gchar *id)
238 {
239 GList *iter = rawudp->priv->remote_candidates;
240 for (; iter; iter = g_list_next(iter)) {
241 JingleRawUdpCandidate *candidate = iter->data;
242 if (!strcmp(candidate->id, id)) {
243 return candidate;
244 }
245 }
246 return NULL;
247 }
248
249 static void
250 jingle_rawudp_add_remote_candidate(JingleRawUdp *rawudp, JingleRawUdpCandidate *candidate)
251 {
252 JingleRawUdpPrivate *priv = JINGLE_RAWUDP_GET_PRIVATE(rawudp);
253 JingleRawUdpCandidate *rawudp_candidate =
254 jingle_rawudp_get_remote_candidate_by_id(rawudp, candidate->id);
255 if (rawudp_candidate != NULL) {
256 priv->remote_candidates = g_list_remove(
257 priv->remote_candidates, rawudp_candidate);
258 g_boxed_free(JINGLE_TYPE_RAWUDP_CANDIDATE, rawudp_candidate);
259 }
260 priv->remote_candidates = g_list_append(priv->remote_candidates, candidate);
207 } 261 }
208 262
209 static JingleTransport * 263 static JingleTransport *
210 jingle_rawudp_parse_internal(xmlnode *rawudp) 264 jingle_rawudp_parse_internal(xmlnode *rawudp)
211 { 265 {
212 JingleTransport *transport = parent_class->parse(rawudp); 266 JingleTransport *transport = parent_class->parse(rawudp);
213 267 JingleRawUdpPrivate *priv = JINGLE_RAWUDP_GET_PRIVATE(transport);
268 xmlnode *candidate = xmlnode_get_child(rawudp, "candidate");
269 JingleRawUdpCandidate *rawudp_candidate;
270
271 for (; candidate; candidate = xmlnode_get_next_twin(candidate)) {
272 rawudp_candidate = jingle_rawudp_candidate_new(
273 xmlnode_get_attrib(candidate, "id"),
274 atoi(xmlnode_get_attrib(candidate, "generation")),
275 atoi(xmlnode_get_attrib(candidate, "component")),
276 xmlnode_get_attrib(candidate, "ip"),
277 atoi(xmlnode_get_attrib(candidate, "port")));
278 jingle_rawudp_add_remote_candidate(JINGLE_RAWUDP(transport), rawudp_candidate);
279 }
280
281 if (g_list_length(priv->remote_candidates) == 1) {
282 /* manufacture rtcp candidate */
283 rawudp_candidate = g_boxed_copy(JINGLE_TYPE_RAWUDP_CANDIDATE, rawudp_candidate);
284 rawudp_candidate->component = 2;
285 rawudp_candidate->port = rawudp_candidate->port + 1;
286 jingle_rawudp_add_remote_candidate(JINGLE_RAWUDP(transport), rawudp_candidate);
287 }
288
214 return transport; 289 return transport;
215 } 290 }
216 291
217 static xmlnode * 292 static xmlnode *
218 jingle_rawudp_to_xml_internal(JingleTransport *transport, xmlnode *content, JingleActionType action) 293 jingle_rawudp_to_xml_internal(JingleTransport *transport, xmlnode *content, JingleActionType action)
219 { 294 {
220 xmlnode *node = parent_class->to_xml(transport, content, action); 295 xmlnode *node = parent_class->to_xml(transport, content, action);
221 296
222 if (action == JINGLE_SESSION_INITIATE || action == JINGLE_TRANSPORT_INFO) { 297 if (action == JINGLE_SESSION_INITIATE || action == JINGLE_TRANSPORT_INFO) {
223 xmlnode *xmltransport = xmlnode_new_child(node, "candidate");
224 JingleRawUdpPrivate *priv = JINGLE_RAWUDP_GET_PRIVATE(transport); 298 JingleRawUdpPrivate *priv = JINGLE_RAWUDP_GET_PRIVATE(transport);
225 gchar *generation = g_strdup_printf("%d", priv->generation); 299 GList *iter = priv->local_candidates;
226 gchar *port = g_strdup_printf("%d", priv->port); 300
227 301 for (; iter; iter = g_list_next(iter)) {
228 xmlnode_set_attrib(xmltransport, "generation", generation); 302 JingleRawUdpCandidate *candidate = iter->data;
229 xmlnode_set_attrib(xmltransport, "id", priv->id); 303
230 xmlnode_set_attrib(xmltransport, "ip", priv->ip); 304 xmlnode *xmltransport = xmlnode_new_child(node, "candidate");
231 xmlnode_set_attrib(xmltransport, "port", port); 305 gchar *generation = g_strdup_printf("%d", candidate->generation);
232 306 gchar *component = g_strdup_printf("%d", candidate->component);
233 g_free(port); 307 gchar *port = g_strdup_printf("%d", candidate->port);
234 g_free(generation); 308
309 xmlnode_set_attrib(xmltransport, "generation", generation);
310 xmlnode_set_attrib(xmltransport, "component", component);
311 xmlnode_set_attrib(xmltransport, "id", candidate->id);
312 xmlnode_set_attrib(xmltransport, "ip", candidate->ip);
313 xmlnode_set_attrib(xmltransport, "port", port);
314
315 g_free(port);
316 g_free(generation);
317 }
235 } 318 }
236 319
237 return node; 320 return node;
238 } 321 }
239 322