gecko/media/mtransport/third_party/nICEr/upstream.diff

2450 lines
79 KiB
Diff

diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_candidate.c src/ice/ice_candidate.c
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_candidate.c 2012-09-16 16:26:08.000000000 -0700
+++ src/ice/ice_candidate.c 2012-10-06 08:30:22.000000000 -0700
@@ -54,36 +54,38 @@
#include "stun_client_ctx.h"
#include "stun_server_ctx.h"
#include "turn_client_ctx.h"
#include "ice_ctx.h"
#include "ice_candidate.h"
#include "ice_reg.h"
#include "ice_util.h"
#include "nr_socket_turn.h"
+static int next_automatic_preference = 224;
+
static int nr_ice_get_foundation(nr_ice_ctx *ctx,nr_ice_candidate *cand);
static int nr_ice_srvrflx_start_stun(nr_ice_candidate *cand, NR_async_cb ready_cb, void *cb_arg);
-static void nr_ice_srvrflx_stun_finished_cb(int sock, int how, void *cb_arg);
+static void nr_ice_srvrflx_stun_finished_cb(NR_SOCKET sock, int how, void *cb_arg);
#ifdef USE_TURN
static int nr_ice_start_relay_turn(nr_ice_candidate *cand, NR_async_cb ready_cb, void *cb_arg);
-static void nr_ice_turn_allocated_cb(int sock, int how, void *cb_arg);
+static void nr_ice_turn_allocated_cb(NR_SOCKET sock, int how, void *cb_arg);
#endif /* USE_TURN */
char *nr_ice_candidate_type_names[]={0,"host","srflx","prflx","relay",0};
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)
{
nr_ice_candidate *cand=0;
nr_ice_candidate *tmp=0;
int r,_status;
-
+
if(!(cand=RCALLOC(sizeof(nr_ice_candidate))))
ABORT(R_NO_MEMORY);
if(!(cand->label=r_strdup(label)))
ABORT(R_NO_MEMORY);
cand->state=NR_ICE_CAND_STATE_CREATED;
cand->ctx=ctx;
cand->isock=isock;
cand->osock=osock;
cand->type=ctype;
cand->stun_server=stun_server;
@@ -189,21 +191,21 @@
if(cand->delay_timer)
NR_async_timer_cancel(cand->delay_timer);
RFREE(cand->foundation);
RFREE(cand->label);
RFREE(cand);
return(0);
}
-void nr_ice_candidate_destroy_cb(int s, int h, void *cb_arg)
+void nr_ice_candidate_destroy_cb(NR_SOCKET s, int h, void *cb_arg)
{
nr_ice_candidate *cand=cb_arg;
nr_ice_candidate_destroy(&cand);
}
/* This algorithm is not super-fast, but I don't think we need a hash
table just yet and it produces a small foundation string */
static int nr_ice_get_foundation(nr_ice_ctx *ctx,nr_ice_candidate *cand)
{
nr_ice_foundation *foundation;
@@ -276,22 +278,38 @@
break;
default:
ABORT(R_INTERNAL);
}
if(type_preference > 126)
r_log(LOG_ICE,LOG_ERR,"Illegal type preference %d",type_preference);
if(r=NR_reg_get2_uchar(NR_ICE_REG_PREF_INTERFACE_PRFX,cand->base.ifname,
- &interface_preference))
- ABORT(r);
+ &interface_preference)) {
+ if (r==R_NOT_FOUND) {
+ if (next_automatic_preference == 1) {
+ r_log(LOG_ICE,LOG_DEBUG,"Out of preference values. Can't assign one for interface %s",cand->base.ifname);
+ ABORT(R_NOT_FOUND);
+ }
+ r_log(LOG_ICE,LOG_DEBUG,"Automatically assigning preference for interface %s->%d",cand->base.ifname,
+ next_automatic_preference);
+ if (r=NR_reg_set2_uchar(NR_ICE_REG_PREF_INTERFACE_PRFX,cand->base.ifname,next_automatic_preference)){
+ ABORT(r);
+ }
+ interface_preference=next_automatic_preference;
+ next_automatic_preference--;
+ }
+ else {
+ ABORT(r);
+ }
+ }
cand->priority=
(type_preference << 24) |
(interface_preference << 16) |
(stun_priority << 8) |
(256 - cand->component_id);
/* S 4.1.2 */
assert(cand->priority>=1&&cand->priority<=2147483647);
@@ -306,21 +324,22 @@
cand->done_cb=ready_cb;
cand->cb_arg=cb_arg;
switch(cand->type){
case HOST:
if(r=nr_socket_getaddr(cand->isock->sock,&cand->addr))
ABORT(r);
cand->osock=cand->isock->sock;
cand->state=NR_ICE_CAND_STATE_INITIALIZED;
- ready_cb(0,0,cb_arg);
+ // Post this so that it doesn't happen in-line
+ NR_ASYNC_SCHEDULE(ready_cb,cb_arg);
break;
#ifdef USE_TURN
case RELAYED:
if(r=nr_ice_start_relay_turn(cand,ready_cb,cb_arg))
ABORT(r);
ABORT(R_WOULDBLOCK);
break;
#endif /* USE_TURN */
case SERVER_REFLEXIVE:
/* Need to start stun */
@@ -333,21 +352,21 @@
ABORT(R_INTERNAL);
}
_status=0;
abort:
if(_status && _status!=R_WOULDBLOCK)
cand->state=NR_ICE_CAND_STATE_FAILED;
return(_status);
}
-static void nr_ice_srvrflx_start_stun_timer_cb(int s, int how, void *cb_arg)
+static void nr_ice_srvrflx_start_stun_timer_cb(NR_SOCKET s, int how, void *cb_arg)
{
nr_ice_candidate *cand=cb_arg;
int r,_status;
cand->delay_timer=0;
/* TODO: if the response is a BINDING-ERROR-RESPONSE, then restart
* TODO: using NR_STUN_CLIENT_MODE_BINDING_REQUEST because the
* TODO: server may not have understood the 0.96-style request */
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))
@@ -387,21 +406,21 @@
_status=0;
abort:
if(_status){
cand->state=NR_ICE_CAND_STATE_FAILED;
}
return(_status);
}
#ifdef USE_TURN
-static void nr_ice_start_relay_turn_timer_cb(int s, int how, void *cb_arg)
+static void nr_ice_start_relay_turn_timer_cb(NR_SOCKET s, int how, void *cb_arg)
{
nr_ice_candidate *cand=cb_arg;
int r,_status;
int i;
cand->delay_timer=0;
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))
ABORT(r);
@@ -443,21 +462,21 @@
_status=0;
abort:
if(_status){
cand->state=NR_ICE_CAND_STATE_FAILED;
}
return(_status);
}
#endif /* USE_TURN */
-static void nr_ice_srvrflx_stun_finished_cb(int sock, int how, void *cb_arg)
+static void nr_ice_srvrflx_stun_finished_cb(NR_SOCKET sock, int how, void *cb_arg)
{
int _status;
nr_ice_candidate *cand=cb_arg;
/* Deregister to suppress duplicates */
if(cand->u.srvrflx.stun_handle){ /* This test because we might have failed before CB registered */
nr_ice_socket_deregister(cand->isock,cand->u.srvrflx.stun_handle);
cand->u.srvrflx.stun_handle=0;
}
@@ -481,40 +500,40 @@
}
_status = 0;
abort:
if(_status){
cand->state=NR_ICE_CAND_STATE_FAILED;
cand->done_cb(0,0,cand->cb_arg);
}
}
#ifdef USE_TURN
-static void nr_ice_turn_allocated_cb(int s, int how, void *cb_arg)
+static void nr_ice_turn_allocated_cb(NR_SOCKET s, int how, void *cb_arg)
{
int r,_status;
nr_ice_candidate *cand=cb_arg;
nr_turn_client_ctx *turn=cand->u.relayed.turn;
int i;
char *label;
/* Deregister to suppress duplicates */
if(cand->u.relayed.turn_handle){ /* This test because we might have failed before CB registered */
nr_ice_socket_deregister(cand->isock,cand->u.relayed.turn_handle);
cand->u.relayed.turn_handle=0;
}
switch(turn->state){
/* OK, we should have a mapped address */
case NR_TURN_CLIENT_STATE_ALLOCATED:
/* switch candidate from TURN mode to STUN mode */
- if(r=nr_concat_strings(&label,"turn-relay(",cand->base.as_string,"|",turn->relay_addr.as_string,")",0))
+ if(r=nr_concat_strings(&label,"turn-relay(",cand->base.as_string,"|",turn->relay_addr.as_string,")",NULL))
ABORT(r);
r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): Switching from TURN (%s) to RELAY (%s)",cand->u.relayed.turn->label,cand->label,label);
/* Copy out mapped address and relay address */
nr_transport_addr_copy(&turn->relay_addr, &cand->u.relayed.turn->stun_ctx[NR_TURN_CLIENT_PHASE_ALLOCATE_REQUEST2]->results.allocate_response2.relay_addr);
nr_transport_addr_copy(&cand->addr, &turn->relay_addr);
r_log(LOG_ICE,LOG_DEBUG,"ICE-CANDIDATE(%s): base=%s, candidate=%s", cand->label, cand->base.as_string, cand->addr.as_string);
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_candidate.h src/ice/ice_candidate.h
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_candidate.h 2012-09-16 16:26:08.000000000 -0700
+++ src/ice/ice_candidate.h 2012-10-06 08:30:22.000000000 -0700
@@ -41,21 +41,22 @@
typedef enum {HOST=1, SERVER_REFLEXIVE, PEER_REFLEXIVE, RELAYED} nr_ice_candidate_type;
struct nr_ice_candidate_ {
char *label;
int state;
#define NR_ICE_CAND_STATE_CREATED 1
#define NR_ICE_CAND_STATE_INITIALIZING 2
#define NR_ICE_CAND_STATE_INITIALIZED 3
#define NR_ICE_CAND_STATE_FAILED 4
-#define NR_ICE_CAND_PEER_CANDIDATE 10
+#define NR_ICE_CAND_PEER_CANDIDATE_UNPAIRED 9
+#define NR_ICE_CAND_PEER_CANDIDATE_PAIRED 10
struct nr_ice_ctx_ *ctx;
nr_ice_socket *isock; /* The socket to read from
(it contains all other candidates
on this socket) */
nr_socket *osock; /* The socket to write to */
nr_ice_media_stream *stream; /* The media stream this is associated with */
nr_ice_component *component; /* The component this is associated with */
nr_ice_candidate_type type; /* The type of the candidate (S 4.1.1) */
UCHAR component_id; /* The component id (S 4.1.2.1) */
nr_transport_addr addr; /* The advertised address;
@@ -89,21 +90,21 @@
TAILQ_ENTRY(nr_ice_candidate_) entry_comp;
};
extern char *nr_ice_candidate_type_names[];
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);
int nr_ice_candidate_initialize(nr_ice_candidate *cand, NR_async_cb ready_cb, void *cb_arg);
int nr_ice_candidate_process_stun(nr_ice_candidate *cand, UCHAR *msg, int len, nr_transport_addr *faddr);
int nr_ice_candidate_destroy(nr_ice_candidate **candp);
-void nr_ice_candidate_destroy_cb(int s, int h, void *cb_arg);
+void nr_ice_candidate_destroy_cb(NR_SOCKET s, int h, void *cb_arg);
int nr_ice_format_candidate_attribute(nr_ice_candidate *cand, char *attr, int maxlen);
int nr_ice_peer_candidate_from_attribute(nr_ice_ctx *ctx,char *attr,nr_ice_media_stream *stream,nr_ice_candidate **candp);
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);
int nr_ice_candidate_compute_priority(nr_ice_candidate *cand);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_candidate_pair.c src/ice/ice_candidate_pair.c
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_candidate_pair.c 2012-09-16 16:26:08.000000000 -0700
+++ src/ice/ice_candidate_pair.c 2012-10-06 08:30:22.000000000 -0700
@@ -37,21 +37,21 @@
#include <assert.h>
#include <string.h>
#include <nr_api.h>
#include "ice_ctx.h"
#include "ice_util.h"
#include "ice_codeword.h"
#include "stun.h"
static char *nr_ice_cand_pair_states[]={"UNKNOWN","FROZEN","WAITING","IN_PROGRESS","FAILED","SUCCEEDED","CANCELLED"};
-static void nr_ice_candidate_pair_restart_stun_controlled_cb(int s, int how, void *cb_arg);
+static void nr_ice_candidate_pair_restart_stun_controlled_cb(NR_SOCKET s, int how, void *cb_arg);
static void nr_ice_candidate_pair_compute_codeword(nr_ice_cand_pair *pair,
nr_ice_candidate *lcand, nr_ice_candidate *rcand);
int nr_ice_candidate_pair_create(nr_ice_peer_ctx *pctx, nr_ice_candidate *lcand,nr_ice_candidate *rcand,nr_ice_cand_pair **pairp)
{
nr_ice_cand_pair *pair=0;
UINT8 o_priority, a_priority;
char *lufrag,*rufrag;
char *lpwd,*rpwd;
char *l2ruser=0,*r2lpass=0;
@@ -61,21 +61,21 @@
UINT8 t_priority;
if(!(pair=RCALLOC(sizeof(nr_ice_cand_pair))))
ABORT(R_NO_MEMORY);
pair->pctx=pctx;
nr_ice_candidate_pair_compute_codeword(pair,lcand,rcand);
if(r=nr_concat_strings(&pair->as_string,pair->codeword,"|",lcand->addr.as_string,"|",
- rcand->addr.as_string,"(",lcand->label,"|",rcand->label,")",0))
+ rcand->addr.as_string,"(",lcand->label,"|",rcand->label,")", NULL))
ABORT(r);
nr_ice_candidate_pair_set_state(pctx,pair,NR_ICE_PAIR_STATE_FROZEN);
pair->local=lcand;
pair->remote=rcand;
/* Priority computation S 5.7.2 */
if(pctx->ctx->flags & NR_ICE_CTX_FLAGS_OFFERER)
{
assert(!(pctx->ctx->flags & NR_ICE_CTX_FLAGS_ANSWERER));
@@ -87,21 +87,21 @@
o_priority=rcand->priority;
a_priority=lcand->priority;
}
pair->priority=(MIN(o_priority, a_priority))<<32 |
(MAX(o_priority, a_priority))<<1 | (o_priority > a_priority?0:1);
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);
/* Foundation */
if(r=nr_concat_strings(&pair->foundation,lcand->foundation,"|",
- rcand->foundation,0))
+ rcand->foundation,NULL))
ABORT(r);
/* OK, now the STUN data */
lufrag=lcand->stream->ufrag?lcand->stream->ufrag:pctx->ctx->ufrag;
lpwd=lcand->stream->pwd?lcand->stream->pwd:pctx->ctx->pwd;
rufrag=rcand->stream->ufrag?rcand->stream->ufrag:pctx->peer_ufrag;
rpwd=rcand->stream->pwd?rcand->stream->pwd:pctx->peer_pwd;
@@ -110,39 +110,39 @@
/* Make a bogus candidate to compute a theoretical peer reflexive
* priority per S 7.1.1.1 */
memcpy(&tmpcand, lcand, sizeof(tmpcand));
tmpcand.type = PEER_REFLEXIVE;
if (r=nr_ice_candidate_compute_priority(&tmpcand))
ABORT(r);
t_priority = tmpcand.priority;
/* Our sending context */
- if(r=nr_concat_strings(&l2ruser,lufrag,":",rufrag,0))
+ if(r=nr_concat_strings(&l2ruser,lufrag,":",rufrag,NULL))
ABORT(r);
if(r=nr_stun_client_ctx_create(pair->as_string,
lcand->osock,
&rcand->addr,RTO,&pair->stun_client))
ABORT(r);
if(!(pair->stun_client->params.ice_binding_request.username=r_strdup(l2ruser)))
ABORT(R_NO_MEMORY);
if(r=r_data_make(&pair->stun_client->params.ice_binding_request.password,(UCHAR *)lpwd,strlen(lpwd)))
ABORT(r);
pair->stun_client->params.ice_binding_request.priority=t_priority;
pair->stun_client->params.ice_binding_request.control = pctx->controlling?
NR_ICE_CONTROLLING:NR_ICE_CONTROLLED;
pair->stun_client->params.ice_binding_request.tiebreaker=pctx->tiebreaker;
/* Our receiving username/passwords. Stash these for later
injection into the stun server ctx*/
- if(r=nr_concat_strings(&pair->r2l_user,rufrag,":",lufrag,0))
+ if(r=nr_concat_strings(&pair->r2l_user,rufrag,":",lufrag,NULL))
ABORT(r);
if(!(r2lpass=r_strdup(rpwd)))
ABORT(R_NO_MEMORY);
INIT_DATA(pair->r2l_pwd,(UCHAR *)r2lpass,strlen(r2lpass));
*pairp=pair;
_status=0;
abort:
RFREE(l2ruser);
@@ -178,21 +178,21 @@
int nr_ice_candidate_pair_unfreeze(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair)
{
assert(pair->state==NR_ICE_PAIR_STATE_FROZEN);
nr_ice_candidate_pair_set_state(pctx,pair,NR_ICE_PAIR_STATE_WAITING);
return(0);
}
-static void nr_ice_candidate_pair_stun_cb(int s, int how, void *cb_arg)
+static void nr_ice_candidate_pair_stun_cb(NR_SOCKET s, int how, void *cb_arg)
{
int r,_status;
nr_ice_cand_pair *pair=cb_arg,*orig_pair;
nr_ice_candidate *cand=0;
nr_stun_message *sres;
nr_transport_addr *request_src;
nr_transport_addr *request_dst;
nr_transport_addr *response_src;
nr_transport_addr response_dst;
nr_stun_message_attribute *attr;
@@ -457,32 +457,47 @@
abort:
return(_status);
}
int nr_ice_candidate_pair_set_state(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair, int state)
{
int r,_status;
r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): setting pair %s to %s",
pctx->label,pair->as_string,nr_ice_cand_pair_states[state]);
- pair->state=state;
- if(pctx->state!=NR_ICE_PAIR_STATE_WAITING){
+ /* NOTE: This function used to reference pctx->state instead of
+ pair->state and the assignment to pair->state was at the top
+ of this function. Because pctx->state was never changed, this seems to have
+ been a typo. The natural logic is "if the state changed
+ decrement the counter" so this implies we should be checking
+ the pair state rather than the pctx->state.
+
+ This didn't cause big problems because waiting_pairs was only
+ used for pacing, so the pacing just was kind of broken.
+
+ This note is here as a reminder until we do more testing
+ and make sure that in fact this was a typo.
+ */
+ if(pair->state!=NR_ICE_PAIR_STATE_WAITING){
if(state==NR_ICE_PAIR_STATE_WAITING)
pctx->waiting_pairs++;
}
else{
if(state!=NR_ICE_PAIR_STATE_WAITING)
pctx->waiting_pairs--;
assert(pctx->waiting_pairs>=0);
}
+ pair->state=state;
+
+
if(pair->state==NR_ICE_PAIR_STATE_FAILED){
if(r=nr_ice_component_failed_pair(pair->remote->component, pair))
ABORT(r);
}
_status=0;
abort:
return(_status);
}
@@ -505,42 +520,42 @@
break;
}
c1=TAILQ_NEXT(c1,entry);
}
if(!c1) TAILQ_INSERT_TAIL(head,pair,entry);
return(0);
}
-void nr_ice_candidate_pair_restart_stun_nominated_cb(int s, int how, void *cb_arg)
+void nr_ice_candidate_pair_restart_stun_nominated_cb(NR_SOCKET s, int how, void *cb_arg)
{
nr_ice_cand_pair *pair=cb_arg;
int r,_status;
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);
nr_stun_client_reset(pair->stun_client);
pair->stun_client->params.ice_binding_request.control=NR_ICE_CONTROLLING;
if(r=nr_stun_client_start(pair->stun_client,NR_ICE_CLIENT_MODE_USE_CANDIDATE,nr_ice_candidate_pair_stun_cb,pair))
ABORT(r);
if(r=nr_ice_ctx_remember_id(pair->pctx->ctx, pair->stun_client->request))
ABORT(r);
_status=0;
abort:
return;
}
-static void nr_ice_candidate_pair_restart_stun_controlled_cb(int s, int how, void *cb_arg)
+static void nr_ice_candidate_pair_restart_stun_controlled_cb(NR_SOCKET s, int how, void *cb_arg)
{
nr_ice_cand_pair *pair=cb_arg;
int r,_status;
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);
nr_stun_client_reset(pair->stun_client);
pair->stun_client->params.ice_binding_request.control=NR_ICE_CONTROLLED;
if(r=nr_stun_client_start(pair->stun_client,NR_ICE_CLIENT_MODE_BINDING_REQUEST,nr_ice_candidate_pair_stun_cb,pair))
@@ -556,21 +571,21 @@
static void nr_ice_candidate_pair_compute_codeword(nr_ice_cand_pair *pair,
nr_ice_candidate *lcand, nr_ice_candidate *rcand)
{
int r,_status;
char *as_string=0;
if(r=nr_concat_strings(&as_string,lcand->addr.as_string,"|",
- rcand->addr.as_string,"(",lcand->label,"|",rcand->label,")",0))
+ rcand->addr.as_string,"(",lcand->label,"|",rcand->label,")",NULL))
ABORT(r);
nr_ice_compute_codeword(as_string,strlen(as_string),pair->codeword);
_status=0;
abort:
RFREE(as_string);
return;
}
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_candidate_pair.h src/ice/ice_candidate_pair.h
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_candidate_pair.h 2012-09-16 16:26:08.000000000 -0700
+++ src/ice/ice_candidate_pair.h 2012-10-06 08:30:22.000000000 -0700
@@ -72,18 +72,18 @@
int nr_ice_candidate_pair_create(nr_ice_peer_ctx *pctx, nr_ice_candidate *lcand,nr_ice_candidate *rcand,nr_ice_cand_pair **pairp);
int nr_ice_candidate_pair_unfreeze(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair);
int nr_ice_candidate_pair_start(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair);
int nr_ice_candidate_pair_set_state(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair, int state);
int nr_ice_candidate_pair_dump_state(nr_ice_cand_pair *pair, FILE *out);
int nr_ice_candidate_pair_cancel(nr_ice_peer_ctx *pctx,nr_ice_cand_pair *pair);
int nr_ice_candidate_pair_select(nr_ice_cand_pair *pair);
int nr_ice_candidate_pair_do_triggered_check(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair);
int nr_ice_candidate_pair_insert(nr_ice_cand_pair_head *head,nr_ice_cand_pair *pair);
-void nr_ice_candidate_pair_restart_stun_nominated_cb(int s, int how, void *cb_arg);
+void nr_ice_candidate_pair_restart_stun_nominated_cb(NR_SOCKET s, int how, void *cb_arg);
int nr_ice_candidate_pair_destroy(nr_ice_cand_pair **pairp);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_component.c src/ice/ice_component.c
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_component.c 2012-09-16 16:26:08.000000000 -0700
+++ src/ice/ice_component.c 2012-10-06 08:30:22.000000000 -0700
@@ -451,21 +451,21 @@
if(r=nr_ice_peer_peer_rflx_candidate_create(comp->stream->pctx->ctx,"prflx",comp,&req->src_addr,&pcand)) {
*error=(r==R_NO_MEMORY)?500:400;
ABORT(r);
}
if(!nr_stun_message_has_attribute(sreq,NR_STUN_ATTR_PRIORITY,&attr)){
r_log(LOG_ICE,LOG_ERR,"ICE-PEER(%s): Rejecting stun request without priority",comp->stream->pctx->label);
*error=487;
ABORT(R_BAD_DATA);
}
pcand->priority=attr->u.priority;
- pcand->state=NR_ICE_CAND_PEER_CANDIDATE;
+ pcand->state=NR_ICE_CAND_PEER_CANDIDATE_PAIRED;;
TAILQ_INSERT_TAIL(&comp->candidates,pcand,entry_comp);
if(r=nr_ice_candidate_pair_create(comp->stream->pctx,cand,pcand,
&pair)) {
*error=(r==R_NO_MEMORY)?500:400;
ABORT(r);
}
nr_ice_candidate_pair_set_state(pair->pctx,pair,NR_ICE_PAIR_STATE_FROZEN);
if(r=nr_ice_candidate_pair_insert(&comp->stream->check_list,pair)) {
@@ -563,30 +563,38 @@
break;
}
/* PAIR with each peer*/
if(TAILQ_EMPTY(&pcomp->candidates)) {
/* can happen if our peer proposes no (or all bogus) candidates */
goto next_cand;
}
pcand=TAILQ_FIRST(&pcomp->candidates);
while(pcand){
- nr_ice_compute_codeword(pcand->label,strlen(pcand->label),codeword);
- r_log(LOG_ICE,LOG_DEBUG,"Examining peer candidate %s:%s",codeword,pcand->label);
-
- if(r=nr_ice_candidate_pair_create(pctx,lcand,pcand,&pair))
- ABORT(r);
-
- if(r=nr_ice_candidate_pair_insert(&pcomp->stream->check_list,
- pair))
- ABORT(r);
+ /* Only pair peer candidates which have not yet been paired.
+ This allows "trickle ICE". (Not yet standardized, but
+ part of WebRTC).
+
+ TODO(ekr@rtfm.com): Add refernece to the spec when there
+ is one.
+ */
+ if (pcand->state = NR_ICE_CAND_PEER_CANDIDATE_UNPAIRED) {
+ nr_ice_compute_codeword(pcand->label,strlen(pcand->label),codeword);
+ r_log(LOG_ICE,LOG_DEBUG,"Examining peer candidate %s:%s",codeword,pcand->label);
+
+ if(r=nr_ice_candidate_pair_create(pctx,lcand,pcand,&pair))
+ ABORT(r);
+ if(r=nr_ice_candidate_pair_insert(&pcomp->stream->check_list,
+ pair))
+ ABORT(r);
+ }
pcand=TAILQ_NEXT(pcand,entry_comp);
}
if(!pair)
ABORT(R_INTERNAL);
/* Add the stun username/password pair from the last pair (any
would do) to the stun contexts */
isock=STAILQ_FIRST(&lcomp->sockets);
while(isock){
@@ -594,20 +602,28 @@
pair->r2l_user,&pair->r2l_pwd,nr_ice_component_stun_server_cb,pcomp))
ABORT(r);
isock=STAILQ_NEXT(isock,entry);
}
next_cand:
lcand=TAILQ_NEXT(lcand,entry_comp);
}
+ /* Mark all peer candidates as paired */
+ pcand=TAILQ_FIRST(&pcomp->candidates);
+ while(pcand){
+ pcand->state = NR_ICE_CAND_PEER_CANDIDATE_PAIRED;
+
+ pcand=TAILQ_NEXT(pcand,entry_comp);
+ }
+
_status=0;
abort:
return(_status);
}
int nr_ice_component_nominated_pair(nr_ice_component *comp, nr_ice_cand_pair *pair)
{
int r,_status;
int fire_cb=0;
nr_ice_cand_pair *p2;
@@ -616,32 +632,32 @@
fire_cb=1;
/* Are we changing what the nominated pair is? */
if(comp->nominated){
if(comp->nominated->priority > pair->priority)
return(0);
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);
}
/* Set the new nominated pair */
- 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);
+ 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);
comp->state=NR_ICE_COMPONENT_NOMINATED;
comp->nominated=pair;
comp->active=pair;
- 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);
+ 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);
/* OK, we need to cancel off everything on this component */
p2=TAILQ_FIRST(&comp->stream->check_list);
while(p2){
if((p2 != pair) && (p2->remote->component->component_id == comp->component_id)){
- 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);
+ 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);
if(r=nr_ice_candidate_pair_cancel(pair->pctx,p2))
ABORT(r);
}
p2=TAILQ_NEXT(p2,entry);
}
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);
if(r=nr_ice_media_stream_component_nominated(comp->stream,comp))
@@ -734,21 +750,21 @@
ABORT(r);
}
_status=0;
abort:
RFREE(pairs);
return(_status);
}
-static void nr_ice_component_keepalive_cb(int s, int how, void *cb_arg)
+static void nr_ice_component_keepalive_cb(NR_SOCKET s, int how, void *cb_arg)
{
nr_ice_component *comp=cb_arg;
UINT4 keepalive_timeout;
assert(comp->keepalive_ctx);
if(NR_reg_get_uint4(NR_ICE_REG_KEEPALIVE_TIMER,&keepalive_timeout)){
keepalive_timeout=15000; /* Default */
}
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_ctx.c src/ice/ice_ctx.c
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_ctx.c 2012-09-16 16:26:08.000000000 -0700
+++ src/ice/ice_ctx.c 2012-10-06 08:30:22.000000000 -0700
@@ -56,21 +56,21 @@
#include "util.h"
int LOG_ICE = 0;
static int nr_ice_random_string(char *str, int len);
static int nr_ice_fetch_stun_servers(int ct, nr_ice_stun_server **out);
#ifdef USE_TURN
static int nr_ice_fetch_turn_servers(int ct, nr_ice_turn_server **out);
#endif /* USE_TURN */
-static void nr_ice_ctx_destroy_cb(int s, int how, void *cb_arg);
+static void nr_ice_ctx_destroy_cb(NR_SOCKET s, int how, void *cb_arg);
int nr_ice_fetch_stun_servers(int ct, nr_ice_stun_server **out)
{
int r,_status;
nr_ice_stun_server *servers = 0;
int i;
NR_registry child;
char *addr=0;
UINT2 port;
in_addr_t addr_int;
@@ -271,21 +271,21 @@
*ctxp=ctx;
_status=0;
abort:
if(_status)
nr_ice_ctx_destroy_cb(0,0,ctx);
return(_status);
}
-static void nr_ice_ctx_destroy_cb(int s, int how, void *cb_arg)
+static void nr_ice_ctx_destroy_cb(NR_SOCKET s, int how, void *cb_arg)
{
nr_ice_ctx *ctx=cb_arg;
nr_ice_foundation *f1,*f2;
nr_ice_media_stream *s1,*s2;
int i;
nr_ice_stun_id *id1,*id2;
RFREE(ctx->label);
RFREE(ctx->stun_servers);
@@ -323,21 +323,21 @@
if(!ctxp || !*ctxp)
return(0);
NR_ASYNC_SCHEDULE(nr_ice_ctx_destroy_cb,*ctxp);
*ctxp=0;
return(0);
}
-void nr_ice_initialize_finished_cb(int s, int h, void *cb_arg)
+void nr_ice_initialize_finished_cb(NR_SOCKET s, int h, void *cb_arg)
{
nr_ice_ctx *ctx=cb_arg;
/* r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): Candidate %s %s",ctx->label,
cand->label, cand->state==NR_ICE_CAND_STATE_INITIALIZED?"INITIALIZED":"FAILED");
*/
ctx->uninitialized_candidates--;
if(ctx->uninitialized_candidates==0){
r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): All candidates initialized",ctx->label);
@@ -368,21 +368,22 @@
stream=STAILQ_FIRST(&ctx->streams);
while(stream){
if(r=nr_ice_media_stream_initialize(ctx,stream))
ABORT(r);
stream=STAILQ_NEXT(stream,entry);
}
if(ctx->uninitialized_candidates)
ABORT(R_WOULDBLOCK);
-
+
+
_status=0;
abort:
return(_status);
}
int nr_ice_add_media_stream(nr_ice_ctx *ctx,char *label,int components, nr_ice_media_stream **streamp)
{
int r,_status;
if(r=nr_ice_media_stream_create(ctx,label,components,streamp))
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_ctx.h src/ice/ice_ctx.h
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_ctx.h 2012-09-16 16:26:08.000000000 -0700
+++ src/ice/ice_ctx.h 2012-10-06 08:30:22.000000000 -0700
@@ -92,23 +92,23 @@
UCHAR id[12];
STAILQ_ENTRY(nr_ice_stun_id_) entry;
} nr_ice_stun_id;
typedef STAILQ_HEAD(nr_ice_stun_id_head_,nr_ice_stun_id_) nr_ice_stun_id_head;
struct nr_ice_ctx_ {
UINT4 flags;
int state;
-#define NR_ICE_STATE_CREATED 1
-#define NR_ICE_STATE_INITIALIZING 2
-#define NR_ICE_STATE_INITIALIZED 3
+#define NR_ICE_STATE_CREATED 1
+#define NR_ICE_STATE_INITIALIZING 2
+#define NR_ICE_STATE_INITIALIZED 3
char *label;
char *ufrag;
char *pwd;
UINT4 Ta;
nr_ice_stun_server *stun_servers; /* The list of stun servers */
int stun_server_ct;
nr_ice_turn_server *turn_servers; /* The list of turn servers */
@@ -133,21 +133,21 @@
int nr_ice_ctx_create(char *label, UINT4 flags, nr_ice_ctx **ctxp);
#define NR_ICE_CTX_FLAGS_OFFERER 1
#define NR_ICE_CTX_FLAGS_ANSWERER (1<<1)
#define NR_ICE_CTX_FLAGS_AGGRESSIVE_NOMINATION (1<<2)
#define NR_ICE_CTX_FLAGS_LITE (1<<3)
int nr_ice_ctx_destroy(nr_ice_ctx **ctxp);
int nr_ice_initialize(nr_ice_ctx *ctx, NR_async_cb done_cb, void *cb_arg);
int nr_ice_add_candidate(nr_ice_ctx *ctx, nr_ice_candidate *cand);
-void nr_ice_initialize_finished_cb(int s, int h, void *cb_arg);
+void nr_ice_initialize_finished_cb(NR_SOCKET s, int h, void *cb_arg);
int nr_ice_add_media_stream(nr_ice_ctx *ctx,char *label,int components, nr_ice_media_stream **streamp);
int nr_ice_get_global_attributes(nr_ice_ctx *ctx,char ***attrsp, int *attrctp);
int nr_ice_ctx_deliver_packet(nr_ice_ctx *ctx, nr_ice_component *comp, nr_transport_addr *source_addr, UCHAR *data, int len);
int nr_ice_ctx_is_known_id(nr_ice_ctx *ctx, UCHAR id[12]);
int nr_ice_ctx_remember_id(nr_ice_ctx *ctx, nr_stun_message *msg);
int nr_ice_ctx_finalize(nr_ice_ctx *ctx, nr_ice_peer_ctx *pctx);
extern int LOG_ICE;
#ifdef __cplusplus
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_media_stream.c src/ice/ice_media_stream.c
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_media_stream.c 2012-09-16 16:26:08.000000000 -0700
+++ src/ice/ice_media_stream.c 2012-10-06 08:30:22.000000000 -0700
@@ -35,21 +35,21 @@
static char *RCSSTRING __UNUSED__="$Id: ice_media_stream.c,v 1.2 2008/04/28 17:59:01 ekr Exp $";
#include <string.h>
#include <assert.h>
#include <nr_api.h>
#include <r_assoc.h>
#include <async_timer.h>
#include "ice_ctx.h"
static char *nr_ice_media_stream_states[]={"INVALID",
- "FROZEN","ACTIVE","COMPLETED","FAILED"
+ "UNPAIRED","FROZEN","ACTIVE","COMPLETED","FAILED"
};
int nr_ice_media_stream_set_state(nr_ice_media_stream *str, int state);
int nr_ice_media_stream_create(nr_ice_ctx *ctx,char *label,int components, nr_ice_media_stream **streamp)
{
int r,_status;
nr_ice_media_stream *stream=0;
nr_ice_component *comp=0;
int i;
@@ -66,29 +66,29 @@
for(i=0;i<components;i++){
/* component-id must be > 0, so increment by 1 */
if(r=nr_ice_component_create(stream, i+1, &comp))
ABORT(r);
}
TAILQ_INIT(&stream->check_list);
stream->component_ct=components;
-
+ stream->ice_state = NR_ICE_MEDIA_STREAM_UNPAIRED;
*streamp=stream;
_status=0;
abort:
if(_status){
nr_ice_media_stream_destroy(&stream);
}
- return(_status);
+ return(_status);
}
int nr_ice_media_stream_destroy(nr_ice_media_stream **streamp)
{
nr_ice_media_stream *stream;
nr_ice_component *c1,*c2;
nr_ice_cand_pair *p1,*p2;
if(!streamp || !*streamp)
return(0);
@@ -200,85 +200,148 @@
if(attrs){
for(index=0;index<attrct;index++){
RFREE(attrs[index]);
}
RFREE(attrs);
}
}
return(_status);
}
+
+/* Get a default candidate per 4.1.4 */
+int nr_ice_media_stream_get_default_candidate(nr_ice_media_stream *stream, int component, nr_ice_candidate **candp)
+ {
+ int _status;
+ nr_ice_component *comp;
+ nr_ice_candidate *cand;
+ nr_ice_candidate *best_cand = NULL;
+
+ comp=STAILQ_FIRST(&stream->components);
+ while(comp){
+ if (comp->component_id == component)
+ break;
+
+ comp=STAILQ_NEXT(comp,entry);
+ }
+
+ if (!comp)
+ ABORT(R_NOT_FOUND);
+
+ /* We have the component. Now find the "best" candidate, making
+ use of the fact that more "reliable" candidate types have
+ higher numbers. So, we sort by type and then priority within
+ type
+ */
+ cand=TAILQ_FIRST(&comp->candidates);
+ while(cand){
+ if (!best_cand) {
+ best_cand = cand;
+ }
+ else {
+ if (best_cand->type < cand->type) {
+ best_cand = cand;
+ } else if (best_cand->type == cand->type) {
+ if (best_cand->priority < cand->priority)
+ best_cand = cand;
+ }
+ }
+
+ cand=TAILQ_NEXT(cand,entry_comp);
+ }
+
+ /* No candidates */
+ if (!best_cand)
+ ABORT(R_NOT_FOUND);
+
+ *candp = best_cand;
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+
int nr_ice_media_stream_pair_candidates(nr_ice_peer_ctx *pctx,nr_ice_media_stream *lstream,nr_ice_media_stream *pstream)
{
int r,_status;
nr_ice_component *pcomp,*lcomp;
pcomp=STAILQ_FIRST(&pstream->components);
lcomp=STAILQ_FIRST(&lstream->components);
while(pcomp){
if(r=nr_ice_component_pair_candidates(pctx,lcomp,pcomp))
ABORT(r);
-
+
lcomp=STAILQ_NEXT(lcomp,entry);
pcomp=STAILQ_NEXT(pcomp,entry);
};
+ if (pstream->ice_state == NR_ICE_MEDIA_STREAM_UNPAIRED) {
+ r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): unfreezing stream %s",pstream->pctx->label,pstream->label);
+ pstream->ice_state = NR_ICE_MEDIA_STREAM_CHECKS_FROZEN;
+ }
+
_status=0;
abort:
return(_status);
}
/* S 5.8 -- run the highest priority WAITING pair or if not available
FROZEN pair */
-static void nr_ice_media_stream_check_timer_cb(int s, int h, void *cb_arg)
+static void nr_ice_media_stream_check_timer_cb(NR_SOCKET s, int h, void *cb_arg)
{
int r,_status;
nr_ice_media_stream *stream=cb_arg;
nr_ice_cand_pair *pair;
int timer_val;
assert(stream->pctx->active_streams!=0);
timer_val=stream->pctx->ctx->Ta*stream->pctx->active_streams;
+ if (stream->ice_state == NR_ICE_MEDIA_STREAM_CHECKS_COMPLETED) {
+ r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): bogus state for stream %s",stream->pctx->label,stream->label);
+ }
assert(stream->ice_state != NR_ICE_MEDIA_STREAM_CHECKS_COMPLETED);
r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): check timer expired for media stream %s",stream->pctx->label,stream->label);
stream->timer=0;
-
/* Find the highest priority WAITING check and move it to RUNNING */
pair=TAILQ_FIRST(&stream->check_list);
while(pair){
if(pair->state==NR_ICE_PAIR_STATE_WAITING)
break;
pair=TAILQ_NEXT(pair,entry);
}
/* Hmmm... No WAITING. Let's look for FROZEN */
if(!pair){
pair=TAILQ_FIRST(&stream->check_list);
-
+
while(pair){
if(pair->state==NR_ICE_PAIR_STATE_FROZEN){
if(r=nr_ice_candidate_pair_unfreeze(stream->pctx,pair))
ABORT(r);
break;
}
pair=TAILQ_NEXT(pair,entry);
}
}
if(pair){
nr_ice_candidate_pair_start(pair->pctx,pair); /* Ignore failures */
NR_ASYNC_TIMER_SET(timer_val,nr_ice_media_stream_check_timer_cb,cb_arg,&stream->timer);
}
+ /* TODO(ekr@rtfm.com): Report on the special case where there are no checks to
+ run at all */
_status=0;
abort:
return;
}
/* Start checks for this media stream (aka check list) */
int nr_ice_media_stream_start_checks(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream)
{
assert(stream->ice_state==NR_ICE_MEDIA_STREAM_CHECKS_FROZEN);
@@ -476,21 +539,23 @@
/* All done... */
r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s)/ICE-STREAM(%s): all components have nominated candidate pairs",stream->pctx->label,stream->label);
nr_ice_media_stream_set_state(stream,NR_ICE_MEDIA_STREAM_CHECKS_COMPLETED);
/* Cancel our timer */
if(stream->timer){
NR_async_timer_cancel(stream->timer);
stream->timer=0;
}
- stream->pctx->handler->vtbl->stream_ready(stream->pctx->handler->obj,stream->local_stream);
+ if (stream->pctx->handler) {
+ stream->pctx->handler->vtbl->stream_ready(stream->pctx->handler->obj,stream->local_stream);
+ }
/* Now tell the peer_ctx that we're done */
if(r=nr_ice_peer_ctx_stream_done(stream->pctx,stream))
ABORT(r);
done:
_status=0;
abort:
return(_status);
}
@@ -515,21 +580,23 @@
p2=TAILQ_NEXT(p2,entry);
}
/* Cancel our timer */
if(stream->timer){
NR_async_timer_cancel(stream->timer);
stream->timer=0;
}
- stream->pctx->handler->vtbl->stream_failed(stream->pctx->handler->obj,stream->local_stream);
+ if (stream->pctx->handler) {
+ stream->pctx->handler->vtbl->stream_failed(stream->pctx->handler->obj,stream->local_stream);
+ }
/* Now tell the peer_ctx that we're done */
if(r=nr_ice_peer_ctx_stream_done(stream->pctx,stream))
ABORT(r);
_status=0;
abort:
return(_status);
}
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_media_stream.h src/ice/ice_media_stream.h
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_media_stream.h 2012-09-16 16:26:08.000000000 -0700
+++ src/ice/ice_media_stream.h 2012-10-06 08:30:22.000000000 -0700
@@ -45,40 +45,43 @@
struct nr_ice_peer_ctx_ *pctx;
struct nr_ice_media_stream_ *local_stream; /* used when this is a peer */
int component_ct;
nr_ice_component_head components;
char *ufrag; /* ICE username */
char *pwd; /* ICE password */
int ice_state;
-#define NR_ICE_MEDIA_STREAM_CHECKS_FROZEN 1
-#define NR_ICE_MEDIA_STREAM_CHECKS_ACTIVE 2
-#define NR_ICE_MEDIA_STREAM_CHECKS_COMPLETED 3
-#define NR_ICE_MEDIA_STREAM_CHECKS_FAILED 4
+
+#define NR_ICE_MEDIA_STREAM_UNPAIRED 1
+#define NR_ICE_MEDIA_STREAM_CHECKS_FROZEN 2
+#define NR_ICE_MEDIA_STREAM_CHECKS_ACTIVE 3
+#define NR_ICE_MEDIA_STREAM_CHECKS_COMPLETED 4
+#define NR_ICE_MEDIA_STREAM_CHECKS_FAILED 5
nr_ice_cand_pair_head check_list;
void *timer; /* Check list periodic timer */
// nr_ice_cand_pair_head valid_list;
-
+
STAILQ_ENTRY(nr_ice_media_stream_) entry;
};
typedef STAILQ_HEAD(nr_ice_media_stream_head_,nr_ice_media_stream_) nr_ice_media_stream_head;
int nr_ice_media_stream_create(struct nr_ice_ctx_ *ctx,char *label, int components, nr_ice_media_stream **streamp);
int nr_ice_media_stream_destroy(nr_ice_media_stream **streamp);
int nr_ice_media_stream_finalize(nr_ice_media_stream *lstr,nr_ice_media_stream *rstr);
int nr_ice_media_stream_initialize(struct nr_ice_ctx_ *ctx, nr_ice_media_stream *stream);
int nr_ice_media_stream_get_attributes(nr_ice_media_stream *stream, char ***attrsp,int *attrctp);
+int nr_ice_media_stream_get_default_candidate(nr_ice_media_stream *stream, int component, nr_ice_candidate **candp);
int nr_ice_media_stream_pair_candidates(nr_ice_peer_ctx *pctx,nr_ice_media_stream *lstream,nr_ice_media_stream *pstream);
int nr_ice_media_stream_start_checks(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream);
int nr_ice_media_stream_unfreeze_pairs(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream);
int nr_ice_media_stream_unfreeze_pairs_foundation(nr_ice_media_stream *stream, char *foundation);
int nr_ice_media_stream_dump_state(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream,FILE *out);
int nr_ice_media_stream_component_nominated(nr_ice_media_stream *stream,nr_ice_component *component);
int nr_ice_media_stream_component_failed(nr_ice_media_stream *stream,nr_ice_component *component);
int nr_ice_media_stream_set_state(nr_ice_media_stream *str, int state);
int nr_ice_media_stream_get_best_candidate(nr_ice_media_stream *str, int component, nr_ice_candidate **candp);
int nr_ice_media_stream_send(nr_ice_peer_ctx *pctx,nr_ice_media_stream *str, int component, UCHAR *data, int len);
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_parser.c src/ice/ice_parser.c
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_parser.c 2012-09-16 16:26:08.000000000 -0700
+++ src/ice/ice_parser.c 2012-10-06 08:30:22.000000000 -0700
@@ -35,20 +35,21 @@
static char *RCSSTRING __UNUSED__="$Id: ice_parser.c,v 1.2 2008/04/28 17:59:01 ekr Exp $";
#include <csi_platform.h>
#include <sys/types.h>
#ifdef WIN32
#include <winsock2.h>
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
+#include <strings.h>
#endif
#include <string.h>
#include <assert.h>
#include <ctype.h>
#include "nr_api.h"
#include "ice_ctx.h"
#include "ice_candidate.h"
#include "ice_reg.h"
static void
@@ -125,21 +126,21 @@
char *rel_addr=0;
if(!(cand=RCALLOC(sizeof(nr_ice_candidate))))
ABORT(R_NO_MEMORY);
if(!(cand->label=r_strdup(orig)))
ABORT(R_NO_MEMORY);
cand->ctx=ctx;
cand->isock=0;
- cand->state=NR_ICE_CAND_PEER_CANDIDATE;
+ cand->state=NR_ICE_CAND_PEER_CANDIDATE_UNPAIRED;
cand->stream=stream;
skip_whitespace(&str);
/* Candidate attr */
if (strncasecmp(str, "candidate:", 10))
ABORT(R_BAD_DATA);
fast_forward(&str, 10);
if (*str == '\0')
ABORT(R_BAD_DATA);
@@ -311,26 +312,31 @@
/* it's expected to be at EOD at this point */
break;
default:
ABORT(R_INTERNAL);
break;
}
skip_whitespace(&str);
- assert(strlen(str) == 0);
-
+ /* This used to be an assert, but we don't want to exit on invalid
+ remote data */
+ if (strlen(str) != 0) {
+ ABORT(R_BAD_DATA);
+ }
+
*candp=cand;
_status=0;
abort:
+ /* TODO(ekr@rtfm.com): Fix memory leak if we have a parse error */
if (_status)
r_log(LOG_ICE,LOG_WARNING,"ICE(%s): Error parsing attribute: %s",ctx->label,orig);
RFREE(connection_address);
RFREE(rel_addr);
return(_status);
}
int
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_peer_ctx.c src/ice/ice_peer_ctx.c
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_peer_ctx.c 2012-09-16 16:26:08.000000000 -0700
+++ src/ice/ice_peer_ctx.c 2012-10-06 08:30:22.000000000 -0700
@@ -35,33 +35,35 @@
static char *RCSSTRING __UNUSED__="$Id: ice_peer_ctx.c,v 1.2 2008/04/28 17:59:01 ekr Exp $";
#include <string.h>
#include <assert.h>
#include <nr_api.h>
#include "ice_ctx.h"
#include "ice_peer_ctx.h"
#include "nr_crypto.h"
#include "async_timer.h"
-static void nr_ice_peer_ctx_destroy_cb(int s, int how, void *cb_arg);
+static void nr_ice_peer_ctx_destroy_cb(NR_SOCKET s, int how, void *cb_arg);
+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);
+static int nr_ice_ctx_parse_candidate(nr_ice_peer_ctx *pctx, nr_ice_media_stream *pstream, char *candidate);
int nr_ice_peer_ctx_create(nr_ice_ctx *ctx, nr_ice_handler *handler,char *label, nr_ice_peer_ctx **pctxp)
{
int r,_status;
nr_ice_peer_ctx *pctx=0;
if(!(pctx=RCALLOC(sizeof(nr_ice_peer_ctx))))
ABORT(R_NO_MEMORY);
if(!(pctx->label=r_strdup(label)))
ABORT(R_NO_MEMORY);
-
+
pctx->ctx=ctx;
pctx->handler=handler;
/* Decide controlling vs. controlled */
if(ctx->flags & NR_ICE_CTX_FLAGS_LITE){
if(pctx->peer_lite){
r_log(LOG_ICE,LOG_ERR,"Both sides are ICE-Lite");
ABORT(R_BAD_DATA);
}
@@ -88,85 +90,177 @@
nr_ice_peer_ctx_destroy_cb(0,0,pctx);
}
return(_status);
}
int nr_ice_peer_ctx_parse_stream_attributes(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, char **attrs, int attr_ct)
{
nr_ice_media_stream *pstream=0;
- nr_ice_candidate *cand=0;
nr_ice_component *comp,*comp2;
int r,_status;
- int i,j;
- /* Note: use component_ct from our own stream since components other
- than this offered by the other side are unusable */
+ /*
+ Note: use component_ct from our own stream since components other
+ than this offered by the other side are unusable */
if(r=nr_ice_media_stream_create(pctx->ctx,stream->label,stream->component_ct,&pstream))
ABORT(r);
-
- /* Match up the local and remote components */
+
+ /* Match up the local and remote components */
comp=STAILQ_FIRST(&stream->components);
comp2=STAILQ_FIRST(&pstream->components);
while(comp){
comp2->local_component=comp;
comp=STAILQ_NEXT(comp,entry);
comp2=STAILQ_NEXT(comp2,entry);
}
-
- pstream->ice_state=NR_ICE_MEDIA_STREAM_CHECKS_FROZEN;
pstream->local_stream=stream;
pstream->pctx=pctx;
+ if (r=nr_ice_peer_ctx_parse_stream_attributes_int(pctx,stream,pstream,attrs,attr_ct))
+ ABORT(r);
+
+
+ STAILQ_INSERT_TAIL(&pctx->peer_streams,pstream,entry);
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+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)
+ {
+ int r;
+ int i;
+
for(i=0;i<attr_ct;i++){
if(!strncmp(attrs[i],"ice-",4)){
- if(r=nr_ice_peer_ctx_parse_media_stream_attribute(pctx,pstream,attrs[i]))
+ if(r=nr_ice_peer_ctx_parse_media_stream_attribute(pctx,pstream,attrs[i])) {
+ r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) specified bogus ICE attribute",pctx->ctx->label,pctx->label);
continue;
- continue;
+ }
}
-
- if(r=nr_ice_peer_candidate_from_attribute(pctx->ctx,attrs[i],pstream,&cand))
- continue;
- if(cand->component_id-1>=pstream->component_ct){
- r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) specified too many components",pctx->ctx->label,pctx->label);
- continue;
+ else if (!strncmp(attrs[i],"candidate",9)){
+ if(r=nr_ice_ctx_parse_candidate(pctx,pstream,attrs[i])) {
+ r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) specified bogus candidate",pctx->ctx->label,pctx->label);
+ continue;
+ }
+ }
+ else {
+ r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) specified bogus attribute",pctx->ctx->label,pctx->label);
}
+ }
- /* Not the fastest way to find a component, but it's what we got */
- j=1;
- for(comp=STAILQ_FIRST(&pstream->components);comp;comp=STAILQ_NEXT(comp,entry)){
- if(j==cand->component_id)
- break;
+ /* Doesn't fail because we just skip errors */
+ return(0);
+ }
- j++;
- }
-
- if(!comp){
- r_log(LOG_ICE,LOG_ERR,"Peer answered with more components than we offered");
- ABORT(R_BAD_DATA);
- }
-
- cand->component=comp;
+static int nr_ice_ctx_parse_candidate(nr_ice_peer_ctx *pctx, nr_ice_media_stream *pstream, char *candidate)
+ {
+ nr_ice_candidate *cand=0;
+ nr_ice_component *comp;
+ int j;
+ int r, _status;
- TAILQ_INSERT_TAIL(&comp->candidates,cand,entry_comp);
+ if(r=nr_ice_peer_candidate_from_attribute(pctx->ctx,candidate,pstream,&cand))
+ ABORT(r);
+ if(cand->component_id-1>=pstream->component_ct){
+ r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) specified too many components",pctx->ctx->label,pctx->label);
+ ABORT(R_BAD_DATA);
}
- STAILQ_INSERT_TAIL(&pctx->peer_streams,pstream,entry);
+ /* Not the fastest way to find a component, but it's what we got */
+ j=1;
+ for(comp=STAILQ_FIRST(&pstream->components);comp;comp=STAILQ_NEXT(comp,entry)){
+ if(j==cand->component_id)
+ break;
+
+ j++;
+ }
+
+ if(!comp){
+ r_log(LOG_ICE,LOG_ERR,"Peer answered with more components than we offered");
+ ABORT(R_BAD_DATA);
+ }
+
+ cand->component=comp;
+
+ TAILQ_INSERT_TAIL(&comp->candidates,cand,entry_comp);
_status=0;
- abort:
+ abort:
+ if (_status) {
+ nr_ice_candidate_destroy(&cand);
+ }
return(_status);
}
+
+
+int nr_ice_peer_ctx_parse_trickle_candidate(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, char *candidate)
+ {
+ /* First need to find the stream. Because we don't have forward pointers,
+ iterate through all the peer streams to find one that matches us */
+ nr_ice_media_stream *pstream;
+ int r,_status;
+ int needs_pairing = 0;
+
+ pstream=STAILQ_FIRST(&pctx->peer_streams);
+ while(pstream) {
+ if (pstream->local_stream == stream)
+ break;
+
+ pstream = STAILQ_NEXT(pstream, entry);
+ }
+ if (!pstream) {
+ r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) has no stream matching stream %s",pctx->ctx->label,pctx->label,stream->label);
+ ABORT(R_NOT_FOUND);
+ }
+
+ switch(pstream->ice_state) {
+ case NR_ICE_MEDIA_STREAM_UNPAIRED:
+ break;
+ case NR_ICE_MEDIA_STREAM_CHECKS_FROZEN:
+ case NR_ICE_MEDIA_STREAM_CHECKS_ACTIVE:
+ needs_pairing = 1;
+ break;
+ default:
+ 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);
+ ABORT(R_ALREADY);
+ break;
+ }
+
+ if(r=nr_ice_ctx_parse_candidate(pctx,pstream,candidate)){
+ ABORT(r);
+ }
+
+ /* If ICE is running (i.e., we are in FROZEN or ACTIVE states)
+ then we need to pair this new candidate. For now we
+ just re-pair the stream which is inefficient but still
+ fine because we suppress duplicate pairing */
+ if (needs_pairing) {
+ if(r=nr_ice_media_stream_pair_candidates(pctx, stream, pstream)) {
+ 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);
+ ABORT(r);
+ }
+ }
+
+ _status =0;
+ abort:
+ return(_status);
+
+ }
+
+
int nr_ice_peer_ctx_pair_candidates(nr_ice_peer_ctx *pctx)
{
nr_ice_media_stream *stream;
int r,_status;
if(STAILQ_EMPTY(&pctx->peer_streams)) {
r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) received no media stream attribributes",pctx->ctx->label,pctx->label);
ABORT(R_FAILED);
}
@@ -177,21 +271,21 @@
ABORT(r);
stream=STAILQ_NEXT(stream,entry);
}
_status=0;
abort:
return(_status);
}
-static void nr_ice_peer_ctx_destroy_cb(int s, int how, void *cb_arg)
+static void nr_ice_peer_ctx_destroy_cb(NR_SOCKET s, int how, void *cb_arg)
{
nr_ice_peer_ctx *pctx=cb_arg;
nr_ice_media_stream *str1,*str2;
RFREE(pctx->label);
RFREE(pctx->peer_ufrag);
RFREE(pctx->peer_pwd);
STAILQ_FOREACH_SAFE(str1, &pctx->peer_streams, entry, str2){
STAILQ_REMOVE(&pctx->peer_streams,str1,nr_ice_media_stream_,entry);
@@ -199,44 +293,79 @@
}
RFREE(pctx);
}
int nr_ice_peer_ctx_destroy(nr_ice_peer_ctx **pctxp)
{
if(!pctxp || !*pctxp)
return(0);
-
+
+ /* Stop calling the handler */
+ (*pctxp)->handler = 0;
+
NR_ASYNC_SCHEDULE(nr_ice_peer_ctx_destroy_cb,*pctxp);
*pctxp=0;
return(0);
}
+
/* Start the checks for the first media stream (S 5.7)
The rest remain FROZEN */
int nr_ice_peer_ctx_start_checks(nr_ice_peer_ctx *pctx)
{
+ return nr_ice_peer_ctx_start_checks2(pctx, 0);
+ }
+
+/* Start checks for some media stream.
+
+ If allow_non_first == 0, then we only look at the first stream,
+ which is 5245-complaint.
+
+ If allow_non_first == 1 then we find the first non-empty stream
+ This is not compliant with RFC 5245 but is necessary to make trickle ICE
+ work plausibly
+*/
+int nr_ice_peer_ctx_start_checks2(nr_ice_peer_ctx *pctx, int allow_non_first)
+ {
int r,_status;
nr_ice_media_stream *stream;
stream=STAILQ_FIRST(&pctx->peer_streams);
if(!stream)
ABORT(R_FAILED);
+ while (stream) {
+ if(!TAILQ_EMPTY(&stream->check_list))
+ break;
+
+ if(!allow_non_first){
+ r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) first stream has empty check list",pctx->ctx->label,pctx->label);
+ ABORT(R_FAILED);
+ }
+
+ stream=STAILQ_NEXT(stream, entry);
+ }
+
+ if (!stream) {
+ r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) no streams with non-empty check lists",pctx->ctx->label,pctx->label);
+ ABORT(R_NOT_FOUND);
+ }
+
if (stream->ice_state == NR_ICE_MEDIA_STREAM_CHECKS_FROZEN) {
- if(r=nr_ice_media_stream_unfreeze_pairs(pctx,stream))
- ABORT(r);
- if(r=nr_ice_media_stream_start_checks(pctx,stream))
- ABORT(r);
+ if(r=nr_ice_media_stream_unfreeze_pairs(pctx,stream))
+ ABORT(r);
+ if(r=nr_ice_media_stream_start_checks(pctx,stream))
+ ABORT(r);
}
_status=0;
abort:
return(_status);
}
#ifndef NDEBUG
int nr_ice_peer_ctx_dump_state(nr_ice_peer_ctx *pctx,FILE *out)
{
@@ -253,26 +382,28 @@
stream=STAILQ_NEXT(stream,entry);
}
fprintf(out,"==========================================\n");
_status=0;
abort:
return(_status);
}
#endif
-static void nr_ice_peer_ctx_fire_done(int s, int how, void *cb_arg)
+static void nr_ice_peer_ctx_fire_done(NR_SOCKET s, int how, void *cb_arg)
{
nr_ice_peer_ctx *pctx=cb_arg;
/* Fire the handler callback to say we're done */
- pctx->handler->vtbl->ice_completed(pctx->handler->obj, pctx);
+ if (pctx->handler) {
+ pctx->handler->vtbl->ice_completed(pctx->handler->obj, pctx);
+ }
}
/* OK, a stream just went ready. Examine all the streams to see if we're
maybe miraculously done */
int nr_ice_peer_ctx_stream_done(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream)
{
int _status;
nr_ice_media_stream *str;
int failed=0;
@@ -365,21 +496,24 @@
NR_TRANSPORT_ADDR_CMP_MODE_ALL))
break;
cand=TAILQ_NEXT(cand,entry_comp);
}
if(!cand)
ABORT(R_REJECTED);
/* OK, there's a match. Call the handler */
- r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): Delivering data", pctx->label);
- pctx->handler->vtbl->msg_recvd(pctx->handler->obj,
- pctx,comp->stream,comp->component_id,data,len);
+ if (pctx->handler) {
+ r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): Delivering data", pctx->label);
+
+ pctx->handler->vtbl->msg_recvd(pctx->handler->obj,
+ pctx,comp->stream,comp->component_id,data,len);
+ }
_status=0;
abort:
return(_status);
}
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_peer_ctx.h src/ice/ice_peer_ctx.h
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_peer_ctx.h 2012-09-16 16:26:08.000000000 -0700
+++ src/ice/ice_peer_ctx.h 2012-10-06 08:30:22.000000000 -0700
@@ -33,23 +33,21 @@
#ifndef _ice_peer_ctx_h
#define _ice_peer_ctx_h
#ifdef __cplusplus
using namespace std;
extern "C" {
#endif /* __cplusplus */
struct nr_ice_peer_ctx_ {
- int state;
char *label;
-
nr_ice_ctx *ctx;
nr_ice_handler *handler;
UCHAR controlling; /* 1 for controlling, 0 for controlled */
UINT8 tiebreaker;
char *peer_ufrag;
char *peer_pwd;
int peer_lite;
int peer_ice_mismatch;
@@ -59,23 +57,26 @@
int waiting_pairs;
STAILQ_ENTRY(nr_ice_peer_ctx_) entry;
};
typedef STAILQ_HEAD(nr_ice_peer_ctx_head_, nr_ice_peer_ctx_) nr_ice_peer_ctx_head;
int nr_ice_peer_ctx_create(nr_ice_ctx *ctx, nr_ice_handler *handler,char *label, nr_ice_peer_ctx **pctxp);
int nr_ice_peer_ctx_destroy(nr_ice_peer_ctx **pctxp);
int nr_ice_peer_ctx_parse_stream_attributes(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, char **attrs, int attr_ct);
+int nr_ice_peer_ctx_parse_trickle_candidate(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, char *cand);
+
int nr_ice_peer_ctx_pair_candidates(nr_ice_peer_ctx *pctx);
int nr_ice_peer_ctx_parse_global_attributes(nr_ice_peer_ctx *pctx, char **attrs, int attr_ct);
int nr_ice_peer_ctx_start_checks(nr_ice_peer_ctx *pctx);
+int nr_ice_peer_ctx_start_checks2(nr_ice_peer_ctx *pctx, int allow_non_first);
int nr_ice_peer_ctx_dump_state(nr_ice_peer_ctx *pctx,FILE *out);
int nr_ice_peer_ctx_log_state(nr_ice_peer_ctx *pctx);
int nr_ice_peer_ctx_stream_done(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream);
int nr_ice_peer_ctx_find_component(nr_ice_peer_ctx *pctx, nr_ice_media_stream *str, int component_id, nr_ice_component **compp);
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);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_socket.c src/ice/ice_socket.c
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_socket.c 2012-09-16 16:26:08.000000000 -0700
+++ src/ice/ice_socket.c 2012-10-06 08:30:22.000000000 -0700
@@ -216,28 +216,34 @@
RFREE(s1);
}
RFREE(isock);
return(0);
}
int nr_ice_socket_close(nr_ice_socket *isock)
{
+#ifdef NR_SOCKET_IS_VOID_PTR
+ NR_SOCKET fd=NULL;
+ NR_SOCKET no_socket = NULL;
+#else
NR_SOCKET fd=-1;
+ NR_SOCKET no_socket = -1;
+#endif
if (!isock||!isock->sock)
return(0);
nr_socket_getfd(isock->sock,&fd);
assert(isock->sock!=0);
- if(fd!=-1){
+ if(fd != no_socket){
NR_ASYNC_CANCEL(fd,NR_ASYNC_WAIT_READ);
NR_ASYNC_CANCEL(fd,NR_ASYNC_WAIT_WRITE);
nr_socket_destroy(&isock->sock);
}
return(0);
}
int nr_ice_socket_register_stun_client(nr_ice_socket *sock, nr_stun_client_ctx *srv,void **handle)
{
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/net/nr_socket.h src/net/nr_socket.h
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/net/nr_socket.h 2012-09-16 16:26:09.000000000 -0700
+++ src/net/nr_socket.h 2012-10-06 08:30:22.000000000 -0700
@@ -38,21 +38,23 @@
#include <sys/types.h>
#ifdef WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <sys/socket.h>
#endif
#include "transport_addr.h"
-#ifdef WIN32
+#ifdef __cplusplus
+#define restrict
+#elif defined(WIN32)
#define restrict __restrict
#endif
typedef struct nr_socket_vtbl_ {
int (*destroy)(void **obj);
int (*ssendto)(void *obj,const void *msg, size_t len, int flags,
nr_transport_addr *addr);
int (*srecvfrom)(void *obj,void * restrict buf, size_t maxlen, size_t *len, int flags,
nr_transport_addr *addr);
int (*getfd)(void *obj, NR_SOCKET *fd);
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/net/transport_addr_reg.c src/net/transport_addr_reg.c
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/net/transport_addr_reg.c 2012-09-16 16:26:09.000000000 -0700
+++ src/net/transport_addr_reg.c 2012-10-06 08:30:22.000000000 -0700
@@ -29,25 +29,27 @@
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
static char *RCSSTRING __UNUSED__="$Id: transport_addr_reg.c,v 1.2 2008/04/28 17:59:03 ekr Exp $";
#include <csi_platform.h>
#include <stdio.h>
+#include <string.h>
#include <memory.h>
#include <sys/types.h>
#ifdef WIN32
#include <winsock2.h>
#else
+#include <strings.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif
#include <assert.h>
#include "nr_api.h"
#include "transport_addr.h"
#include "transport_addr_reg.h"
@@ -83,20 +85,22 @@
if ((r=NR_reg_get2_uint2(prefix, "port", &port))) {
if (r != R_NOT_FOUND)
ABORT(r);
port = 0;
}
if ((r=NR_reg_alloc2_string(prefix, "protocol", &protocol))) {
if (r != R_NOT_FOUND)
ABORT(r);
+ p = IPPROTO_UDP;
+
protocol = 0;
}
else {
if (!strcasecmp("tcp", protocol))
p = IPPROTO_TCP;
else if (!strcasecmp("udp", protocol))
p = IPPROTO_UDP;
else
ABORT(R_BAD_DATA);
}
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/addrs.c src/stun/addrs.c
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/addrs.c 2012-09-16 16:26:10.000000000 -0700
+++ src/stun/addrs.c 2012-10-06 09:42:43.000000000 -0700
@@ -46,20 +46,22 @@
#include <sys/sysctl.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/syslog.h>
#include <net/if.h>
#ifndef LINUX
#include <net/if_var.h>
#include <net/if_dl.h>
#include <net/if_types.h>
#include <sys/sockio.h>
+#else
+#include <linux/if.h>
#endif
#include <net/route.h>
/* IP */
#include <netinet/in.h>
#ifdef LINUX
#include "sys/ioctl.h"
#else
#include <netinet/in_var.h>
#endif
@@ -105,20 +107,23 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <err.h>
static void stun_rt_xaddrs(caddr_t, caddr_t, struct rt_addrinfo *);
static int stun_grab_addrs(char *name, int addrcount,
struct ifa_msghdr *ifam,
nr_transport_addr addrs[], int maxaddrs, int *count);
+static int
+nr_stun_is_duplicate_addr(nr_transport_addr addrs[], int count, nr_transport_addr *addr);
+
/*
* Expand the compacted form of addresses as returned via the
* configuration read via sysctl().
*/
#define ROUNDUP(a) \
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
static void
@@ -135,21 +140,21 @@
continue;
rtinfo->rti_info[i] = sa = (struct sockaddr *)cp;
ADVANCE(cp, sa);
}
}
static int
stun_grab_addrs(char *name, int addrcount, struct ifa_msghdr *ifam, nr_transport_addr addrs[], int maxaddrs, int *count)
{
int r,_status;
- NR_SOCKET s = -1;
+ int s = -1;
struct ifreq ifr;
struct rt_addrinfo info;
struct sockaddr_in *sin;
ifr.ifr_addr.sa_family = AF_INET;
strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0) {
r_log(NR_LOG_STUN, LOG_WARNING, "unable to obtain addresses from socket");
ABORT(R_FAILED);
@@ -180,21 +185,20 @@
addrcount--;
if (*count >= maxaddrs) {
r_log(NR_LOG_STUN, LOG_WARNING, "Address list truncated at %d out of entries", maxaddrs, maxaddrs+addrcount);
break;
}
ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen);
}
-
_status = 0;
abort:
if (s != -1) close(s);
return _status;
}
static int
stun_get_mib_addrs(nr_transport_addr addrs[], int maxaddrs, int *count)
{
int _status;
@@ -551,44 +555,48 @@
#else
static int
stun_get_siocgifconf_addrs(nr_transport_addr addrs[], int maxaddrs, int *count)
{
struct ifconf ifc;
int _status;
int s = socket( AF_INET, SOCK_DGRAM, 0 );
int len = 100 * sizeof(struct ifreq);
int r;
+ int e;
+ char *ptr;
+ int tl;
+ int n;
+ struct ifreq ifr2;
char buf[ len ];
ifc.ifc_len = len;
ifc.ifc_buf = buf;
- int e = ioctl(s,SIOCGIFCONF,&ifc);
- char *ptr = buf;
- int tl = ifc.ifc_len;
- int n=0;
+ e = ioctl(s,SIOCGIFCONF,&ifc);
+ ptr = buf;
+ tl = ifc.ifc_len;
+ n=0;
while ( (tl > 0) && ( n < maxaddrs) )
{
struct ifreq* ifr = (struct ifreq *)ptr;
#ifdef LINUX
- int si = sizeof(ifr->ifr_name) + sizeof(ifr->ifr_addr);
+ int si = sizeof(struct ifreq);
#else
int si = sizeof(ifr->ifr_name) + MAX(ifr->ifr_addr.sa_len, sizeof(ifr->ifr_addr));
#endif
tl -= si;
ptr += si;
- struct ifreq ifr2;
ifr2 = *ifr;
e = ioctl(s,SIOCGIFADDR,&ifr2);
if ( e == -1 )
{
continue;
}
//r_log(NR_LOG_STUN, LOG_ERR, "ioctl addr e = %d",e);
@@ -603,21 +611,21 @@
close(s);
*count = n;
_status = 0;
return _status;
}
#endif
-int
+static int
nr_stun_is_duplicate_addr(nr_transport_addr addrs[], int count, nr_transport_addr *addr)
{
int i;
int different;
for (i = 0; i < count; ++i) {
different = nr_transport_addr_cmp(&addrs[i], addr, NR_TRANSPORT_ADDR_CMP_MODE_ALL);
if (!different)
return 1; /* duplicate */
}
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/nr_socket_turn.c src/stun/nr_socket_turn.c
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/nr_socket_turn.c 2012-09-16 16:26:10.000000000 -0700
+++ src/stun/nr_socket_turn.c 2012-10-06 08:30:22.000000000 -0700
@@ -246,17 +246,19 @@
default:
assert(0);
break;
}
return R_FAILED;
}
static int nr_socket_turn_close(void *obj)
{
+#ifndef NDEBUG
nr_socket_turn *sturn=obj;
assert(sturn->magic_cookie == nr_socket_turn_magic_cookie);
+#endif
return 0;
}
#endif /* USE_TURN */
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/stun_client_ctx.c src/stun/stun_client_ctx.c
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/stun_client_ctx.c 2012-09-16 16:26:10.000000000 -0700
+++ src/stun/stun_client_ctx.c 2012-10-06 08:30:22.000000000 -0700
@@ -38,21 +38,22 @@
#include <string.h>
#include <nr_api.h>
#include "stun.h"
#include "async_timer.h"
#include "registry.h"
#include "stun_reg.h"
#include "r_time.h"
static int nr_stun_client_send_request(nr_stun_client_ctx *ctx);
-static void nr_stun_client_timer_expired_cb(int a, int b, void *cb_arg);
+static void nr_stun_client_timer_expired_cb(NR_SOCKET s, int b, void *cb_arg);
+static int nr_stun_client_get_password(void *arg, nr_stun_message *msg, Data **password);
int nr_stun_client_ctx_create(char *label, nr_socket *sock, nr_transport_addr *peer, UINT4 RTO, nr_stun_client_ctx **ctxp)
{
nr_stun_client_ctx *ctx=0;
int r,_status;
if ((r=nr_stun_startup()))
ABORT(r);
if(!(ctx=RCALLOC(sizeof(nr_stun_client_ctx))))
@@ -185,21 +186,21 @@
ctx->finished_cb = 0;
ctx->cb_arg = 0;
ctx->request_ct = 0;
ctx->timeout_ms = 0;
ctx->state = NR_STUN_CLIENT_STATE_INITTED;
return 0;
}
-static void nr_stun_client_timer_expired_cb(int a, int b, void *cb_arg)
+static void nr_stun_client_timer_expired_cb(NR_SOCKET s, int b, void *cb_arg)
{
int _status;
nr_stun_client_ctx *ctx=cb_arg;
struct timeval now;
INT8 ms_waited;
/* Prevent this timer from being cancelled later */
ctx->timer_handle=0;
/* Shouldn't happen */
@@ -387,21 +388,21 @@
}
_status=0;
abort:
if (_status) {
ctx->state=NR_STUN_CLIENT_STATE_FAILED;
}
return(_status);
}
-int nr_stun_client_get_password(void *arg, nr_stun_message *msg, Data **password)
+static int nr_stun_client_get_password(void *arg, nr_stun_message *msg, Data **password)
{
*password = (Data*)arg;
if (!arg)
return(R_NOT_FOUND);
return(0);
}
int nr_stun_client_process_response(nr_stun_client_ctx *ctx, UCHAR *msg, int len, nr_transport_addr *peer_addr)
{
int r,_status;
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/stun_codec.c src/stun/stun_codec.c
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/stun_codec.c 2012-09-16 16:26:10.000000000 -0700
+++ src/stun/stun_codec.c 2012-10-06 08:30:22.000000000 -0700
@@ -73,20 +73,22 @@
static int nr_stun_decode_htonll(UCHAR *buf, int buflen, int *offset, UINT8 *data);
static int nr_stun_decode(int length, UCHAR *buf, int buflen, int *offset, UCHAR *data);
static int nr_stun_attr_string_illegal(nr_stun_attr_info *attr_info, int len, void *data, int max_bytes, int max_chars);
static int nr_stun_attr_error_code_illegal(nr_stun_attr_info *attr_info, int attrlen, void *data);
static int nr_stun_attr_nonce_illegal(nr_stun_attr_info *attr_info, int attrlen, void *data);
static int nr_stun_attr_realm_illegal(nr_stun_attr_info *attr_info, int attrlen, void *data);
static int nr_stun_attr_server_illegal(nr_stun_attr_info *attr_info, int attrlen, void *data);
static int nr_stun_attr_username_illegal(nr_stun_attr_info *attr_info, int attrlen, void *data);
+static int
+nr_stun_attr_codec_fingerprint_decode(nr_stun_attr_info *attr_info, int attrlen, UCHAR *buf, int offset, int buflen, void *data);
int
nr_stun_encode_htons(UINT2 data, int buflen, UCHAR *buf, int *offset)
{
UINT2 d = htons(data);
if (*offset + sizeof(d) >= buflen) {
r_log(NR_LOG_STUN, LOG_WARNING, "Attempted buffer overrun: %d + %d >= %d", *offset, sizeof(d), buflen);
return R_BAD_DATA;
@@ -632,21 +634,21 @@
}
fingerprint->checksum = checksum ^ 0x5354554e;
r_log(NR_LOG_STUN, LOG_DEBUG, "Computed FINGERPRINT %08x", fingerprint->checksum);
fingerprint->valid = 1;
return nr_stun_attr_codec_UINT4.encode(attr_info, &fingerprint->checksum, offset, buflen, buf, attrlen);
}
-int
+static int
nr_stun_attr_codec_fingerprint_decode(nr_stun_attr_info *attr_info, int attrlen, UCHAR *buf, int offset, int buflen, void *data)
{
int r,_status;
nr_stun_attr_fingerprint *fingerprint = data;
nr_stun_message_header *header = (nr_stun_message_header*)buf;
int length;
UINT4 checksum;
if ((r=nr_stun_attr_codec_UINT4.decode(attr_info, attrlen, buf, offset, buflen, &fingerprint->checksum)))
ABORT(r);
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/stun_proc.c src/stun/stun_proc.c
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/stun_proc.c 2012-09-16 16:26:10.000000000 -0700
+++ src/stun/stun_proc.c 2012-10-06 08:30:22.000000000 -0700
@@ -43,20 +43,22 @@
#include <time.h>
#else /* UNIX */
#include <string.h>
#endif /* end UNIX */
#include <assert.h>
#include "stun.h"
#include "stun_reg.h"
#include "registry.h"
+static int
+nr_stun_add_realm_and_nonce(int new_nonce, nr_stun_server_client *clnt, nr_stun_message *res);
/* draft-ietf-behave-rfc3489bis-10.txt S 7.3 */
int
nr_stun_receive_message(nr_stun_message *req, nr_stun_message *msg)
{
int _status;
nr_stun_message_attribute *attr;
#ifdef USE_RFC_3489_BACKWARDS_COMPATIBLE
/* if this message was generated by an RFC 3489 impementation,
@@ -371,21 +373,21 @@
/* nothing to check in this case */
break;
#endif /* USE_STUND_0_96 */
}
_status=0;
abort:
return _status;
}
-int
+static int
nr_stun_add_realm_and_nonce(int new_nonce, nr_stun_server_client *clnt, nr_stun_message *res)
{
int r,_status;
char *realm = 0;
char *nonce;
UINT2 size;
if ((r=NR_reg_alloc_string(NR_STUN_REG_PREF_SERVER_REALM, &realm)))
ABORT(r);
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/stun_server_ctx.c src/stun/stun_server_ctx.c
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/stun_server_ctx.c 2012-09-16 16:26:10.000000000 -0700
+++ src/stun/stun_server_ctx.c 2012-10-06 08:30:22.000000000 -0700
@@ -114,21 +114,21 @@
STAILQ_INSERT_TAIL(&ctx->clients,clnt,entry);
_status=0;
abort:
if(_status){
nr_stun_server_destroy_client(clnt);
}
return(_status);
}
-int nr_stun_server_get_password(void *arg, nr_stun_message *msg, Data **password)
+static int nr_stun_server_get_password(void *arg, nr_stun_message *msg, Data **password)
{
int _status;
nr_stun_server_ctx *ctx = (nr_stun_server_ctx*)arg;
nr_stun_server_client *clnt = 0;
nr_stun_message_attribute *username_attribute;
if ((nr_stun_get_message_client(ctx, msg, &clnt))) {
if (! nr_stun_message_has_attribute(msg, NR_STUN_ATTR_USERNAME, &username_attribute)) {
r_log(NR_LOG_STUN,LOG_NOTICE,"STUN-SERVER(%s): Missing Username",ctx->label);
ABORT(R_NOT_FOUND);
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/stun_util.c src/stun/stun_util.c
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/stun_util.c 2012-09-16 16:26:10.000000000 -0700
+++ src/stun/stun_util.c 2012-10-06 08:30:22.000000000 -0700
@@ -94,21 +94,20 @@
_status = 0;
abort:
return _status;
}
int
nr_stun_find_local_addresses(nr_transport_addr addrs[], int maxaddrs, int *count)
{
int r,_status;
NR_registry *children = 0;
- int i;
if ((r=NR_reg_get_child_count(NR_STUN_REG_PREF_ADDRESS_PRFX, (unsigned int*)count)))
if (r == R_NOT_FOUND)
*count = 0;
else
ABORT(r);
if (*count == 0) {
if ((r=nr_stun_get_addrs(addrs, maxaddrs, 1, count)))
ABORT(r);
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/turn_client_ctx.c src/stun/turn_client_ctx.c
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/turn_client_ctx.c 2012-09-16 16:26:10.000000000 -0700
+++ src/stun/turn_client_ctx.c 2012-10-06 08:30:22.000000000 -0700
@@ -55,21 +55,24 @@
};
static int TURN_PHASE_MODE[NUMBER_OF_STUN_CTX] = {
NR_TURN_CLIENT_MODE_ALLOCATE_REQUEST1,
NR_TURN_CLIENT_MODE_ALLOCATE_REQUEST2,
NR_TURN_CLIENT_MODE_SET_ACTIVE_DEST_REQUEST
};
static int nr_turn_client_next_action(nr_turn_client_ctx *ctx, int stun_ctx_state);
-static void nr_turn_client_cb(int s, int how, void *cb_arg);
+static void nr_turn_client_cb(NR_SOCKET s, int how, void *cb_arg);
+static int
+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);
+
int
nr_turn_client_next_action(nr_turn_client_ctx *ctx, int stun_ctx_state)
{
int r,_status;
assert(ctx->phase >= -1 && ctx->phase < NUMBER_OF_STUN_CTX);
switch (ctx->state) {
//case NR_TURN_CLIENT_STATE_ALLOCATING:
@@ -147,21 +150,21 @@
* because as a side effect this ctx may be operated on in the
* callback */
finished_cb(0,0,ctx->cb_arg);
}
}
return(_status);
}
void
-nr_turn_client_cb(int s, int how, void *cb_arg)
+nr_turn_client_cb(NR_SOCKET s, int how, void *cb_arg)
{
int r,_status;
nr_turn_client_ctx *ctx = (nr_turn_client_ctx*)cb_arg;
nr_stun_client_ctx *stun_ctx = ctx->stun_ctx[ctx->phase];
assert(ctx->phase >= 0);
if ((r=nr_turn_client_next_action(ctx, stun_ctx->state)))
ABORT(r);
@@ -234,21 +237,21 @@
RFREE(ctx->username);
r_data_destroy(&ctx->password);
RFREE(ctx->label);
RFREE(ctx);
return(0);
}
-int
+static int
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)
{
int r,_status;
nr_stun_client_allocate_request1_params *allocate_request1 = 0;
nr_stun_client_allocate_request2_params *allocate_request2 = 0;
nr_stun_client_allocate_response1_results *allocate_response1 = 0;
// nr_stun_client_allocate_response2_results *allocate_response2;
if (ctx->state != NR_TURN_CLIENT_STATE_INITTED)
ABORT(R_NOT_PERMITTED);
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/util/ice_util.c src/util/ice_util.c
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/util/ice_util.c 2012-09-16 16:26:10.000000000 -0700
+++ src/util/ice_util.c 2012-10-06 08:30:22.000000000 -0700
@@ -31,20 +31,21 @@
*/
#include <stdarg.h>
static char *RCSSTRING __UNUSED__="$Id: ice_util.c,v 1.2 2008/04/28 17:59:05 ekr Exp $";
#include <stdarg.h>
#include <string.h>
#include "nr_api.h"
+#include "ice_util.h"
int nr_concat_strings(char **outp,...)
{
va_list ap;
char *s,*out=0;
int len=0;
int _status;
va_start(ap,outp);
while(s=va_arg(ap,char *)){
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/util/mbslen.c src/util/mbslen.c
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/util/mbslen.c 2012-09-16 16:26:10.000000000 -0700
+++ src/util/mbslen.c 2012-10-06 08:31:01.000000000 -0700
@@ -56,21 +56,21 @@
{
#ifdef DARWIN
static locale_t loc = 0;
static int initialized = 0;
#endif /* DARWIN */
#ifdef WIN32
char *my_locale=0;
unsigned int i;
#endif /* WIN32 */
int _status;
- int nbytes;
+ size_t nbytes;
int nchars;
mbstate_t mbs;
#ifdef DARWIN
if (! initialized) {
initialized = 1;
loc = newlocale(LC_CTYPE_MASK, "UTF-8", LC_GLOBAL_LOCALE);
}
if (loc == 0) {
@@ -102,25 +102,28 @@
memset(&mbs, 0, sizeof(mbs));
nchars = 0;
#ifdef DARWIN
while (*s != '\0' && (nbytes = mbrlen_l(s, strlen(s), &mbs, loc)) != 0)
#else
while (*s != '\0' && (nbytes = mbrlen(s, strlen(s), &mbs)) != 0)
#endif /* DARWIN */
{
- assert(nbytes >= 0);
- if (nbytes == (size_t)-1) /* should never happen */
+ if (nbytes == (size_t)-1) /* should never happen */ {
+ assert(0);
ABORT(R_INTERNAL);
- if (nbytes == (size_t)-2) /* encoding error */
+ }
+ if (nbytes == (size_t)-2) /* encoding error */ {
+ assert(0);
ABORT(R_BAD_DATA);
+ }
s += nbytes;
++nchars;
}
*ncharsp = nchars;
_status = 0;
abort:
#ifdef WIN32