mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 13:21:05 +00:00
Bug 1006809 - update triggered check behavior to RFC 5245. r+bwc r=mjf
--HG-- extra : transplant_source : q%BDT%0A%29%7B%7C%A0%92%B1%AE%81%AA%EE%94%9B%A0b3%A7
This commit is contained in:
parent
d7a175fd88
commit
b912f1ee3a
@ -314,15 +314,44 @@ nsresult NrIceMediaStream::GetCandidatePairs(std::vector<NrIceCandidatePair>*
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nr_ice_cand_pair *p1;
|
||||
nr_ice_cand_pair *p1, *p2;
|
||||
out_pairs->clear();
|
||||
|
||||
TAILQ_FOREACH(p1, &peer_stream->check_list, entry) {
|
||||
TAILQ_FOREACH(p1, &peer_stream->check_list, check_queue_entry) {
|
||||
MOZ_ASSERT(p1);
|
||||
MOZ_ASSERT(p1->local);
|
||||
MOZ_ASSERT(p1->remote);
|
||||
NrIceCandidatePair pair;
|
||||
|
||||
p2 = TAILQ_FIRST(&peer_stream->check_list);
|
||||
while (p2) {
|
||||
if (p1 == p2) {
|
||||
/* Don't compare with our self. */
|
||||
p2=TAILQ_NEXT(p2, check_queue_entry);
|
||||
continue;
|
||||
}
|
||||
if (strncmp(p1->codeword,p2->codeword,sizeof(p1->codeword))==0) {
|
||||
/* In case of duplicate pairs we only report the one winning pair */
|
||||
if (
|
||||
((p2->remote->component && (p2->remote->component->active == p2)) &&
|
||||
!(p1->remote->component && (p1->remote->component->active == p1))) ||
|
||||
((p2->peer_nominated || p2->nominated) &&
|
||||
!(p1->peer_nominated || p1->nominated)) ||
|
||||
(p2->priority > p1->priority) ||
|
||||
((p2->state == NR_ICE_PAIR_STATE_SUCCEEDED) &&
|
||||
(p1->state != NR_ICE_PAIR_STATE_SUCCEEDED))
|
||||
) {
|
||||
/* p2 is a better pair. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
p2=TAILQ_NEXT(p2, check_queue_entry);
|
||||
}
|
||||
if (p2) {
|
||||
/* p2 points to a duplicate but better pair so skip this one */
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (p1->state) {
|
||||
case NR_ICE_PAIR_STATE_FROZEN:
|
||||
pair.state = NrIceCandidatePair::State::STATE_FROZEN;
|
||||
|
@ -909,10 +909,15 @@ class IceTestPeer : public sigslot::has_slots<> {
|
||||
DumpCandidatePair(pairs[p]);
|
||||
return false;
|
||||
} else if (priority == pairs[p].priority) {
|
||||
std::cerr << "Duplicate priority in subseqent pairs:" << std::endl;
|
||||
DumpCandidatePair(pairs[p-1]);
|
||||
DumpCandidatePair(pairs[p]);
|
||||
return false;
|
||||
if (!IceCandidatePairCompare()(pairs[p], pairs[p-1]) &&
|
||||
!IceCandidatePairCompare()(pairs[p-1], pairs[p])) {
|
||||
std::cerr << "Ignoring identical pair from trigger check" << std::endl;
|
||||
} else {
|
||||
std::cerr << "Duplicate priority in subseqent pairs:" << std::endl;
|
||||
DumpCandidatePair(pairs[p-1]);
|
||||
DumpCandidatePair(pairs[p]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
priority = pairs[p].priority;
|
||||
}
|
||||
@ -2120,7 +2125,7 @@ TEST_F(IceConnectTest, TestLoopbackOnlySortOf) {
|
||||
Init(true, false);
|
||||
AddStream("first", 1);
|
||||
SetCandidateFilter(IsLoopbackCandidate);
|
||||
ASSERT_TRUE(Gather());
|
||||
ASSERT_TRUE(Gather(kDefaultTimeout, false));
|
||||
SetExpectedRemoteCandidateAddr("127.0.0.1");
|
||||
Connect();
|
||||
}
|
||||
|
@ -247,7 +247,7 @@ static void nr_ice_candidate_pair_stun_cb(NR_SOCKET s, int how, void *cb_arg)
|
||||
else if(!nr_transport_addr_cmp(&pair->local->addr,&pair->stun_client->results.ice_binding_response.mapped_addr,NR_TRANSPORT_ADDR_CMP_MODE_ALL)){
|
||||
nr_ice_candidate_pair_set_state(pair->pctx,pair,NR_ICE_PAIR_STATE_SUCCEEDED);
|
||||
}
|
||||
else{
|
||||
else if(pair->stun_client->state == NR_STUN_CLIENT_STATE_DONE) {
|
||||
/* OK, this didn't correspond to a pair on the check list, but
|
||||
it probably matches one of our candidates */
|
||||
|
||||
@ -394,32 +394,82 @@ int nr_ice_candidate_pair_start(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair)
|
||||
return(_status);
|
||||
}
|
||||
|
||||
static int nr_ice_candidate_copy_for_triggered_check(nr_ice_cand_pair *pair)
|
||||
{
|
||||
int r,_status;
|
||||
nr_ice_cand_pair *copy;
|
||||
|
||||
if(r=nr_ice_candidate_pair_create(pair->pctx, pair->local, pair->remote, ©))
|
||||
ABORT(r);
|
||||
|
||||
/* Preserve nomination status */
|
||||
copy->peer_nominated= pair->peer_nominated;
|
||||
copy->nominated = pair->nominated;
|
||||
|
||||
r_log(LOG_ICE,LOG_INFO,"CAND-PAIR(%s): Adding pair to check list and trigger check queue: %s",pair->codeword,pair->as_string);
|
||||
if(r=nr_ice_candidate_pair_insert(&pair->remote->stream->check_list,copy))
|
||||
ABORT(r);
|
||||
nr_ice_candidate_pair_trigger_check_append(&pair->remote->stream->trigger_check_queue,copy);
|
||||
|
||||
copy->triggered = 1;
|
||||
nr_ice_candidate_pair_set_state(copy->pctx,copy,NR_ICE_PAIR_STATE_WAITING);
|
||||
|
||||
_status=0;
|
||||
abort:
|
||||
return(_status);
|
||||
}
|
||||
|
||||
int nr_ice_candidate_pair_do_triggered_check(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair)
|
||||
{
|
||||
int r,_status;
|
||||
|
||||
r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s)/CAND-PAIR(%s): triggered check on %s",pctx->label,pair->codeword,pair->as_string);
|
||||
|
||||
switch(pair->state){
|
||||
case NR_ICE_PAIR_STATE_FROZEN:
|
||||
nr_ice_candidate_pair_set_state(pctx,pair,NR_ICE_PAIR_STATE_WAITING);
|
||||
/* Fall through */
|
||||
case NR_ICE_PAIR_STATE_WAITING:
|
||||
/* Start the checks */
|
||||
if(r=nr_ice_candidate_pair_start(pctx,pair))
|
||||
ABORT(r);
|
||||
break;
|
||||
case NR_ICE_PAIR_STATE_IN_PROGRESS:
|
||||
if(r=nr_stun_client_force_retransmit(pair->stun_client))
|
||||
ABORT(r);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
if(pair->state==NR_ICE_PAIR_STATE_CANCELLED) {
|
||||
r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/CAND_PAIR(%s): Ignoring matching but canceled pair",pctx->label,pair->codeword);
|
||||
return(0);
|
||||
} else if(pair->state==NR_ICE_PAIR_STATE_SUCCEEDED) {
|
||||
r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/CAND_PAIR(%s): No new trigger check for succeeded pair",pctx->label,pair->codeword);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Activate the media stream if required */
|
||||
if(pair->remote->stream->ice_state==NR_ICE_MEDIA_STREAM_CHECKS_FROZEN){
|
||||
/* Do not run this logic more than once on a given pair */
|
||||
if(!pair->triggered){
|
||||
r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s)/CAND-PAIR(%s): triggered check on %s",pctx->label,pair->codeword,pair->as_string);
|
||||
|
||||
pair->triggered=1;
|
||||
|
||||
switch(pair->state){
|
||||
case NR_ICE_PAIR_STATE_FAILED:
|
||||
/* OK, there was a pair, it's just invalid: According to Section
|
||||
* 7.2.1.4, we need to resurrect it */
|
||||
r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s)/CAND-PAIR(%s): received STUN check on failed pair, resurrecting: %s",pctx->label,pair->codeword,pair->as_string);
|
||||
/* fall through */
|
||||
case NR_ICE_PAIR_STATE_FROZEN:
|
||||
nr_ice_candidate_pair_set_state(pctx,pair,NR_ICE_PAIR_STATE_WAITING);
|
||||
/* fall through even further */
|
||||
case NR_ICE_PAIR_STATE_WAITING:
|
||||
/* Append it additionally to the trigger check queue */
|
||||
r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s)/CAND-PAIR(%s): Inserting pair to trigger check queue: %s",pctx->label,pair->codeword,pair->as_string);
|
||||
nr_ice_candidate_pair_trigger_check_append(&pair->remote->stream->trigger_check_queue,pair);
|
||||
break;
|
||||
case NR_ICE_PAIR_STATE_IN_PROGRESS:
|
||||
/* Instead of trying to maintain two stun contexts on the same pair,
|
||||
* and handling heterogenous responses and error conditions, we instead
|
||||
* create a second pair that is identical except that it has the
|
||||
* |triggered| bit set. We also cancel the original pair, but it can
|
||||
* still succeed on its own in the special waiting state. */
|
||||
if(r=nr_ice_candidate_copy_for_triggered_check(pair))
|
||||
ABORT(r);
|
||||
nr_ice_candidate_pair_cancel(pair->pctx,pair,1);
|
||||
break;
|
||||
default:
|
||||
/* all states are handled - a new/unknown state should not
|
||||
* automatically enter the start_checks() below */
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Ensure that the timers are running to start checks on the topmost entry
|
||||
* of the triggered check queue. */
|
||||
if(r=nr_ice_media_stream_start_checks(pair->pctx,pair->remote->stream))
|
||||
ABORT(r);
|
||||
}
|
||||
@ -429,12 +479,16 @@ int nr_ice_candidate_pair_do_triggered_check(nr_ice_peer_ctx *pctx, nr_ice_cand_
|
||||
return(_status);
|
||||
}
|
||||
|
||||
int nr_ice_candidate_pair_cancel(nr_ice_peer_ctx *pctx,nr_ice_cand_pair *pair)
|
||||
int nr_ice_candidate_pair_cancel(nr_ice_peer_ctx *pctx,nr_ice_cand_pair *pair, int move_to_wait_state)
|
||||
{
|
||||
if(pair->state != NR_ICE_PAIR_STATE_FAILED){
|
||||
/* If it's already running we need to terminate the stun */
|
||||
if(pair->state==NR_ICE_PAIR_STATE_IN_PROGRESS){
|
||||
nr_stun_client_cancel(pair->stun_client);
|
||||
if(move_to_wait_state) {
|
||||
nr_stun_client_wait(pair->stun_client);
|
||||
} else {
|
||||
nr_stun_client_cancel(pair->stun_client);
|
||||
}
|
||||
}
|
||||
nr_ice_candidate_pair_set_state(pctx,pair,NR_ICE_PAIR_STATE_CANCELLED);
|
||||
}
|
||||
@ -506,7 +560,8 @@ int nr_ice_candidate_pair_set_state(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pai
|
||||
pair->state=state;
|
||||
|
||||
|
||||
if(pair->state==NR_ICE_PAIR_STATE_FAILED){
|
||||
if(pair->state==NR_ICE_PAIR_STATE_FAILED ||
|
||||
pair->state==NR_ICE_PAIR_STATE_CANCELLED){
|
||||
if(r=nr_ice_component_failed_pair(pair->remote->component, pair))
|
||||
ABORT(r);
|
||||
}
|
||||
@ -524,6 +579,17 @@ int nr_ice_candidate_pair_dump_state(nr_ice_cand_pair *pair, FILE *out)
|
||||
}
|
||||
|
||||
|
||||
int nr_ice_candidate_pair_trigger_check_append(nr_ice_cand_pair_head *head,nr_ice_cand_pair *pair)
|
||||
{
|
||||
if(pair->triggered_check_queue_entry.tqe_next ||
|
||||
pair->triggered_check_queue_entry.tqe_prev)
|
||||
return(0);
|
||||
|
||||
TAILQ_INSERT_TAIL(head,pair,triggered_check_queue_entry);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int nr_ice_candidate_pair_insert(nr_ice_cand_pair_head *head,nr_ice_cand_pair *pair)
|
||||
{
|
||||
nr_ice_cand_pair *c1;
|
||||
@ -531,13 +597,13 @@ int nr_ice_candidate_pair_insert(nr_ice_cand_pair_head *head,nr_ice_cand_pair *p
|
||||
c1=TAILQ_FIRST(head);
|
||||
while(c1){
|
||||
if(c1->priority < pair->priority){
|
||||
TAILQ_INSERT_BEFORE(c1,pair,entry);
|
||||
TAILQ_INSERT_BEFORE(c1,pair,check_queue_entry);
|
||||
break;
|
||||
}
|
||||
|
||||
c1=TAILQ_NEXT(c1,entry);
|
||||
c1=TAILQ_NEXT(c1,check_queue_entry);
|
||||
}
|
||||
if(!c1) TAILQ_INSERT_TAIL(head,pair,entry);
|
||||
if(!c1) TAILQ_INSERT_TAIL(head,pair,check_queue_entry);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
@ -56,6 +56,8 @@ struct nr_ice_cand_pair_ {
|
||||
on this check */
|
||||
UCHAR nominated; /* Is this nominated or not */
|
||||
|
||||
UCHAR triggered; /* Ignore further trigger check requests */
|
||||
|
||||
UINT8 priority; /* The priority for this pair */
|
||||
nr_ice_candidate *local; /* The local candidate */
|
||||
nr_ice_candidate *remote; /* The remote candidate */
|
||||
@ -68,7 +70,8 @@ struct nr_ice_cand_pair_ {
|
||||
void *restart_role_change_cb_timer;
|
||||
void *restart_nominated_cb_timer;
|
||||
|
||||
TAILQ_ENTRY(nr_ice_cand_pair_) entry;
|
||||
TAILQ_ENTRY(nr_ice_cand_pair_) check_queue_entry; /* the check list */
|
||||
TAILQ_ENTRY(nr_ice_cand_pair_) triggered_check_queue_entry; /* the trigger check queue */
|
||||
};
|
||||
|
||||
int nr_ice_candidate_pair_create(nr_ice_peer_ctx *pctx, nr_ice_candidate *lcand,nr_ice_candidate *rcand,nr_ice_cand_pair **pairp);
|
||||
@ -76,10 +79,11 @@ int nr_ice_candidate_pair_unfreeze(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair
|
||||
int nr_ice_candidate_pair_start(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair);
|
||||
int nr_ice_candidate_pair_set_state(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair, int state);
|
||||
int nr_ice_candidate_pair_dump_state(nr_ice_cand_pair *pair, FILE *out);
|
||||
int nr_ice_candidate_pair_cancel(nr_ice_peer_ctx *pctx,nr_ice_cand_pair *pair);
|
||||
int nr_ice_candidate_pair_cancel(nr_ice_peer_ctx *pctx,nr_ice_cand_pair *pair, int move_to_wait_state);
|
||||
int nr_ice_candidate_pair_select(nr_ice_cand_pair *pair);
|
||||
int nr_ice_candidate_pair_do_triggered_check(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair);
|
||||
int nr_ice_candidate_pair_insert(nr_ice_cand_pair_head *head,nr_ice_cand_pair *pair);
|
||||
int nr_ice_candidate_pair_trigger_check_append(nr_ice_cand_pair_head *head,nr_ice_cand_pair *pair);
|
||||
void nr_ice_candidate_pair_restart_stun_nominated_cb(NR_SOCKET s, int how, void *cb_arg);
|
||||
int nr_ice_candidate_pair_destroy(nr_ice_cand_pair **pairp);
|
||||
void nr_ice_candidate_pair_role_change(nr_ice_cand_pair *pair);
|
||||
|
@ -704,6 +704,57 @@ int nr_ice_component_maybe_prune_candidate(nr_ice_ctx *ctx, nr_ice_component *co
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nr_ice_component_pair_matches_check(nr_ice_component *comp, nr_ice_cand_pair *pair, nr_transport_addr *local_addr, nr_stun_server_request *req)
|
||||
{
|
||||
if(pair->remote->component->component_id!=comp->component_id)
|
||||
return(0);
|
||||
|
||||
if(nr_transport_addr_cmp(&pair->local->base,local_addr,NR_TRANSPORT_ADDR_CMP_MODE_ALL))
|
||||
return(0);
|
||||
|
||||
if(nr_transport_addr_cmp(&pair->remote->addr,&req->src_addr,NR_TRANSPORT_ADDR_CMP_MODE_ALL))
|
||||
return(0);
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
static int nr_ice_component_handle_triggered_check(nr_ice_component *comp, nr_ice_cand_pair *pair, nr_stun_server_request *req, int *error)
|
||||
{
|
||||
nr_stun_message *sreq=req->request;
|
||||
int r=0,_status;
|
||||
|
||||
if(nr_stun_message_has_attribute(sreq,NR_STUN_ATTR_USE_CANDIDATE,0)){
|
||||
if(comp->stream->pctx->controlling){
|
||||
r_log(LOG_ICE,LOG_WARNING,"ICE-PEER(%s)/CAND_PAIR(%s): Peer sent USE-CANDIDATE but is controlled",comp->stream->pctx->label, pair->codeword);
|
||||
}
|
||||
else{
|
||||
/* If this is the first time we've noticed this is nominated...*/
|
||||
pair->peer_nominated=1;
|
||||
|
||||
if(pair->state==NR_ICE_PAIR_STATE_SUCCEEDED && !pair->nominated){
|
||||
pair->nominated=1;
|
||||
|
||||
if(r=nr_ice_component_nominated_pair(pair->remote->component, pair)) {
|
||||
*error=(r==R_NO_MEMORY)?500:400;
|
||||
ABORT(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Note: the RFC says to trigger first and then nominate. But in that case
|
||||
* the canceled trigger pair would get nominated and the cloned trigger pair
|
||||
* would not get the nomination status cloned with it.*/
|
||||
if(r=nr_ice_candidate_pair_do_triggered_check(comp->stream->pctx,pair)) {
|
||||
*error=(r==R_NO_MEMORY)?500:400;
|
||||
ABORT(r);
|
||||
}
|
||||
|
||||
_status=0;
|
||||
abort:
|
||||
return(r);
|
||||
}
|
||||
|
||||
/* Section 7.2.1 */
|
||||
static int nr_ice_component_process_incoming_check(nr_ice_component *comp, nr_transport_addr *local_addr, nr_stun_server_request *req, int *error)
|
||||
{
|
||||
@ -711,12 +762,8 @@ static int nr_ice_component_process_incoming_check(nr_ice_component *comp, nr_tr
|
||||
nr_ice_candidate *pcand=0;
|
||||
nr_stun_message *sreq=req->request;
|
||||
nr_stun_message_attribute *attr;
|
||||
int component_id_matched;
|
||||
int local_addr_matched;
|
||||
int remote_addr_matched;
|
||||
nr_ice_cand_pair *found_invalid=0;
|
||||
int r=0,_status;
|
||||
int new_pcand_created=0;
|
||||
int found_valid=0;
|
||||
|
||||
r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/STREAM(%s)/COMP(%d): received request from %s",comp->stream->pctx->label,comp->stream->label,comp->component_id,req->src_addr.as_string);
|
||||
|
||||
@ -767,157 +814,84 @@ static int nr_ice_component_process_incoming_check(nr_ice_component *comp, nr_tr
|
||||
|
||||
pair=TAILQ_FIRST(&comp->stream->check_list);
|
||||
while(pair){
|
||||
component_id_matched = 0;
|
||||
local_addr_matched = 0;
|
||||
remote_addr_matched = 0;
|
||||
|
||||
if(pair->remote->component->component_id!=comp->component_id)
|
||||
goto next_pair;
|
||||
component_id_matched = 1;
|
||||
|
||||
if(nr_transport_addr_cmp(&pair->local->base,local_addr,NR_TRANSPORT_ADDR_CMP_MODE_ALL))
|
||||
goto next_pair;
|
||||
local_addr_matched=1;
|
||||
|
||||
|
||||
if(nr_transport_addr_cmp(&pair->remote->addr,&req->src_addr,NR_TRANSPORT_ADDR_CMP_MODE_ALL))
|
||||
goto next_pair;
|
||||
remote_addr_matched = 1;
|
||||
|
||||
if(pair->state==NR_ICE_PAIR_STATE_FAILED){
|
||||
found_invalid=pair;
|
||||
goto next_pair;
|
||||
}
|
||||
|
||||
if (local_addr_matched && remote_addr_matched){
|
||||
/* Since triggered checks create duplicate pairs (in this implementation)
|
||||
* we are willing to handle multiple matches here. */
|
||||
if(nr_ice_component_pair_matches_check(comp, pair, local_addr, req)){
|
||||
r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/CAND_PAIR(%s): Found a matching pair for received check: %s",comp->stream->pctx->label,pair->codeword,pair->as_string);
|
||||
break; /* OK, this is a known pair */
|
||||
}
|
||||
|
||||
next_pair:
|
||||
pair=TAILQ_NEXT(pair,entry);
|
||||
}
|
||||
|
||||
if(!pair){
|
||||
if(!found_invalid){
|
||||
/* First find our local component candidate */
|
||||
nr_ice_candidate *cand;
|
||||
|
||||
r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): no matching pair",comp->stream->pctx->label);
|
||||
cand=TAILQ_FIRST(&comp->local_component->candidates);
|
||||
while(cand){
|
||||
if(!nr_transport_addr_cmp(&cand->addr,local_addr,NR_TRANSPORT_ADDR_CMP_MODE_ALL))
|
||||
break;
|
||||
|
||||
cand=TAILQ_NEXT(cand,entry_comp);
|
||||
}
|
||||
|
||||
/* Well, this really shouldn't happen, but it's an error from the
|
||||
other side, so we just throw an error and keep going */
|
||||
if(!cand){
|
||||
r_log(LOG_ICE,LOG_WARNING,"ICE-PEER(%s): stun request to unknown local address %s, discarding",comp->stream->pctx->label,local_addr->as_string);
|
||||
|
||||
*error=400;
|
||||
ABORT(R_NOT_FOUND);
|
||||
}
|
||||
|
||||
/* Try to find matching peer active tcp candidate */
|
||||
pcand=TAILQ_FIRST(&comp->candidates);
|
||||
while(pcand){
|
||||
if(pcand->tcp_type == TCP_TYPE_ACTIVE) {
|
||||
if(!nr_transport_addr_cmp(&pcand->addr,&req->src_addr,NR_TRANSPORT_ADDR_CMP_MODE_ALL))
|
||||
break;
|
||||
}
|
||||
|
||||
pcand=TAILQ_NEXT(pcand,entry_comp);
|
||||
}
|
||||
|
||||
if (!pcand){
|
||||
/* We now need to make a peer reflexive */
|
||||
if(r=nr_ice_peer_peer_rflx_candidate_create(comp->stream->pctx->ctx,"prflx",comp,&req->src_addr,&pcand)) {
|
||||
*error=(r==R_NO_MEMORY)?500:400;
|
||||
ABORT(r);
|
||||
}
|
||||
new_pcand_created=1;
|
||||
if(!nr_stun_message_has_attribute(sreq,NR_STUN_ATTR_PRIORITY,&attr)){
|
||||
r_log(LOG_ICE,LOG_WARNING,"ICE-PEER(%s): Rejecting stun request without priority",comp->stream->pctx->label);
|
||||
*error=487;
|
||||
ABORT(R_BAD_DATA);
|
||||
}
|
||||
pcand->priority=attr->u.priority;
|
||||
}
|
||||
|
||||
pcand->state=NR_ICE_CAND_PEER_CANDIDATE_PAIRED;
|
||||
|
||||
if(r=nr_ice_candidate_pair_create(comp->stream->pctx,cand,pcand,
|
||||
&pair)) {
|
||||
*error=(r==R_NO_MEMORY)?500:400;
|
||||
if(r=nr_ice_component_handle_triggered_check(comp, pair, req, error))
|
||||
ABORT(r);
|
||||
}
|
||||
nr_ice_candidate_pair_set_state(pair->pctx,pair,NR_ICE_PAIR_STATE_FROZEN);
|
||||
|
||||
if(r=nr_ice_component_insert_pair(comp,pair)) {
|
||||
*error=(r==R_NO_MEMORY)?500:400;
|
||||
nr_ice_candidate_pair_destroy(&pair);
|
||||
ABORT(r);
|
||||
}
|
||||
|
||||
/* Do this last, since any call to ABORT will destroy pcand */
|
||||
if (new_pcand_created){
|
||||
TAILQ_INSERT_TAIL(&comp->candidates,pcand,entry_comp);
|
||||
pcand=0;
|
||||
}
|
||||
}
|
||||
else{
|
||||
/* OK, there was a pair, it's just invalid: According to Section
|
||||
7.2.1.4, we need to resurrect it
|
||||
*/
|
||||
if(found_invalid->state == NR_ICE_PAIR_STATE_FAILED){
|
||||
pair=found_invalid;
|
||||
|
||||
r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s)/CAND-PAIR(%s): received STUN check on invalid pair, resurrecting: %s",comp->stream->pctx->label,pair->codeword,pair->as_string);
|
||||
nr_ice_candidate_pair_set_state(pair->pctx,pair,NR_ICE_PAIR_STATE_WAITING);
|
||||
}
|
||||
else{
|
||||
/* This shouldn't happen */
|
||||
r_log(LOG_ICE,LOG_ERR,"ICE-PEER(%s)/CAND-PAIR(%s): received STUN check on invalid pair that was not in state FAILED; this should not happen: %s",comp->stream->pctx->label,pair->codeword,pair->as_string);
|
||||
*error=500;
|
||||
ABORT(R_BAD_DATA);
|
||||
}
|
||||
++found_valid;
|
||||
}
|
||||
pair=TAILQ_NEXT(pair,check_queue_entry);
|
||||
}
|
||||
|
||||
/* OK, we've got a pair to work with. Turn it on */
|
||||
assert(pair);
|
||||
if(nr_stun_message_has_attribute(sreq,NR_STUN_ATTR_USE_CANDIDATE,0)){
|
||||
if(comp->stream->pctx->controlling){
|
||||
r_log(LOG_ICE,LOG_WARNING,"ICE-PEER(%s)/CAND_PAIR(%s): Peer sent USE-CANDIDATE but is controlled",comp->stream->pctx->label, pair->codeword);
|
||||
if(!found_valid){
|
||||
/* There were no matching pairs, so we need to create a new peer
|
||||
* reflexive candidate pair. */
|
||||
|
||||
if(!nr_stun_message_has_attribute(sreq,NR_STUN_ATTR_PRIORITY,&attr)){
|
||||
r_log(LOG_ICE,LOG_WARNING,"ICE-PEER(%s): Rejecting stun request without priority",comp->stream->pctx->label);
|
||||
*error=400;
|
||||
ABORT(R_BAD_DATA);
|
||||
}
|
||||
else{
|
||||
/* If this is the first time we've noticed this is nominated...*/
|
||||
pair->peer_nominated=1;
|
||||
|
||||
if(pair->state==NR_ICE_PAIR_STATE_SUCCEEDED && !pair->nominated){
|
||||
pair->nominated=1;
|
||||
/* Find our local component candidate */
|
||||
nr_ice_candidate *cand;
|
||||
|
||||
if(r=nr_ice_component_nominated_pair(pair->remote->component, pair)) {
|
||||
*error=(r==R_NO_MEMORY)?500:400;
|
||||
ABORT(r);
|
||||
}
|
||||
}
|
||||
r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): no matching pair",comp->stream->pctx->label);
|
||||
cand=TAILQ_FIRST(&comp->local_component->candidates);
|
||||
while(cand){
|
||||
if(!nr_transport_addr_cmp(&cand->addr,local_addr,NR_TRANSPORT_ADDR_CMP_MODE_ALL))
|
||||
break;
|
||||
|
||||
cand=TAILQ_NEXT(cand,entry_comp);
|
||||
}
|
||||
}
|
||||
|
||||
if(r=nr_ice_candidate_pair_do_triggered_check(comp->stream->pctx,pair)) {
|
||||
*error=(r==R_NO_MEMORY)?500:400;
|
||||
ABORT(r);
|
||||
/* Well, this really shouldn't happen, but it's an error from the
|
||||
other side, so we just throw an error and keep going */
|
||||
if(!cand){
|
||||
r_log(LOG_ICE,LOG_WARNING,"ICE-PEER(%s): stun request to unknown local address %s, discarding",comp->stream->pctx->label,local_addr->as_string);
|
||||
|
||||
*error=400;
|
||||
ABORT(R_NOT_FOUND);
|
||||
}
|
||||
|
||||
/* Now make a peer reflexive (remote) candidate */
|
||||
if(r=nr_ice_peer_peer_rflx_candidate_create(comp->stream->pctx->ctx,"prflx",comp,&req->src_addr,&pcand)) {
|
||||
*error=(r==R_NO_MEMORY)?500:400;
|
||||
ABORT(r);
|
||||
}
|
||||
pcand->priority=attr->u.priority;
|
||||
pcand->state=NR_ICE_CAND_PEER_CANDIDATE_PAIRED;
|
||||
|
||||
/* Finally, create the candidate pair, insert into the check list, and
|
||||
* apply the incoming check to it. */
|
||||
if(r=nr_ice_candidate_pair_create(comp->stream->pctx,cand,pcand,
|
||||
&pair)) {
|
||||
*error=(r==R_NO_MEMORY)?500:400;
|
||||
ABORT(r);
|
||||
}
|
||||
|
||||
nr_ice_candidate_pair_set_state(pair->pctx,pair,NR_ICE_PAIR_STATE_FROZEN);
|
||||
if(r=nr_ice_component_insert_pair(comp,pair)) {
|
||||
*error=(r==R_NO_MEMORY)?500:400;
|
||||
nr_ice_candidate_pair_destroy(&pair);
|
||||
ABORT(r);
|
||||
}
|
||||
|
||||
/* Do this last, since any call to ABORT will destroy pcand */
|
||||
TAILQ_INSERT_TAIL(&comp->candidates,pcand,entry_comp);
|
||||
pcand=0;
|
||||
|
||||
/* Finally start the trigger check if needed */
|
||||
if(r=nr_ice_component_handle_triggered_check(comp, pair, req, error))
|
||||
ABORT(r);
|
||||
}
|
||||
|
||||
_status=0;
|
||||
abort:
|
||||
if(_status){
|
||||
if (new_pcand_created)
|
||||
nr_ice_candidate_destroy(&pcand);
|
||||
nr_ice_candidate_destroy(&pcand);
|
||||
assert(*error != 0);
|
||||
if(r!=R_NO_MEMORY) assert(*error != 500);
|
||||
}
|
||||
@ -1013,6 +987,14 @@ int nr_ice_component_pair_candidate(nr_ice_peer_ctx *pctx, nr_ice_component *pco
|
||||
continue;
|
||||
if(pcand->addr.ip_version != lcand->addr.ip_version)
|
||||
continue;
|
||||
/* This prevents our ice_unittest from pairing a loopback with a host
|
||||
* candidate. */
|
||||
if(nr_transport_addr_is_loopback(&lcand->addr) &&
|
||||
!nr_transport_addr_is_loopback(&pcand->addr))
|
||||
continue;
|
||||
if(!nr_transport_addr_is_loopback(&lcand->addr) &&
|
||||
nr_transport_addr_is_loopback(&pcand->addr))
|
||||
continue;
|
||||
|
||||
/*
|
||||
Two modes, depending on |pair_all_remote|
|
||||
@ -1124,15 +1106,11 @@ static int nr_ice_component_stun_server_default_cb(void *cb_arg,nr_stun_server_c
|
||||
int nr_ice_component_nominated_pair(nr_ice_component *comp, nr_ice_cand_pair *pair)
|
||||
{
|
||||
int r,_status;
|
||||
int fire_cb=0;
|
||||
nr_ice_cand_pair *p2;
|
||||
|
||||
if(!comp->nominated)
|
||||
fire_cb=1;
|
||||
|
||||
/* Are we changing what the nominated pair is? */
|
||||
if(comp->nominated){
|
||||
if(comp->nominated->priority > pair->priority)
|
||||
if(comp->nominated->priority >= pair->priority)
|
||||
return(0);
|
||||
r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s)/STREAM(%s)/COMP(%d)/CAND-PAIR(%s): replacing pair %s with CAND-PAIR(%s)",comp->stream->pctx->label,comp->stream->label,comp->component_id,comp->nominated->codeword,comp->nominated->as_string,pair->codeword);
|
||||
}
|
||||
@ -1146,19 +1124,33 @@ int nr_ice_component_nominated_pair(nr_ice_component *comp, nr_ice_cand_pair *pa
|
||||
r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s)/STREAM(%s)/COMP(%d)/CAND-PAIR(%s): cancelling all pairs but %s",comp->stream->pctx->label,comp->stream->label,comp->component_id,pair->codeword,pair->as_string);
|
||||
|
||||
/* Cancel checks in WAITING and FROZEN per ICE S 8.1.2 */
|
||||
p2=TAILQ_FIRST(&comp->stream->trigger_check_queue);
|
||||
while(p2){
|
||||
if((p2 != pair) &&
|
||||
(p2->remote->component->component_id == comp->component_id)) {
|
||||
assert(p2->state == NR_ICE_PAIR_STATE_WAITING ||
|
||||
p2->state == NR_ICE_PAIR_STATE_CANCELLED);
|
||||
r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s)/STREAM(%s)/COMP(%d)/CAND-PAIR(%s): cancelling FROZEN/WAITING pair %s in trigger check queue because CAND-PAIR(%s) was nominated.",comp->stream->pctx->label,comp->stream->label,comp->component_id,p2->codeword,p2->as_string,pair->codeword);
|
||||
|
||||
if(r=nr_ice_candidate_pair_cancel(pair->pctx,p2,0))
|
||||
ABORT(r);
|
||||
}
|
||||
|
||||
p2=TAILQ_NEXT(p2,triggered_check_queue_entry);
|
||||
}
|
||||
p2=TAILQ_FIRST(&comp->stream->check_list);
|
||||
while(p2){
|
||||
if((p2 != pair) &&
|
||||
(p2->remote->component->component_id == comp->component_id) &&
|
||||
((p2->state == NR_ICE_PAIR_STATE_FROZEN) ||
|
||||
(p2->state == NR_ICE_PAIR_STATE_WAITING))) {
|
||||
(p2->state == NR_ICE_PAIR_STATE_WAITING))) {
|
||||
r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s)/STREAM(%s)/COMP(%d)/CAND-PAIR(%s): cancelling FROZEN/WAITING pair %s because CAND-PAIR(%s) was nominated.",comp->stream->pctx->label,comp->stream->label,comp->component_id,p2->codeword,p2->as_string,pair->codeword);
|
||||
|
||||
if(r=nr_ice_candidate_pair_cancel(pair->pctx,p2))
|
||||
if(r=nr_ice_candidate_pair_cancel(pair->pctx,p2,0))
|
||||
ABORT(r);
|
||||
}
|
||||
|
||||
p2=TAILQ_NEXT(p2,entry);
|
||||
p2=TAILQ_NEXT(p2,check_queue_entry);
|
||||
}
|
||||
r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/STREAM(%s)/COMP(%d): cancelling done",comp->stream->pctx->label,comp->stream->label,comp->component_id);
|
||||
|
||||
@ -1193,7 +1185,7 @@ static int nr_ice_component_have_all_pairs_failed(nr_ice_component *comp)
|
||||
}
|
||||
}
|
||||
|
||||
p2=TAILQ_NEXT(p2,entry);
|
||||
p2=TAILQ_NEXT(p2,check_queue_entry);
|
||||
}
|
||||
|
||||
return(1);
|
||||
@ -1233,7 +1225,7 @@ int nr_ice_component_select_pair(nr_ice_peer_ctx *pctx, nr_ice_component *comp)
|
||||
if (comp->component_id == pair->local->component_id)
|
||||
ct++;
|
||||
|
||||
pair=TAILQ_NEXT(pair,entry);
|
||||
pair=TAILQ_NEXT(pair,check_queue_entry);
|
||||
}
|
||||
|
||||
/* Make and fill the array */
|
||||
@ -1246,7 +1238,7 @@ int nr_ice_component_select_pair(nr_ice_peer_ctx *pctx, nr_ice_component *comp)
|
||||
if (comp->component_id == pair->local->component_id)
|
||||
pairs[ct++]=pair;
|
||||
|
||||
pair=TAILQ_NEXT(pair,entry);
|
||||
pair=TAILQ_NEXT(pair,check_queue_entry);
|
||||
}
|
||||
|
||||
if (pctx->handler) {
|
||||
|
@ -72,6 +72,7 @@ int nr_ice_media_stream_create(nr_ice_ctx *ctx,char *label,int components, nr_ic
|
||||
}
|
||||
|
||||
TAILQ_INIT(&stream->check_list);
|
||||
TAILQ_INIT(&stream->trigger_check_queue);
|
||||
|
||||
stream->component_ct=components;
|
||||
stream->ice_state = NR_ICE_MEDIA_STREAM_UNPAIRED;
|
||||
@ -101,8 +102,10 @@ int nr_ice_media_stream_destroy(nr_ice_media_stream **streamp)
|
||||
nr_ice_component_destroy(&c1);
|
||||
}
|
||||
|
||||
TAILQ_FOREACH_SAFE(p1, &stream->check_list, entry, p2){
|
||||
TAILQ_REMOVE(&stream->check_list,p1,entry);
|
||||
/* Note: all the entries from the trigger check queue are held in here as
|
||||
* well, so we only clean up the super set. */
|
||||
TAILQ_FOREACH_SAFE(p1, &stream->check_list, check_queue_entry, p2){
|
||||
TAILQ_REMOVE(&stream->check_list,p1,check_queue_entry);
|
||||
nr_ice_candidate_pair_destroy(&p1);
|
||||
}
|
||||
|
||||
@ -308,46 +311,66 @@ int nr_ice_media_stream_service_pre_answer_requests(nr_ice_peer_ctx *pctx, nr_ic
|
||||
return(_status);
|
||||
}
|
||||
|
||||
/* S 5.8 -- run the highest priority WAITING pair or if not available
|
||||
FROZEN pair */
|
||||
/* S 5.8 -- run the first pair from the triggered check queue (even after
|
||||
* checks have completed S 8.1.2) or run the highest priority WAITING pair or
|
||||
* if not available FROZEN pair from the check queue */
|
||||
static void nr_ice_media_stream_check_timer_cb(NR_SOCKET s, int h, void *cb_arg)
|
||||
{
|
||||
int r,_status;
|
||||
nr_ice_media_stream *stream=cb_arg;
|
||||
nr_ice_cand_pair *pair;
|
||||
nr_ice_cand_pair *pair = 0;
|
||||
int timer_val;
|
||||
int timer_multiplier;
|
||||
|
||||
assert(stream->pctx->active_streams!=0);
|
||||
|
||||
timer_val=stream->pctx->ctx->Ta*stream->pctx->active_streams;
|
||||
|
||||
timer_multiplier=stream->pctx->active_streams;
|
||||
/* Once the checks are completed we don't have an active streams any more,
|
||||
* but we still need to process triggered checks. */
|
||||
if (stream->ice_state == NR_ICE_MEDIA_STREAM_CHECKS_COMPLETED) {
|
||||
r_log(LOG_ICE,LOG_ERR,"ICE-PEER(%s): (bug) bogus state for stream %s",stream->pctx->label,stream->label);
|
||||
assert(timer_multiplier==0);
|
||||
timer_multiplier=1;
|
||||
}
|
||||
assert(stream->ice_state != NR_ICE_MEDIA_STREAM_CHECKS_COMPLETED);
|
||||
|
||||
assert(timer_multiplier!=0);
|
||||
timer_val=stream->pctx->ctx->Ta*timer_multiplier;
|
||||
|
||||
r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): check timer expired for media stream %s",stream->pctx->label,stream->label);
|
||||
stream->timer=0;
|
||||
|
||||
/* Find the highest priority WAITING check and move it to RUNNING */
|
||||
pair=TAILQ_FIRST(&stream->check_list);
|
||||
/* The trigger check queue has the highest priority */
|
||||
pair=TAILQ_FIRST(&stream->trigger_check_queue);
|
||||
while(pair){
|
||||
if(pair->state==NR_ICE_PAIR_STATE_WAITING)
|
||||
if(pair->state==NR_ICE_PAIR_STATE_WAITING){
|
||||
/* Remove the pair from he trigger check queue */
|
||||
r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): Removing pair from trigger check queue %s",stream->pctx->label,pair->as_string);
|
||||
TAILQ_REMOVE(&stream->trigger_check_queue,pair,triggered_check_queue_entry);
|
||||
break;
|
||||
pair=TAILQ_NEXT(pair,entry);
|
||||
}
|
||||
pair=TAILQ_NEXT(pair,triggered_check_queue_entry);
|
||||
}
|
||||
|
||||
/* Hmmm... No WAITING. Let's look for FROZEN */
|
||||
if(!pair){
|
||||
pair=TAILQ_FIRST(&stream->check_list);
|
||||
|
||||
while(pair){
|
||||
if(pair->state==NR_ICE_PAIR_STATE_FROZEN){
|
||||
if(r=nr_ice_candidate_pair_unfreeze(stream->pctx,pair))
|
||||
ABORT(r);
|
||||
break;
|
||||
if (stream->ice_state != NR_ICE_MEDIA_STREAM_CHECKS_COMPLETED) {
|
||||
if(!pair){
|
||||
/* Find the highest priority WAITING check and move it to RUNNING */
|
||||
pair=TAILQ_FIRST(&stream->check_list);
|
||||
while(pair){
|
||||
if(pair->state==NR_ICE_PAIR_STATE_WAITING)
|
||||
break;
|
||||
pair=TAILQ_NEXT(pair,check_queue_entry);
|
||||
}
|
||||
}
|
||||
|
||||
/* Hmmm... No WAITING. Let's look for FROZEN */
|
||||
if(!pair){
|
||||
pair=TAILQ_FIRST(&stream->check_list);
|
||||
|
||||
while(pair){
|
||||
if(pair->state==NR_ICE_PAIR_STATE_FROZEN){
|
||||
if(r=nr_ice_candidate_pair_unfreeze(stream->pctx,pair))
|
||||
ABORT(r);
|
||||
break;
|
||||
}
|
||||
pair=TAILQ_NEXT(pair,check_queue_entry);
|
||||
}
|
||||
pair=TAILQ_NEXT(pair,entry);
|
||||
}
|
||||
}
|
||||
|
||||
@ -364,20 +387,25 @@ static void nr_ice_media_stream_check_timer_cb(NR_SOCKET s, int h, void *cb_arg)
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Start checks for this media stream (aka check list) */
|
||||
int nr_ice_media_stream_start_checks(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream)
|
||||
{
|
||||
int r,_status;
|
||||
|
||||
/* Don't start the check timer if the stream is done (failed/completed) */
|
||||
if (stream->ice_state > NR_ICE_MEDIA_STREAM_CHECKS_ACTIVE) {
|
||||
/* Don't start the check timer if the stream is failed */
|
||||
if (stream->ice_state == NR_ICE_MEDIA_STREAM_CHECKS_FAILED) {
|
||||
assert(0);
|
||||
ABORT(R_INTERNAL);
|
||||
}
|
||||
|
||||
if(r=nr_ice_media_stream_set_state(stream,NR_ICE_MEDIA_STREAM_CHECKS_ACTIVE))
|
||||
ABORT(r);
|
||||
/* Even if the stream is completed already remote can still create a new
|
||||
* triggered check request which needs to fire, but not change our stream
|
||||
* state. */
|
||||
if (stream->ice_state != NR_ICE_MEDIA_STREAM_CHECKS_COMPLETED) {
|
||||
if(r=nr_ice_media_stream_set_state(stream,NR_ICE_MEDIA_STREAM_CHECKS_ACTIVE)) {
|
||||
ABORT(r);
|
||||
}
|
||||
}
|
||||
|
||||
if (!stream->timer) {
|
||||
r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s)/ICE-STREAM(%s): Starting check timer for stream.",pctx->label,stream->label);
|
||||
@ -419,7 +447,7 @@ int nr_ice_media_stream_unfreeze_pairs(nr_ice_peer_ctx *pctx, nr_ice_media_strea
|
||||
}
|
||||
|
||||
/* Already exists... fall through */
|
||||
pair=TAILQ_NEXT(pair,entry);
|
||||
pair=TAILQ_NEXT(pair,check_queue_entry);
|
||||
}
|
||||
|
||||
_status=0;
|
||||
@ -442,7 +470,7 @@ static int nr_ice_media_stream_unfreeze_pairs_match(nr_ice_media_stream *stream,
|
||||
ABORT(r);
|
||||
unfroze++;
|
||||
}
|
||||
pair=TAILQ_NEXT(pair,entry);
|
||||
pair=TAILQ_NEXT(pair,check_queue_entry);
|
||||
}
|
||||
|
||||
if(!unfroze)
|
||||
@ -532,7 +560,7 @@ int nr_ice_media_stream_dump_state(nr_ice_peer_ctx *pctx, nr_ice_media_stream *s
|
||||
while(pair){
|
||||
nr_ice_candidate_pair_dump_state(pair,out);
|
||||
|
||||
pair=TAILQ_NEXT(pair,entry);
|
||||
pair=TAILQ_NEXT(pair,check_queue_entry);
|
||||
}
|
||||
|
||||
return(0);
|
||||
@ -625,10 +653,10 @@ int nr_ice_media_stream_component_failed(nr_ice_media_stream *stream,nr_ice_comp
|
||||
/* OK, we need to cancel off everything on this component */
|
||||
p2=TAILQ_FIRST(&stream->check_list);
|
||||
while(p2){
|
||||
if(r=nr_ice_candidate_pair_cancel(p2->pctx,p2))
|
||||
if(r=nr_ice_candidate_pair_cancel(p2->pctx,p2,0))
|
||||
ABORT(r);
|
||||
|
||||
p2=TAILQ_NEXT(p2,entry);
|
||||
p2=TAILQ_NEXT(p2,check_queue_entry);
|
||||
}
|
||||
|
||||
/* Cancel our timer */
|
||||
@ -823,7 +851,7 @@ int nr_ice_media_stream_pair_new_trickle_candidate(nr_ice_peer_ctx *pctx, nr_ice
|
||||
ABORT(r);
|
||||
|
||||
_status=0;
|
||||
abort:
|
||||
abort:
|
||||
return(_status);
|
||||
}
|
||||
|
||||
@ -846,7 +874,7 @@ int nr_ice_media_stream_disable_component(nr_ice_media_stream *stream, int compo
|
||||
comp->state = NR_ICE_COMPONENT_DISABLED;
|
||||
|
||||
_status=0;
|
||||
abort:
|
||||
abort:
|
||||
return(_status);
|
||||
}
|
||||
|
||||
@ -858,7 +886,7 @@ void nr_ice_media_stream_role_change(nr_ice_media_stream *stream)
|
||||
pair=TAILQ_FIRST(&stream->check_list);
|
||||
while(pair){
|
||||
nr_ice_candidate_pair_role_change(pair);
|
||||
pair=TAILQ_NEXT(pair,entry);
|
||||
pair=TAILQ_NEXT(pair,check_queue_entry);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -63,6 +63,7 @@ struct nr_ice_media_stream_ {
|
||||
#define NR_ICE_MEDIA_STREAM_CHECKS_FAILED 5
|
||||
|
||||
nr_ice_cand_pair_head check_list;
|
||||
nr_ice_cand_pair_head trigger_check_queue;
|
||||
void *timer; /* Check list periodic timer */
|
||||
|
||||
/* nr_ice_cand_pair_head valid_list; */
|
||||
|
@ -501,13 +501,15 @@ static int nr_socket_buffered_stun_write(void *obj,const void *msg, size_t len,
|
||||
sock->pending += len;
|
||||
}
|
||||
|
||||
if (sock->pending && !already_armed) {
|
||||
if (sock->pending) {
|
||||
if (!already_armed) {
|
||||
if ((r=nr_socket_buffered_stun_arm_writable_cb(sock)))
|
||||
ABORT(r);
|
||||
}
|
||||
r_log(LOG_GENERIC, LOG_INFO, "Write buffer not empty for %s %u - %s armed (@%p)",
|
||||
sock->remote_addr.as_string, (uint32_t)sock->pending,
|
||||
already_armed ? "already" : "", &sock->pending);
|
||||
}
|
||||
r_log(LOG_GENERIC, LOG_INFO, "Write buffer not empty for %s %u - %s armed (@%p)",
|
||||
sock->remote_addr.as_string, (uint32_t)sock->pending,
|
||||
already_armed ? "already" : "", &sock->pending);
|
||||
|
||||
*written = original_len;
|
||||
|
||||
|
@ -460,9 +460,8 @@ int nr_stun_client_process_response(nr_stun_client_ctx *ctx, UCHAR *msg, int len
|
||||
|
||||
ATTACH_DATA(hmac_key, hmac_key_d);
|
||||
|
||||
if(ctx->state==NR_STUN_CLIENT_STATE_CANCELLED)
|
||||
ABORT(R_REJECTED);
|
||||
if (ctx->state != NR_STUN_CLIENT_STATE_RUNNING)
|
||||
if ((ctx->state != NR_STUN_CLIENT_STATE_RUNNING) &&
|
||||
(ctx->state != NR_STUN_CLIENT_STATE_WAITING))
|
||||
ABORT(R_REJECTED);
|
||||
|
||||
r_log(NR_LOG_STUN,LOG_DEBUG,"STUN-CLIENT(%s): Inspecting STUN response (my_addr=%s, peer_addr=%s)",ctx->label,ctx->my_addr.as_string,peer_addr->as_string);
|
||||
@ -750,7 +749,8 @@ int nr_stun_client_process_response(nr_stun_client_ctx *ctx, UCHAR *msg, int len
|
||||
r_log(NR_LOG_STUN,LOG_WARNING,"STUN-CLIENT(%s): Error processing response: %s, stun error code %d.", ctx->label, nr_strerror(_status), (int)ctx->error_code);
|
||||
}
|
||||
|
||||
if (ctx->state != NR_STUN_CLIENT_STATE_RUNNING) {
|
||||
if ((ctx->state != NR_STUN_CLIENT_STATE_RUNNING) &&
|
||||
(ctx->state != NR_STUN_CLIENT_STATE_WAITING)) {
|
||||
/* Cancel the timer firing */
|
||||
if (ctx->timer_handle) {
|
||||
NR_async_timer_cancel(ctx->timer_handle);
|
||||
@ -798,6 +798,17 @@ int nr_stun_client_cancel(nr_stun_client_ctx *ctx)
|
||||
return(0);
|
||||
}
|
||||
|
||||
int nr_stun_client_wait(nr_stun_client_ctx *ctx)
|
||||
{
|
||||
nr_stun_client_cancel(ctx);
|
||||
ctx->state=NR_STUN_CLIENT_STATE_WAITING;
|
||||
|
||||
ctx->request_ct = ctx->maximum_transmits;
|
||||
ctx->timeout_ms = ctx->maximum_transmits_timeout_ms;
|
||||
NR_ASYNC_TIMER_SET(ctx->timeout_ms, nr_stun_client_timer_expired_cb, ctx, &ctx->timer_handle);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int nr_stun_client_failed(nr_stun_client_ctx *ctx)
|
||||
{
|
||||
|
@ -137,6 +137,7 @@ struct nr_stun_client_ctx_ {
|
||||
#define NR_STUN_CLIENT_STATE_FAILED 3
|
||||
#define NR_STUN_CLIENT_STATE_TIMED_OUT 4
|
||||
#define NR_STUN_CLIENT_STATE_CANCELLED 5
|
||||
#define NR_STUN_CLIENT_STATE_WAITING 6
|
||||
|
||||
int mode;
|
||||
#define NR_STUN_CLIENT_MODE_BINDING_REQUEST_SHORT_TERM_AUTH 1
|
||||
@ -191,6 +192,7 @@ int nr_stun_client_ctx_destroy(nr_stun_client_ctx **ctxp);
|
||||
int nr_stun_transport_addr_check(nr_transport_addr* addr, UINT4 mask);
|
||||
int nr_stun_client_process_response(nr_stun_client_ctx *ctx, UCHAR *msg, int len, nr_transport_addr *peer_addr);
|
||||
int nr_stun_client_cancel(nr_stun_client_ctx *ctx);
|
||||
int nr_stun_client_wait(nr_stun_client_ctx *ctx);
|
||||
int nr_stun_client_failed(nr_stun_client_ctx *ctx);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user