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

changeset 0
6474c204b198
     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 +

mercurial