media/mtransport/third_party/nICEr/src/ice/ice_parser.c

branch
TOR_BUG_9701
changeset 8
97036ab72558
equal deleted inserted replaced
-1:000000000000 0:040d670ecb66
1 /*
2 Copyright (c) 2007, Adobe Systems, Incorporated
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11
12 * Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15
16 * Neither the name of Adobe Systems, Network Resonance nor the names of its
17 contributors may be used to endorse or promote products derived from
18 this software without specific prior written permission.
19
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33
34
35 static char *RCSSTRING __UNUSED__="$Id: ice_parser.c,v 1.2 2008/04/28 17:59:01 ekr Exp $";
36
37 #include <csi_platform.h>
38 #include <sys/types.h>
39 #ifdef WIN32
40 #include <winsock2.h>
41 #else
42 #include <sys/socket.h>
43 #include <netinet/in.h>
44 #include <arpa/inet.h>
45 #include <strings.h>
46 #endif
47 #include <string.h>
48 #include <assert.h>
49 #include <ctype.h>
50 #include "nr_api.h"
51 #include "ice_ctx.h"
52 #include "ice_candidate.h"
53 #include "ice_reg.h"
54
55 static void
56 skip_whitespace(char **str)
57 {
58 char *c = *str;
59 while (*c == ' ')
60 ++c;
61
62 *str = c;
63 }
64
65 static void
66 fast_forward(char **str, int skip)
67 {
68 char *c = *str;
69 while (*c != '\0' && skip-- > 0)
70 ++c;
71
72 *str = c;
73 }
74
75 static void
76 skip_to_past_space(char **str)
77 {
78 char *c = *str;
79 while (*c != ' ' && *c != '\0')
80 ++c;
81
82 *str = c;
83
84 skip_whitespace(str);
85 }
86
87 static int
88 grab_token(char **str, char **out)
89 {
90 int _status;
91 char *c = *str;
92 int len;
93 char *tmp;
94
95 while (*c != ' ' && *c != '\0')
96 ++c;
97
98 len = c - *str;
99
100 tmp = RMALLOC(len + 1);
101 if (!tmp)
102 ABORT(R_NO_MEMORY);
103
104 memcpy(tmp, *str, len);
105 tmp[len] = '\0';
106
107 *str = c;
108 *out = tmp;
109
110 _status = 0;
111 abort:
112 return _status;
113 }
114
115 int
116 nr_ice_peer_candidate_from_attribute(nr_ice_ctx *ctx,char *orig,nr_ice_media_stream *stream,nr_ice_candidate **candp)
117 {
118 int r,_status;
119 char* str = orig;
120 nr_ice_candidate *cand;
121 char *connection_address=0;
122 unsigned int port;
123 in_addr_t addr;
124 int i;
125 unsigned int component_id;
126 char *rel_addr=0;
127
128 if(!(cand=RCALLOC(sizeof(nr_ice_candidate))))
129 ABORT(R_NO_MEMORY);
130
131 if(!(cand->label=r_strdup(orig)))
132 ABORT(R_NO_MEMORY);
133
134 cand->ctx=ctx;
135 cand->isock=0;
136 cand->state=NR_ICE_CAND_PEER_CANDIDATE_UNPAIRED;
137 cand->stream=stream;
138 skip_whitespace(&str);
139
140 /* Candidate attr */
141 if (strncasecmp(str, "candidate:", 10))
142 ABORT(R_BAD_DATA);
143
144 fast_forward(&str, 10);
145 if (*str == '\0')
146 ABORT(R_BAD_DATA);
147
148 skip_whitespace(&str);
149 if (*str == '\0')
150 ABORT(R_BAD_DATA);
151
152 /* Foundation */
153 if ((r=grab_token(&str, &cand->foundation)))
154 ABORT(r);
155
156 if (*str == '\0')
157 ABORT(R_BAD_DATA);
158
159 skip_whitespace(&str);
160 if (*str == '\0')
161 ABORT(R_BAD_DATA);
162
163 /* component */
164 if (sscanf(str, "%u", &component_id) != 1)
165 ABORT(R_BAD_DATA);
166
167 if (component_id < 1 || component_id > 256)
168 ABORT(R_BAD_DATA);
169
170 cand->component_id = (UCHAR)component_id;
171
172 skip_to_past_space(&str);
173 if (*str == '\0')
174 ABORT(R_BAD_DATA);
175
176 /* Protocol */
177 if (strncasecmp(str, "UDP", 3))
178 ABORT(R_BAD_DATA);
179
180 fast_forward(&str, 3);
181 if (*str == '\0')
182 ABORT(R_BAD_DATA);
183
184 skip_whitespace(&str);
185 if (*str == '\0')
186 ABORT(R_BAD_DATA);
187
188 /* priority */
189 if (sscanf(str, "%u", &cand->priority) != 1)
190 ABORT(R_BAD_DATA);
191
192 if (cand->priority < 1)
193 ABORT(R_BAD_DATA);
194
195 skip_to_past_space(&str);
196 if (*str == '\0')
197 ABORT(R_BAD_DATA);
198
199 /* Peer address/port */
200 if ((r=grab_token(&str, &connection_address)))
201 ABORT(r);
202
203 if (*str == '\0')
204 ABORT(R_BAD_DATA);
205
206 addr = inet_addr(connection_address);
207 if (addr == INADDR_NONE)
208 ABORT(R_BAD_DATA);
209
210 skip_whitespace(&str);
211 if (*str == '\0')
212 ABORT(R_BAD_DATA);
213
214 if (sscanf(str, "%u", &port) != 1)
215 ABORT(R_BAD_DATA);
216
217 if (port < 1 || port > 0x0FFFF)
218 ABORT(R_BAD_DATA);
219
220 /* Assume v4 for now */
221 if(r=nr_ip4_port_to_transport_addr(ntohl(addr),port,IPPROTO_UDP,&cand->addr))
222 ABORT(r);
223
224 skip_to_past_space(&str);
225 if (*str == '\0')
226 ABORT(R_BAD_DATA);
227
228 /* Type */
229 if (strncasecmp("typ", str, 3))
230 ABORT(R_BAD_DATA);
231
232 fast_forward(&str, 3);
233 if (*str == '\0')
234 ABORT(R_BAD_DATA);
235
236 skip_whitespace(&str);
237 if (*str == '\0')
238 ABORT(R_BAD_DATA);
239
240 assert(nr_ice_candidate_type_names[0] == 0);
241 #if __STDC_VERSION__ >= 201112L
242 _Static_assert(nr_ice_candidate_type_names[0] == 0,"Candidate name array is misformatted");
243 #endif
244
245 for (i = 1; nr_ice_candidate_type_names[i]; ++i) {
246 if(!strncasecmp(nr_ice_candidate_type_names[i], str, strlen(nr_ice_candidate_type_names[i]))) {
247 cand->type=i;
248 break;
249 }
250 }
251 if (nr_ice_candidate_type_names[i] == 0)
252 ABORT(R_BAD_DATA);
253
254 fast_forward(&str, strlen(nr_ice_candidate_type_names[i]));
255
256 /* Look for the other side's raddr, rport */
257 /* raddr, rport */
258 switch (cand->type) {
259 case HOST:
260 break;
261 case SERVER_REFLEXIVE:
262 case PEER_REFLEXIVE:
263 case RELAYED:
264
265 skip_whitespace(&str);
266 if (*str == '\0')
267 ABORT(R_BAD_DATA);
268
269 if (strncasecmp("raddr", str, 5))
270 ABORT(R_BAD_DATA);
271
272 fast_forward(&str, 5);
273 if (*str == '\0')
274 ABORT(R_BAD_DATA);
275
276 skip_whitespace(&str);
277 if (*str == '\0')
278 ABORT(R_BAD_DATA);
279
280 if ((r=grab_token(&str, &rel_addr)))
281 ABORT(r);
282
283 if (*str == '\0')
284 ABORT(R_BAD_DATA);
285
286 addr = inet_addr(rel_addr);
287 if (addr == INADDR_NONE)
288 ABORT(R_BAD_DATA);
289
290 skip_whitespace(&str);
291 if (*str == '\0')
292 ABORT(R_BAD_DATA);
293
294 if (strncasecmp("rport", str, 5))
295 ABORT(R_BAD_DATA);
296
297 fast_forward(&str, 5);
298 if (*str == '\0')
299 ABORT(R_BAD_DATA);
300
301 skip_whitespace(&str);
302 if (*str == '\0')
303 ABORT(R_BAD_DATA);
304
305 if (sscanf(str, "%u", &port) != 1)
306 ABORT(R_BAD_DATA);
307
308 if (port < 1 || port > 0x0FFFF)
309 ABORT(R_BAD_DATA);
310
311 /* Assume v4 for now */
312 if(r=nr_ip4_port_to_transport_addr(ntohl(addr),port,IPPROTO_UDP,&cand->base))
313 ABORT(r);
314
315 skip_to_past_space(&str);
316 /* it's expected to be at EOD at this point */
317
318 break;
319 default:
320 ABORT(R_INTERNAL);
321 break;
322 }
323
324 skip_whitespace(&str);
325
326 /* Ignore extensions per RFC 5245 S 15.1 */
327 #if 0
328 /* This used to be an assert, but we don't want to exit on invalid
329 remote data */
330 if (strlen(str) != 0) {
331 ABORT(R_BAD_DATA);
332 }
333 #endif
334
335 nr_ice_candidate_compute_codeword(cand);
336
337 *candp=cand;
338
339 _status=0;
340 abort:
341 if (_status){
342 r_log(LOG_ICE,LOG_WARNING,"ICE(%s): Error parsing attribute: %s",ctx->label,orig);
343 nr_ice_candidate_destroy(&cand);
344 }
345
346 RFREE(connection_address);
347 RFREE(rel_addr);
348 return(_status);
349 }
350
351
352 int
353 nr_ice_peer_ctx_parse_media_stream_attribute(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, char *attr)
354 {
355 int r,_status;
356 char *orig = 0;
357 char *str;
358
359 orig = str = attr;
360
361 if (!strncasecmp(str, "ice-ufrag:", 10)) {
362 fast_forward(&str, 10);
363 if (*str == '\0')
364 ABORT(R_BAD_DATA);
365
366 skip_whitespace(&str);
367 if (*str == '\0')
368 ABORT(R_BAD_DATA);
369
370 if ((r=grab_token(&str, &stream->ufrag)))
371 ABORT(r);
372 }
373 else if (!strncasecmp(str, "ice-pwd:", 8)) {
374 fast_forward(&str, 8);
375 if (*str == '\0')
376 ABORT(R_BAD_DATA);
377
378 skip_whitespace(&str);
379 if (*str == '\0')
380 ABORT(R_BAD_DATA);
381
382 if ((r=grab_token(&str, &stream->pwd)))
383 ABORT(r);
384 }
385 else {
386 ABORT(R_BAD_DATA);
387 }
388
389 skip_whitespace(&str);
390
391 /* RFC 5245 grammar doesn't have an extension point for ice-pwd or
392 ice-ufrag: if there's anything left on the line, we treat it as bad. */
393 if (str[0] != '\0') {
394 ABORT(R_BAD_DATA);
395 }
396
397 _status=0;
398 abort:
399 if (_status) {
400 if (orig)
401 r_log(LOG_ICE,LOG_WARNING,"ICE-PEER(%s): Error parsing attribute: %s",pctx->label,orig);
402 }
403
404 return(_status);
405 }
406
407 int
408 nr_ice_peer_ctx_parse_global_attributes(nr_ice_peer_ctx *pctx, char **attrs, int attr_ct)
409 {
410 int r,_status;
411 int i;
412 char *orig = 0;
413 char *str;
414 char *component_id = 0;
415 char *connection_address = 0;
416 unsigned int port;
417 in_addr_t addr;
418 char *ice_option_tag = 0;
419
420 for(i=0;i<attr_ct;i++){
421 orig = str = attrs[i];
422
423 component_id = 0;
424 connection_address = 0;
425 ice_option_tag = 0;
426
427 if (!strncasecmp(str, "remote-candidates:", 18)) {
428 fast_forward(&str, 18);
429 skip_whitespace(&str);
430
431 while (*str != '\0') {
432 if ((r=grab_token(&str, &component_id)))
433 ABORT(r);
434
435 if (*str == '\0')
436 ABORT(R_BAD_DATA);
437
438 skip_whitespace(&str);
439 if (*str == '\0')
440 ABORT(R_BAD_DATA);
441
442 if ((r=grab_token(&str, &connection_address)))
443 ABORT(r);
444
445 if (*str == '\0')
446 ABORT(R_BAD_DATA);
447
448 addr = inet_addr(connection_address);
449 if (addr == INADDR_NONE)
450 ABORT(R_BAD_DATA);
451
452 skip_whitespace(&str);
453 if (*str == '\0')
454 ABORT(R_BAD_DATA);
455
456 if (sscanf(str, "%u", &port) != 1)
457 ABORT(R_BAD_DATA);
458
459 if (port < 1 || port > 0x0FFFF)
460 ABORT(R_BAD_DATA);
461
462 skip_to_past_space(&str);
463
464 #if 0
465 /* TODO: !nn! just drop on the floor for now, later put somewhere */
466 /* Assume v4 for now */
467 if(r=nr_ip4_port_to_transport_addr(ntohl(addr),port,IPPROTO_UDP,&candidate->base))
468 ABORT(r);
469
470 TAILQ_INSERT_TAIL(head, elm, field);
471 #endif
472
473 component_id = 0; /* prevent free */
474 RFREE(connection_address);
475 connection_address = 0; /* prevent free */
476 }
477 }
478 else if (!strncasecmp(str, "ice-lite", 8)) {
479 pctx->peer_lite = 1;
480
481 fast_forward(&str, 8);
482 }
483 else if (!strncasecmp(str, "ice-mismatch", 12)) {
484 pctx->peer_ice_mismatch = 1;
485
486 fast_forward(&str, 12);
487 }
488 else if (!strncasecmp(str, "ice-ufrag:", 10)) {
489 fast_forward(&str, 10);
490 if (*str == '\0')
491 ABORT(R_BAD_DATA);
492
493 skip_whitespace(&str);
494 if (*str == '\0')
495 ABORT(R_BAD_DATA);
496
497 RFREE(pctx->peer_ufrag);
498 pctx->peer_ufrag = 0;
499 if ((r=grab_token(&str, &pctx->peer_ufrag)))
500 ABORT(r);
501 }
502 else if (!strncasecmp(str, "ice-pwd:", 8)) {
503 fast_forward(&str, 8);
504 if (*str == '\0')
505 ABORT(R_BAD_DATA);
506
507 skip_whitespace(&str);
508 if (*str == '\0')
509 ABORT(R_BAD_DATA);
510
511 RFREE(pctx->peer_pwd);
512 pctx->peer_pwd = 0;
513 if ((r=grab_token(&str, &pctx->peer_pwd)))
514 ABORT(r);
515 }
516 else if (!strncasecmp(str, "ice-options:", 12)) {
517 fast_forward(&str, 12);
518 skip_whitespace(&str);
519
520 while (*str != '\0') {
521 if ((r=grab_token(&str, &ice_option_tag)))
522 ABORT(r);
523
524 skip_whitespace(&str);
525
526 //TODO: for now, just throw away; later put somewhere
527 RFREE(ice_option_tag);
528
529 ice_option_tag = 0; /* prevent free */
530 }
531 }
532 else {
533 ABORT(R_BAD_DATA);
534 }
535
536 skip_whitespace(&str);
537
538 /* RFC 5245 grammar doesn't have an extension point for any of the
539 preceding attributes: if there's anything left on the line, we
540 treat it as bad data. */
541 if (str[0] != '\0') {
542 ABORT(R_BAD_DATA);
543 }
544 }
545
546 _status=0;
547 abort:
548 if (_status) {
549 if (orig)
550 r_log(LOG_ICE,LOG_WARNING,"ICE-PEER(%s): Error parsing attribute: %s",pctx->label,orig);
551 }
552
553 RFREE(connection_address);
554 RFREE(component_id);
555 RFREE(ice_option_tag);
556 return(_status);
557 }
558

mercurial