media/mtransport/third_party/nICEr/upstream.diff

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_candidate.c src/ice/ice_candidate.c
     2 --- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_candidate.c	2012-09-16 16:26:08.000000000 -0700
     3 +++ src/ice/ice_candidate.c	2012-10-06 08:30:22.000000000 -0700
     4 @@ -54,36 +54,38 @@
     6  #include "stun_client_ctx.h"
     7  #include "stun_server_ctx.h"
     8  #include "turn_client_ctx.h"
     9  #include "ice_ctx.h"
    10  #include "ice_candidate.h"
    11  #include "ice_reg.h"
    12  #include "ice_util.h"
    13  #include "nr_socket_turn.h"
    15 +static int next_automatic_preference = 224;
    16 +
    17  static int nr_ice_get_foundation(nr_ice_ctx *ctx,nr_ice_candidate *cand);
    18  static int nr_ice_srvrflx_start_stun(nr_ice_candidate *cand, NR_async_cb ready_cb, void *cb_arg);
    19 -static void nr_ice_srvrflx_stun_finished_cb(int sock, int how, void *cb_arg);
    20 +static void nr_ice_srvrflx_stun_finished_cb(NR_SOCKET sock, int how, void *cb_arg);
    21  #ifdef USE_TURN
    22  static int nr_ice_start_relay_turn(nr_ice_candidate *cand, NR_async_cb ready_cb, void *cb_arg);
    23 -static void nr_ice_turn_allocated_cb(int sock, int how, void *cb_arg);
    24 +static void nr_ice_turn_allocated_cb(NR_SOCKET sock, int how, void *cb_arg);
    25  #endif /* USE_TURN */
    27  char *nr_ice_candidate_type_names[]={0,"host","srflx","prflx","relay",0};
    29  int nr_ice_candidate_create(nr_ice_ctx *ctx,char *label,nr_ice_component *comp,nr_ice_socket *isock, nr_socket *osock, nr_ice_candidate_type ctype, nr_ice_stun_server *stun_server, UCHAR component_id, nr_ice_candidate **candp)
    30    {
    31      nr_ice_candidate *cand=0;
    32      nr_ice_candidate *tmp=0;
    33      int r,_status;
    34 - 
    35 +
    36      if(!(cand=RCALLOC(sizeof(nr_ice_candidate))))
    37        ABORT(R_NO_MEMORY);
    38      if(!(cand->label=r_strdup(label)))
    39        ABORT(R_NO_MEMORY);
    40      cand->state=NR_ICE_CAND_STATE_CREATED;
    41      cand->ctx=ctx;
    42      cand->isock=isock;
    43      cand->osock=osock;
    44      cand->type=ctype;
    45      cand->stun_server=stun_server;
    46 @@ -189,21 +191,21 @@
    47      if(cand->delay_timer)
    48        NR_async_timer_cancel(cand->delay_timer);
    50      RFREE(cand->foundation);
    51      RFREE(cand->label);
    52      RFREE(cand);
    54      return(0);
    55    }
    57 -void nr_ice_candidate_destroy_cb(int s, int h, void *cb_arg)
    58 +void nr_ice_candidate_destroy_cb(NR_SOCKET s, int h, void *cb_arg)
    59    {
    60      nr_ice_candidate *cand=cb_arg;
    61      nr_ice_candidate_destroy(&cand);
    62    }
    64  /* This algorithm is not super-fast, but I don't think we need a hash
    65     table just yet and it produces a small foundation string */
    66  static int nr_ice_get_foundation(nr_ice_ctx *ctx,nr_ice_candidate *cand)
    67    {
    68      nr_ice_foundation *foundation;
    69 @@ -276,22 +278,38 @@
    70          break;
    71        default:
    72          ABORT(R_INTERNAL);
    73      }
    75      if(type_preference > 126)
    76        r_log(LOG_ICE,LOG_ERR,"Illegal type preference %d",type_preference);
    79      if(r=NR_reg_get2_uchar(NR_ICE_REG_PREF_INTERFACE_PRFX,cand->base.ifname,
    80 -      &interface_preference))
    81 -      ABORT(r);
    82 +      &interface_preference)) {
    83 +      if (r==R_NOT_FOUND) {
    84 +        if (next_automatic_preference == 1) {
    85 +          r_log(LOG_ICE,LOG_DEBUG,"Out of preference values. Can't assign one for interface %s",cand->base.ifname);
    86 +          ABORT(R_NOT_FOUND);
    87 +        }
    88 +        r_log(LOG_ICE,LOG_DEBUG,"Automatically assigning preference for interface %s->%d",cand->base.ifname,
    89 +          next_automatic_preference);
    90 +        if (r=NR_reg_set2_uchar(NR_ICE_REG_PREF_INTERFACE_PRFX,cand->base.ifname,next_automatic_preference)){
    91 +          ABORT(r);
    92 +        }
    93 +        interface_preference=next_automatic_preference;
    94 +        next_automatic_preference--;
    95 +      }
    96 +      else {
    97 +        ABORT(r);
    98 +      }
    99 +    }
   101      cand->priority=
   102        (type_preference << 24) |
   103        (interface_preference << 16) |
   104        (stun_priority << 8) |
   105        (256 - cand->component_id);
   107      /* S 4.1.2 */    
   108      assert(cand->priority>=1&&cand->priority<=2147483647);
   110 @@ -306,21 +324,22 @@
   112      cand->done_cb=ready_cb;
   113      cand->cb_arg=cb_arg;
   115      switch(cand->type){
   116        case HOST:
   117          if(r=nr_socket_getaddr(cand->isock->sock,&cand->addr))
   118            ABORT(r);
   119          cand->osock=cand->isock->sock;
   120          cand->state=NR_ICE_CAND_STATE_INITIALIZED;
   121 -        ready_cb(0,0,cb_arg);
   122 +        // Post this so that it doesn't happen in-line
   123 +        NR_ASYNC_SCHEDULE(ready_cb,cb_arg);
   124          break;
   125  #ifdef USE_TURN
   126        case RELAYED:
   127          if(r=nr_ice_start_relay_turn(cand,ready_cb,cb_arg))
   128            ABORT(r);
   129          ABORT(R_WOULDBLOCK);
   130          break;
   131  #endif /* USE_TURN */
   132        case SERVER_REFLEXIVE:
   133          /* Need to start stun */
   134 @@ -333,21 +352,21 @@
   135          ABORT(R_INTERNAL);
   136      }
   138      _status=0;
   139    abort:
   140      if(_status && _status!=R_WOULDBLOCK)
   141        cand->state=NR_ICE_CAND_STATE_FAILED;
   142      return(_status);
   143    }
   145 -static void nr_ice_srvrflx_start_stun_timer_cb(int s, int how, void *cb_arg)
   146 +static void nr_ice_srvrflx_start_stun_timer_cb(NR_SOCKET s, int how, void *cb_arg)
   147    {
   148      nr_ice_candidate *cand=cb_arg;
   149      int r,_status;
   151      cand->delay_timer=0;
   153  /* TODO: if the response is a BINDING-ERROR-RESPONSE, then restart
   154   * TODO: using NR_STUN_CLIENT_MODE_BINDING_REQUEST because the
   155   * TODO: server may not have understood the 0.96-style request */
   156      if(r=nr_stun_client_start(cand->u.srvrflx.stun, NR_STUN_CLIENT_MODE_BINDING_REQUEST_STUND_0_96, nr_ice_srvrflx_stun_finished_cb, cand))
   157 @@ -387,21 +406,21 @@
   159      _status=0;
   160    abort:
   161      if(_status){
   162        cand->state=NR_ICE_CAND_STATE_FAILED;
   163      }
   164      return(_status);
   165    }
   167  #ifdef USE_TURN
   168 -static void nr_ice_start_relay_turn_timer_cb(int s, int how, void *cb_arg)
   169 +static void nr_ice_start_relay_turn_timer_cb(NR_SOCKET s, int how, void *cb_arg)
   170    {
   171      nr_ice_candidate *cand=cb_arg;
   172      int r,_status;
   173      int i;
   175      cand->delay_timer=0;
   177      if(r=nr_turn_client_allocate(cand->u.relayed.turn, cand->u.relayed.server->username, cand->u.relayed.server->password, cand->u.relayed.server->bandwidth_kbps, cand->u.relayed.server->lifetime_secs, nr_ice_turn_allocated_cb, cand))
   178        ABORT(r);
   180 @@ -443,21 +462,21 @@
   182      _status=0;
   183    abort:
   184      if(_status){
   185        cand->state=NR_ICE_CAND_STATE_FAILED;
   186      }
   187      return(_status);
   188    }
   189  #endif /* USE_TURN */
   191 -static void nr_ice_srvrflx_stun_finished_cb(int sock, int how, void *cb_arg)
   192 +static void nr_ice_srvrflx_stun_finished_cb(NR_SOCKET sock, int how, void *cb_arg)
   193    {
   194      int _status;
   195      nr_ice_candidate *cand=cb_arg;
   197      /* Deregister to suppress duplicates */
   198      if(cand->u.srvrflx.stun_handle){ /* This test because we might have failed before CB registered */
   199        nr_ice_socket_deregister(cand->isock,cand->u.srvrflx.stun_handle);
   200        cand->u.srvrflx.stun_handle=0;
   201      }
   203 @@ -481,40 +500,40 @@
   204      }
   205      _status = 0;
   206    abort:
   207      if(_status){
   208        cand->state=NR_ICE_CAND_STATE_FAILED;
   209        cand->done_cb(0,0,cand->cb_arg);
   210      }
   211    }
   213  #ifdef USE_TURN
   214 -static void nr_ice_turn_allocated_cb(int s, int how, void *cb_arg)
   215 +static void nr_ice_turn_allocated_cb(NR_SOCKET s, int how, void *cb_arg)
   216    {
   217      int r,_status;
   218      nr_ice_candidate *cand=cb_arg;
   219      nr_turn_client_ctx *turn=cand->u.relayed.turn;
   220      int i;
   221      char *label;
   223      /* Deregister to suppress duplicates */
   224      if(cand->u.relayed.turn_handle){ /* This test because we might have failed before CB registered */
   225        nr_ice_socket_deregister(cand->isock,cand->u.relayed.turn_handle);
   226        cand->u.relayed.turn_handle=0;
   227      }
   229      switch(turn->state){
   230      /* OK, we should have a mapped address */
   231      case NR_TURN_CLIENT_STATE_ALLOCATED:
   232          /* switch candidate from TURN mode to STUN mode */
   234 -        if(r=nr_concat_strings(&label,"turn-relay(",cand->base.as_string,"|",turn->relay_addr.as_string,")",0))
   235 +        if(r=nr_concat_strings(&label,"turn-relay(",cand->base.as_string,"|",turn->relay_addr.as_string,")",NULL))
   236            ABORT(r);
   238          r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): Switching from TURN (%s) to RELAY (%s)",cand->u.relayed.turn->label,cand->label,label);
   240          /* Copy out mapped address and relay address */
   241          nr_transport_addr_copy(&turn->relay_addr, &cand->u.relayed.turn->stun_ctx[NR_TURN_CLIENT_PHASE_ALLOCATE_REQUEST2]->results.allocate_response2.relay_addr);
   242          nr_transport_addr_copy(&cand->addr, &turn->relay_addr);
   244          r_log(LOG_ICE,LOG_DEBUG,"ICE-CANDIDATE(%s): base=%s, candidate=%s", cand->label, cand->base.as_string, cand->addr.as_string);
   246 diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_candidate.h src/ice/ice_candidate.h
   247 --- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_candidate.h	2012-09-16 16:26:08.000000000 -0700
   248 +++ src/ice/ice_candidate.h	2012-10-06 08:30:22.000000000 -0700
   249 @@ -41,21 +41,22 @@
   251  typedef enum {HOST=1, SERVER_REFLEXIVE, PEER_REFLEXIVE, RELAYED} nr_ice_candidate_type;
   253  struct nr_ice_candidate_ {
   254    char *label;
   255    int state;
   256  #define NR_ICE_CAND_STATE_CREATED          1
   257  #define NR_ICE_CAND_STATE_INITIALIZING     2
   258  #define NR_ICE_CAND_STATE_INITIALIZED      3
   259  #define NR_ICE_CAND_STATE_FAILED           4
   260 -#define NR_ICE_CAND_PEER_CANDIDATE         10
   261 +#define NR_ICE_CAND_PEER_CANDIDATE_UNPAIRED 9
   262 +#define NR_ICE_CAND_PEER_CANDIDATE_PAIRED   10
   263    struct nr_ice_ctx_ *ctx;
   264    nr_ice_socket *isock;               /* The socket to read from
   265                                           (it contains all other candidates
   266                                           on this socket) */
   267    nr_socket *osock;                   /* The socket to write to */
   268    nr_ice_media_stream *stream;        /* The media stream this is associated with */
   269    nr_ice_component *component;        /* The component this is associated with */
   270    nr_ice_candidate_type type;         /* The type of the candidate (S 4.1.1) */
   271    UCHAR component_id;                 /* The component id (S 4.1.2.1) */
   272    nr_transport_addr addr;             /* The advertised address;
   273 @@ -89,21 +90,21 @@
   274    TAILQ_ENTRY(nr_ice_candidate_) entry_comp;
   275  };
   277  extern char *nr_ice_candidate_type_names[];
   280  int nr_ice_candidate_create(struct nr_ice_ctx_ *ctx,char *label, nr_ice_component *component, nr_ice_socket *isock, nr_socket *osock, nr_ice_candidate_type ctype, nr_ice_stun_server *stun_server, UCHAR component_id, nr_ice_candidate **candp);
   281  int nr_ice_candidate_initialize(nr_ice_candidate *cand, NR_async_cb ready_cb, void *cb_arg);
   282  int nr_ice_candidate_process_stun(nr_ice_candidate *cand, UCHAR *msg, int len, nr_transport_addr *faddr);
   283  int nr_ice_candidate_destroy(nr_ice_candidate **candp);
   284 -void nr_ice_candidate_destroy_cb(int s, int h, void *cb_arg);
   285 +void nr_ice_candidate_destroy_cb(NR_SOCKET s, int h, void *cb_arg);
   286  int nr_ice_format_candidate_attribute(nr_ice_candidate *cand, char *attr, int maxlen);
   287  int nr_ice_peer_candidate_from_attribute(nr_ice_ctx *ctx,char *attr,nr_ice_media_stream *stream,nr_ice_candidate **candp);
   288  int nr_ice_peer_peer_rflx_candidate_create(nr_ice_ctx *ctx,char *label, nr_ice_component *comp,nr_transport_addr *addr, nr_ice_candidate **candp);
   289  int nr_ice_candidate_compute_priority(nr_ice_candidate *cand);
   291  #ifdef __cplusplus
   292  }
   293  #endif /* __cplusplus */
   294  #endif
   296 diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_candidate_pair.c src/ice/ice_candidate_pair.c
   297 --- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_candidate_pair.c	2012-09-16 16:26:08.000000000 -0700
   298 +++ src/ice/ice_candidate_pair.c	2012-10-06 08:30:22.000000000 -0700
   299 @@ -37,21 +37,21 @@
   300  #include <assert.h>
   301  #include <string.h>
   302  #include <nr_api.h>
   303  #include "ice_ctx.h"
   304  #include "ice_util.h"
   305  #include "ice_codeword.h"
   306  #include "stun.h"
   308  static char *nr_ice_cand_pair_states[]={"UNKNOWN","FROZEN","WAITING","IN_PROGRESS","FAILED","SUCCEEDED","CANCELLED"};
   310 -static void nr_ice_candidate_pair_restart_stun_controlled_cb(int s, int how, void *cb_arg);
   311 +static void nr_ice_candidate_pair_restart_stun_controlled_cb(NR_SOCKET s, int how, void *cb_arg);
   312  static void nr_ice_candidate_pair_compute_codeword(nr_ice_cand_pair *pair,
   313    nr_ice_candidate *lcand, nr_ice_candidate *rcand);
   315  int nr_ice_candidate_pair_create(nr_ice_peer_ctx *pctx, nr_ice_candidate *lcand,nr_ice_candidate *rcand,nr_ice_cand_pair **pairp)
   316    {
   317      nr_ice_cand_pair *pair=0;
   318      UINT8 o_priority, a_priority;
   319      char *lufrag,*rufrag;
   320      char *lpwd,*rpwd;
   321      char *l2ruser=0,*r2lpass=0;
   322 @@ -61,21 +61,21 @@
   323      UINT8 t_priority;
   325      if(!(pair=RCALLOC(sizeof(nr_ice_cand_pair))))
   326        ABORT(R_NO_MEMORY);
   328      pair->pctx=pctx;
   330      nr_ice_candidate_pair_compute_codeword(pair,lcand,rcand);
   332      if(r=nr_concat_strings(&pair->as_string,pair->codeword,"|",lcand->addr.as_string,"|",
   333 -         rcand->addr.as_string,"(",lcand->label,"|",rcand->label,")",0))
   334 +        rcand->addr.as_string,"(",lcand->label,"|",rcand->label,")", NULL))
   335        ABORT(r);
   337      nr_ice_candidate_pair_set_state(pctx,pair,NR_ICE_PAIR_STATE_FROZEN);
   338      pair->local=lcand;
   339      pair->remote=rcand;
   341      /* Priority computation S 5.7.2 */
   342      if(pctx->ctx->flags & NR_ICE_CTX_FLAGS_OFFERER)
   343      {
   344        assert(!(pctx->ctx->flags & NR_ICE_CTX_FLAGS_ANSWERER));
   345 @@ -87,21 +87,21 @@
   346        o_priority=rcand->priority;
   347        a_priority=lcand->priority;
   348      }
   349      pair->priority=(MIN(o_priority, a_priority))<<32 | 
   350        (MAX(o_priority, a_priority))<<1 | (o_priority > a_priority?0:1);
   352      r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): Pairing candidate %s (%x):%s (%x) priority=%llu (%llx) codeword=%s",pctx->ctx->label,lcand->addr.as_string,lcand->priority,rcand->addr.as_string,rcand->priority,pair->priority,pair->priority,pair->codeword);
   354      /* Foundation */
   355      if(r=nr_concat_strings(&pair->foundation,lcand->foundation,"|",
   356 -      rcand->foundation,0))
   357 +      rcand->foundation,NULL))
   358        ABORT(r);
   361      /* OK, now the STUN data */
   362      lufrag=lcand->stream->ufrag?lcand->stream->ufrag:pctx->ctx->ufrag;
   363      lpwd=lcand->stream->pwd?lcand->stream->pwd:pctx->ctx->pwd;
   364      rufrag=rcand->stream->ufrag?rcand->stream->ufrag:pctx->peer_ufrag;
   365      rpwd=rcand->stream->pwd?rcand->stream->pwd:pctx->peer_pwd;
   368 @@ -110,39 +110,39 @@
   370      /* Make a bogus candidate to compute a theoretical peer reflexive
   371       * priority per S 7.1.1.1 */
   372      memcpy(&tmpcand, lcand, sizeof(tmpcand));
   373      tmpcand.type = PEER_REFLEXIVE;
   374      if (r=nr_ice_candidate_compute_priority(&tmpcand))
   375        ABORT(r);
   376      t_priority = tmpcand.priority;
   378      /* Our sending context */
   379 -    if(r=nr_concat_strings(&l2ruser,lufrag,":",rufrag,0))
   380 +    if(r=nr_concat_strings(&l2ruser,lufrag,":",rufrag,NULL))
   381        ABORT(r);
   382      if(r=nr_stun_client_ctx_create(pair->as_string,
   383        lcand->osock,
   384        &rcand->addr,RTO,&pair->stun_client))
   385        ABORT(r);
   386      if(!(pair->stun_client->params.ice_binding_request.username=r_strdup(l2ruser)))
   387        ABORT(R_NO_MEMORY);
   388      if(r=r_data_make(&pair->stun_client->params.ice_binding_request.password,(UCHAR *)lpwd,strlen(lpwd)))
   389        ABORT(r);
   390      pair->stun_client->params.ice_binding_request.priority=t_priority;
   391      pair->stun_client->params.ice_binding_request.control = pctx->controlling?
   392        NR_ICE_CONTROLLING:NR_ICE_CONTROLLED;
   394      pair->stun_client->params.ice_binding_request.tiebreaker=pctx->tiebreaker;
   396      /* Our receiving username/passwords. Stash these for later 
   397         injection into the stun server ctx*/
   398 -    if(r=nr_concat_strings(&pair->r2l_user,rufrag,":",lufrag,0))
   399 +    if(r=nr_concat_strings(&pair->r2l_user,rufrag,":",lufrag,NULL))
   400        ABORT(r);
   401      if(!(r2lpass=r_strdup(rpwd)))
   402        ABORT(R_NO_MEMORY);
   403      INIT_DATA(pair->r2l_pwd,(UCHAR *)r2lpass,strlen(r2lpass));
   405      *pairp=pair;
   407      _status=0;
   408    abort:
   409      RFREE(l2ruser);
   410 @@ -178,21 +178,21 @@
   412  int nr_ice_candidate_pair_unfreeze(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair)
   413    {
   414      assert(pair->state==NR_ICE_PAIR_STATE_FROZEN);
   416      nr_ice_candidate_pair_set_state(pctx,pair,NR_ICE_PAIR_STATE_WAITING);
   418      return(0);
   419    }
   421 -static void nr_ice_candidate_pair_stun_cb(int s, int how, void *cb_arg)
   422 +static void nr_ice_candidate_pair_stun_cb(NR_SOCKET s, int how, void *cb_arg)
   423    {
   424      int r,_status;
   425      nr_ice_cand_pair *pair=cb_arg,*orig_pair;
   426      nr_ice_candidate *cand=0;
   427      nr_stun_message *sres;
   428      nr_transport_addr *request_src;
   429      nr_transport_addr *request_dst;
   430      nr_transport_addr *response_src;
   431      nr_transport_addr response_dst;
   432      nr_stun_message_attribute *attr;
   433 @@ -457,32 +457,47 @@
   434    abort:
   435      return(_status);
   436   }
   438  int nr_ice_candidate_pair_set_state(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair, int state)
   439    {
   440      int r,_status;
   442      r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): setting pair %s to %s",
   443        pctx->label,pair->as_string,nr_ice_cand_pair_states[state]);
   444 -    pair->state=state;
   446 -    if(pctx->state!=NR_ICE_PAIR_STATE_WAITING){
   447 +    /* NOTE: This function used to reference pctx->state instead of
   448 +       pair->state and the assignment to pair->state was at the top
   449 +       of this function. Because pctx->state was never changed, this seems to have
   450 +       been a typo. The natural logic is "if the state changed
   451 +       decrement the counter" so this implies we should be checking
   452 +       the pair state rather than the pctx->state.
   453 +
   454 +       This didn't cause big problems because waiting_pairs was only
   455 +       used for pacing, so the pacing just was kind of broken.
   456 +       
   457 +       This note is here as a reminder until we do more testing
   458 +       and make sure that in fact this was a typo.
   459 +    */
   460 +    if(pair->state!=NR_ICE_PAIR_STATE_WAITING){
   461        if(state==NR_ICE_PAIR_STATE_WAITING)
   462          pctx->waiting_pairs++;
   463      }
   464      else{
   465        if(state!=NR_ICE_PAIR_STATE_WAITING)
   466          pctx->waiting_pairs--;
   468        assert(pctx->waiting_pairs>=0);
   469      }
   470 +    pair->state=state;
   471 +
   472 +
   473      if(pair->state==NR_ICE_PAIR_STATE_FAILED){
   474        if(r=nr_ice_component_failed_pair(pair->remote->component, pair))
   475          ABORT(r);
   476      }
   478      _status=0;
   479    abort:
   480      return(_status);
   481    }
   483 @@ -505,42 +520,42 @@
   484          break;
   485        }
   487        c1=TAILQ_NEXT(c1,entry);
   488      }
   489      if(!c1) TAILQ_INSERT_TAIL(head,pair,entry);
   491      return(0);
   492    }
   494 -void nr_ice_candidate_pair_restart_stun_nominated_cb(int s, int how, void *cb_arg)
   495 +void nr_ice_candidate_pair_restart_stun_nominated_cb(NR_SOCKET s, int how, void *cb_arg)
   496    {
   497      nr_ice_cand_pair *pair=cb_arg;
   498      int r,_status;
   500      r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/STREAM(%s):%d: Restarting pair %s as nominated",pair->pctx->label,pair->local->stream->label,pair->remote->component->component_id,pair->as_string);
   502      nr_stun_client_reset(pair->stun_client);
   503      pair->stun_client->params.ice_binding_request.control=NR_ICE_CONTROLLING;
   505      if(r=nr_stun_client_start(pair->stun_client,NR_ICE_CLIENT_MODE_USE_CANDIDATE,nr_ice_candidate_pair_stun_cb,pair))
   506        ABORT(r);
   508      if(r=nr_ice_ctx_remember_id(pair->pctx->ctx, pair->stun_client->request))
   509        ABORT(r);
   511      _status=0;
   512    abort:
   513      return;
   514    }
   516 -static void nr_ice_candidate_pair_restart_stun_controlled_cb(int s, int how, void *cb_arg)
   517 +static void nr_ice_candidate_pair_restart_stun_controlled_cb(NR_SOCKET s, int how, void *cb_arg)
   518    {
   519      nr_ice_cand_pair *pair=cb_arg;
   520      int r,_status;
   522      r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/STREAM(%s):%d: Restarting pair %s as CONTROLLED",pair->pctx->label,pair->local->stream->label,pair->remote->component->component_id,pair->as_string);
   524      nr_stun_client_reset(pair->stun_client);
   525      pair->stun_client->params.ice_binding_request.control=NR_ICE_CONTROLLED;
   527      if(r=nr_stun_client_start(pair->stun_client,NR_ICE_CLIENT_MODE_BINDING_REQUEST,nr_ice_candidate_pair_stun_cb,pair))
   528 @@ -556,21 +571,21 @@
   532  static void nr_ice_candidate_pair_compute_codeword(nr_ice_cand_pair *pair,
   533    nr_ice_candidate *lcand, nr_ice_candidate *rcand)
   534    {
   535      int r,_status;
   536      char *as_string=0;
   538      if(r=nr_concat_strings(&as_string,lcand->addr.as_string,"|",
   539 -      rcand->addr.as_string,"(",lcand->label,"|",rcand->label,")",0))
   540 +      rcand->addr.as_string,"(",lcand->label,"|",rcand->label,")",NULL))
   541        ABORT(r);
   543      nr_ice_compute_codeword(as_string,strlen(as_string),pair->codeword);
   545      _status=0;
   546        abort:
   547      RFREE(as_string);
   548  return;
   549    }
   551 diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_candidate_pair.h src/ice/ice_candidate_pair.h
   552 --- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_candidate_pair.h	2012-09-16 16:26:08.000000000 -0700
   553 +++ src/ice/ice_candidate_pair.h	2012-10-06 08:30:22.000000000 -0700
   554 @@ -72,18 +72,18 @@
   556  int nr_ice_candidate_pair_create(nr_ice_peer_ctx *pctx, nr_ice_candidate *lcand,nr_ice_candidate *rcand,nr_ice_cand_pair **pairp);
   557  int nr_ice_candidate_pair_unfreeze(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair);
   558  int nr_ice_candidate_pair_start(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair);
   559  int nr_ice_candidate_pair_set_state(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair, int state);
   560  int nr_ice_candidate_pair_dump_state(nr_ice_cand_pair *pair, FILE *out);
   561  int nr_ice_candidate_pair_cancel(nr_ice_peer_ctx *pctx,nr_ice_cand_pair *pair);
   562  int nr_ice_candidate_pair_select(nr_ice_cand_pair *pair);
   563  int nr_ice_candidate_pair_do_triggered_check(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair);
   564  int nr_ice_candidate_pair_insert(nr_ice_cand_pair_head *head,nr_ice_cand_pair *pair);
   565 -void nr_ice_candidate_pair_restart_stun_nominated_cb(int s, int how, void *cb_arg);
   566 +void nr_ice_candidate_pair_restart_stun_nominated_cb(NR_SOCKET s, int how, void *cb_arg);
   567  int nr_ice_candidate_pair_destroy(nr_ice_cand_pair **pairp);
   569  #ifdef __cplusplus
   570  }
   571  #endif /* __cplusplus */
   572  #endif
   574 diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_component.c src/ice/ice_component.c
   575 --- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_component.c	2012-09-16 16:26:08.000000000 -0700
   576 +++ src/ice/ice_component.c	2012-10-06 08:30:22.000000000 -0700
   577 @@ -451,21 +451,21 @@
   578          if(r=nr_ice_peer_peer_rflx_candidate_create(comp->stream->pctx->ctx,"prflx",comp,&req->src_addr,&pcand)) {
   579            *error=(r==R_NO_MEMORY)?500:400;
   580            ABORT(r);
   581          }
   582          if(!nr_stun_message_has_attribute(sreq,NR_STUN_ATTR_PRIORITY,&attr)){
   583            r_log(LOG_ICE,LOG_ERR,"ICE-PEER(%s): Rejecting stun request without priority",comp->stream->pctx->label);
   584            *error=487;
   585            ABORT(R_BAD_DATA);
   586          }
   587          pcand->priority=attr->u.priority;
   588 -        pcand->state=NR_ICE_CAND_PEER_CANDIDATE;
   589 +        pcand->state=NR_ICE_CAND_PEER_CANDIDATE_PAIRED;;
   590          TAILQ_INSERT_TAIL(&comp->candidates,pcand,entry_comp);
   592          if(r=nr_ice_candidate_pair_create(comp->stream->pctx,cand,pcand,
   593               &pair)) {
   594            *error=(r==R_NO_MEMORY)?500:400;
   595            ABORT(r);
   596          }
   597          nr_ice_candidate_pair_set_state(pair->pctx,pair,NR_ICE_PAIR_STATE_FROZEN);        
   599          if(r=nr_ice_candidate_pair_insert(&comp->stream->check_list,pair)) {
   600 @@ -563,30 +563,38 @@
   601            break;
   602        }
   604        /* PAIR with each peer*/
   605        if(TAILQ_EMPTY(&pcomp->candidates)) {
   606            /* can happen if our peer proposes no (or all bogus) candidates */
   607            goto next_cand;
   608        }
   609        pcand=TAILQ_FIRST(&pcomp->candidates);
   610        while(pcand){
   611 -        nr_ice_compute_codeword(pcand->label,strlen(pcand->label),codeword);
   612 -        r_log(LOG_ICE,LOG_DEBUG,"Examining peer candidate %s:%s",codeword,pcand->label);
   613 -
   614 -        if(r=nr_ice_candidate_pair_create(pctx,lcand,pcand,&pair))
   615 -          ABORT(r);
   616 -        
   617 -        if(r=nr_ice_candidate_pair_insert(&pcomp->stream->check_list,
   618 -          pair))
   619 -          ABORT(r);
   620 +        /* Only pair peer candidates which have not yet been paired.
   621 +           This allows "trickle ICE". (Not yet standardized, but
   622 +           part of WebRTC).
   623 +
   624 +           TODO(ekr@rtfm.com): Add refernece to the spec when there
   625 +           is one.
   626 +         */
   627 +        if (pcand->state = NR_ICE_CAND_PEER_CANDIDATE_UNPAIRED) {
   628 +          nr_ice_compute_codeword(pcand->label,strlen(pcand->label),codeword);
   629 +          r_log(LOG_ICE,LOG_DEBUG,"Examining peer candidate %s:%s",codeword,pcand->label);
   630 +          
   631 +          if(r=nr_ice_candidate_pair_create(pctx,lcand,pcand,&pair))
   632 +            ABORT(r);
   634 +          if(r=nr_ice_candidate_pair_insert(&pcomp->stream->check_list,
   635 +              pair))
   636 +            ABORT(r);
   637 +        }
   638          pcand=TAILQ_NEXT(pcand,entry_comp);
   639        }
   641        if(!pair)
   642          ABORT(R_INTERNAL);
   644        /* Add the stun username/password pair from the last pair (any 
   645           would do) to the stun contexts */
   646        isock=STAILQ_FIRST(&lcomp->sockets);
   647        while(isock){
   648 @@ -594,20 +602,28 @@
   649             pair->r2l_user,&pair->r2l_pwd,nr_ice_component_stun_server_cb,pcomp))
   650            ABORT(r);
   652          isock=STAILQ_NEXT(isock,entry);
   653        }
   655      next_cand:
   656        lcand=TAILQ_NEXT(lcand,entry_comp);
   657      } 
   659 +    /* Mark all peer candidates as paired */
   660 +    pcand=TAILQ_FIRST(&pcomp->candidates);
   661 +    while(pcand){
   662 +      pcand->state = NR_ICE_CAND_PEER_CANDIDATE_PAIRED;
   663 +      
   664 +      pcand=TAILQ_NEXT(pcand,entry_comp);
   665 +    }
   666 +
   667      _status=0;
   668    abort:
   669      return(_status);
   670    }
   672  int nr_ice_component_nominated_pair(nr_ice_component *comp, nr_ice_cand_pair *pair)
   673    {
   674      int r,_status;
   675      int fire_cb=0;
   676      nr_ice_cand_pair *p2;
   677 @@ -616,32 +632,32 @@
   678        fire_cb=1;
   680      /* Are we changing what the nominated pair is? */
   681      if(comp->nominated){
   682        if(comp->nominated->priority > pair->priority)
   683          return(0);
   684        r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/STREAM(%s)/comp(%d): replacing pair %s with pair %s",comp->stream->pctx->label,comp->stream->label,comp->component_id,comp->nominated->as_string,pair->as_string);
   685      }
   687      /* Set the new nominated pair */
   688 -    r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/STREAM(%s)/comp(%d): nominated pair is %s (0x%x)",comp->stream->pctx->label,comp->stream->label,comp->component_id,pair->as_string,(int)pair);
   689 +    r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/STREAM(%s)/comp(%d): nominated pair is %s (0x%p)",comp->stream->pctx->label,comp->stream->label,comp->component_id,pair->as_string,pair);
   690      comp->state=NR_ICE_COMPONENT_NOMINATED;
   691      comp->nominated=pair;
   692      comp->active=pair;
   694 -    r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/STREAM(%s)/comp(%d): cancelling all pairs but %s (0x%x)",comp->stream->pctx->label,comp->stream->label,comp->component_id,pair->as_string,(int)pair);
   695 +    r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/STREAM(%s)/comp(%d): cancelling all pairs but %s (0x%p)",comp->stream->pctx->label,comp->stream->label,comp->component_id,pair->as_string,pair);
   697      /* OK, we need to cancel off everything on this component */
   698      p2=TAILQ_FIRST(&comp->stream->check_list);
   699      while(p2){
   700        if((p2 != pair) && (p2->remote->component->component_id == comp->component_id)){
   701 -        r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/STREAM(%s)/comp(%d): cancelling pair %s (0x%x)",comp->stream->pctx->label,comp->stream->label,comp->component_id,p2->as_string,(int)p2);
   702 +        r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/STREAM(%s)/comp(%d): cancelling pair %s (0x%p)",comp->stream->pctx->label,comp->stream->label,comp->component_id,p2->as_string,p2);
   704          if(r=nr_ice_candidate_pair_cancel(pair->pctx,p2))
   705            ABORT(r);
   706        }
   708        p2=TAILQ_NEXT(p2,entry);
   709      }
   710      r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/STREAM(%s)/comp(%d): cancelling done",comp->stream->pctx->label,comp->stream->label,comp->component_id);
   712      if(r=nr_ice_media_stream_component_nominated(comp->stream,comp))
   713 @@ -734,21 +750,21 @@
   714          ABORT(r);
   715      }
   717      _status=0;
   718    abort:
   719      RFREE(pairs);
   720      return(_status);
   721    }
   724 -static void nr_ice_component_keepalive_cb(int s, int how, void *cb_arg)
   725 +static void nr_ice_component_keepalive_cb(NR_SOCKET s, int how, void *cb_arg)
   726    {
   727      nr_ice_component *comp=cb_arg;
   728      UINT4 keepalive_timeout;
   730      assert(comp->keepalive_ctx);
   732      if(NR_reg_get_uint4(NR_ICE_REG_KEEPALIVE_TIMER,&keepalive_timeout)){
   733        keepalive_timeout=15000; /* Default */
   734      }
   736 diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_ctx.c src/ice/ice_ctx.c
   737 --- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_ctx.c	2012-09-16 16:26:08.000000000 -0700
   738 +++ src/ice/ice_ctx.c	2012-10-06 08:30:22.000000000 -0700
   739 @@ -56,21 +56,21 @@
   740  #include "util.h"
   743  int LOG_ICE = 0;
   745  static int nr_ice_random_string(char *str, int len);
   746  static int nr_ice_fetch_stun_servers(int ct, nr_ice_stun_server **out);
   747  #ifdef USE_TURN
   748  static int nr_ice_fetch_turn_servers(int ct, nr_ice_turn_server **out);
   749  #endif /* USE_TURN */
   750 -static void nr_ice_ctx_destroy_cb(int s, int how, void *cb_arg);
   751 +static void nr_ice_ctx_destroy_cb(NR_SOCKET s, int how, void *cb_arg);
   753  int nr_ice_fetch_stun_servers(int ct, nr_ice_stun_server **out)
   754    {
   755      int r,_status;
   756      nr_ice_stun_server *servers = 0;
   757      int i;
   758      NR_registry child;
   759      char *addr=0;
   760      UINT2 port;
   761      in_addr_t addr_int;
   762 @@ -271,21 +271,21 @@
   763      *ctxp=ctx;
   765      _status=0;
   766    abort:
   767      if(_status)
   768        nr_ice_ctx_destroy_cb(0,0,ctx);
   770      return(_status);
   771    }
   773 -static void nr_ice_ctx_destroy_cb(int s, int how, void *cb_arg)
   774 +static void nr_ice_ctx_destroy_cb(NR_SOCKET s, int how, void *cb_arg)
   775    {
   776      nr_ice_ctx *ctx=cb_arg;
   777      nr_ice_foundation *f1,*f2;
   778      nr_ice_media_stream *s1,*s2;
   779      int i;
   780      nr_ice_stun_id *id1,*id2;
   782      RFREE(ctx->label);
   784      RFREE(ctx->stun_servers);
   785 @@ -323,21 +323,21 @@
   786      if(!ctxp || !*ctxp)
   787        return(0);
   789      NR_ASYNC_SCHEDULE(nr_ice_ctx_destroy_cb,*ctxp);
   791      *ctxp=0;
   793      return(0);
   794    }
   796 -void nr_ice_initialize_finished_cb(int s, int h, void *cb_arg)
   797 +void nr_ice_initialize_finished_cb(NR_SOCKET s, int h, void *cb_arg)
   798    {
   799      nr_ice_ctx *ctx=cb_arg;
   801  /*    r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): Candidate %s %s",ctx->label,
   802        cand->label, cand->state==NR_ICE_CAND_STATE_INITIALIZED?"INITIALIZED":"FAILED");
   803  */
   804      ctx->uninitialized_candidates--;
   806      if(ctx->uninitialized_candidates==0){
   807        r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): All candidates initialized",ctx->label);
   808 @@ -368,21 +368,22 @@
   809      stream=STAILQ_FIRST(&ctx->streams);
   810      while(stream){
   811        if(r=nr_ice_media_stream_initialize(ctx,stream))
   812          ABORT(r);
   814        stream=STAILQ_NEXT(stream,entry);
   815      }
   817      if(ctx->uninitialized_candidates)
   818        ABORT(R_WOULDBLOCK);
   819 -
   820 +    
   821 +    
   822      _status=0;
   823    abort:
   824      return(_status);
   825    }
   827  int nr_ice_add_media_stream(nr_ice_ctx *ctx,char *label,int components, nr_ice_media_stream **streamp)
   828    {
   829      int r,_status;
   831      if(r=nr_ice_media_stream_create(ctx,label,components,streamp))
   832 diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_ctx.h src/ice/ice_ctx.h
   833 --- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_ctx.h	2012-09-16 16:26:08.000000000 -0700
   834 +++ src/ice/ice_ctx.h	2012-10-06 08:30:22.000000000 -0700
   835 @@ -92,23 +92,23 @@
   836    UCHAR id[12];
   838    STAILQ_ENTRY(nr_ice_stun_id_) entry;
   839  } nr_ice_stun_id;
   841  typedef STAILQ_HEAD(nr_ice_stun_id_head_,nr_ice_stun_id_) nr_ice_stun_id_head;
   843  struct nr_ice_ctx_ {
   844    UINT4 flags;
   845    int state;
   846 -#define NR_ICE_STATE_CREATED      1
   847 -#define NR_ICE_STATE_INITIALIZING 2
   848 -#define NR_ICE_STATE_INITIALIZED  3
   849 +#define NR_ICE_STATE_CREATED          1
   850 +#define NR_ICE_STATE_INITIALIZING     2
   851 +#define NR_ICE_STATE_INITIALIZED      3
   852    char *label;
   854    char *ufrag;
   855    char *pwd;
   857    UINT4 Ta;
   859    nr_ice_stun_server *stun_servers;           /* The list of stun servers */
   860    int stun_server_ct;
   861    nr_ice_turn_server *turn_servers;           /* The list of turn servers */
   862 @@ -133,21 +133,21 @@
   864  int nr_ice_ctx_create(char *label, UINT4 flags, nr_ice_ctx **ctxp);
   865  #define NR_ICE_CTX_FLAGS_OFFERER                           1
   866  #define NR_ICE_CTX_FLAGS_ANSWERER                          (1<<1)
   867  #define NR_ICE_CTX_FLAGS_AGGRESSIVE_NOMINATION             (1<<2)
   868  #define NR_ICE_CTX_FLAGS_LITE                              (1<<3)
   870  int nr_ice_ctx_destroy(nr_ice_ctx **ctxp);
   871  int nr_ice_initialize(nr_ice_ctx *ctx, NR_async_cb done_cb, void *cb_arg);
   872  int nr_ice_add_candidate(nr_ice_ctx *ctx, nr_ice_candidate *cand);
   873 -void nr_ice_initialize_finished_cb(int s, int h, void *cb_arg);
   874 +void nr_ice_initialize_finished_cb(NR_SOCKET s, int h, void *cb_arg);
   875  int nr_ice_add_media_stream(nr_ice_ctx *ctx,char *label,int components, nr_ice_media_stream **streamp);
   876  int nr_ice_get_global_attributes(nr_ice_ctx *ctx,char ***attrsp, int *attrctp);
   877  int nr_ice_ctx_deliver_packet(nr_ice_ctx *ctx, nr_ice_component *comp, nr_transport_addr *source_addr, UCHAR *data, int len);
   878  int nr_ice_ctx_is_known_id(nr_ice_ctx *ctx, UCHAR id[12]);
   879  int nr_ice_ctx_remember_id(nr_ice_ctx *ctx, nr_stun_message *msg);
   880  int nr_ice_ctx_finalize(nr_ice_ctx *ctx, nr_ice_peer_ctx *pctx);
   882  extern int LOG_ICE;
   884  #ifdef __cplusplus
   885 diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_media_stream.c src/ice/ice_media_stream.c
   886 --- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_media_stream.c	2012-09-16 16:26:08.000000000 -0700
   887 +++ src/ice/ice_media_stream.c	2012-10-06 08:30:22.000000000 -0700
   888 @@ -35,21 +35,21 @@
   889  static char *RCSSTRING __UNUSED__="$Id: ice_media_stream.c,v 1.2 2008/04/28 17:59:01 ekr Exp $";
   891  #include <string.h>
   892  #include <assert.h>
   893  #include <nr_api.h>
   894  #include <r_assoc.h>
   895  #include <async_timer.h>
   896  #include "ice_ctx.h"
   898  static char *nr_ice_media_stream_states[]={"INVALID",
   899 -  "FROZEN","ACTIVE","COMPLETED","FAILED"
   900 +  "UNPAIRED","FROZEN","ACTIVE","COMPLETED","FAILED"
   901  };
   903  int nr_ice_media_stream_set_state(nr_ice_media_stream *str, int state);
   905  int nr_ice_media_stream_create(nr_ice_ctx *ctx,char *label,int components, nr_ice_media_stream **streamp)
   906    {
   907      int r,_status;
   908      nr_ice_media_stream *stream=0;
   909      nr_ice_component *comp=0;
   910      int i;
   911 @@ -66,29 +66,29 @@
   912      for(i=0;i<components;i++){
   913        /* component-id must be > 0, so increment by 1 */
   914        if(r=nr_ice_component_create(stream, i+1, &comp))
   915          ABORT(r);
   917      }
   919      TAILQ_INIT(&stream->check_list);
   921      stream->component_ct=components;
   922 -    
   923 +    stream->ice_state = NR_ICE_MEDIA_STREAM_UNPAIRED;
   924      *streamp=stream;
   926      _status=0;
   927    abort:
   928      if(_status){
   929        nr_ice_media_stream_destroy(&stream);
   930      }
   931 -    return(_status);            
   932 +    return(_status);
   933    }
   935  int nr_ice_media_stream_destroy(nr_ice_media_stream **streamp)
   936    {
   937      nr_ice_media_stream *stream;
   938      nr_ice_component *c1,*c2;
   939      nr_ice_cand_pair *p1,*p2;
   940      if(!streamp || !*streamp)
   941        return(0);
   943 @@ -200,85 +200,148 @@
   944        if(attrs){
   945          for(index=0;index<attrct;index++){
   946            RFREE(attrs[index]);
   947          }
   948          RFREE(attrs);
   949        }
   950      }
   951      return(_status);
   952    }
   954 +
   955 +/* Get a default candidate per 4.1.4 */
   956 +int nr_ice_media_stream_get_default_candidate(nr_ice_media_stream *stream, int component, nr_ice_candidate **candp)
   957 +  {
   958 +    int _status;
   959 +    nr_ice_component *comp;
   960 +    nr_ice_candidate *cand;
   961 +    nr_ice_candidate *best_cand = NULL;
   962 +
   963 +    comp=STAILQ_FIRST(&stream->components);
   964 +    while(comp){
   965 +      if (comp->component_id == component)
   966 +        break;
   967 +      
   968 +      comp=STAILQ_NEXT(comp,entry);
   969 +    }
   970 +    
   971 +    if (!comp)
   972 +      ABORT(R_NOT_FOUND);
   973 +
   974 +    /* We have the component. Now find the "best" candidate, making 
   975 +       use of the fact that more "reliable" candidate types have
   976 +       higher numbers. So, we sort by type and then priority within
   977 +       type
   978 +    */
   979 +    cand=TAILQ_FIRST(&comp->candidates);
   980 +    while(cand){
   981 +      if (!best_cand) {
   982 +        best_cand = cand;
   983 +      }
   984 +      else {
   985 +        if (best_cand->type < cand->type) {
   986 +          best_cand = cand;
   987 +        } else if (best_cand->type == cand->type) { 
   988 +          if (best_cand->priority < cand->priority)
   989 +            best_cand = cand;
   990 +        }
   991 +      }
   992 +
   993 +      cand=TAILQ_NEXT(cand,entry_comp);
   994 +    }
   995 +    
   996 +    /* No candidates */
   997 +    if (!best_cand)
   998 +      ABORT(R_NOT_FOUND);
   999 +
  1000 +    *candp = best_cand;
  1002 +    _status=0;
  1003 +  abort:
  1004 +    return(_status);
  1005 +  }
  1008  int nr_ice_media_stream_pair_candidates(nr_ice_peer_ctx *pctx,nr_ice_media_stream *lstream,nr_ice_media_stream *pstream)
  1010      int r,_status;
  1011      nr_ice_component *pcomp,*lcomp;
  1013      pcomp=STAILQ_FIRST(&pstream->components);
  1014      lcomp=STAILQ_FIRST(&lstream->components);
  1015      while(pcomp){
  1016        if(r=nr_ice_component_pair_candidates(pctx,lcomp,pcomp))
  1017          ABORT(r);
  1020        lcomp=STAILQ_NEXT(lcomp,entry);
  1021        pcomp=STAILQ_NEXT(pcomp,entry);
  1022      };
  1024 +    if (pstream->ice_state == NR_ICE_MEDIA_STREAM_UNPAIRED) {
  1025 +      r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): unfreezing stream %s",pstream->pctx->label,pstream->label);
  1026 +      pstream->ice_state = NR_ICE_MEDIA_STREAM_CHECKS_FROZEN;
  1027 +    }
  1029      _status=0;
  1030    abort:
  1031      return(_status);
  1034  /* S 5.8 -- run the highest priority WAITING pair or if not available
  1035     FROZEN pair */
  1036 -static void nr_ice_media_stream_check_timer_cb(int s, int h, void *cb_arg)
  1037 +static void nr_ice_media_stream_check_timer_cb(NR_SOCKET s, int h, void *cb_arg)
  1039      int r,_status;
  1040      nr_ice_media_stream *stream=cb_arg;
  1041      nr_ice_cand_pair *pair;
  1042      int timer_val;
  1044      assert(stream->pctx->active_streams!=0);
  1046      timer_val=stream->pctx->ctx->Ta*stream->pctx->active_streams;
  1048 +    if (stream->ice_state == NR_ICE_MEDIA_STREAM_CHECKS_COMPLETED) {
  1049 +      r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): bogus state for stream %s",stream->pctx->label,stream->label);
  1050 +    }
  1051      assert(stream->ice_state != NR_ICE_MEDIA_STREAM_CHECKS_COMPLETED);
  1053      r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): check timer expired for media stream %s",stream->pctx->label,stream->label);
  1054      stream->timer=0;
  1057      /* Find the highest priority WAITING check and move it to RUNNING */
  1058      pair=TAILQ_FIRST(&stream->check_list);
  1059      while(pair){
  1060        if(pair->state==NR_ICE_PAIR_STATE_WAITING)
  1061          break;
  1062        pair=TAILQ_NEXT(pair,entry);
  1065      /* Hmmm... No WAITING. Let's look for FROZEN */
  1066      if(!pair){
  1067        pair=TAILQ_FIRST(&stream->check_list);
  1070        while(pair){
  1071          if(pair->state==NR_ICE_PAIR_STATE_FROZEN){
  1072            if(r=nr_ice_candidate_pair_unfreeze(stream->pctx,pair))
  1073              ABORT(r);
  1074            break;
  1076          pair=TAILQ_NEXT(pair,entry);
  1080      if(pair){
  1081        nr_ice_candidate_pair_start(pair->pctx,pair); /* Ignore failures */
  1082        NR_ASYNC_TIMER_SET(timer_val,nr_ice_media_stream_check_timer_cb,cb_arg,&stream->timer);
  1084 +    /* TODO(ekr@rtfm.com): Report on the special case where there are no checks to
  1085 +       run at all */
  1086      _status=0;
  1087    abort:
  1088      return;
  1092  /* Start checks for this media stream (aka check list) */
  1093  int nr_ice_media_stream_start_checks(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream)
  1095      assert(stream->ice_state==NR_ICE_MEDIA_STREAM_CHECKS_FROZEN);
  1096 @@ -476,21 +539,23 @@
  1097      /* All done... */
  1098      r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s)/ICE-STREAM(%s): all components have nominated candidate pairs",stream->pctx->label,stream->label);
  1099      nr_ice_media_stream_set_state(stream,NR_ICE_MEDIA_STREAM_CHECKS_COMPLETED);
  1101      /* Cancel our timer */
  1102      if(stream->timer){
  1103        NR_async_timer_cancel(stream->timer);
  1104        stream->timer=0;
  1107 -    stream->pctx->handler->vtbl->stream_ready(stream->pctx->handler->obj,stream->local_stream);
  1108 +    if (stream->pctx->handler) {
  1109 +      stream->pctx->handler->vtbl->stream_ready(stream->pctx->handler->obj,stream->local_stream);
  1110 +    }
  1112      /* Now tell the peer_ctx that we're done */
  1113      if(r=nr_ice_peer_ctx_stream_done(stream->pctx,stream))
  1114        ABORT(r);
  1116    done:
  1117      _status=0;
  1118    abort:
  1119      return(_status);
  1121 @@ -515,21 +580,23 @@
  1123        p2=TAILQ_NEXT(p2,entry);
  1126      /* Cancel our timer */
  1127      if(stream->timer){
  1128        NR_async_timer_cancel(stream->timer);
  1129        stream->timer=0;
  1132 -    stream->pctx->handler->vtbl->stream_failed(stream->pctx->handler->obj,stream->local_stream);
  1133 +    if (stream->pctx->handler) {
  1134 +      stream->pctx->handler->vtbl->stream_failed(stream->pctx->handler->obj,stream->local_stream);
  1135 +    }
  1137      /* Now tell the peer_ctx that we're done */
  1138      if(r=nr_ice_peer_ctx_stream_done(stream->pctx,stream))
  1139        ABORT(r);
  1141      _status=0;
  1142    abort:
  1143      return(_status);
  1146 diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_media_stream.h src/ice/ice_media_stream.h
  1147 --- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_media_stream.h	2012-09-16 16:26:08.000000000 -0700
  1148 +++ src/ice/ice_media_stream.h	2012-10-06 08:30:22.000000000 -0700
  1149 @@ -45,40 +45,43 @@
  1150    struct nr_ice_peer_ctx_ *pctx;
  1152    struct nr_ice_media_stream_ *local_stream; /* used when this is a peer */
  1153    int component_ct;
  1154    nr_ice_component_head components;
  1156    char *ufrag;    /* ICE username */
  1157    char *pwd;    /* ICE password */
  1159    int ice_state;
  1160 -#define NR_ICE_MEDIA_STREAM_CHECKS_FROZEN      1
  1161 -#define NR_ICE_MEDIA_STREAM_CHECKS_ACTIVE      2
  1162 -#define NR_ICE_MEDIA_STREAM_CHECKS_COMPLETED   3
  1163 -#define NR_ICE_MEDIA_STREAM_CHECKS_FAILED      4
  1165 +#define NR_ICE_MEDIA_STREAM_UNPAIRED           1
  1166 +#define NR_ICE_MEDIA_STREAM_CHECKS_FROZEN      2
  1167 +#define NR_ICE_MEDIA_STREAM_CHECKS_ACTIVE      3
  1168 +#define NR_ICE_MEDIA_STREAM_CHECKS_COMPLETED   4
  1169 +#define NR_ICE_MEDIA_STREAM_CHECKS_FAILED      5
  1171    nr_ice_cand_pair_head check_list;
  1172    void *timer;  /* Check list periodic timer */
  1174  //  nr_ice_cand_pair_head valid_list;
  1177    STAILQ_ENTRY(nr_ice_media_stream_) entry;
  1178  };
  1180  typedef STAILQ_HEAD(nr_ice_media_stream_head_,nr_ice_media_stream_) nr_ice_media_stream_head;
  1182  int nr_ice_media_stream_create(struct nr_ice_ctx_ *ctx,char *label, int components, nr_ice_media_stream **streamp);
  1183  int nr_ice_media_stream_destroy(nr_ice_media_stream **streamp);
  1184  int nr_ice_media_stream_finalize(nr_ice_media_stream *lstr,nr_ice_media_stream *rstr);
  1185  int nr_ice_media_stream_initialize(struct nr_ice_ctx_ *ctx, nr_ice_media_stream *stream);
  1186  int nr_ice_media_stream_get_attributes(nr_ice_media_stream *stream, char ***attrsp,int *attrctp);
  1187 +int nr_ice_media_stream_get_default_candidate(nr_ice_media_stream *stream, int component, nr_ice_candidate **candp);
  1188  int nr_ice_media_stream_pair_candidates(nr_ice_peer_ctx *pctx,nr_ice_media_stream *lstream,nr_ice_media_stream *pstream);
  1189  int nr_ice_media_stream_start_checks(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream);
  1190  int nr_ice_media_stream_unfreeze_pairs(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream);
  1191  int nr_ice_media_stream_unfreeze_pairs_foundation(nr_ice_media_stream *stream, char *foundation);
  1192  int nr_ice_media_stream_dump_state(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream,FILE *out);
  1193  int nr_ice_media_stream_component_nominated(nr_ice_media_stream *stream,nr_ice_component *component);
  1194  int nr_ice_media_stream_component_failed(nr_ice_media_stream *stream,nr_ice_component *component);
  1195  int nr_ice_media_stream_set_state(nr_ice_media_stream *str, int state);
  1196  int nr_ice_media_stream_get_best_candidate(nr_ice_media_stream *str, int component, nr_ice_candidate **candp);
  1197  int nr_ice_media_stream_send(nr_ice_peer_ctx *pctx,nr_ice_media_stream *str, int component, UCHAR *data, int len);
  1198 diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_parser.c src/ice/ice_parser.c
  1199 --- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_parser.c	2012-09-16 16:26:08.000000000 -0700
  1200 +++ src/ice/ice_parser.c	2012-10-06 08:30:22.000000000 -0700
  1201 @@ -35,20 +35,21 @@
  1202  static char *RCSSTRING __UNUSED__="$Id: ice_parser.c,v 1.2 2008/04/28 17:59:01 ekr Exp $";
  1204  #include <csi_platform.h>
  1205  #include <sys/types.h>
  1206  #ifdef WIN32
  1207  #include <winsock2.h>
  1208  #else
  1209  #include <sys/socket.h>
  1210  #include <netinet/in.h>
  1211  #include <arpa/inet.h>
  1212 +#include <strings.h>
  1213  #endif
  1214  #include <string.h>
  1215  #include <assert.h>
  1216  #include <ctype.h>
  1217  #include "nr_api.h"
  1218  #include "ice_ctx.h"
  1219  #include "ice_candidate.h"
  1220  #include "ice_reg.h"
  1222  static void
  1223 @@ -125,21 +126,21 @@
  1224      char *rel_addr=0;
  1226      if(!(cand=RCALLOC(sizeof(nr_ice_candidate))))
  1227          ABORT(R_NO_MEMORY);
  1229      if(!(cand->label=r_strdup(orig)))
  1230          ABORT(R_NO_MEMORY);
  1232      cand->ctx=ctx;
  1233      cand->isock=0;
  1234 -    cand->state=NR_ICE_CAND_PEER_CANDIDATE;
  1235 +    cand->state=NR_ICE_CAND_PEER_CANDIDATE_UNPAIRED;
  1236      cand->stream=stream;
  1237      skip_whitespace(&str);
  1239      /* Candidate attr */
  1240      if (strncasecmp(str, "candidate:", 10))
  1241          ABORT(R_BAD_DATA);
  1243      fast_forward(&str, 10);
  1244      if (*str == '\0')
  1245          ABORT(R_BAD_DATA);
  1246 @@ -311,26 +312,31 @@
  1247          /* it's expected to be at EOD at this point */
  1249          break;
  1250      default:
  1251          ABORT(R_INTERNAL);
  1252          break;
  1255      skip_whitespace(&str);
  1257 -    assert(strlen(str) == 0);
  1259 +    /* This used to be an assert, but we don't want to exit on invalid
  1260 +       remote data */
  1261 +    if (strlen(str) != 0) {
  1262 +      ABORT(R_BAD_DATA);
  1263 +    }
  1265      *candp=cand;
  1267      _status=0;
  1268    abort:
  1269 +    /* TODO(ekr@rtfm.com): Fix memory leak if we have a parse error */
  1270      if (_status)
  1271          r_log(LOG_ICE,LOG_WARNING,"ICE(%s): Error parsing attribute: %s",ctx->label,orig);
  1273      RFREE(connection_address);
  1274      RFREE(rel_addr);
  1275      return(_status);
  1279  int
  1280 diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_peer_ctx.c src/ice/ice_peer_ctx.c
  1281 --- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_peer_ctx.c	2012-09-16 16:26:08.000000000 -0700
  1282 +++ src/ice/ice_peer_ctx.c	2012-10-06 08:30:22.000000000 -0700
  1283 @@ -35,33 +35,35 @@
  1284  static char *RCSSTRING __UNUSED__="$Id: ice_peer_ctx.c,v 1.2 2008/04/28 17:59:01 ekr Exp $";
  1286  #include <string.h>
  1287  #include <assert.h>
  1288  #include <nr_api.h>
  1289  #include "ice_ctx.h"
  1290  #include "ice_peer_ctx.h"
  1291  #include "nr_crypto.h"
  1292  #include "async_timer.h"
  1294 -static void nr_ice_peer_ctx_destroy_cb(int s, int how, void *cb_arg);
  1295 +static void nr_ice_peer_ctx_destroy_cb(NR_SOCKET s, int how, void *cb_arg);
  1296 +static int nr_ice_peer_ctx_parse_stream_attributes_int(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, nr_ice_media_stream *pstream, char **attrs, int attr_ct);
  1297 +static int nr_ice_ctx_parse_candidate(nr_ice_peer_ctx *pctx, nr_ice_media_stream *pstream, char *candidate);
  1299  int nr_ice_peer_ctx_create(nr_ice_ctx *ctx, nr_ice_handler *handler,char *label, nr_ice_peer_ctx **pctxp)
  1301      int r,_status;
  1302      nr_ice_peer_ctx *pctx=0;
  1304      if(!(pctx=RCALLOC(sizeof(nr_ice_peer_ctx))))
  1305        ABORT(R_NO_MEMORY);
  1307      if(!(pctx->label=r_strdup(label)))
  1308        ABORT(R_NO_MEMORY);
  1311      pctx->ctx=ctx;
  1312      pctx->handler=handler;
  1314      /* Decide controlling vs. controlled */
  1315      if(ctx->flags & NR_ICE_CTX_FLAGS_LITE){
  1316        if(pctx->peer_lite){
  1317          r_log(LOG_ICE,LOG_ERR,"Both sides are ICE-Lite");
  1318          ABORT(R_BAD_DATA);
  1321 @@ -88,85 +90,177 @@
  1322        nr_ice_peer_ctx_destroy_cb(0,0,pctx);
  1324      return(_status);
  1329  int nr_ice_peer_ctx_parse_stream_attributes(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, char **attrs, int attr_ct)
  1331      nr_ice_media_stream *pstream=0;
  1332 -    nr_ice_candidate *cand=0;
  1333      nr_ice_component *comp,*comp2;
  1334      int r,_status;
  1335 -    int i,j;
  1337 -    /* Note: use component_ct from our own stream since components other
  1338 -       than this offered by the other side are unusable */
  1339 +    /*
  1340 +      Note: use component_ct from our own stream since components other
  1341 +      than this offered by the other side are unusable */
  1342      if(r=nr_ice_media_stream_create(pctx->ctx,stream->label,stream->component_ct,&pstream))
  1343        ABORT(r);
  1345 -    /* Match up the local and remote components */ 
  1347 +    /* Match up the local and remote components */
  1348      comp=STAILQ_FIRST(&stream->components);
  1349      comp2=STAILQ_FIRST(&pstream->components);
  1350      while(comp){
  1351        comp2->local_component=comp;
  1353        comp=STAILQ_NEXT(comp,entry);
  1354        comp2=STAILQ_NEXT(comp2,entry);
  1358 -    pstream->ice_state=NR_ICE_MEDIA_STREAM_CHECKS_FROZEN;
  1359      pstream->local_stream=stream;
  1360      pstream->pctx=pctx;
  1362 +    if (r=nr_ice_peer_ctx_parse_stream_attributes_int(pctx,stream,pstream,attrs,attr_ct))
  1363 +      ABORT(r);
  1366 +    STAILQ_INSERT_TAIL(&pctx->peer_streams,pstream,entry);
  1368 +    _status=0;
  1369 +  abort:
  1370 +    return(_status);
  1371 +  }
  1373 +static int nr_ice_peer_ctx_parse_stream_attributes_int(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, nr_ice_media_stream *pstream, char **attrs, int attr_ct)
  1374 +  {
  1375 +    int r;
  1376 +    int i;
  1378      for(i=0;i<attr_ct;i++){
  1379        if(!strncmp(attrs[i],"ice-",4)){
  1380 -        if(r=nr_ice_peer_ctx_parse_media_stream_attribute(pctx,pstream,attrs[i]))
  1381 +        if(r=nr_ice_peer_ctx_parse_media_stream_attribute(pctx,pstream,attrs[i])) {
  1382 +          r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) specified bogus ICE attribute",pctx->ctx->label,pctx->label);
  1383            continue;
  1384 -        continue;
  1385 +        }
  1388 -      if(r=nr_ice_peer_candidate_from_attribute(pctx->ctx,attrs[i],pstream,&cand))
  1389 -        continue;
  1390 -      if(cand->component_id-1>=pstream->component_ct){
  1391 -        r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) specified too many components",pctx->ctx->label,pctx->label);
  1392 -        continue;
  1393 +      else if (!strncmp(attrs[i],"candidate",9)){
  1394 +        if(r=nr_ice_ctx_parse_candidate(pctx,pstream,attrs[i])) {
  1395 +          r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) specified bogus candidate",pctx->ctx->label,pctx->label);
  1396 +          continue;
  1397 +        }
  1398 +      }
  1399 +      else {
  1400 +        r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) specified bogus attribute",pctx->ctx->label,pctx->label);
  1402 +    }
  1404 -      /* Not the fastest way to find a component, but it's what we got */
  1405 -      j=1;
  1406 -      for(comp=STAILQ_FIRST(&pstream->components);comp;comp=STAILQ_NEXT(comp,entry)){
  1407 -        if(j==cand->component_id)
  1408 -          break;
  1409 +    /* Doesn't fail because we just skip errors */
  1410 +    return(0);
  1411 +  }
  1413 -        j++;
  1414 -      }
  1416 -      if(!comp){
  1417 -        r_log(LOG_ICE,LOG_ERR,"Peer answered with more components than we offered");
  1418 -        ABORT(R_BAD_DATA);
  1419 -      }
  1421 -      cand->component=comp;
  1422 +static int nr_ice_ctx_parse_candidate(nr_ice_peer_ctx *pctx, nr_ice_media_stream *pstream, char *candidate)
  1423 +  {
  1424 +    nr_ice_candidate *cand=0;
  1425 +    nr_ice_component *comp;
  1426 +    int j;
  1427 +    int r, _status;
  1429 -      TAILQ_INSERT_TAIL(&comp->candidates,cand,entry_comp);
  1430 +    if(r=nr_ice_peer_candidate_from_attribute(pctx->ctx,candidate,pstream,&cand))
  1431 +      ABORT(r);
  1432 +    if(cand->component_id-1>=pstream->component_ct){
  1433 +      r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) specified too many components",pctx->ctx->label,pctx->label);
  1434 +      ABORT(R_BAD_DATA);
  1437 -    STAILQ_INSERT_TAIL(&pctx->peer_streams,pstream,entry);
  1438 +    /* Not the fastest way to find a component, but it's what we got */
  1439 +    j=1;
  1440 +    for(comp=STAILQ_FIRST(&pstream->components);comp;comp=STAILQ_NEXT(comp,entry)){
  1441 +      if(j==cand->component_id)
  1442 +        break;
  1444 +      j++;
  1445 +    }
  1447 +    if(!comp){
  1448 +      r_log(LOG_ICE,LOG_ERR,"Peer answered with more components than we offered");
  1449 +      ABORT(R_BAD_DATA);
  1450 +    }
  1452 +    cand->component=comp;
  1454 +    TAILQ_INSERT_TAIL(&comp->candidates,cand,entry_comp);
  1456      _status=0;
  1457 -  abort:
  1458 + abort:
  1459 +    if (_status) {
  1460 +      nr_ice_candidate_destroy(&cand);
  1461 +    }
  1462      return(_status);
  1467 +int nr_ice_peer_ctx_parse_trickle_candidate(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, char *candidate)
  1468 +  {
  1469 +    /* First need to find the stream. Because we don't have forward pointers,
  1470 +       iterate through all the peer streams to find one that matches us */
  1471 +    nr_ice_media_stream *pstream;
  1472 +    int r,_status;
  1473 +    int needs_pairing = 0;
  1475 +    pstream=STAILQ_FIRST(&pctx->peer_streams);
  1476 +    while(pstream) {
  1477 +      if (pstream->local_stream == stream)
  1478 +        break;
  1480 +      pstream = STAILQ_NEXT(pstream, entry);
  1481 +    }
  1482 +    if (!pstream) {
  1483 +      r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) has no stream matching stream %s",pctx->ctx->label,pctx->label,stream->label);
  1484 +      ABORT(R_NOT_FOUND);
  1485 +    }
  1487 +    switch(pstream->ice_state) {
  1488 +      case NR_ICE_MEDIA_STREAM_UNPAIRED:
  1489 +        break;
  1490 +      case NR_ICE_MEDIA_STREAM_CHECKS_FROZEN:
  1491 +      case NR_ICE_MEDIA_STREAM_CHECKS_ACTIVE:
  1492 +        needs_pairing = 1;
  1493 +        break;
  1494 +      default:
  1495 +        r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s), stream(%s) tried to trickle ICE in inappropriate state %d",pctx->ctx->label,pctx->label,stream->label,pstream->ice_state);
  1496 +        ABORT(R_ALREADY);
  1497 +        break;
  1498 +    }
  1500 +    if(r=nr_ice_ctx_parse_candidate(pctx,pstream,candidate)){
  1501 +      ABORT(r);
  1502 +    }
  1504 +    /* If ICE is running (i.e., we are in FROZEN or ACTIVE states)
  1505 +       then we need to pair this new candidate. For now we
  1506 +       just re-pair the stream which is inefficient but still
  1507 +       fine because we suppress duplicate pairing */
  1508 +    if (needs_pairing) {
  1509 +      if(r=nr_ice_media_stream_pair_candidates(pctx, stream, pstream)) {
  1510 +        r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s), stream(%s) failed to pair trickle ICE candidates",pctx->ctx->label,pctx->label,stream->label);
  1511 +        ABORT(r);
  1512 +      }
  1513 +    }
  1515 +    _status =0;
  1516 + abort:
  1517 +    return(_status);
  1519 +  }
  1522  int nr_ice_peer_ctx_pair_candidates(nr_ice_peer_ctx *pctx)
  1524      nr_ice_media_stream *stream;
  1525      int r,_status;
  1527      if(STAILQ_EMPTY(&pctx->peer_streams)) {
  1528          r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) received no media stream attribributes",pctx->ctx->label,pctx->label);
  1529          ABORT(R_FAILED);
  1532 @@ -177,21 +271,21 @@
  1533          ABORT(r);
  1535        stream=STAILQ_NEXT(stream,entry);
  1538      _status=0;
  1539    abort:
  1540      return(_status);
  1543 -static void nr_ice_peer_ctx_destroy_cb(int s, int how, void *cb_arg)
  1544 +static void nr_ice_peer_ctx_destroy_cb(NR_SOCKET s, int how, void *cb_arg)
  1546      nr_ice_peer_ctx *pctx=cb_arg;
  1547      nr_ice_media_stream *str1,*str2;
  1549      RFREE(pctx->label);
  1550      RFREE(pctx->peer_ufrag);
  1551      RFREE(pctx->peer_pwd);
  1553      STAILQ_FOREACH_SAFE(str1, &pctx->peer_streams, entry, str2){
  1554        STAILQ_REMOVE(&pctx->peer_streams,str1,nr_ice_media_stream_,entry);
  1555 @@ -199,44 +293,79 @@
  1558      RFREE(pctx);
  1561  int nr_ice_peer_ctx_destroy(nr_ice_peer_ctx **pctxp)
  1564      if(!pctxp || !*pctxp)
  1565        return(0);
  1568 +    /* Stop calling the handler */
  1569 +    (*pctxp)->handler = 0;
  1571      NR_ASYNC_SCHEDULE(nr_ice_peer_ctx_destroy_cb,*pctxp);
  1573      *pctxp=0;
  1575      return(0);
  1579  /* Start the checks for the first media stream (S 5.7)
  1580     The rest remain FROZEN */
  1581  int nr_ice_peer_ctx_start_checks(nr_ice_peer_ctx *pctx)
  1583 +    return nr_ice_peer_ctx_start_checks2(pctx, 0);
  1584 +  }
  1586 +/* Start checks for some media stream.
  1588 +   If allow_non_first == 0, then we only look at the first stream,
  1589 +   which is 5245-complaint.
  1591 +   If allow_non_first == 1 then we find the first non-empty stream
  1592 +   This is not compliant with RFC 5245 but is necessary to make trickle ICE
  1593 +   work plausibly
  1594 +*/
  1595 +int nr_ice_peer_ctx_start_checks2(nr_ice_peer_ctx *pctx, int allow_non_first)
  1596 +  {
  1597      int r,_status;
  1598      nr_ice_media_stream *stream;
  1600      stream=STAILQ_FIRST(&pctx->peer_streams);
  1601      if(!stream)
  1602        ABORT(R_FAILED);
  1604 +    while (stream) {
  1605 +      if(!TAILQ_EMPTY(&stream->check_list))
  1606 +        break;
  1608 +      if(!allow_non_first){
  1609 +        r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) first stream has empty check list",pctx->ctx->label,pctx->label);
  1610 +        ABORT(R_FAILED);
  1611 +      }
  1613 +      stream=STAILQ_NEXT(stream, entry);
  1614 +    }
  1616 +    if (!stream) {
  1617 +      r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) no streams with non-empty check lists",pctx->ctx->label,pctx->label);
  1618 +      ABORT(R_NOT_FOUND);
  1619 +    }
  1621      if (stream->ice_state == NR_ICE_MEDIA_STREAM_CHECKS_FROZEN) {
  1622 -        if(r=nr_ice_media_stream_unfreeze_pairs(pctx,stream))
  1623 -          ABORT(r);
  1624 -        if(r=nr_ice_media_stream_start_checks(pctx,stream))
  1625 -          ABORT(r);
  1626 +      if(r=nr_ice_media_stream_unfreeze_pairs(pctx,stream))
  1627 +        ABORT(r);
  1628 +      if(r=nr_ice_media_stream_start_checks(pctx,stream))
  1629 +        ABORT(r);
  1632      _status=0;
  1633    abort:
  1634      return(_status);
  1637  #ifndef NDEBUG
  1638  int nr_ice_peer_ctx_dump_state(nr_ice_peer_ctx *pctx,FILE *out)
  1640 @@ -253,26 +382,28 @@
  1641        stream=STAILQ_NEXT(stream,entry);
  1643      fprintf(out,"==========================================\n");
  1645      _status=0;
  1646    abort:
  1647      return(_status);
  1649  #endif
  1651 -static void nr_ice_peer_ctx_fire_done(int s, int how, void *cb_arg)
  1652 +static void nr_ice_peer_ctx_fire_done(NR_SOCKET s, int how, void *cb_arg)
  1654      nr_ice_peer_ctx *pctx=cb_arg;
  1656      /* Fire the handler callback to say we're done */
  1657 -    pctx->handler->vtbl->ice_completed(pctx->handler->obj, pctx);
  1658 +    if (pctx->handler) {
  1659 +      pctx->handler->vtbl->ice_completed(pctx->handler->obj, pctx);
  1660 +    }
  1664  /* OK, a stream just went ready. Examine all the streams to see if we're
  1665     maybe miraculously done */
  1666  int nr_ice_peer_ctx_stream_done(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream)
  1668      int _status;
  1669      nr_ice_media_stream *str;
  1670      int failed=0;
  1671 @@ -365,21 +496,24 @@
  1672          NR_TRANSPORT_ADDR_CMP_MODE_ALL))
  1673          break;
  1675        cand=TAILQ_NEXT(cand,entry_comp);
  1678      if(!cand)
  1679        ABORT(R_REJECTED);
  1681      /* OK, there's a match. Call the handler */
  1682 -    r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): Delivering data", pctx->label);
  1684 -    pctx->handler->vtbl->msg_recvd(pctx->handler->obj,
  1685 -      pctx,comp->stream,comp->component_id,data,len);
  1686 +    if (pctx->handler) {
  1687 +      r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): Delivering data", pctx->label);
  1689 +      pctx->handler->vtbl->msg_recvd(pctx->handler->obj,
  1690 +        pctx,comp->stream,comp->component_id,data,len);
  1691 +    }
  1693      _status=0;
  1694    abort:
  1695      return(_status);
  1699 diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_peer_ctx.h src/ice/ice_peer_ctx.h
  1700 --- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_peer_ctx.h	2012-09-16 16:26:08.000000000 -0700
  1701 +++ src/ice/ice_peer_ctx.h	2012-10-06 08:30:22.000000000 -0700
  1702 @@ -33,23 +33,21 @@
  1705  #ifndef _ice_peer_ctx_h
  1706  #define _ice_peer_ctx_h
  1707  #ifdef __cplusplus
  1708  using namespace std;
  1709  extern "C" {
  1710  #endif /* __cplusplus */
  1712  struct nr_ice_peer_ctx_ {
  1713 -  int state;
  1714    char *label;
  1716    nr_ice_ctx *ctx;
  1717    nr_ice_handler *handler;
  1719    UCHAR controlling; /* 1 for controlling, 0 for controlled */
  1720    UINT8 tiebreaker;
  1722    char *peer_ufrag;
  1723    char *peer_pwd;
  1724    int peer_lite;
  1725    int peer_ice_mismatch;
  1726 @@ -59,23 +57,26 @@
  1727    int waiting_pairs;
  1729    STAILQ_ENTRY(nr_ice_peer_ctx_) entry;
  1730  };
  1732  typedef STAILQ_HEAD(nr_ice_peer_ctx_head_, nr_ice_peer_ctx_) nr_ice_peer_ctx_head;
  1734  int nr_ice_peer_ctx_create(nr_ice_ctx *ctx, nr_ice_handler *handler,char *label, nr_ice_peer_ctx **pctxp);
  1735  int nr_ice_peer_ctx_destroy(nr_ice_peer_ctx **pctxp);
  1736  int nr_ice_peer_ctx_parse_stream_attributes(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, char **attrs, int attr_ct);
  1737 +int nr_ice_peer_ctx_parse_trickle_candidate(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, char *cand);
  1739  int nr_ice_peer_ctx_pair_candidates(nr_ice_peer_ctx *pctx);
  1740  int nr_ice_peer_ctx_parse_global_attributes(nr_ice_peer_ctx *pctx, char **attrs, int attr_ct);
  1741  int nr_ice_peer_ctx_start_checks(nr_ice_peer_ctx *pctx);
  1742 +int nr_ice_peer_ctx_start_checks2(nr_ice_peer_ctx *pctx, int allow_non_first);
  1743  int nr_ice_peer_ctx_dump_state(nr_ice_peer_ctx *pctx,FILE *out);
  1744  int nr_ice_peer_ctx_log_state(nr_ice_peer_ctx *pctx);
  1745  int nr_ice_peer_ctx_stream_done(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream);
  1746  int nr_ice_peer_ctx_find_component(nr_ice_peer_ctx *pctx, nr_ice_media_stream *str, int component_id, nr_ice_component **compp);
  1747  int nr_ice_peer_ctx_deliver_packet_maybe(nr_ice_peer_ctx *pctx, nr_ice_component *comp, nr_transport_addr *source_addr, UCHAR *data, int len);
  1748  #ifdef __cplusplus
  1750  #endif /* __cplusplus */
  1751  #endif
  1753 diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_socket.c src/ice/ice_socket.c
  1754 --- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_socket.c	2012-09-16 16:26:08.000000000 -0700
  1755 +++ src/ice/ice_socket.c	2012-10-06 08:30:22.000000000 -0700
  1756 @@ -216,28 +216,34 @@
  1757        RFREE(s1);
  1760      RFREE(isock);
  1762      return(0);
  1765  int nr_ice_socket_close(nr_ice_socket *isock)
  1767 +#ifdef NR_SOCKET_IS_VOID_PTR
  1768 +    NR_SOCKET fd=NULL;
  1769 +    NR_SOCKET no_socket = NULL;
  1770 +#else
  1771      NR_SOCKET fd=-1;
  1772 +    NR_SOCKET no_socket = -1;
  1773 +#endif
  1775      if (!isock||!isock->sock)
  1776        return(0);
  1778      nr_socket_getfd(isock->sock,&fd);
  1779      assert(isock->sock!=0);
  1780 -    if(fd!=-1){
  1781 +    if(fd != no_socket){
  1782        NR_ASYNC_CANCEL(fd,NR_ASYNC_WAIT_READ);
  1783        NR_ASYNC_CANCEL(fd,NR_ASYNC_WAIT_WRITE);
  1784        nr_socket_destroy(&isock->sock);
  1787      return(0);
  1790  int nr_ice_socket_register_stun_client(nr_ice_socket *sock, nr_stun_client_ctx *srv,void **handle)
  1792 diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/net/nr_socket.h src/net/nr_socket.h
  1793 --- /Users/ekr/dev/mtransport-import-references/nICEr/src/net/nr_socket.h	2012-09-16 16:26:09.000000000 -0700
  1794 +++ src/net/nr_socket.h	2012-10-06 08:30:22.000000000 -0700
  1795 @@ -38,21 +38,23 @@
  1796  #include <sys/types.h>
  1797  #ifdef WIN32
  1798  #include <winsock2.h>
  1799  #include <ws2tcpip.h>
  1800  #else
  1801  #include <sys/socket.h>
  1802  #endif
  1804  #include "transport_addr.h"
  1806 -#ifdef WIN32
  1807 +#ifdef __cplusplus
  1808 +#define restrict
  1809 +#elif defined(WIN32)
  1810  #define restrict __restrict
  1811  #endif
  1813  typedef struct nr_socket_vtbl_ {
  1814    int (*destroy)(void **obj);
  1815    int (*ssendto)(void *obj,const void *msg, size_t len, int flags,
  1816      nr_transport_addr *addr);
  1817    int (*srecvfrom)(void *obj,void * restrict buf, size_t maxlen, size_t *len, int flags,
  1818      nr_transport_addr *addr);
  1819    int (*getfd)(void *obj, NR_SOCKET *fd);
  1820 diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/net/transport_addr_reg.c src/net/transport_addr_reg.c
  1821 --- /Users/ekr/dev/mtransport-import-references/nICEr/src/net/transport_addr_reg.c	2012-09-16 16:26:09.000000000 -0700
  1822 +++ src/net/transport_addr_reg.c	2012-10-06 08:30:22.000000000 -0700
  1823 @@ -29,25 +29,27 @@
  1824  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  1825  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  1826  */
  1830  static char *RCSSTRING __UNUSED__="$Id: transport_addr_reg.c,v 1.2 2008/04/28 17:59:03 ekr Exp $";
  1832  #include <csi_platform.h>
  1833  #include <stdio.h>
  1834 +#include <string.h>
  1835  #include <memory.h>
  1836  #include <sys/types.h>
  1837  #ifdef WIN32
  1838  #include <winsock2.h>
  1839  #else
  1840 +#include <strings.h>
  1841  #include <unistd.h>
  1842  #include <sys/socket.h>
  1843  #include <netinet/in.h>
  1844  #include <arpa/inet.h>
  1845  #endif
  1846  #include <assert.h>
  1847  #include "nr_api.h"
  1848  #include "transport_addr.h"
  1849  #include "transport_addr_reg.h"
  1851 @@ -83,20 +85,22 @@
  1853      if ((r=NR_reg_get2_uint2(prefix, "port", &port))) {
  1854          if (r != R_NOT_FOUND)
  1855              ABORT(r);
  1856          port = 0;
  1859      if ((r=NR_reg_alloc2_string(prefix, "protocol", &protocol))) {
  1860          if (r != R_NOT_FOUND)
  1861              ABORT(r);
  1862 +        p = IPPROTO_UDP;
  1864          protocol = 0;
  1866      else {
  1867          if (!strcasecmp("tcp", protocol))
  1868              p = IPPROTO_TCP;
  1869          else if (!strcasecmp("udp", protocol))
  1870              p = IPPROTO_UDP;
  1871          else
  1872              ABORT(R_BAD_DATA);
  1874 diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/addrs.c src/stun/addrs.c
  1875 --- /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/addrs.c	2012-09-16 16:26:10.000000000 -0700
  1876 +++ src/stun/addrs.c	2012-10-06 09:42:43.000000000 -0700
  1877 @@ -46,20 +46,22 @@
  1878  #include <sys/sysctl.h>
  1879  #include <sys/param.h>
  1880  #include <sys/socket.h>
  1881  #include <sys/syslog.h>
  1882  #include <net/if.h>
  1883  #ifndef LINUX
  1884  #include <net/if_var.h>
  1885  #include <net/if_dl.h>
  1886  #include <net/if_types.h>
  1887  #include <sys/sockio.h>
  1888 +#else
  1889 +#include <linux/if.h>
  1890  #endif
  1891  #include <net/route.h>
  1893  /* IP */
  1894  #include <netinet/in.h>
  1895  #ifdef LINUX
  1896  #include "sys/ioctl.h"
  1897  #else
  1898  #include <netinet/in_var.h>
  1899  #endif
  1900 @@ -105,20 +107,23 @@
  1901   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  1902   * SUCH DAMAGE.
  1903   */
  1905  #include <err.h>
  1907  static void stun_rt_xaddrs(caddr_t, caddr_t, struct rt_addrinfo *);
  1908  static int stun_grab_addrs(char *name, int addrcount,
  1909                 struct ifa_msghdr *ifam,
  1910                 nr_transport_addr addrs[], int maxaddrs, int *count);
  1911 +static int
  1912 +nr_stun_is_duplicate_addr(nr_transport_addr addrs[], int count, nr_transport_addr *addr);
  1915  /*
  1916   * Expand the compacted form of addresses as returned via the
  1917   * configuration read via sysctl().
  1918   */
  1919  #define ROUNDUP(a) \
  1920      ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
  1921  #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
  1923  static void
  1924 @@ -135,21 +140,21 @@
  1925              continue;
  1926          rtinfo->rti_info[i] = sa = (struct sockaddr *)cp;
  1927          ADVANCE(cp, sa);
  1931  static int
  1932  stun_grab_addrs(char *name, int addrcount, struct ifa_msghdr *ifam, nr_transport_addr addrs[], int maxaddrs, int *count)
  1934      int r,_status;
  1935 -    NR_SOCKET s = -1;
  1936 +    int s = -1;
  1937      struct ifreq ifr;
  1938      struct rt_addrinfo info;
  1939      struct sockaddr_in *sin;
  1941      ifr.ifr_addr.sa_family = AF_INET;
  1942      strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
  1944      if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0) {
  1945        r_log(NR_LOG_STUN, LOG_WARNING, "unable to obtain addresses from socket");
  1946        ABORT(R_FAILED);
  1947 @@ -180,21 +185,20 @@
  1948          addrcount--;
  1950          if (*count >= maxaddrs) {
  1951              r_log(NR_LOG_STUN, LOG_WARNING, "Address list truncated at %d out of entries", maxaddrs, maxaddrs+addrcount);
  1952              break;
  1955          ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen);
  1959      _status = 0;
  1960    abort:
  1961      if (s != -1) close(s);
  1962      return _status;
  1965  static int
  1966  stun_get_mib_addrs(nr_transport_addr addrs[], int maxaddrs, int *count)
  1968      int _status;
  1969 @@ -551,44 +555,48 @@
  1970  #else
  1972  static int
  1973  stun_get_siocgifconf_addrs(nr_transport_addr addrs[], int maxaddrs, int *count)
  1975     struct ifconf ifc;
  1976     int _status;
  1977     int s = socket( AF_INET, SOCK_DGRAM, 0 );
  1978     int len = 100 * sizeof(struct ifreq);
  1979     int r;
  1980 +   int e;
  1981 +   char *ptr;
  1982 +   int tl;
  1983 +   int n;
  1984 +   struct ifreq ifr2;
  1986     char buf[ len ];
  1988     ifc.ifc_len = len;
  1989     ifc.ifc_buf = buf;
  1991 -   int e = ioctl(s,SIOCGIFCONF,&ifc);
  1992 -   char *ptr = buf;
  1993 -   int tl = ifc.ifc_len;
  1994 -   int n=0;
  1995 +   e = ioctl(s,SIOCGIFCONF,&ifc);
  1996 +   ptr = buf;
  1997 +   tl = ifc.ifc_len;
  1998 +   n=0;
  2000     while ( (tl > 0) && ( n < maxaddrs) )
  2002        struct ifreq* ifr = (struct ifreq *)ptr;
  2004  #ifdef LINUX
  2005 -      int si = sizeof(ifr->ifr_name) + sizeof(ifr->ifr_addr);
  2006 +      int si = sizeof(struct ifreq);
  2007  #else
  2008        int si = sizeof(ifr->ifr_name) + MAX(ifr->ifr_addr.sa_len, sizeof(ifr->ifr_addr));
  2009  #endif
  2010        tl -= si;
  2011        ptr += si;
  2013 -      struct ifreq ifr2;
  2014        ifr2 = *ifr;
  2016        e = ioctl(s,SIOCGIFADDR,&ifr2);
  2017        if ( e == -1 )
  2019            continue;
  2022        //r_log(NR_LOG_STUN, LOG_ERR, "ioctl addr e = %d",e);
  2024 @@ -603,21 +611,21 @@
  2026     close(s);
  2028     *count = n;
  2030      _status = 0;
  2031      return _status;
  2033  #endif
  2035 -int
  2036 +static int
  2037  nr_stun_is_duplicate_addr(nr_transport_addr addrs[], int count, nr_transport_addr *addr)
  2039      int i;
  2040      int different;
  2042      for (i = 0; i < count; ++i) {
  2043          different = nr_transport_addr_cmp(&addrs[i], addr, NR_TRANSPORT_ADDR_CMP_MODE_ALL);
  2044          if (!different) 
  2045              return 1;  /* duplicate */
  2047 diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/nr_socket_turn.c src/stun/nr_socket_turn.c
  2048 --- /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/nr_socket_turn.c	2012-09-16 16:26:10.000000000 -0700
  2049 +++ src/stun/nr_socket_turn.c	2012-10-06 08:30:22.000000000 -0700
  2050 @@ -246,17 +246,19 @@
  2051      default:
  2052          assert(0);
  2053          break;
  2056      return R_FAILED;
  2059  static int nr_socket_turn_close(void *obj)
  2061 +#ifndef NDEBUG
  2062      nr_socket_turn *sturn=obj;
  2063      assert(sturn->magic_cookie == nr_socket_turn_magic_cookie);
  2064 +#endif
  2066      return 0;
  2069  #endif /* USE_TURN */
  2070 diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/stun_client_ctx.c src/stun/stun_client_ctx.c
  2071 --- /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/stun_client_ctx.c	2012-09-16 16:26:10.000000000 -0700
  2072 +++ src/stun/stun_client_ctx.c	2012-10-06 08:30:22.000000000 -0700
  2073 @@ -38,21 +38,22 @@
  2074  #include <string.h>
  2076  #include <nr_api.h>
  2077  #include "stun.h"
  2078  #include "async_timer.h"
  2079  #include "registry.h"
  2080  #include "stun_reg.h"
  2081  #include "r_time.h"
  2083  static int nr_stun_client_send_request(nr_stun_client_ctx *ctx);
  2084 -static void nr_stun_client_timer_expired_cb(int a, int b, void *cb_arg);
  2085 +static void nr_stun_client_timer_expired_cb(NR_SOCKET s, int b, void *cb_arg);
  2086 +static int nr_stun_client_get_password(void *arg, nr_stun_message *msg, Data **password);
  2088  int nr_stun_client_ctx_create(char *label, nr_socket *sock, nr_transport_addr *peer, UINT4 RTO, nr_stun_client_ctx **ctxp)
  2090      nr_stun_client_ctx *ctx=0;
  2091      int r,_status;
  2093      if ((r=nr_stun_startup()))
  2094        ABORT(r);
  2096      if(!(ctx=RCALLOC(sizeof(nr_stun_client_ctx))))
  2097 @@ -185,21 +186,21 @@
  2098      ctx->finished_cb   = 0;
  2099      ctx->cb_arg        = 0;
  2100      ctx->request_ct    = 0;
  2101      ctx->timeout_ms    = 0;
  2103      ctx->state = NR_STUN_CLIENT_STATE_INITTED;
  2105      return 0;
  2108 -static void nr_stun_client_timer_expired_cb(int a, int b, void *cb_arg)
  2109 +static void nr_stun_client_timer_expired_cb(NR_SOCKET s, int b, void *cb_arg)
  2111      int _status;
  2112      nr_stun_client_ctx *ctx=cb_arg;
  2113      struct timeval now;
  2114      INT8 ms_waited;
  2116      /* Prevent this timer from being cancelled later */
  2117      ctx->timer_handle=0;
  2119      /* Shouldn't happen */
  2120 @@ -387,21 +388,21 @@
  2123      _status=0;
  2124    abort:
  2125      if (_status) {
  2126        ctx->state=NR_STUN_CLIENT_STATE_FAILED;
  2128      return(_status);
  2131 -int nr_stun_client_get_password(void *arg, nr_stun_message *msg, Data **password)
  2132 +static int nr_stun_client_get_password(void *arg, nr_stun_message *msg, Data **password)
  2134      *password = (Data*)arg;
  2135      if (!arg)
  2136          return(R_NOT_FOUND);
  2137      return(0);
  2140  int nr_stun_client_process_response(nr_stun_client_ctx *ctx, UCHAR *msg, int len, nr_transport_addr *peer_addr)
  2142      int r,_status;
  2143 diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/stun_codec.c src/stun/stun_codec.c
  2144 --- /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/stun_codec.c	2012-09-16 16:26:10.000000000 -0700
  2145 +++ src/stun/stun_codec.c	2012-10-06 08:30:22.000000000 -0700
  2146 @@ -73,20 +73,22 @@
  2147  static int nr_stun_decode_htonll(UCHAR *buf, int buflen, int *offset, UINT8 *data);
  2148  static int nr_stun_decode(int length, UCHAR *buf, int buflen, int *offset, UCHAR *data);
  2150  static int nr_stun_attr_string_illegal(nr_stun_attr_info *attr_info, int len, void *data, int max_bytes, int max_chars);
  2152  static int nr_stun_attr_error_code_illegal(nr_stun_attr_info *attr_info, int attrlen, void *data);
  2153  static int nr_stun_attr_nonce_illegal(nr_stun_attr_info *attr_info, int attrlen, void *data);
  2154  static int nr_stun_attr_realm_illegal(nr_stun_attr_info *attr_info, int attrlen, void *data);
  2155  static int nr_stun_attr_server_illegal(nr_stun_attr_info *attr_info, int attrlen, void *data);
  2156  static int nr_stun_attr_username_illegal(nr_stun_attr_info *attr_info, int attrlen, void *data);
  2157 +static int
  2158 +nr_stun_attr_codec_fingerprint_decode(nr_stun_attr_info *attr_info, int attrlen, UCHAR *buf, int offset, int buflen, void *data);
  2161  int
  2162  nr_stun_encode_htons(UINT2 data, int buflen, UCHAR *buf, int *offset)
  2164     UINT2 d = htons(data);
  2166     if (*offset + sizeof(d) >= buflen) {
  2167        r_log(NR_LOG_STUN, LOG_WARNING, "Attempted buffer overrun: %d + %d >= %d", *offset, sizeof(d), buflen);
  2168        return R_BAD_DATA;
  2169 @@ -632,21 +634,21 @@
  2172      fingerprint->checksum = checksum ^ 0x5354554e;
  2174      r_log(NR_LOG_STUN, LOG_DEBUG, "Computed FINGERPRINT %08x", fingerprint->checksum);
  2176      fingerprint->valid = 1;
  2177      return nr_stun_attr_codec_UINT4.encode(attr_info, &fingerprint->checksum, offset, buflen, buf, attrlen);
  2180 -int
  2181 +static int
  2182  nr_stun_attr_codec_fingerprint_decode(nr_stun_attr_info *attr_info, int attrlen, UCHAR *buf, int offset, int buflen, void *data)
  2184      int r,_status;
  2185      nr_stun_attr_fingerprint *fingerprint = data;
  2186      nr_stun_message_header *header = (nr_stun_message_header*)buf;
  2187      int length;
  2188      UINT4 checksum;
  2190      if ((r=nr_stun_attr_codec_UINT4.decode(attr_info, attrlen, buf, offset, buflen, &fingerprint->checksum)))
  2191          ABORT(r);
  2192 diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/stun_proc.c src/stun/stun_proc.c
  2193 --- /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/stun_proc.c	2012-09-16 16:26:10.000000000 -0700
  2194 +++ src/stun/stun_proc.c	2012-10-06 08:30:22.000000000 -0700
  2195 @@ -43,20 +43,22 @@
  2196  #include <time.h>
  2197  #else   /* UNIX */
  2198  #include <string.h>
  2199  #endif  /* end UNIX */
  2200  #include <assert.h>
  2202  #include "stun.h"
  2203  #include "stun_reg.h"
  2204  #include "registry.h"
  2206 +static int
  2207 +nr_stun_add_realm_and_nonce(int new_nonce, nr_stun_server_client *clnt, nr_stun_message *res);
  2209  /* draft-ietf-behave-rfc3489bis-10.txt S 7.3 */
  2210  int
  2211  nr_stun_receive_message(nr_stun_message *req, nr_stun_message *msg)
  2213      int _status;
  2214      nr_stun_message_attribute *attr;
  2216  #ifdef USE_RFC_3489_BACKWARDS_COMPATIBLE
  2217      /* if this message was generated by an RFC 3489 impementation,
  2218 @@ -371,21 +373,21 @@
  2219          /* nothing to check in this case */
  2220          break;
  2221  #endif /* USE_STUND_0_96 */
  2224     _status=0;
  2225   abort:
  2226       return _status;
  2229 -int
  2230 +static int
  2231  nr_stun_add_realm_and_nonce(int new_nonce, nr_stun_server_client *clnt, nr_stun_message *res)
  2233      int r,_status;
  2234      char *realm = 0;
  2235      char *nonce;
  2236      UINT2 size;
  2238      if ((r=NR_reg_alloc_string(NR_STUN_REG_PREF_SERVER_REALM, &realm)))
  2239          ABORT(r);
  2241 diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/stun_server_ctx.c src/stun/stun_server_ctx.c
  2242 --- /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/stun_server_ctx.c	2012-09-16 16:26:10.000000000 -0700
  2243 +++ src/stun/stun_server_ctx.c	2012-10-06 08:30:22.000000000 -0700
  2244 @@ -114,21 +114,21 @@
  2245      STAILQ_INSERT_TAIL(&ctx->clients,clnt,entry);
  2247      _status=0;
  2248    abort:
  2249      if(_status){
  2250        nr_stun_server_destroy_client(clnt);
  2252      return(_status);
  2255 -int nr_stun_server_get_password(void *arg, nr_stun_message *msg, Data **password)
  2256 +static int nr_stun_server_get_password(void *arg, nr_stun_message *msg, Data **password)
  2258      int _status;
  2259      nr_stun_server_ctx *ctx = (nr_stun_server_ctx*)arg;
  2260      nr_stun_server_client *clnt = 0;
  2261      nr_stun_message_attribute *username_attribute;
  2263      if ((nr_stun_get_message_client(ctx, msg, &clnt))) {
  2264          if (! nr_stun_message_has_attribute(msg, NR_STUN_ATTR_USERNAME, &username_attribute)) {
  2265             r_log(NR_LOG_STUN,LOG_NOTICE,"STUN-SERVER(%s): Missing Username",ctx->label);
  2266             ABORT(R_NOT_FOUND);
  2267 diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/stun_util.c src/stun/stun_util.c
  2268 --- /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/stun_util.c	2012-09-16 16:26:10.000000000 -0700
  2269 +++ src/stun/stun_util.c	2012-10-06 08:30:22.000000000 -0700
  2270 @@ -94,21 +94,20 @@
  2271      _status = 0;
  2272    abort:
  2273      return _status;
  2276  int
  2277  nr_stun_find_local_addresses(nr_transport_addr addrs[], int maxaddrs, int *count)
  2279      int r,_status;
  2280      NR_registry *children = 0;
  2281 -    int i;
  2283      if ((r=NR_reg_get_child_count(NR_STUN_REG_PREF_ADDRESS_PRFX, (unsigned int*)count)))
  2284          if (r == R_NOT_FOUND)
  2285              *count = 0;
  2286          else
  2287              ABORT(r);
  2289      if (*count == 0) {
  2290          if ((r=nr_stun_get_addrs(addrs, maxaddrs, 1, count)))
  2291              ABORT(r);
  2292 diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/turn_client_ctx.c src/stun/turn_client_ctx.c
  2293 --- /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/turn_client_ctx.c	2012-09-16 16:26:10.000000000 -0700
  2294 +++ src/stun/turn_client_ctx.c	2012-10-06 08:30:22.000000000 -0700
  2295 @@ -55,21 +55,24 @@
  2296  };
  2298  static int TURN_PHASE_MODE[NUMBER_OF_STUN_CTX] = {
  2299      NR_TURN_CLIENT_MODE_ALLOCATE_REQUEST1,
  2300      NR_TURN_CLIENT_MODE_ALLOCATE_REQUEST2,
  2301      NR_TURN_CLIENT_MODE_SET_ACTIVE_DEST_REQUEST
  2302  };
  2305  static int nr_turn_client_next_action(nr_turn_client_ctx *ctx, int stun_ctx_state);
  2306 -static void nr_turn_client_cb(int s, int how, void *cb_arg);
  2307 +static void nr_turn_client_cb(NR_SOCKET s, int how, void *cb_arg);
  2308 +static int
  2309 +nr_turn_client_prepare_start(nr_turn_client_ctx *ctx, char *username, Data *password, UINT4 bandwidth_kbps, UINT4 lifetime_secs, NR_async_cb finished_cb, void *cb_arg);
  2312  int
  2313  nr_turn_client_next_action(nr_turn_client_ctx *ctx, int stun_ctx_state)
  2315      int r,_status;
  2317      assert(ctx->phase >= -1 && ctx->phase < NUMBER_OF_STUN_CTX);
  2319      switch (ctx->state) {
  2320      //case NR_TURN_CLIENT_STATE_ALLOCATING:
  2321 @@ -147,21 +150,21 @@
  2322               * because as a side effect this ctx may be operated on in the
  2323               * callback */
  2324              finished_cb(0,0,ctx->cb_arg);
  2328      return(_status);
  2331  void
  2332 -nr_turn_client_cb(int s, int how, void *cb_arg)
  2333 +nr_turn_client_cb(NR_SOCKET s, int how, void *cb_arg)
  2335      int r,_status;
  2336      nr_turn_client_ctx *ctx = (nr_turn_client_ctx*)cb_arg;
  2337      nr_stun_client_ctx *stun_ctx = ctx->stun_ctx[ctx->phase];
  2339      assert(ctx->phase >= 0);
  2341      if ((r=nr_turn_client_next_action(ctx, stun_ctx->state)))
  2342          ABORT(r);
  2344 @@ -234,21 +237,21 @@
  2346      RFREE(ctx->username);
  2347      r_data_destroy(&ctx->password);
  2349      RFREE(ctx->label);
  2350      RFREE(ctx);
  2352      return(0);
  2355 -int
  2356 +static int
  2357  nr_turn_client_prepare_start(nr_turn_client_ctx *ctx, char *username, Data *password, UINT4 bandwidth_kbps, UINT4 lifetime_secs, NR_async_cb finished_cb, void *cb_arg)
  2359      int r,_status;
  2360      nr_stun_client_allocate_request1_params          *allocate_request1 = 0;
  2361      nr_stun_client_allocate_request2_params          *allocate_request2 = 0;
  2362      nr_stun_client_allocate_response1_results        *allocate_response1 = 0;
  2363  //    nr_stun_client_allocate_response2_results        *allocate_response2;
  2365      if (ctx->state != NR_TURN_CLIENT_STATE_INITTED)
  2366          ABORT(R_NOT_PERMITTED);
  2367 diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/util/ice_util.c src/util/ice_util.c
  2368 --- /Users/ekr/dev/mtransport-import-references/nICEr/src/util/ice_util.c	2012-09-16 16:26:10.000000000 -0700
  2369 +++ src/util/ice_util.c	2012-10-06 08:30:22.000000000 -0700
  2370 @@ -31,20 +31,21 @@
  2371  */
  2373  #include <stdarg.h>
  2376  static char *RCSSTRING __UNUSED__="$Id: ice_util.c,v 1.2 2008/04/28 17:59:05 ekr Exp $";
  2378  #include <stdarg.h>
  2379  #include <string.h>
  2380  #include "nr_api.h"
  2381 +#include "ice_util.h"
  2383  int nr_concat_strings(char **outp,...)
  2385      va_list ap;
  2386      char *s,*out=0;
  2387      int len=0;
  2388      int _status;
  2390      va_start(ap,outp);
  2391      while(s=va_arg(ap,char *)){
  2392 diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/util/mbslen.c src/util/mbslen.c
  2393 --- /Users/ekr/dev/mtransport-import-references/nICEr/src/util/mbslen.c	2012-09-16 16:26:10.000000000 -0700
  2394 +++ src/util/mbslen.c	2012-10-06 08:31:01.000000000 -0700
  2395 @@ -56,21 +56,21 @@
  2397  #ifdef DARWIN
  2398      static locale_t loc = 0;
  2399      static int initialized = 0;
  2400  #endif /* DARWIN */
  2401  #ifdef WIN32
  2402      char *my_locale=0;
  2403      unsigned int i;
  2404  #endif  /* WIN32 */
  2405      int _status;
  2406 -    int nbytes;
  2407 +    size_t nbytes;
  2408      int nchars;
  2409      mbstate_t mbs;
  2411  #ifdef DARWIN
  2412      if (! initialized) {
  2413          initialized = 1;
  2414          loc = newlocale(LC_CTYPE_MASK, "UTF-8", LC_GLOBAL_LOCALE);
  2417      if (loc == 0) {
  2418 @@ -102,25 +102,28 @@
  2420      memset(&mbs, 0, sizeof(mbs));
  2421      nchars = 0;
  2423  #ifdef DARWIN
  2424      while (*s != '\0' && (nbytes = mbrlen_l(s, strlen(s), &mbs, loc)) != 0)
  2425  #else
  2426      while (*s != '\0' && (nbytes = mbrlen(s, strlen(s), &mbs)) != 0)
  2427  #endif /* DARWIN */
  2429 -        assert(nbytes >= 0);
  2430 -        if (nbytes == (size_t)-1)   /* should never happen */
  2431 +        if (nbytes == (size_t)-1)   /* should never happen */ {
  2432 +	    assert(0);
  2433              ABORT(R_INTERNAL);
  2434 -        if (nbytes == (size_t)-2)   /* encoding error */
  2435 +	}
  2436 +        if (nbytes == (size_t)-2)   /* encoding error */ {
  2437 +	    assert(0);
  2438              ABORT(R_BAD_DATA);
  2439 +	}
  2441          s += nbytes;
  2442          ++nchars;
  2445      *ncharsp = nchars;
  2447      _status = 0;
  2448    abort:
  2449  #ifdef WIN32

mercurial