1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/mtransport/third_party/nICEr/src/ice/ice_socket.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,362 @@ 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_socket.c,v 1.2 2008/04/28 17:59:01 ekr Exp $"; 1.39 + 1.40 +#include <assert.h> 1.41 +#include <string.h> 1.42 +#include "nr_api.h" 1.43 +#include "ice_ctx.h" 1.44 +#include "stun.h" 1.45 + 1.46 +static void nr_ice_socket_readable_cb(NR_SOCKET s, int how, void *cb_arg) 1.47 + { 1.48 + int r; 1.49 + nr_ice_stun_ctx *sc1,*sc2; 1.50 + nr_ice_socket *sock=cb_arg; 1.51 + UCHAR buf[8192]; 1.52 + char string[256]; 1.53 + nr_transport_addr addr; 1.54 + int len; 1.55 + size_t len_s; 1.56 + int is_stun; 1.57 + int is_req; 1.58 + int is_ind; 1.59 + int processed_indication=0; 1.60 + 1.61 + nr_socket *stun_srv_sock=sock->sock; 1.62 + 1.63 + r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): Socket ready to read",sock->ctx->label); 1.64 + 1.65 + /* Re-arm first! */ 1.66 + NR_ASYNC_WAIT(s,how,nr_ice_socket_readable_cb,cb_arg); 1.67 + 1.68 + if(r=nr_socket_recvfrom(sock->sock,buf,sizeof(buf),&len_s,0,&addr)){ 1.69 + if (r != R_WOULDBLOCK && (sock->type != NR_ICE_SOCKET_TYPE_DGRAM)) { 1.70 + /* Report this error upward. Bug 946423 */ 1.71 + r_log(LOG_ICE,LOG_ERR,"ICE(%s): Error on reliable socket. Abandoning.",sock->ctx->label); 1.72 + NR_ASYNC_CANCEL(s, NR_ASYNC_WAIT_READ); 1.73 + } 1.74 + return; 1.75 + } 1.76 + 1.77 + /* Deal with the fact that sizeof(int) and sizeof(size_t) may not 1.78 + be the same */ 1.79 + if (len_s > (size_t)INT_MAX) 1.80 + return; 1.81 + 1.82 + len = (int)len_s; 1.83 + 1.84 +#ifdef USE_TURN 1.85 + re_process: 1.86 +#endif /* USE_TURN */ 1.87 + r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): Read %d bytes %sfrom %s",sock->ctx->label,len,(processed_indication ? "relayed " : ""),addr.as_string); 1.88 + 1.89 + /* First question: is this STUN or not? */ 1.90 + is_stun=nr_is_stun_message(buf,len); 1.91 + 1.92 + if(is_stun){ 1.93 + is_req=nr_is_stun_request_message(buf,len); 1.94 + is_ind=is_req?0:nr_is_stun_indication_message(buf,len); 1.95 + 1.96 + snprintf(string, sizeof(string)-1, "ICE(%s): Message is STUN (%s)",sock->ctx->label, 1.97 + is_req ? "request" : (is_ind ? "indication" : "other")); 1.98 + r_dump(NR_LOG_STUN, LOG_DEBUG, string, (char*)buf, len); 1.99 + 1.100 + 1.101 + /* We need to offer it to all of our stun contexts 1.102 + to see who bites */ 1.103 + sc1=TAILQ_FIRST(&sock->stun_ctxs); 1.104 + while(sc1){ 1.105 + sc2=TAILQ_NEXT(sc1,entry); 1.106 + 1.107 + r=-1; 1.108 + switch(sc1->type){ 1.109 + /* This has been deleted, prune... */ 1.110 + case NR_ICE_STUN_NONE: 1.111 + TAILQ_REMOVE(&sock->stun_ctxs,sc1,entry); 1.112 + RFREE(sc1); 1.113 + break; 1.114 + 1.115 + case NR_ICE_STUN_CLIENT: 1.116 + if(!(is_req||is_ind)){ 1.117 + r=nr_stun_client_process_response(sc1->u.client,buf,len,&addr); 1.118 + } 1.119 + break; 1.120 + 1.121 + case NR_ICE_STUN_SERVER: 1.122 + if(is_req){ 1.123 + r=nr_stun_server_process_request(sc1->u.server,stun_srv_sock,(char *)buf,len,&addr,NR_STUN_AUTH_RULE_SHORT_TERM); 1.124 + } 1.125 + break; 1.126 +#ifdef USE_TURN 1.127 + case NR_ICE_TURN_CLIENT: 1.128 + /* data indications are ok, so don't ignore those */ 1.129 + /* Check that this is from the right TURN server address. Else 1.130 + skip */ 1.131 + if (nr_transport_addr_cmp( 1.132 + &sc1->u.turn_client.turn_client->turn_server_addr, 1.133 + &addr, NR_TRANSPORT_ADDR_CMP_MODE_ALL)) 1.134 + break; 1.135 + 1.136 + if(!is_req){ 1.137 + if(!is_ind) 1.138 + r=nr_turn_client_process_response(sc1->u.turn_client.turn_client,buf,len,&addr); 1.139 + else{ 1.140 + nr_transport_addr n_addr; 1.141 + size_t n_len; 1.142 + 1.143 + if (processed_indication) { 1.144 + /* Don't allow recursively wrapped indications */ 1.145 + r_log(LOG_ICE, LOG_WARNING, 1.146 + "ICE(%s): discarding recursively wrapped indication", 1.147 + sock->ctx->label); 1.148 + break; 1.149 + } 1.150 + /* This is a bit of a hack. If it's a data indication, strip 1.151 + off the TURN framing and re-enter. This works because 1.152 + all STUN processing is on the same physical socket. 1.153 + We don't care about other kinds of indication */ 1.154 + r=nr_turn_client_parse_data_indication( 1.155 + sc1->u.turn_client.turn_client, &addr, 1.156 + buf, len, buf, &n_len, len, &n_addr); 1.157 + if(!r){ 1.158 + r_log(LOG_ICE,LOG_DEBUG,"Unwrapped a data indication."); 1.159 + len=n_len; 1.160 + nr_transport_addr_copy(&addr,&n_addr); 1.161 + stun_srv_sock=sc1->u.turn_client.turn_sock; 1.162 + processed_indication=1; 1.163 + goto re_process; 1.164 + } 1.165 + } 1.166 + } 1.167 + break; 1.168 +#endif /* USE_TURN */ 1.169 + 1.170 + default: 1.171 + assert(0); /* Can't happen */ 1.172 + return; 1.173 + } 1.174 + if(!r) { 1.175 + break; 1.176 + } 1.177 + 1.178 + sc1=sc2; 1.179 + } 1.180 + if(!sc1){ 1.181 + if (nr_ice_ctx_is_known_id(sock->ctx,((nr_stun_message_header*)buf)->id.octet)) 1.182 + r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): Message is a retransmit",sock->ctx->label); 1.183 + else 1.184 + r_log(LOG_ICE,LOG_NOTICE,"ICE(%s): Message does not correspond to any registered stun ctx",sock->ctx->label); 1.185 + } 1.186 + } 1.187 + else{ 1.188 + r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): Message is not STUN",sock->ctx->label); 1.189 + 1.190 + nr_ice_ctx_deliver_packet(sock->ctx, sock->component, &addr, buf, len); 1.191 + } 1.192 + 1.193 + return; 1.194 + } 1.195 + 1.196 +int nr_ice_socket_create(nr_ice_ctx *ctx,nr_ice_component *comp, nr_socket *nsock, nr_ice_socket **sockp) 1.197 + { 1.198 + nr_ice_socket *sock=0; 1.199 + NR_SOCKET fd; 1.200 + nr_transport_addr addr; 1.201 + int r,_status; 1.202 + 1.203 + if(!(sock=RCALLOC(sizeof(nr_ice_socket)))) 1.204 + ABORT(R_NO_MEMORY); 1.205 + 1.206 + sock->sock=nsock; 1.207 + sock->ctx=ctx; 1.208 + sock->component=comp; 1.209 + 1.210 + if(r=nr_socket_getaddr(nsock, &addr)) 1.211 + ABORT(r); 1.212 + 1.213 + if (addr.protocol == IPPROTO_UDP) { 1.214 + sock->type = NR_ICE_SOCKET_TYPE_DGRAM; 1.215 + } 1.216 + else { 1.217 + assert(addr.protocol == IPPROTO_TCP); 1.218 + sock->type = NR_ICE_SOCKET_TYPE_STREAM; 1.219 + } 1.220 + 1.221 + TAILQ_INIT(&sock->candidates); 1.222 + TAILQ_INIT(&sock->stun_ctxs); 1.223 + 1.224 + if(r=nr_socket_getfd(nsock,&fd)) 1.225 + ABORT(r); 1.226 + 1.227 + NR_ASYNC_WAIT(fd,NR_ASYNC_WAIT_READ,nr_ice_socket_readable_cb,sock); 1.228 + 1.229 + *sockp=sock; 1.230 + 1.231 + _status=0; 1.232 + abort: 1.233 + if(_status) RFREE(sock); 1.234 + return(_status); 1.235 + } 1.236 + 1.237 + 1.238 +int nr_ice_socket_destroy(nr_ice_socket **isockp) 1.239 + { 1.240 + nr_ice_stun_ctx *s1,*s2; 1.241 + nr_ice_socket *isock; 1.242 + 1.243 + if(!isockp || !*isockp) 1.244 + return(0); 1.245 + 1.246 + isock=*isockp; 1.247 + *isockp=0; 1.248 + 1.249 + /* Close the socket */ 1.250 + nr_ice_socket_close(isock); 1.251 + 1.252 + /* The STUN server */ 1.253 + nr_stun_server_ctx_destroy(&isock->stun_server); 1.254 + 1.255 + /* Now clean up the STUN ctxs */ 1.256 + TAILQ_FOREACH_SAFE(s1, &isock->stun_ctxs, entry, s2){ 1.257 + TAILQ_REMOVE(&isock->stun_ctxs, s1, entry); 1.258 + RFREE(s1); 1.259 + } 1.260 + 1.261 + RFREE(isock); 1.262 + 1.263 + return(0); 1.264 + } 1.265 + 1.266 +int nr_ice_socket_close(nr_ice_socket *isock) 1.267 + { 1.268 +#ifdef NR_SOCKET_IS_VOID_PTR 1.269 + NR_SOCKET fd=NULL; 1.270 + NR_SOCKET no_socket = NULL; 1.271 +#else 1.272 + NR_SOCKET fd=-1; 1.273 + NR_SOCKET no_socket = -1; 1.274 +#endif 1.275 + 1.276 + if (!isock||!isock->sock) 1.277 + return(0); 1.278 + 1.279 + nr_socket_getfd(isock->sock,&fd); 1.280 + assert(isock->sock!=0); 1.281 + if(fd != no_socket){ 1.282 + NR_ASYNC_CANCEL(fd,NR_ASYNC_WAIT_READ); 1.283 + NR_ASYNC_CANCEL(fd,NR_ASYNC_WAIT_WRITE); 1.284 + nr_socket_destroy(&isock->sock); 1.285 + } 1.286 + 1.287 + return(0); 1.288 + } 1.289 + 1.290 +int nr_ice_socket_register_stun_client(nr_ice_socket *sock, nr_stun_client_ctx *srv,void **handle) 1.291 + { 1.292 + nr_ice_stun_ctx *sc=0; 1.293 + int _status; 1.294 + 1.295 + if(!(sc=RCALLOC(sizeof(nr_ice_stun_ctx)))) 1.296 + ABORT(R_NO_MEMORY); 1.297 + 1.298 + sc->type=NR_ICE_STUN_CLIENT; 1.299 + sc->u.client=srv; 1.300 + 1.301 + TAILQ_INSERT_TAIL(&sock->stun_ctxs,sc,entry); 1.302 + 1.303 + *handle=sc; 1.304 + 1.305 + _status=0; 1.306 + abort: 1.307 + return(_status); 1.308 + } 1.309 + 1.310 +int nr_ice_socket_register_stun_server(nr_ice_socket *sock, nr_stun_server_ctx *srv,void **handle) 1.311 + { 1.312 + nr_ice_stun_ctx *sc=0; 1.313 + int _status; 1.314 + 1.315 + if(!(sc=RCALLOC(sizeof(nr_ice_stun_ctx)))) 1.316 + ABORT(R_NO_MEMORY); 1.317 + 1.318 + sc->type=NR_ICE_STUN_SERVER; 1.319 + sc->u.server=srv; 1.320 + 1.321 + TAILQ_INSERT_TAIL(&sock->stun_ctxs,sc,entry); 1.322 + 1.323 + *handle=sc; 1.324 + 1.325 + _status=0; 1.326 + abort: 1.327 + return(_status); 1.328 + } 1.329 + 1.330 +int nr_ice_socket_register_turn_client(nr_ice_socket *sock, nr_turn_client_ctx *srv, 1.331 + nr_socket *turn_socket, void **handle) 1.332 + { 1.333 + nr_ice_stun_ctx *sc=0; 1.334 + int _status; 1.335 + 1.336 + if(!(sc=RCALLOC(sizeof(nr_ice_stun_ctx)))) 1.337 + ABORT(R_NO_MEMORY); 1.338 + 1.339 + sc->type=NR_ICE_TURN_CLIENT; 1.340 + sc->u.turn_client.turn_client=srv; 1.341 + sc->u.turn_client.turn_sock=turn_socket; 1.342 + 1.343 + TAILQ_INSERT_TAIL(&sock->stun_ctxs,sc,entry); 1.344 + 1.345 + *handle=sc; 1.346 + 1.347 + _status=0; 1.348 + abort: 1.349 + return(_status); 1.350 + } 1.351 + 1.352 +/* Just mark it deregistered. Don't delete it now because it's not safe 1.353 + in the CB, which is where this is likely to be called */ 1.354 +int nr_ice_socket_deregister(nr_ice_socket *sock, void *handle) 1.355 + { 1.356 + nr_ice_stun_ctx *sc=handle; 1.357 + 1.358 + if(!sc) 1.359 + return(0); 1.360 + 1.361 + sc->type=NR_ICE_STUN_NONE; 1.362 + 1.363 + return(0); 1.364 + } 1.365 +