int nr_ice_candidate_pair_create(nr_ice_peer_ctx *pctx, nr_ice_candidate *lcand,nr_ice_candidate *rcand,nr_ice_cand_pair **pairp) { nr_ice_cand_pair *pair=0; UINT8 o_priority, a_priority; int r,_status; UINT4 RTO; nr_ice_candidate tmpcand; UINT8 t_priority; if(!(pair=RCALLOC(sizeof(nr_ice_cand_pair)))) ABORT(R_NO_MEMORY); pair->pctx=pctx; nr_ice_candidate_pair_compute_codeword(pair,lcand,rcand); if(r=nr_concat_strings(&pair->as_string,pair->codeword,"|",lcand->addr.as_string,"|", rcand->addr.as_string,"(",lcand->label,"|",rcand->label,")", NULL)) ABORT(r); nr_ice_candidate_pair_set_state(pctx,pair,NR_ICE_PAIR_STATE_FROZEN); pair->local=lcand; pair->remote=rcand; /* Priority computation S 5.7.2 */ if(pctx->ctx->flags & NR_ICE_CTX_FLAGS_OFFERER) { assert(!(pctx->ctx->flags & NR_ICE_CTX_FLAGS_ANSWERER)); o_priority=lcand->priority; a_priority=rcand->priority; } else{ o_priority=rcand->priority; a_priority=lcand->priority; } pair->priority=(MIN(o_priority, a_priority))<<32 | (MAX(o_priority, a_priority))<<1 | (o_priority > a_priority?0:1); /* TODO([email protected]): Would be nice to log why this candidate was created (initial pair generation, triggered check, and new trickle candidate seem to be the possibilities here). */ r_log(LOG_ICE,LOG_INFO,"ICE(%s)/CAND-PAIR(%s): Pairing candidate %s (%x):%s (%x) priority=%llu (%llx)",pctx->ctx->label,pair->codeword,lcand->addr.as_string,lcand->priority,rcand->addr.as_string,rcand->priority,pair->priority,pair->priority); /* Foundation */ if(r=nr_concat_strings(&pair->foundation,lcand->foundation,"|", rcand->foundation,NULL)) ABORT(r); /* Compute the RTO per S 16 */ RTO = MAX(100, (pctx->ctx->Ta * pctx->waiting_pairs)); /* Make a bogus candidate to compute a theoretical peer reflexive * priority per S 7.1.1.1 */ memcpy(&tmpcand, lcand, sizeof(tmpcand)); tmpcand.type = PEER_REFLEXIVE; if (r=nr_ice_candidate_compute_priority(&tmpcand)) ABORT(r); t_priority = tmpcand.priority; /* Our sending context */ if(r=nr_stun_client_ctx_create(pair->as_string, lcand->osock, &rcand->addr,RTO,&pair->stun_client)) ABORT(r); if(!(pair->stun_client->params.ice_binding_request.username=r_strdup(rcand->stream->l2r_user))) ABORT(R_NO_MEMORY); if(r=r_data_copy(&pair->stun_client->params.ice_binding_request.password, &rcand->stream->l2r_pass)) ABORT(r); pair->stun_client->params.ice_binding_request.priority=t_priority; /* TODO([email protected]): Do we need to frob this when we change role. Bug 890667 */ pair->stun_client->params.ice_binding_request.control = pctx->controlling? NR_ICE_CONTROLLING:NR_ICE_CONTROLLED; pair->stun_client->params.ice_use_candidate.priority=t_priority; pair->stun_client->params.ice_binding_request.tiebreaker=pctx->tiebreaker; *pairp=pair; _status=0; abort: if(_status){ nr_ice_candidate_pair_destroy(&pair); } return(_status); }
int nr_ice_candidate_pair_create(nr_ice_peer_ctx *pctx, nr_ice_candidate *lcand,nr_ice_candidate *rcand,nr_ice_cand_pair **pairp) { nr_ice_cand_pair *pair=0; UINT8 o_priority, a_priority; char *lufrag,*rufrag; char *lpwd,*rpwd; char *l2ruser=0,*r2lpass=0; int r,_status; UINT4 RTO; nr_ice_candidate tmpcand; UINT8 t_priority; if(!(pair=RCALLOC(sizeof(nr_ice_cand_pair)))) ABORT(R_NO_MEMORY); pair->pctx=pctx; nr_ice_candidate_pair_compute_codeword(pair,lcand,rcand); if(r=nr_concat_strings(&pair->as_string,pair->codeword,"|",lcand->addr.as_string,"|", rcand->addr.as_string,"(",lcand->label,"|",rcand->label,")",0)) ABORT(r); nr_ice_candidate_pair_set_state(pctx,pair,NR_ICE_PAIR_STATE_FROZEN); pair->local=lcand; pair->remote=rcand; /* Priority computation S 5.7.2 */ if(pctx->ctx->flags & NR_ICE_CTX_FLAGS_OFFERER) { assert(!(pctx->ctx->flags & NR_ICE_CTX_FLAGS_ANSWERER)); o_priority=lcand->priority; a_priority=rcand->priority; } else{ o_priority=rcand->priority; a_priority=lcand->priority; } pair->priority=(MIN(o_priority, a_priority))<<32 | (MAX(o_priority, a_priority))<<1 | (o_priority > a_priority?0:1); r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): Pairing candidate %s (%x):%s (%x) priority=%llu (%llx) codeword=%s",pctx->ctx->label,lcand->addr.as_string,lcand->priority,rcand->addr.as_string,rcand->priority,pair->priority,pair->priority,pair->codeword); /* Foundation */ if(r=nr_concat_strings(&pair->foundation,lcand->foundation,"|", rcand->foundation,0)) ABORT(r); /* OK, now the STUN data */ lufrag=lcand->stream->ufrag?lcand->stream->ufrag:pctx->ctx->ufrag; lpwd=lcand->stream->pwd?lcand->stream->pwd:pctx->ctx->pwd; rufrag=rcand->stream->ufrag?rcand->stream->ufrag:pctx->peer_ufrag; rpwd=rcand->stream->pwd?rcand->stream->pwd:pctx->peer_pwd; /* Compute the RTO per S 16 */ RTO = MAX(100, (pctx->ctx->Ta * pctx->waiting_pairs)); /* Make a bogus candidate to compute a theoretical peer reflexive * priority per S 7.1.1.1 */ memcpy(&tmpcand, lcand, sizeof(tmpcand)); tmpcand.type = PEER_REFLEXIVE; if (r=nr_ice_candidate_compute_priority(&tmpcand)) ABORT(r); t_priority = tmpcand.priority; /* Our sending context */ if(r=nr_concat_strings(&l2ruser,lufrag,":",rufrag,0)) ABORT(r); if(r=nr_stun_client_ctx_create(pair->as_string, lcand->osock, &rcand->addr,RTO,&pair->stun_client)) ABORT(r); if(!(pair->stun_client->params.ice_binding_request.username=r_strdup(l2ruser))) ABORT(R_NO_MEMORY); if(r=r_data_make(&pair->stun_client->params.ice_binding_request.password,(UCHAR *)lpwd,strlen(lpwd))) ABORT(r); pair->stun_client->params.ice_binding_request.priority=t_priority; pair->stun_client->params.ice_binding_request.control = pctx->controlling? NR_ICE_CONTROLLING:NR_ICE_CONTROLLED; pair->stun_client->params.ice_binding_request.tiebreaker=pctx->tiebreaker; /* Our receiving username/passwords. Stash these for later injection into the stun server ctx*/ if(r=nr_concat_strings(&pair->r2l_user,rufrag,":",lufrag,0)) ABORT(r); if(!(r2lpass=r_strdup(rpwd))) ABORT(R_NO_MEMORY); INIT_DATA(pair->r2l_pwd,(UCHAR *)r2lpass,strlen(r2lpass)); *pairp=pair; _status=0; abort: RFREE(l2ruser); if(_status){ RFREE(r2lpass); } return(_status); }