static void nr_ice_candidate_pair_restart(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair) { int r,_status; UINT4 mode; nr_ice_candidate_pair_set_state(pctx,pair,NR_ICE_PAIR_STATE_IN_PROGRESS); /* Start STUN */ if(pair->pctx->controlling && (pair->pctx->ctx->flags & NR_ICE_CTX_FLAGS_AGGRESSIVE_NOMINATION)) mode=NR_ICE_CLIENT_MODE_USE_CANDIDATE; else mode=NR_ICE_CLIENT_MODE_BINDING_REQUEST; nr_stun_client_reset(pair->stun_client); if(r=nr_stun_client_start(pair->stun_client,mode,nr_ice_candidate_pair_stun_cb,pair)) ABORT(r); if ((r=nr_ice_ctx_remember_id(pair->pctx->ctx, pair->stun_client->request))) { /* ignore if this fails (which it shouldn't) because it's only an * optimization and the cleanup routines are not going to do the right * thing if this fails */ assert(0); } _status=0; abort: if(_status){ /* Don't fire the CB, but schedule it to fire ASAP */ assert(!pair->stun_cb_timer); NR_ASYNC_TIMER_SET(0,nr_ice_candidate_pair_stun_cb,pair, &pair->stun_cb_timer); _status=0; } }
static void nr_ice_candidate_pair_restart_stun_controlled_cb(int s, int how, void *cb_arg) { nr_ice_cand_pair *pair=cb_arg; int r,_status; r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/STREAM(%s):%d: Restarting pair %s as CONTROLLED",pair->pctx->label,pair->local->stream->label,pair->remote->component->component_id,pair->as_string); nr_stun_client_reset(pair->stun_client); pair->stun_client->params.ice_binding_request.control=NR_ICE_CONTROLLED; if(r=nr_stun_client_start(pair->stun_client,NR_ICE_CLIENT_MODE_BINDING_REQUEST,nr_ice_candidate_pair_stun_cb,pair)) ABORT(r); if(r=nr_ice_ctx_remember_id(pair->pctx->ctx, pair->stun_client->request)) ABORT(r); _status=0; abort: return; }
void nr_ice_candidate_pair_restart_stun_nominated_cb(NR_SOCKET s, int how, void *cb_arg) { nr_ice_cand_pair *pair=cb_arg; int r,_status; pair->restart_nominated_cb_timer=0; r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s)/STREAM(%s)/CAND-PAIR(%s)/COMP(%d): Restarting pair as nominated: %s",pair->pctx->label,pair->local->stream->label,pair->codeword,pair->remote->component->component_id,pair->as_string); nr_stun_client_reset(pair->stun_client); if(r=nr_stun_client_start(pair->stun_client,NR_ICE_CLIENT_MODE_USE_CANDIDATE,nr_ice_candidate_pair_stun_cb,pair)) ABORT(r); if(r=nr_ice_ctx_remember_id(pair->pctx->ctx, pair->stun_client->request)) ABORT(r); _status=0; abort: return; }
static int nr_turn_stun_ctx_start(nr_turn_stun_ctx *ctx) { int r, _status; nr_turn_client_ctx *tctx = ctx->tctx; if ((r=nr_stun_client_reset(ctx->stun))) { r_log(NR_LOG_TURN, LOG_ERR, "TURN(%s): Couldn't reset STUN", tctx->label); ABORT(r); } if ((r=nr_stun_client_start(ctx->stun, ctx->mode, nr_turn_stun_ctx_cb, ctx))) { r_log(NR_LOG_TURN, LOG_ERR, "TURN(%s): Couldn't start STUN", tctx->label); ABORT(r); } _status=0; abort: return _status; }
int nr_stun_client_restart(nr_stun_client_ctx *ctx) { int r,_status; int mode; NR_async_cb finished_cb; void *cb_arg; nr_stun_message_attribute *ec; nr_stun_message_attribute *as; if (ctx->state != NR_STUN_CLIENT_STATE_RUNNING) ABORT(R_NOT_PERMITTED); assert(ctx->retry_ct <= 2); if (ctx->retry_ct > 2) ABORT(R_NOT_PERMITTED); ++ctx->retry_ct; mode = ctx->mode; finished_cb = ctx->finished_cb; cb_arg = ctx->cb_arg; if (nr_stun_message_has_attribute(ctx->response, NR_STUN_ATTR_ERROR_CODE, &ec) && ec->u.error_code.number == 300) { if (nr_stun_message_has_attribute(ctx->response, NR_STUN_ATTR_ALTERNATE_SERVER, &as)) { nr_transport_addr_copy(&ctx->peer_addr, &as->u.alternate_server); } } nr_stun_client_reset(ctx); if (r=nr_stun_client_start(ctx, mode, finished_cb, cb_arg)) ABORT(r); _status=0; abort: return(_status); }
int nr_ice_candidate_pair_start(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair) { int r,_status; UINT4 mode; nr_ice_candidate_pair_set_state(pctx,pair,NR_ICE_PAIR_STATE_IN_PROGRESS); /* Register the stun ctx for when responses come in*/ if(r=nr_ice_socket_register_stun_client(pair->local->isock,pair->stun_client,&pair->stun_client_handle)) ABORT(r); /* Start STUN */ if(pair->pctx->controlling && (pair->pctx->ctx->flags & NR_ICE_CTX_FLAGS_AGGRESSIVE_NOMINATION)) mode=NR_ICE_CLIENT_MODE_USE_CANDIDATE; else mode=NR_ICE_CLIENT_MODE_BINDING_REQUEST; if(r=nr_stun_client_start(pair->stun_client,mode,nr_ice_candidate_pair_stun_cb,pair)) ABORT(r); if ((r=nr_ice_ctx_remember_id(pair->pctx->ctx, pair->stun_client->request))) { /* ignore if this fails (which it shouldn't) because it's only an * optimization and the cleanup routines are not going to do the right * thing if this fails */ assert(0); } _status=0; abort: if(_status){ /* Don't fire the CB, but schedule it to fire */ NR_ASYNC_SCHEDULE(nr_ice_candidate_pair_stun_cb,pair); _status=0; } return(_status); }
int nr_turn_client_next_action(nr_turn_client_ctx *ctx, int stun_ctx_state) { int r,_status; assert(ctx->phase >= -1 && ctx->phase < NUMBER_OF_STUN_CTX); switch (ctx->state) { //case NR_TURN_CLIENT_STATE_ALLOCATING: case NR_TURN_CLIENT_STATE_RUNNING: case NR_TURN_CLIENT_STATE_ALLOCATED: /* these are the acceptable states */ break; default: assert(0); ABORT(R_INTERNAL); /* should never happen */ break; } if (ctx->phase != NR_TURN_CLIENT_PHASE_INITIALIZED && ctx->state != NR_TURN_CLIENT_STATE_ALLOCATED) { r_log(NR_LOG_TURN,LOG_DEBUG,"TURN-CLIENT(%s): Finishing phase %s", ctx->label, TURN_PHASE_LABEL[ctx->phase]); } switch (stun_ctx_state) { case NR_STUN_CLIENT_STATE_DONE: /* sanity check that NR_TURN_CLIENT_PHASE_SET_ACTIVE_DEST is the final phase */ assert(NUMBER_OF_STUN_CTX == NR_TURN_CLIENT_PHASE_SET_ACTIVE_DEST+1); if (ctx->phase == NR_TURN_CLIENT_PHASE_SET_ACTIVE_DEST) { #if 0 ctx->state = NR_TURN_CLIENT_STATE_ACTIVE; #else assert(0); ABORT(R_INTERNAL); #endif r_log(NR_LOG_TURN,LOG_DEBUG,"TURN-CLIENT(%s): Active", ctx->label); } else if (ctx->phase == NR_TURN_CLIENT_PHASE_ALLOCATE_REQUEST2 && ctx->state != NR_TURN_CLIENT_STATE_ALLOCATED) { ctx->state = NR_TURN_CLIENT_STATE_ALLOCATED; r_log(NR_LOG_TURN,LOG_DEBUG,"TURN-CLIENT(%s): Allocated", ctx->label); } else { ++(ctx->phase); if (ctx->phase > NUMBER_OF_STUN_CTX) { ABORT(R_INTERNAL); } ctx->state=NR_TURN_CLIENT_STATE_RUNNING; r_log(NR_LOG_TURN,LOG_DEBUG,"TURN-CLIENT(%s): Starting phase %s", ctx->label, TURN_PHASE_LABEL[ctx->phase]); if ((r=nr_stun_client_start(ctx->stun_ctx[ctx->phase], TURN_PHASE_MODE[ctx->phase], nr_turn_client_cb, ctx))) ABORT(r); } break; case NR_STUN_CLIENT_STATE_FAILED: ctx->state = NR_TURN_CLIENT_STATE_FAILED; r_log(NR_LOG_TURN,LOG_DEBUG,"TURN-CLIENT(%s): Failed in phase %s", ctx->label, TURN_PHASE_LABEL[ctx->phase]); ABORT(R_FAILED); break; case NR_STUN_CLIENT_STATE_TIMED_OUT: ctx->state = NR_TURN_CLIENT_STATE_TIMED_OUT; r_log(NR_LOG_TURN,LOG_DEBUG,"TURN-CLIENT(%s): Timed out", ctx->label); ABORT(R_INTERRUPTED); break; default: assert(0); ABORT(R_INTERNAL); /* should never happen */ break; } _status=0; abort: if (ctx->state != NR_TURN_CLIENT_STATE_RUNNING) { if (ctx->finished_cb) { NR_async_cb finished_cb = ctx->finished_cb; ctx->finished_cb = 0; /* prevent 2nd call */ /* finished_cb call must be absolutely last thing in function * because as a side effect this ctx may be operated on in the * callback */ finished_cb(0,0,ctx->cb_arg); } } return(_status); }