1diff -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 @@
5
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"
14
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 */
26
27 char *nr_ice_candidate_type_names[]={0,"host","srflx","prflx","relay",0};
28
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);
49
50     RFREE(cand->foundation);
51     RFREE(cand->label);
52     RFREE(cand);
53
54     return(0);
55   }
56
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   }
63
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     }
74
75     if(type_preference > 126)
76       r_log(LOG_ICE,LOG_ERR,"Illegal type preference %d",type_preference);
77
78
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+    }
100
101     cand->priority=
102       (type_preference << 24) |
103       (interface_preference << 16) |
104       (stun_priority << 8) |
105       (256 - cand->component_id);
106
107     /* S 4.1.2 */
108     assert(cand->priority>=1&&cand->priority<=2147483647);
109
110@@ -306,21 +324,22 @@
111
112     cand->done_cb=ready_cb;
113     cand->cb_arg=cb_arg;
114
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     }
137
138     _status=0;
139   abort:
140     if(_status && _status!=R_WOULDBLOCK)
141       cand->state=NR_ICE_CAND_STATE_FAILED;
142     return(_status);
143   }
144
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;
150
151     cand->delay_timer=0;
152
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 @@
158
159     _status=0;
160   abort:
161     if(_status){
162       cand->state=NR_ICE_CAND_STATE_FAILED;
163     }
164     return(_status);
165   }
166
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;
174
175     cand->delay_timer=0;
176
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);
179
180@@ -443,21 +462,21 @@
181
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 */
190
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;
196
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     }
202
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   }
212
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;
222
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     }
228
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 */
233
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);
237
238         r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): Switching from TURN (%s) to RELAY (%s)",cand->u.relayed.turn->label,cand->label,label);
239
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);
243
244         r_log(LOG_ICE,LOG_DEBUG,"ICE-CANDIDATE(%s): base=%s, candidate=%s", cand->label, cand->base.as_string, cand->addr.as_string);
245
246diff -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 @@
250
251 typedef enum {HOST=1, SERVER_REFLEXIVE, PEER_REFLEXIVE, RELAYED} nr_ice_candidate_type;
252
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 };
276
277 extern char *nr_ice_candidate_type_names[];
278
279
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);
290
291 #ifdef __cplusplus
292 }
293 #endif /* __cplusplus */
294 #endif
295
296diff -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"
307
308 static char *nr_ice_cand_pair_states[]={"UNKNOWN","FROZEN","WAITING","IN_PROGRESS","FAILED","SUCCEEDED","CANCELLED"};
309
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);
314
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;
324
325     if(!(pair=RCALLOC(sizeof(nr_ice_cand_pair))))
326       ABORT(R_NO_MEMORY);
327
328     pair->pctx=pctx;
329
330     nr_ice_candidate_pair_compute_codeword(pair,lcand,rcand);
331
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);
336
337     nr_ice_candidate_pair_set_state(pctx,pair,NR_ICE_PAIR_STATE_FROZEN);
338     pair->local=lcand;
339     pair->remote=rcand;
340
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);
351
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);
353
354     /* Foundation */
355     if(r=nr_concat_strings(&pair->foundation,lcand->foundation,"|",
356-      rcand->foundation,0))
357+      rcand->foundation,NULL))
358       ABORT(r);
359
360
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;
366
367
368@@ -110,39 +110,39 @@
369
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;
377
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;
393
394     pair->stun_client->params.ice_binding_request.tiebreaker=pctx->tiebreaker;
395
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));
404
405     *pairp=pair;
406
407     _status=0;
408   abort:
409     RFREE(l2ruser);
410@@ -178,21 +178,21 @@
411
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);
415
416     nr_ice_candidate_pair_set_state(pctx,pair,NR_ICE_PAIR_STATE_WAITING);
417
418     return(0);
419   }
420
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  }
437
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;
441
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;
445
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--;
467
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     }
477
478     _status=0;
479   abort:
480     return(_status);
481   }
482
483@@ -505,42 +520,42 @@
484         break;
485       }
486
487       c1=TAILQ_NEXT(c1,entry);
488     }
489     if(!c1) TAILQ_INSERT_TAIL(head,pair,entry);
490
491     return(0);
492   }
493
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;
499
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);
501
502     nr_stun_client_reset(pair->stun_client);
503     pair->stun_client->params.ice_binding_request.control=NR_ICE_CONTROLLING;
504
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);
507
508     if(r=nr_ice_ctx_remember_id(pair->pctx->ctx, pair->stun_client->request))
509       ABORT(r);
510
511     _status=0;
512   abort:
513     return;
514   }
515
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;
521
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);
523
524     nr_stun_client_reset(pair->stun_client);
525     pair->stun_client->params.ice_binding_request.control=NR_ICE_CONTROLLED;
526
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 @@
529
530
531
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;
537
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);
542
543     nr_ice_compute_codeword(as_string,strlen(as_string),pair->codeword);
544
545     _status=0;
546       abort:
547     RFREE(as_string);
548 return;
549   }
550
551diff -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 @@
555
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);
568
569 #ifdef __cplusplus
570 }
571 #endif /* __cplusplus */
572 #endif
573
574diff -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);
591
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);
598
599         if(r=nr_ice_candidate_pair_insert(&comp->stream->check_list,pair)) {
600@@ -563,30 +563,38 @@
601           break;
602       }
603
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);
633
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       }
640
641       if(!pair)
642         ABORT(R_INTERNAL);
643
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);
651
652         isock=STAILQ_NEXT(isock,entry);
653       }
654
655     next_cand:
656       lcand=TAILQ_NEXT(lcand,entry_comp);
657     }
658
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   }
671
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;
679
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     }
686
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;
693
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);
696
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);
703
704         if(r=nr_ice_candidate_pair_cancel(pair->pctx,p2))
705           ABORT(r);
706       }
707
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);
711
712     if(r=nr_ice_media_stream_component_nominated(comp->stream,comp))
713@@ -734,21 +750,21 @@
714         ABORT(r);
715     }
716
717     _status=0;
718   abort:
719     RFREE(pairs);
720     return(_status);
721   }
722
723
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;
729
730     assert(comp->keepalive_ctx);
731
732     if(NR_reg_get_uint4(NR_ICE_REG_KEEPALIVE_TIMER,&keepalive_timeout)){
733       keepalive_timeout=15000; /* Default */
734     }
735
736diff -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"
741
742
743 int LOG_ICE = 0;
744
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);
752
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;
764
765     _status=0;
766   abort:
767     if(_status)
768       nr_ice_ctx_destroy_cb(0,0,ctx);
769
770     return(_status);
771   }
772
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;
781
782     RFREE(ctx->label);
783
784     RFREE(ctx->stun_servers);
785@@ -323,21 +323,21 @@
786     if(!ctxp || !*ctxp)
787       return(0);
788
789     NR_ASYNC_SCHEDULE(nr_ice_ctx_destroy_cb,*ctxp);
790
791     *ctxp=0;
792
793     return(0);
794   }
795
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;
800
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--;
805
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);
813
814       stream=STAILQ_NEXT(stream,entry);
815     }
816
817     if(ctx->uninitialized_candidates)
818       ABORT(R_WOULDBLOCK);
819-
820+
821+
822     _status=0;
823   abort:
824     return(_status);
825   }
826
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;
830
831     if(r=nr_ice_media_stream_create(ctx,label,components,streamp))
832diff -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];
837
838   STAILQ_ENTRY(nr_ice_stun_id_) entry;
839 } nr_ice_stun_id;
840
841 typedef STAILQ_HEAD(nr_ice_stun_id_head_,nr_ice_stun_id_) nr_ice_stun_id_head;
842
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;
853
854   char *ufrag;
855   char *pwd;
856
857   UINT4 Ta;
858
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 @@
863
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)
869
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);
881
882 extern int LOG_ICE;
883
884 #ifdef __cplusplus
885diff -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 $";
890
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"
897
898 static char *nr_ice_media_stream_states[]={"INVALID",
899-  "FROZEN","ACTIVE","COMPLETED","FAILED"
900+  "UNPAIRED","FROZEN","ACTIVE","COMPLETED","FAILED"
901 };
902
903 int nr_ice_media_stream_set_state(nr_ice_media_stream *str, int state);
904
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);
916
917     }
918
919     TAILQ_INIT(&stream->check_list);
920
921     stream->component_ct=components;
922-
923+    stream->ice_state = NR_ICE_MEDIA_STREAM_UNPAIRED;
924     *streamp=stream;
925
926     _status=0;
927   abort:
928     if(_status){
929       nr_ice_media_stream_destroy(&stream);
930     }
931-    return(_status);
932+    return(_status);
933   }
934
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);
942
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   }
953
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;
1001+
1002+    _status=0;
1003+  abort:
1004+    return(_status);
1005+  }
1006+
1007+
1008 int nr_ice_media_stream_pair_candidates(nr_ice_peer_ctx *pctx,nr_ice_media_stream *lstream,nr_ice_media_stream *pstream)
1009   {
1010     int r,_status;
1011     nr_ice_component *pcomp,*lcomp;
1012
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);
1018-
1019+
1020       lcomp=STAILQ_NEXT(lcomp,entry);
1021       pcomp=STAILQ_NEXT(pcomp,entry);
1022     };
1023
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+    }
1028+
1029     _status=0;
1030   abort:
1031     return(_status);
1032   }
1033
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)
1038   {
1039     int r,_status;
1040     nr_ice_media_stream *stream=cb_arg;
1041     nr_ice_cand_pair *pair;
1042     int timer_val;
1043
1044     assert(stream->pctx->active_streams!=0);
1045
1046     timer_val=stream->pctx->ctx->Ta*stream->pctx->active_streams;
1047
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);
1052
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;
1055
1056-
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);
1063     }
1064
1065     /* Hmmm... No WAITING. Let's look for FROZEN */
1066     if(!pair){
1067       pair=TAILQ_FIRST(&stream->check_list);
1068-
1069+
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;
1075         }
1076         pair=TAILQ_NEXT(pair,entry);
1077       }
1078     }
1079
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);
1083     }
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;
1089   }
1090
1091
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)
1094   {
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);
1100
1101     /* Cancel our timer */
1102     if(stream->timer){
1103       NR_async_timer_cancel(stream->timer);
1104       stream->timer=0;
1105     }
1106
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+    }
1111
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);
1115
1116   done:
1117     _status=0;
1118   abort:
1119     return(_status);
1120   }
1121@@ -515,21 +580,23 @@
1122
1123       p2=TAILQ_NEXT(p2,entry);
1124     }
1125
1126     /* Cancel our timer */
1127     if(stream->timer){
1128       NR_async_timer_cancel(stream->timer);
1129       stream->timer=0;
1130     }
1131
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+    }
1136
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);
1140
1141     _status=0;
1142   abort:
1143     return(_status);
1144   }
1145
1146diff -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;
1151
1152   struct nr_ice_media_stream_ *local_stream; /* used when this is a peer */
1153   int component_ct;
1154   nr_ice_component_head components;
1155
1156   char *ufrag;    /* ICE username */
1157   char *pwd;    /* ICE password */
1158
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
1164+
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
1170
1171   nr_ice_cand_pair_head check_list;
1172   void *timer;  /* Check list periodic timer */
1173
1174 //  nr_ice_cand_pair_head valid_list;
1175-
1176+
1177   STAILQ_ENTRY(nr_ice_media_stream_) entry;
1178 };
1179
1180 typedef STAILQ_HEAD(nr_ice_media_stream_head_,nr_ice_media_stream_) nr_ice_media_stream_head;
1181
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);
1198diff -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 $";
1203
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"
1221
1222 static void
1223@@ -125,21 +126,21 @@
1224     char *rel_addr=0;
1225
1226     if(!(cand=RCALLOC(sizeof(nr_ice_candidate))))
1227         ABORT(R_NO_MEMORY);
1228
1229     if(!(cand->label=r_strdup(orig)))
1230         ABORT(R_NO_MEMORY);
1231
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);
1238
1239     /* Candidate attr */
1240     if (strncasecmp(str, "candidate:", 10))
1241         ABORT(R_BAD_DATA);
1242
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 */
1248
1249         break;
1250     default:
1251         ABORT(R_INTERNAL);
1252         break;
1253     }
1254
1255     skip_whitespace(&str);
1256
1257-    assert(strlen(str) == 0);
1258-
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+    }
1264+
1265     *candp=cand;
1266
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);
1272
1273     RFREE(connection_address);
1274     RFREE(rel_addr);
1275     return(_status);
1276 }
1277
1278
1279 int
1280diff -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 $";
1285
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"
1293
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);
1298
1299 int nr_ice_peer_ctx_create(nr_ice_ctx *ctx, nr_ice_handler *handler,char *label, nr_ice_peer_ctx **pctxp)
1300   {
1301     int r,_status;
1302     nr_ice_peer_ctx *pctx=0;
1303
1304     if(!(pctx=RCALLOC(sizeof(nr_ice_peer_ctx))))
1305       ABORT(R_NO_MEMORY);
1306
1307     if(!(pctx->label=r_strdup(label)))
1308       ABORT(R_NO_MEMORY);
1309-
1310+
1311     pctx->ctx=ctx;
1312     pctx->handler=handler;
1313
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);
1319       }
1320
1321@@ -88,85 +90,177 @@
1322       nr_ice_peer_ctx_destroy_cb(0,0,pctx);
1323     }
1324     return(_status);
1325   }
1326
1327
1328
1329 int nr_ice_peer_ctx_parse_stream_attributes(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, char **attrs, int attr_ct)
1330   {
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;
1336
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);
1344-
1345-    /* Match up the local and remote components */
1346+
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;
1352
1353       comp=STAILQ_NEXT(comp,entry);
1354       comp2=STAILQ_NEXT(comp2,entry);
1355     }
1356-
1357
1358-    pstream->ice_state=NR_ICE_MEDIA_STREAM_CHECKS_FROZEN;
1359     pstream->local_stream=stream;
1360     pstream->pctx=pctx;
1361
1362+    if (r=nr_ice_peer_ctx_parse_stream_attributes_int(pctx,stream,pstream,attrs,attr_ct))
1363+      ABORT(r);
1364+
1365+
1366+    STAILQ_INSERT_TAIL(&pctx->peer_streams,pstream,entry);
1367+
1368+    _status=0;
1369+  abort:
1370+    return(_status);
1371+  }
1372+
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;
1377+
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+        }
1386       }
1387-
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);
1401       }
1402+    }
1403
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+  }
1412
1413-        j++;
1414-      }
1415-
1416-      if(!comp){
1417-        r_log(LOG_ICE,LOG_ERR,"Peer answered with more components than we offered");
1418-        ABORT(R_BAD_DATA);
1419-      }
1420-
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;
1428
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);
1435     }
1436
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;
1443+
1444+      j++;
1445+    }
1446+
1447+    if(!comp){
1448+      r_log(LOG_ICE,LOG_ERR,"Peer answered with more components than we offered");
1449+      ABORT(R_BAD_DATA);
1450+    }
1451+
1452+    cand->component=comp;
1453+
1454+    TAILQ_INSERT_TAIL(&comp->candidates,cand,entry_comp);
1455
1456     _status=0;
1457-  abort:
1458+ abort:
1459+    if (_status) {
1460+      nr_ice_candidate_destroy(&cand);
1461+    }
1462     return(_status);
1463   }
1464
1465+
1466+
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;
1474+
1475+    pstream=STAILQ_FIRST(&pctx->peer_streams);
1476+    while(pstream) {
1477+      if (pstream->local_stream == stream)
1478+        break;
1479+
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+    }
1486+
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+    }
1499+
1500+    if(r=nr_ice_ctx_parse_candidate(pctx,pstream,candidate)){
1501+      ABORT(r);
1502+    }
1503+
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+    }
1514+
1515+    _status =0;
1516+ abort:
1517+    return(_status);
1518+
1519+  }
1520+
1521+
1522 int nr_ice_peer_ctx_pair_candidates(nr_ice_peer_ctx *pctx)
1523   {
1524     nr_ice_media_stream *stream;
1525     int r,_status;
1526
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);
1530     }
1531
1532@@ -177,21 +271,21 @@
1533         ABORT(r);
1534
1535       stream=STAILQ_NEXT(stream,entry);
1536     }
1537
1538     _status=0;
1539   abort:
1540     return(_status);
1541   }
1542
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)
1545   {
1546     nr_ice_peer_ctx *pctx=cb_arg;
1547     nr_ice_media_stream *str1,*str2;
1548
1549     RFREE(pctx->label);
1550     RFREE(pctx->peer_ufrag);
1551     RFREE(pctx->peer_pwd);
1552
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 @@
1556     }
1557
1558     RFREE(pctx);
1559   }
1560
1561 int nr_ice_peer_ctx_destroy(nr_ice_peer_ctx **pctxp)
1562   {
1563
1564     if(!pctxp || !*pctxp)
1565       return(0);
1566-
1567+
1568+    /* Stop calling the handler */
1569+    (*pctxp)->handler = 0;
1570+
1571     NR_ASYNC_SCHEDULE(nr_ice_peer_ctx_destroy_cb,*pctxp);
1572
1573     *pctxp=0;
1574
1575     return(0);
1576   }
1577
1578+
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)
1582   {
1583+    return nr_ice_peer_ctx_start_checks2(pctx, 0);
1584+  }
1585+
1586+/* Start checks for some media stream.
1587+
1588+   If allow_non_first == 0, then we only look at the first stream,
1589+   which is 5245-complaint.
1590+
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;
1599
1600     stream=STAILQ_FIRST(&pctx->peer_streams);
1601     if(!stream)
1602       ABORT(R_FAILED);
1603
1604+    while (stream) {
1605+      if(!TAILQ_EMPTY(&stream->check_list))
1606+        break;
1607+
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+      }
1612+
1613+      stream=STAILQ_NEXT(stream, entry);
1614+    }
1615+
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+    }
1620+
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);
1630     }
1631
1632     _status=0;
1633   abort:
1634     return(_status);
1635   }
1636
1637 #ifndef NDEBUG
1638 int nr_ice_peer_ctx_dump_state(nr_ice_peer_ctx *pctx,FILE *out)
1639   {
1640@@ -253,26 +382,28 @@
1641       stream=STAILQ_NEXT(stream,entry);
1642     }
1643     fprintf(out,"==========================================\n");
1644
1645     _status=0;
1646   abort:
1647     return(_status);
1648   }
1649 #endif
1650
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)
1653   {
1654     nr_ice_peer_ctx *pctx=cb_arg;
1655
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+    }
1661   }
1662
1663
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)
1667   {
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;
1674
1675       cand=TAILQ_NEXT(cand,entry_comp);
1676     }
1677
1678     if(!cand)
1679       ABORT(R_REJECTED);
1680
1681     /* OK, there's a match. Call the handler */
1682-    r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): Delivering data", pctx->label);
1683
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);
1688+
1689+      pctx->handler->vtbl->msg_recvd(pctx->handler->obj,
1690+        pctx,comp->stream,comp->component_id,data,len);
1691+    }
1692
1693     _status=0;
1694   abort:
1695     return(_status);
1696   }
1697
1698
1699diff -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 @@
1703
1704
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 */
1711
1712 struct nr_ice_peer_ctx_ {
1713-  int state;
1714   char *label;
1715-
1716   nr_ice_ctx *ctx;
1717   nr_ice_handler *handler;
1718
1719   UCHAR controlling; /* 1 for controlling, 0 for controlled */
1720   UINT8 tiebreaker;
1721
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;
1728
1729   STAILQ_ENTRY(nr_ice_peer_ctx_) entry;
1730 };
1731
1732 typedef STAILQ_HEAD(nr_ice_peer_ctx_head_, nr_ice_peer_ctx_) nr_ice_peer_ctx_head;
1733
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);
1738+
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
1749 }
1750 #endif /* __cplusplus */
1751 #endif
1752
1753diff -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);
1758     }
1759
1760     RFREE(isock);
1761
1762     return(0);
1763   }
1764
1765 int nr_ice_socket_close(nr_ice_socket *isock)
1766   {
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
1774
1775     if (!isock||!isock->sock)
1776       return(0);
1777
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);
1785     }
1786
1787     return(0);
1788   }
1789
1790 int nr_ice_socket_register_stun_client(nr_ice_socket *sock, nr_stun_client_ctx *srv,void **handle)
1791   {
1792diff -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
1803
1804 #include "transport_addr.h"
1805
1806-#ifdef WIN32
1807+#ifdef __cplusplus
1808+#define restrict
1809+#elif defined(WIN32)
1810 #define restrict __restrict
1811 #endif
1812
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);
1820diff -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 */
1827
1828
1829
1830 static char *RCSSTRING __UNUSED__="$Id: transport_addr_reg.c,v 1.2 2008/04/28 17:59:03 ekr Exp $";
1831
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"
1850
1851@@ -83,20 +85,22 @@
1852
1853     if ((r=NR_reg_get2_uint2(prefix, "port", &port))) {
1854         if (r != R_NOT_FOUND)
1855             ABORT(r);
1856         port = 0;
1857     }
1858
1859     if ((r=NR_reg_alloc2_string(prefix, "protocol", &protocol))) {
1860         if (r != R_NOT_FOUND)
1861             ABORT(r);
1862+        p = IPPROTO_UDP;
1863+
1864         protocol = 0;
1865     }
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);
1873     }
1874diff -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>
1892
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  */
1904
1905 #include <err.h>
1906
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);
1913+
1914
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))
1922
1923 static void
1924@@ -135,21 +140,21 @@
1925             continue;
1926         rtinfo->rti_info[i] = sa = (struct sockaddr *)cp;
1927         ADVANCE(cp, sa);
1928     }
1929 }
1930
1931 static int
1932 stun_grab_addrs(char *name, int addrcount, struct ifa_msghdr *ifam, nr_transport_addr addrs[], int maxaddrs, int *count)
1933 {
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;
1940
1941     ifr.ifr_addr.sa_family = AF_INET;
1942     strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
1943
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--;
1949
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;
1953         }
1954
1955         ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen);
1956     }
1957
1958-
1959     _status = 0;
1960   abort:
1961     if (s != -1) close(s);
1962     return _status;
1963 }
1964
1965 static int
1966 stun_get_mib_addrs(nr_transport_addr addrs[], int maxaddrs, int *count)
1967 {
1968     int _status;
1969@@ -551,44 +555,48 @@
1970 #else
1971
1972 static int
1973 stun_get_siocgifconf_addrs(nr_transport_addr addrs[], int maxaddrs, int *count)
1974 {
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;
1985
1986    char buf[ len ];
1987
1988    ifc.ifc_len = len;
1989    ifc.ifc_buf = buf;
1990
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;
1999
2000    while ( (tl > 0) && ( n < maxaddrs) )
2001    {
2002       struct ifreq* ifr = (struct ifreq *)ptr;
2003
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;
2012
2013-      struct ifreq ifr2;
2014       ifr2 = *ifr;
2015
2016       e = ioctl(s,SIOCGIFADDR,&ifr2);
2017       if ( e == -1 )
2018       {
2019           continue;
2020       }
2021
2022       //r_log(NR_LOG_STUN, LOG_ERR, "ioctl addr e = %d",e);
2023
2024@@ -603,21 +611,21 @@
2025
2026    close(s);
2027
2028    *count = n;
2029
2030     _status = 0;
2031     return _status;
2032 }
2033 #endif
2034
2035-int
2036+static int
2037 nr_stun_is_duplicate_addr(nr_transport_addr addrs[], int count, nr_transport_addr *addr)
2038 {
2039     int i;
2040     int different;
2041
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 */
2046     }
2047diff -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;
2054     }
2055
2056     return R_FAILED;
2057   }
2058
2059 static int nr_socket_turn_close(void *obj)
2060   {
2061+#ifndef NDEBUG
2062     nr_socket_turn *sturn=obj;
2063     assert(sturn->magic_cookie == nr_socket_turn_magic_cookie);
2064+#endif
2065
2066     return 0;
2067   }
2068
2069 #endif /* USE_TURN */
2070diff -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>
2075
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"
2082
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);
2087
2088 int nr_stun_client_ctx_create(char *label, nr_socket *sock, nr_transport_addr *peer, UINT4 RTO, nr_stun_client_ctx **ctxp)
2089   {
2090     nr_stun_client_ctx *ctx=0;
2091     int r,_status;
2092
2093     if ((r=nr_stun_startup()))
2094       ABORT(r);
2095
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;
2102
2103     ctx->state = NR_STUN_CLIENT_STATE_INITTED;
2104
2105     return 0;
2106 }
2107
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)
2110   {
2111     int _status;
2112     nr_stun_client_ctx *ctx=cb_arg;
2113     struct timeval now;
2114     INT8 ms_waited;
2115
2116     /* Prevent this timer from being cancelled later */
2117     ctx->timer_handle=0;
2118
2119     /* Shouldn't happen */
2120@@ -387,21 +388,21 @@
2121     }
2122
2123     _status=0;
2124   abort:
2125     if (_status) {
2126       ctx->state=NR_STUN_CLIENT_STATE_FAILED;
2127     }
2128     return(_status);
2129   }
2130
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)
2133 {
2134     *password = (Data*)arg;
2135     if (!arg)
2136         return(R_NOT_FOUND);
2137     return(0);
2138 }
2139
2140 int nr_stun_client_process_response(nr_stun_client_ctx *ctx, UCHAR *msg, int len, nr_transport_addr *peer_addr)
2141   {
2142     int r,_status;
2143diff -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);
2149
2150 static int nr_stun_attr_string_illegal(nr_stun_attr_info *attr_info, int len, void *data, int max_bytes, int max_chars);
2151
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);
2159
2160
2161 int
2162 nr_stun_encode_htons(UINT2 data, int buflen, UCHAR *buf, int *offset)
2163 {
2164    UINT2 d = htons(data);
2165
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 @@
2170     }
2171
2172     fingerprint->checksum = checksum ^ 0x5354554e;
2173
2174     r_log(NR_LOG_STUN, LOG_DEBUG, "Computed FINGERPRINT %08x", fingerprint->checksum);
2175
2176     fingerprint->valid = 1;
2177     return nr_stun_attr_codec_UINT4.encode(attr_info, &fingerprint->checksum, offset, buflen, buf, attrlen);
2178 }
2179
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)
2183 {
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;
2189
2190     if ((r=nr_stun_attr_codec_UINT4.decode(attr_info, attrlen, buf, offset, buflen, &fingerprint->checksum)))
2191         ABORT(r);
2192diff -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>
2201
2202 #include "stun.h"
2203 #include "stun_reg.h"
2204 #include "registry.h"
2205
2206+static int
2207+nr_stun_add_realm_and_nonce(int new_nonce, nr_stun_server_client *clnt, nr_stun_message *res);
2208
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)
2212 {
2213     int _status;
2214     nr_stun_message_attribute *attr;
2215
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 */
2222     }
2223
2224    _status=0;
2225  abort:
2226      return _status;
2227 }
2228
2229-int
2230+static int
2231 nr_stun_add_realm_and_nonce(int new_nonce, nr_stun_server_client *clnt, nr_stun_message *res)
2232 {
2233     int r,_status;
2234     char *realm = 0;
2235     char *nonce;
2236     UINT2 size;
2237
2238     if ((r=NR_reg_alloc_string(NR_STUN_REG_PREF_SERVER_REALM, &realm)))
2239         ABORT(r);
2240
2241diff -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);
2246
2247     _status=0;
2248   abort:
2249     if(_status){
2250       nr_stun_server_destroy_client(clnt);
2251     }
2252     return(_status);
2253   }
2254
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)
2257   {
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;
2262
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);
2267diff -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;
2274 }
2275
2276 int
2277 nr_stun_find_local_addresses(nr_transport_addr addrs[], int maxaddrs, int *count)
2278 {
2279     int r,_status;
2280     NR_registry *children = 0;
2281-    int i;
2282
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);
2288
2289     if (*count == 0) {
2290         if ((r=nr_stun_get_addrs(addrs, maxaddrs, 1, count)))
2291             ABORT(r);
2292diff -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 };
2297
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 };
2303
2304
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);
2310+
2311
2312 int
2313 nr_turn_client_next_action(nr_turn_client_ctx *ctx, int stun_ctx_state)
2314 {
2315     int r,_status;
2316
2317     assert(ctx->phase >= -1 && ctx->phase < NUMBER_OF_STUN_CTX);
2318
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);
2325         }
2326     }
2327
2328     return(_status);
2329 }
2330
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)
2334 {
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];
2338
2339     assert(ctx->phase >= 0);
2340
2341     if ((r=nr_turn_client_next_action(ctx, stun_ctx->state)))
2342         ABORT(r);
2343
2344@@ -234,21 +237,21 @@
2345
2346     RFREE(ctx->username);
2347     r_data_destroy(&ctx->password);
2348
2349     RFREE(ctx->label);
2350     RFREE(ctx);
2351
2352     return(0);
2353 }
2354
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)
2358 {
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;
2364
2365     if (ctx->state != NR_TURN_CLIENT_STATE_INITTED)
2366         ABORT(R_NOT_PERMITTED);
2367diff -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 */
2372
2373 #include <stdarg.h>
2374
2375
2376 static char *RCSSTRING __UNUSED__="$Id: ice_util.c,v 1.2 2008/04/28 17:59:05 ekr Exp $";
2377
2378 #include <stdarg.h>
2379 #include <string.h>
2380 #include "nr_api.h"
2381+#include "ice_util.h"
2382
2383 int nr_concat_strings(char **outp,...)
2384   {
2385     va_list ap;
2386     char *s,*out=0;
2387     int len=0;
2388     int _status;
2389
2390     va_start(ap,outp);
2391     while(s=va_arg(ap,char *)){
2392diff -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 @@
2396 {
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;
2410
2411 #ifdef DARWIN
2412     if (! initialized) {
2413         initialized = 1;
2414         loc = newlocale(LC_CTYPE_MASK, "UTF-8", LC_GLOBAL_LOCALE);
2415     }
2416
2417     if (loc == 0) {
2418@@ -102,25 +102,28 @@
2419
2420     memset(&mbs, 0, sizeof(mbs));
2421     nchars = 0;
2422
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 */
2428     {
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+	}
2440
2441         s += nbytes;
2442         ++nchars;
2443     }
2444
2445     *ncharsp = nchars;
2446
2447     _status = 0;
2448   abort:
2449 #ifdef WIN32
2450