1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/mtransport/third_party/nICEr/src/ice/ice_parser.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,558 @@ 1.4 +/* 1.5 +Copyright (c) 2007, Adobe Systems, Incorporated 1.6 +All rights reserved. 1.7 + 1.8 +Redistribution and use in source and binary forms, with or without 1.9 +modification, are permitted provided that the following conditions are 1.10 +met: 1.11 + 1.12 +* Redistributions of source code must retain the above copyright 1.13 + notice, this list of conditions and the following disclaimer. 1.14 + 1.15 +* Redistributions in binary form must reproduce the above copyright 1.16 + notice, this list of conditions and the following disclaimer in the 1.17 + documentation and/or other materials provided with the distribution. 1.18 + 1.19 +* Neither the name of Adobe Systems, Network Resonance nor the names of its 1.20 + contributors may be used to endorse or promote products derived from 1.21 + this software without specific prior written permission. 1.22 + 1.23 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.24 +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.25 +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1.26 +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1.27 +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1.28 +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1.29 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.30 +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.31 +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.32 +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1.33 +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.34 +*/ 1.35 + 1.36 + 1.37 + 1.38 +static char *RCSSTRING __UNUSED__="$Id: ice_parser.c,v 1.2 2008/04/28 17:59:01 ekr Exp $"; 1.39 + 1.40 +#include <csi_platform.h> 1.41 +#include <sys/types.h> 1.42 +#ifdef WIN32 1.43 +#include <winsock2.h> 1.44 +#else 1.45 +#include <sys/socket.h> 1.46 +#include <netinet/in.h> 1.47 +#include <arpa/inet.h> 1.48 +#include <strings.h> 1.49 +#endif 1.50 +#include <string.h> 1.51 +#include <assert.h> 1.52 +#include <ctype.h> 1.53 +#include "nr_api.h" 1.54 +#include "ice_ctx.h" 1.55 +#include "ice_candidate.h" 1.56 +#include "ice_reg.h" 1.57 + 1.58 +static void 1.59 +skip_whitespace(char **str) 1.60 +{ 1.61 + char *c = *str; 1.62 + while (*c == ' ') 1.63 + ++c; 1.64 + 1.65 + *str = c; 1.66 +} 1.67 + 1.68 +static void 1.69 +fast_forward(char **str, int skip) 1.70 +{ 1.71 + char *c = *str; 1.72 + while (*c != '\0' && skip-- > 0) 1.73 + ++c; 1.74 + 1.75 + *str = c; 1.76 +} 1.77 + 1.78 +static void 1.79 +skip_to_past_space(char **str) 1.80 +{ 1.81 + char *c = *str; 1.82 + while (*c != ' ' && *c != '\0') 1.83 + ++c; 1.84 + 1.85 + *str = c; 1.86 + 1.87 + skip_whitespace(str); 1.88 +} 1.89 + 1.90 +static int 1.91 +grab_token(char **str, char **out) 1.92 +{ 1.93 + int _status; 1.94 + char *c = *str; 1.95 + int len; 1.96 + char *tmp; 1.97 + 1.98 + while (*c != ' ' && *c != '\0') 1.99 + ++c; 1.100 + 1.101 + len = c - *str; 1.102 + 1.103 + tmp = RMALLOC(len + 1); 1.104 + if (!tmp) 1.105 + ABORT(R_NO_MEMORY); 1.106 + 1.107 + memcpy(tmp, *str, len); 1.108 + tmp[len] = '\0'; 1.109 + 1.110 + *str = c; 1.111 + *out = tmp; 1.112 + 1.113 + _status = 0; 1.114 +abort: 1.115 + return _status; 1.116 +} 1.117 + 1.118 +int 1.119 +nr_ice_peer_candidate_from_attribute(nr_ice_ctx *ctx,char *orig,nr_ice_media_stream *stream,nr_ice_candidate **candp) 1.120 +{ 1.121 + int r,_status; 1.122 + char* str = orig; 1.123 + nr_ice_candidate *cand; 1.124 + char *connection_address=0; 1.125 + unsigned int port; 1.126 + in_addr_t addr; 1.127 + int i; 1.128 + unsigned int component_id; 1.129 + char *rel_addr=0; 1.130 + 1.131 + if(!(cand=RCALLOC(sizeof(nr_ice_candidate)))) 1.132 + ABORT(R_NO_MEMORY); 1.133 + 1.134 + if(!(cand->label=r_strdup(orig))) 1.135 + ABORT(R_NO_MEMORY); 1.136 + 1.137 + cand->ctx=ctx; 1.138 + cand->isock=0; 1.139 + cand->state=NR_ICE_CAND_PEER_CANDIDATE_UNPAIRED; 1.140 + cand->stream=stream; 1.141 + skip_whitespace(&str); 1.142 + 1.143 + /* Candidate attr */ 1.144 + if (strncasecmp(str, "candidate:", 10)) 1.145 + ABORT(R_BAD_DATA); 1.146 + 1.147 + fast_forward(&str, 10); 1.148 + if (*str == '\0') 1.149 + ABORT(R_BAD_DATA); 1.150 + 1.151 + skip_whitespace(&str); 1.152 + if (*str == '\0') 1.153 + ABORT(R_BAD_DATA); 1.154 + 1.155 + /* Foundation */ 1.156 + if ((r=grab_token(&str, &cand->foundation))) 1.157 + ABORT(r); 1.158 + 1.159 + if (*str == '\0') 1.160 + ABORT(R_BAD_DATA); 1.161 + 1.162 + skip_whitespace(&str); 1.163 + if (*str == '\0') 1.164 + ABORT(R_BAD_DATA); 1.165 + 1.166 + /* component */ 1.167 + if (sscanf(str, "%u", &component_id) != 1) 1.168 + ABORT(R_BAD_DATA); 1.169 + 1.170 + if (component_id < 1 || component_id > 256) 1.171 + ABORT(R_BAD_DATA); 1.172 + 1.173 + cand->component_id = (UCHAR)component_id; 1.174 + 1.175 + skip_to_past_space(&str); 1.176 + if (*str == '\0') 1.177 + ABORT(R_BAD_DATA); 1.178 + 1.179 + /* Protocol */ 1.180 + if (strncasecmp(str, "UDP", 3)) 1.181 + ABORT(R_BAD_DATA); 1.182 + 1.183 + fast_forward(&str, 3); 1.184 + if (*str == '\0') 1.185 + ABORT(R_BAD_DATA); 1.186 + 1.187 + skip_whitespace(&str); 1.188 + if (*str == '\0') 1.189 + ABORT(R_BAD_DATA); 1.190 + 1.191 + /* priority */ 1.192 + if (sscanf(str, "%u", &cand->priority) != 1) 1.193 + ABORT(R_BAD_DATA); 1.194 + 1.195 + if (cand->priority < 1) 1.196 + ABORT(R_BAD_DATA); 1.197 + 1.198 + skip_to_past_space(&str); 1.199 + if (*str == '\0') 1.200 + ABORT(R_BAD_DATA); 1.201 + 1.202 + /* Peer address/port */ 1.203 + if ((r=grab_token(&str, &connection_address))) 1.204 + ABORT(r); 1.205 + 1.206 + if (*str == '\0') 1.207 + ABORT(R_BAD_DATA); 1.208 + 1.209 + addr = inet_addr(connection_address); 1.210 + if (addr == INADDR_NONE) 1.211 + ABORT(R_BAD_DATA); 1.212 + 1.213 + skip_whitespace(&str); 1.214 + if (*str == '\0') 1.215 + ABORT(R_BAD_DATA); 1.216 + 1.217 + if (sscanf(str, "%u", &port) != 1) 1.218 + ABORT(R_BAD_DATA); 1.219 + 1.220 + if (port < 1 || port > 0x0FFFF) 1.221 + ABORT(R_BAD_DATA); 1.222 + 1.223 + /* Assume v4 for now */ 1.224 + if(r=nr_ip4_port_to_transport_addr(ntohl(addr),port,IPPROTO_UDP,&cand->addr)) 1.225 + ABORT(r); 1.226 + 1.227 + skip_to_past_space(&str); 1.228 + if (*str == '\0') 1.229 + ABORT(R_BAD_DATA); 1.230 + 1.231 + /* Type */ 1.232 + if (strncasecmp("typ", str, 3)) 1.233 + ABORT(R_BAD_DATA); 1.234 + 1.235 + fast_forward(&str, 3); 1.236 + if (*str == '\0') 1.237 + ABORT(R_BAD_DATA); 1.238 + 1.239 + skip_whitespace(&str); 1.240 + if (*str == '\0') 1.241 + ABORT(R_BAD_DATA); 1.242 + 1.243 + assert(nr_ice_candidate_type_names[0] == 0); 1.244 +#if __STDC_VERSION__ >= 201112L 1.245 + _Static_assert(nr_ice_candidate_type_names[0] == 0,"Candidate name array is misformatted"); 1.246 +#endif 1.247 + 1.248 + for (i = 1; nr_ice_candidate_type_names[i]; ++i) { 1.249 + if(!strncasecmp(nr_ice_candidate_type_names[i], str, strlen(nr_ice_candidate_type_names[i]))) { 1.250 + cand->type=i; 1.251 + break; 1.252 + } 1.253 + } 1.254 + if (nr_ice_candidate_type_names[i] == 0) 1.255 + ABORT(R_BAD_DATA); 1.256 + 1.257 + fast_forward(&str, strlen(nr_ice_candidate_type_names[i])); 1.258 + 1.259 + /* Look for the other side's raddr, rport */ 1.260 + /* raddr, rport */ 1.261 + switch (cand->type) { 1.262 + case HOST: 1.263 + break; 1.264 + case SERVER_REFLEXIVE: 1.265 + case PEER_REFLEXIVE: 1.266 + case RELAYED: 1.267 + 1.268 + skip_whitespace(&str); 1.269 + if (*str == '\0') 1.270 + ABORT(R_BAD_DATA); 1.271 + 1.272 + if (strncasecmp("raddr", str, 5)) 1.273 + ABORT(R_BAD_DATA); 1.274 + 1.275 + fast_forward(&str, 5); 1.276 + if (*str == '\0') 1.277 + ABORT(R_BAD_DATA); 1.278 + 1.279 + skip_whitespace(&str); 1.280 + if (*str == '\0') 1.281 + ABORT(R_BAD_DATA); 1.282 + 1.283 + if ((r=grab_token(&str, &rel_addr))) 1.284 + ABORT(r); 1.285 + 1.286 + if (*str == '\0') 1.287 + ABORT(R_BAD_DATA); 1.288 + 1.289 + addr = inet_addr(rel_addr); 1.290 + if (addr == INADDR_NONE) 1.291 + ABORT(R_BAD_DATA); 1.292 + 1.293 + skip_whitespace(&str); 1.294 + if (*str == '\0') 1.295 + ABORT(R_BAD_DATA); 1.296 + 1.297 + if (strncasecmp("rport", str, 5)) 1.298 + ABORT(R_BAD_DATA); 1.299 + 1.300 + fast_forward(&str, 5); 1.301 + if (*str == '\0') 1.302 + ABORT(R_BAD_DATA); 1.303 + 1.304 + skip_whitespace(&str); 1.305 + if (*str == '\0') 1.306 + ABORT(R_BAD_DATA); 1.307 + 1.308 + if (sscanf(str, "%u", &port) != 1) 1.309 + ABORT(R_BAD_DATA); 1.310 + 1.311 + if (port < 1 || port > 0x0FFFF) 1.312 + ABORT(R_BAD_DATA); 1.313 + 1.314 + /* Assume v4 for now */ 1.315 + if(r=nr_ip4_port_to_transport_addr(ntohl(addr),port,IPPROTO_UDP,&cand->base)) 1.316 + ABORT(r); 1.317 + 1.318 + skip_to_past_space(&str); 1.319 + /* it's expected to be at EOD at this point */ 1.320 + 1.321 + break; 1.322 + default: 1.323 + ABORT(R_INTERNAL); 1.324 + break; 1.325 + } 1.326 + 1.327 + skip_whitespace(&str); 1.328 + 1.329 + /* Ignore extensions per RFC 5245 S 15.1 */ 1.330 +#if 0 1.331 + /* This used to be an assert, but we don't want to exit on invalid 1.332 + remote data */ 1.333 + if (strlen(str) != 0) { 1.334 + ABORT(R_BAD_DATA); 1.335 + } 1.336 +#endif 1.337 + 1.338 + nr_ice_candidate_compute_codeword(cand); 1.339 + 1.340 + *candp=cand; 1.341 + 1.342 + _status=0; 1.343 + abort: 1.344 + if (_status){ 1.345 + r_log(LOG_ICE,LOG_WARNING,"ICE(%s): Error parsing attribute: %s",ctx->label,orig); 1.346 + nr_ice_candidate_destroy(&cand); 1.347 + } 1.348 + 1.349 + RFREE(connection_address); 1.350 + RFREE(rel_addr); 1.351 + return(_status); 1.352 +} 1.353 + 1.354 + 1.355 +int 1.356 +nr_ice_peer_ctx_parse_media_stream_attribute(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, char *attr) 1.357 +{ 1.358 + int r,_status; 1.359 + char *orig = 0; 1.360 + char *str; 1.361 + 1.362 + orig = str = attr; 1.363 + 1.364 + if (!strncasecmp(str, "ice-ufrag:", 10)) { 1.365 + fast_forward(&str, 10); 1.366 + if (*str == '\0') 1.367 + ABORT(R_BAD_DATA); 1.368 + 1.369 + skip_whitespace(&str); 1.370 + if (*str == '\0') 1.371 + ABORT(R_BAD_DATA); 1.372 + 1.373 + if ((r=grab_token(&str, &stream->ufrag))) 1.374 + ABORT(r); 1.375 + } 1.376 + else if (!strncasecmp(str, "ice-pwd:", 8)) { 1.377 + fast_forward(&str, 8); 1.378 + if (*str == '\0') 1.379 + ABORT(R_BAD_DATA); 1.380 + 1.381 + skip_whitespace(&str); 1.382 + if (*str == '\0') 1.383 + ABORT(R_BAD_DATA); 1.384 + 1.385 + if ((r=grab_token(&str, &stream->pwd))) 1.386 + ABORT(r); 1.387 + } 1.388 + else { 1.389 + ABORT(R_BAD_DATA); 1.390 + } 1.391 + 1.392 + skip_whitespace(&str); 1.393 + 1.394 + /* RFC 5245 grammar doesn't have an extension point for ice-pwd or 1.395 + ice-ufrag: if there's anything left on the line, we treat it as bad. */ 1.396 + if (str[0] != '\0') { 1.397 + ABORT(R_BAD_DATA); 1.398 + } 1.399 + 1.400 + _status=0; 1.401 + abort: 1.402 + if (_status) { 1.403 + if (orig) 1.404 + r_log(LOG_ICE,LOG_WARNING,"ICE-PEER(%s): Error parsing attribute: %s",pctx->label,orig); 1.405 + } 1.406 + 1.407 + return(_status); 1.408 +} 1.409 + 1.410 +int 1.411 +nr_ice_peer_ctx_parse_global_attributes(nr_ice_peer_ctx *pctx, char **attrs, int attr_ct) 1.412 +{ 1.413 + int r,_status; 1.414 + int i; 1.415 + char *orig = 0; 1.416 + char *str; 1.417 + char *component_id = 0; 1.418 + char *connection_address = 0; 1.419 + unsigned int port; 1.420 + in_addr_t addr; 1.421 + char *ice_option_tag = 0; 1.422 + 1.423 + for(i=0;i<attr_ct;i++){ 1.424 + orig = str = attrs[i]; 1.425 + 1.426 + component_id = 0; 1.427 + connection_address = 0; 1.428 + ice_option_tag = 0; 1.429 + 1.430 + if (!strncasecmp(str, "remote-candidates:", 18)) { 1.431 + fast_forward(&str, 18); 1.432 + skip_whitespace(&str); 1.433 + 1.434 + while (*str != '\0') { 1.435 + if ((r=grab_token(&str, &component_id))) 1.436 + ABORT(r); 1.437 + 1.438 + if (*str == '\0') 1.439 + ABORT(R_BAD_DATA); 1.440 + 1.441 + skip_whitespace(&str); 1.442 + if (*str == '\0') 1.443 + ABORT(R_BAD_DATA); 1.444 + 1.445 + if ((r=grab_token(&str, &connection_address))) 1.446 + ABORT(r); 1.447 + 1.448 + if (*str == '\0') 1.449 + ABORT(R_BAD_DATA); 1.450 + 1.451 + addr = inet_addr(connection_address); 1.452 + if (addr == INADDR_NONE) 1.453 + ABORT(R_BAD_DATA); 1.454 + 1.455 + skip_whitespace(&str); 1.456 + if (*str == '\0') 1.457 + ABORT(R_BAD_DATA); 1.458 + 1.459 + if (sscanf(str, "%u", &port) != 1) 1.460 + ABORT(R_BAD_DATA); 1.461 + 1.462 + if (port < 1 || port > 0x0FFFF) 1.463 + ABORT(R_BAD_DATA); 1.464 + 1.465 + skip_to_past_space(&str); 1.466 + 1.467 +#if 0 1.468 + /* TODO: !nn! just drop on the floor for now, later put somewhere */ 1.469 + /* Assume v4 for now */ 1.470 + if(r=nr_ip4_port_to_transport_addr(ntohl(addr),port,IPPROTO_UDP,&candidate->base)) 1.471 + ABORT(r); 1.472 + 1.473 + TAILQ_INSERT_TAIL(head, elm, field); 1.474 +#endif 1.475 + 1.476 + component_id = 0; /* prevent free */ 1.477 + RFREE(connection_address); 1.478 + connection_address = 0; /* prevent free */ 1.479 + } 1.480 + } 1.481 + else if (!strncasecmp(str, "ice-lite", 8)) { 1.482 + pctx->peer_lite = 1; 1.483 + 1.484 + fast_forward(&str, 8); 1.485 + } 1.486 + else if (!strncasecmp(str, "ice-mismatch", 12)) { 1.487 + pctx->peer_ice_mismatch = 1; 1.488 + 1.489 + fast_forward(&str, 12); 1.490 + } 1.491 + else if (!strncasecmp(str, "ice-ufrag:", 10)) { 1.492 + fast_forward(&str, 10); 1.493 + if (*str == '\0') 1.494 + ABORT(R_BAD_DATA); 1.495 + 1.496 + skip_whitespace(&str); 1.497 + if (*str == '\0') 1.498 + ABORT(R_BAD_DATA); 1.499 + 1.500 + RFREE(pctx->peer_ufrag); 1.501 + pctx->peer_ufrag = 0; 1.502 + if ((r=grab_token(&str, &pctx->peer_ufrag))) 1.503 + ABORT(r); 1.504 + } 1.505 + else if (!strncasecmp(str, "ice-pwd:", 8)) { 1.506 + fast_forward(&str, 8); 1.507 + if (*str == '\0') 1.508 + ABORT(R_BAD_DATA); 1.509 + 1.510 + skip_whitespace(&str); 1.511 + if (*str == '\0') 1.512 + ABORT(R_BAD_DATA); 1.513 + 1.514 + RFREE(pctx->peer_pwd); 1.515 + pctx->peer_pwd = 0; 1.516 + if ((r=grab_token(&str, &pctx->peer_pwd))) 1.517 + ABORT(r); 1.518 + } 1.519 + else if (!strncasecmp(str, "ice-options:", 12)) { 1.520 + fast_forward(&str, 12); 1.521 + skip_whitespace(&str); 1.522 + 1.523 + while (*str != '\0') { 1.524 + if ((r=grab_token(&str, &ice_option_tag))) 1.525 + ABORT(r); 1.526 + 1.527 + skip_whitespace(&str); 1.528 + 1.529 + //TODO: for now, just throw away; later put somewhere 1.530 + RFREE(ice_option_tag); 1.531 + 1.532 + ice_option_tag = 0; /* prevent free */ 1.533 + } 1.534 + } 1.535 + else { 1.536 + ABORT(R_BAD_DATA); 1.537 + } 1.538 + 1.539 + skip_whitespace(&str); 1.540 + 1.541 + /* RFC 5245 grammar doesn't have an extension point for any of the 1.542 + preceding attributes: if there's anything left on the line, we 1.543 + treat it as bad data. */ 1.544 + if (str[0] != '\0') { 1.545 + ABORT(R_BAD_DATA); 1.546 + } 1.547 + } 1.548 + 1.549 + _status=0; 1.550 + abort: 1.551 + if (_status) { 1.552 + if (orig) 1.553 + r_log(LOG_ICE,LOG_WARNING,"ICE-PEER(%s): Error parsing attribute: %s",pctx->label,orig); 1.554 + } 1.555 + 1.556 + RFREE(connection_address); 1.557 + RFREE(component_id); 1.558 + RFREE(ice_option_tag); 1.559 + return(_status); 1.560 +} 1.561 +