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