Mercurial > pidgin.yaz
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 |