bool TestNrSocket::allow_ingress(const nr_transport_addr &from, PortMapping **port_mapping_used) const { // This is only called for traffic arriving at a port mapping MOZ_ASSERT(nat_->enabled_); MOZ_ASSERT(!nat_->is_an_internal_tuple(from)); *port_mapping_used = get_port_mapping(from, nat_->filtering_type_); if (!(*port_mapping_used)) { r_log(LOG_GENERIC, LOG_INFO, "TestNrSocket %s denying ingress from %s: " "Filtered", internal_socket_->my_addr().as_string, from.as_string); return false; } if (is_port_mapping_stale(**port_mapping_used)) { r_log(LOG_GENERIC, LOG_INFO, "TestNrSocket %s denying ingress from %s: " "Stale port mapping", internal_socket_->my_addr().as_string, from.as_string); return false; } if (!nat_->allow_hairpinning_ && nat_->is_my_external_tuple(from)) { r_log(LOG_GENERIC, LOG_INFO, "TestNrSocket %s denying ingress from %s: " "Hairpinning disallowed", internal_socket_->my_addr().as_string, from.as_string); return false; } return true; }
int TestNrSocket::PortMapping::sendto(const void *msg, size_t len, const nr_transport_addr &to) { MOZ_ASSERT(remote_address_.protocol != IPPROTO_TCP); r_log(LOG_GENERIC, LOG_DEBUG, "PortMapping %s -> %s sending to %s", external_socket_->my_addr().as_string, remote_address_.as_string, to.as_string); last_used_ = PR_IntervalNow(); int r = external_socket_->sendto(msg, len, 0, // TODO(bug 1170299): Remove const_cast when no longer necessary const_cast<nr_transport_addr*>(&to)); if (r == R_WOULDBLOCK) { r_log(LOG_GENERIC, LOG_DEBUG, "Enqueueing UDP packet to %s", to.as_string); send_queue_.push_back(RefPtr<UdpPacket>(new UdpPacket(msg, len, to))); return 0; } if (r) { r_log(LOG_GENERIC,LOG_ERR, "Error: %d", r); } return r; }
int nr_ice_candidate_pair_select(nr_ice_cand_pair *pair) { int r,_status; if(!pair){ r_log(LOG_ICE,LOG_ERR,"ICE-PAIR: No pair chosen"); ABORT(R_BAD_ARGS); } if(pair->state!=NR_ICE_PAIR_STATE_SUCCEEDED){ r_log(LOG_ICE,LOG_ERR,"ICE-PEER(%s)/CAND-PAIR(%s): tried to install non-succeeded pair, ignoring: %s",pair->pctx->label,pair->codeword,pair->as_string); } else{ /* Ok, they chose one */ /* 1. Send a new request with nominated. Do it as a scheduled event to avoid reentrancy issues. Only do this if it hasn't happened already (though this shouldn't happen.) */ if(!pair->restart_nominated_cb_timer) NR_ASYNC_TIMER_SET(0,nr_ice_candidate_pair_restart_stun_nominated_cb,pair,&pair->restart_nominated_cb_timer); /* 2. Tell ourselves this pair is ready */ if(r=nr_ice_component_nominated_pair(pair->remote->component, pair)) ABORT(r); } _status=0; abort: return(_status); }
RefPtr<NrSocketBase> TestNrSocket::create_external_socket( const nr_transport_addr &dest_addr) const { MOZ_ASSERT(nat_->enabled_); MOZ_ASSERT(!nat_->is_an_internal_tuple(dest_addr)); int r; nr_transport_addr nat_external_addr; // Open the socket on an arbitrary port, on the same address. // TODO(bug 1170299): Remove const_cast when no longer necessary if ((r = nr_transport_addr_copy( &nat_external_addr, const_cast<nr_transport_addr*>(&internal_socket_->my_addr())))) { r_log(LOG_GENERIC,LOG_CRIT, "%s: Failure in nr_transport_addr_copy: %d", __FUNCTION__, r); return nullptr; } if ((r = nr_transport_addr_set_port(&nat_external_addr, 0))) { r_log(LOG_GENERIC,LOG_CRIT, "%s: Failure in nr_transport_addr_set_port: %d", __FUNCTION__, r); return nullptr; } RefPtr<NrSocketBase> external_socket; r = NrSocketBase::CreateSocket(&nat_external_addr, &external_socket); if (r) { r_log(LOG_GENERIC,LOG_CRIT, "%s: Failure in NrSocket::create: %d", __FUNCTION__, r); return nullptr; } return external_socket; }
int nr_ice_candidate_pair_select(nr_ice_cand_pair *pair) { int r,_status; if(!pair){ r_log(LOG_ICE,LOG_ERR,"ICE-PAIR: No pair chosen"); ABORT(R_BAD_ARGS); } if(pair->state!=NR_ICE_PAIR_STATE_SUCCEEDED){ r_log(LOG_ICE,LOG_ERR,"ICE-PEER(%s): tried to install non-succeeded pair %s, ignoring",pair->pctx->label,pair->as_string); } else{ /* Ok, they chose one */ /* 1. Send a new request with nominated. Do it as a scheduled event to avoid reentrancy issues */ NR_ASYNC_SCHEDULE(nr_ice_candidate_pair_restart_stun_nominated_cb,pair); /* 2. Tell ourselves this pair is ready */ if(r=nr_ice_component_nominated_pair(pair->remote->component, pair)) ABORT(r); } _status=0; abort: return(_status); }
static int nr_turn_client_start_refresh_timer(nr_turn_client_ctx *tctx, nr_turn_stun_ctx *sctx, UINT4 lifetime) { int _status; assert(!tctx->refresh_timer_handle); if (lifetime <= TURN_REFRESH_SLACK_SECONDS) { r_log(NR_LOG_TURN, LOG_ERR, "Too short lifetime specified for turn %u", lifetime); ABORT(R_BAD_DATA); } if (lifetime > 3600) lifetime = 3600; lifetime -= TURN_REFRESH_SLACK_SECONDS; r_log(NR_LOG_TURN, LOG_DEBUG, "TURN(%s): Setting refresh timer for %u seconds", tctx->label, lifetime); NR_ASYNC_TIMER_SET(lifetime * 1000, nr_turn_client_refresh_timer_cb, sctx, &tctx->refresh_timer_handle); _status=0; abort: if (_status) { nr_turn_client_failed(tctx); } return _status; }
int TestNrSocket::PortMapping::send_from_queue() { MOZ_ASSERT(remote_address_.protocol != IPPROTO_TCP); int r = 0; while (!send_queue_.empty()) { UdpPacket &packet = *send_queue_.front(); r_log(LOG_GENERIC, LOG_DEBUG, "PortMapping %s -> %s sending from queue to %s", external_socket_->my_addr().as_string, remote_address_.as_string, packet.remote_address_.as_string); r = external_socket_->sendto(packet.buffer_->data(), packet.buffer_->len(), 0, &packet.remote_address_); if (r) { if (r != R_WOULDBLOCK) { r_log(LOG_GENERIC, LOG_ERR, "%s: Fatal error %d, stop trying", __FUNCTION__, r); send_queue_.clear(); } else { r_log(LOG_GENERIC, LOG_DEBUG, "Would block, will retry later"); } break; } send_queue_.pop_front(); } return r; }
static void nr_stun_client_timer_expired_cb(int a, int b, void *cb_arg) { int _status; nr_stun_client_ctx *ctx=cb_arg; struct timeval now; INT8 ms_waited; /* Prevent this timer from being cancelled later */ ctx->timer_handle=0; /* Shouldn't happen */ if(ctx->state==NR_STUN_CLIENT_STATE_CANCELLED) ABORT(R_REJECTED); gettimeofday(&now, 0); if (r_timeval_diff_ms(&now, &ctx->timer_set, &ms_waited)) { r_log(NR_LOG_STUN,LOG_DEBUG,"STUN-CLIENT(%s): Timer expired",ctx->label); } else { r_log(NR_LOG_STUN,LOG_DEBUG,"STUN-CLIENT(%s): Timer expired (after %llu ms)",ctx->label, ms_waited); } if (ctx->request_ct >= ctx->maximum_transmits) { r_log(NR_LOG_STUN,LOG_DEBUG,"STUN-CLIENT(%s): Timed out",ctx->label); ctx->state=NR_STUN_CLIENT_STATE_TIMED_OUT; ABORT(R_FAILED); } if (ctx->state != NR_STUN_CLIENT_STATE_RUNNING) ABORT(R_NOT_PERMITTED); /* as a side effect will reset the timer */ nr_stun_client_send_request(ctx); _status = 0; abort: if (ctx->state != NR_STUN_CLIENT_STATE_RUNNING) { /* Cancel the timer firing */ if (ctx->timer_handle) { NR_async_timer_cancel(ctx->timer_handle); ctx->timer_handle=0; } 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; }
// This should be called on the STS thread. int NrSocket::sendto(const void *msg, size_t len, int flags, nr_transport_addr *to) { ASSERT_ON_THREAD(ststhread_); int r,_status; PRNetAddr naddr; int32_t status; if ((r=nr_transport_addr_to_praddr(to, &naddr))) ABORT(r); if(fd_==nullptr) ABORT(R_EOD); if (nr_is_stun_request_message((UCHAR*)msg, len)) { // Global rate limiting for stun requests, to mitigate the ice hammer DoS // (see http://tools.ietf.org/html/draft-thomson-mmusic-ice-webrtc) // Tolerate rate of 8k/sec, for one second. static SimpleTokenBucket burst(8192*1, 8192); // Tolerate rate of 3.6k/sec over twenty seconds. static SimpleTokenBucket sustained(3686*20, 3686); // Check number of tokens in each bucket. if (burst.getTokens(UINT32_MAX) < len || sustained.getTokens(UINT32_MAX) < len) { r_log(LOG_GENERIC, LOG_ERR, "Global rate limit for STUN requests exceeded."); MOZ_ASSERT("Global rate limit for STUN requests exceeded. Go bug " "[email protected] if you weren't intentionally spamming " "ICE candidates, or don't know what that means."); ABORT(R_WOULDBLOCK); } // Take len tokens from both buckets. // (not threadsafe, but no problem since this is only called from STS) burst.getTokens(len); sustained.getTokens(len); } // TODO: Convert flags? status = PR_SendTo(fd_, msg, len, flags, &naddr, PR_INTERVAL_NO_WAIT); if (status < 0 || (size_t)status != len) { if (PR_GetError() == PR_WOULD_BLOCK_ERROR) ABORT(R_WOULDBLOCK); r_log(LOG_GENERIC, LOG_INFO, "Error in sendto %s", to->as_string); ABORT(R_IO_ERROR); } _status=0; abort: return(_status); }
int nr_turn_client_process_response(nr_turn_client_ctx *ctx, UCHAR *msg, int len, nr_transport_addr *turn_server_addr) { int r,_status; nr_stun_client_ctx *stun_ctx; assert(ctx->phase >= 0 && ctx->phase < NUMBER_OF_STUN_CTX); if (ctx->phase < 0 || ctx->phase > NUMBER_OF_STUN_CTX) ABORT(R_INTERNAL); /* should never happen */ stun_ctx = ctx->stun_ctx[ctx->phase]; if (ctx->state != NR_TURN_CLIENT_STATE_RUNNING && ctx->state != NR_TURN_CLIENT_STATE_ALLOCATED) { #if 0 //TODO: !nn! it really shouldn't be the case that we're processing a response in this state, //TODO: but perhaps we failed and we haven't taken ourself off the //TODO: ASYNC wait list, so an outstanding packet can cause us this grief assert(0); ABORT(R_INTERNAL); /* should never happen */ #else //TODO: !nn! fix so we can never get into this state r_log(NR_LOG_TURN,LOG_ERR,"TURN-CLIENT(%s): dropping packet in phase %s", ctx->label, TURN_PHASE_LABEL[ctx->phase]); return R_INTERNAL; #endif } if (ctx->phase != NR_TURN_CLIENT_PHASE_INITIALIZED) { r_log(NR_LOG_TURN,LOG_DEBUG,"TURN-CLIENT(%s): Received response in phase %s", ctx->label, TURN_PHASE_LABEL[ctx->phase]); } else { ABORT(R_INTERNAL); } if ((r=nr_stun_client_process_response(stun_ctx, msg, len, turn_server_addr))) ABORT(r); _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); }
int nr_stun_get_addrs(nr_local_addr addrs[], int maxaddrs, int drop_loopback, int drop_link_local, int *count) { int r,_status=0; int i; char typestr[100]; #ifdef WIN32 _status = stun_get_win32_addrs(addrs, maxaddrs, count); #else _status = stun_getifaddrs(addrs, maxaddrs, count); #endif if ((r=nr_stun_remove_duplicate_addrs(addrs, drop_loopback, drop_link_local, count))) ABORT(r); for (i = 0; i < *count; ++i) { nr_local_addr_fmt_info_string(addrs+i,typestr,sizeof(typestr)); r_log(NR_LOG_STUN, LOG_DEBUG, "Address %d: %s on %s, type: %s\n", i,addrs[i].addr.as_string,addrs[i].addr.ifname,typestr); } abort: return _status; }
int nr_ice_candidate_pair_set_state(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair, int state) { int r,_status; r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): setting pair %s to %s", pctx->label,pair->as_string,nr_ice_cand_pair_states[state]); pair->state=state; if(pctx->state!=NR_ICE_PAIR_STATE_WAITING){ if(state==NR_ICE_PAIR_STATE_WAITING) pctx->waiting_pairs++; } else{ if(state!=NR_ICE_PAIR_STATE_WAITING) pctx->waiting_pairs--; assert(pctx->waiting_pairs>=0); } if(pair->state==NR_ICE_PAIR_STATE_FAILED){ if(r=nr_ice_component_failed_pair(pair->remote->component, pair)) ABORT(r); } _status=0; abort: return(_status); }
int nr_turn_client_cancel(nr_turn_client_ctx *ctx) { nr_turn_stun_ctx *stun = 0; if (ctx->state == NR_TURN_CLIENT_STATE_CANCELLED || ctx->state == NR_TURN_CLIENT_STATE_FAILED) return(0); if (ctx->label) r_log(NR_LOG_TURN, LOG_INFO, "TURN(%s): cancelling", ctx->label); /* Cancel the STUN client ctxs */ stun = STAILQ_FIRST(&ctx->stun_ctxs); while (stun) { nr_stun_client_cancel(stun->stun); stun = STAILQ_NEXT(stun, entry); } /* Cancel the timers, if not already cancelled */ NR_async_timer_cancel(ctx->connected_timer_handle); NR_async_timer_cancel(ctx->refresh_timer_handle); ctx->state = NR_TURN_CLIENT_STATE_CANCELLED; return(0); }
// This should be called on the STS thread. int NrSocket::sendto(const void *msg, size_t len, int flags, nr_transport_addr *to) { ASSERT_ON_THREAD(ststhread_); int r,_status; PRNetAddr naddr; int32_t status; if ((r=nr_transport_addr_to_praddr(to, &naddr))) ABORT(r); if(fd_==nullptr) ABORT(R_EOD); // TODO: Convert flags? status = PR_SendTo(fd_, msg, len, flags, &naddr, PR_INTERVAL_NO_WAIT); if (status < 0 || (size_t)status != len) { if (PR_GetError() == PR_WOULD_BLOCK_ERROR) ABORT(R_WOULDBLOCK); r_log(LOG_GENERIC, LOG_INFO, "Error in sendto %s", to->as_string); ABORT(R_IO_ERROR); } _status=0; abort: return(_status); }
int NrSocket::recvfrom(void * buf, size_t maxlen, size_t *len, int flags, nr_transport_addr *from) { ASSERT_ON_THREAD(ststhread_); int r,_status; PRNetAddr nfrom; int32_t status; status = PR_RecvFrom(fd_, buf, maxlen, flags, &nfrom, PR_INTERVAL_NO_WAIT); if (status <= 0) { if (PR_GetError() == PR_WOULD_BLOCK_ERROR) ABORT(R_WOULDBLOCK); r_log(LOG_GENERIC, LOG_INFO, "Error in recvfrom"); ABORT(R_IO_ERROR); } *len=status; if((r=nr_praddr_to_transport_addr(&nfrom,from,my_addr_.protocol,0))) ABORT(r); //r_log(LOG_GENERIC,LOG_DEBUG,"Read %d bytes from %s",*len,addr->as_string); _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; } /* Activate the media stream if required */ if(pair->remote->stream->ice_state==NR_ICE_MEDIA_STREAM_CHECKS_FROZEN){ if(r=nr_ice_media_stream_start_checks(pair->pctx,pair->remote->stream)) ABORT(r); } _status=0; abort: return(_status); }
int nr_stun_client_force_retransmit(nr_stun_client_ctx *ctx) { int r,_status; if (ctx->state != NR_STUN_CLIENT_STATE_RUNNING) ABORT(R_NOT_PERMITTED); if (ctx->request_ct > ctx->maximum_transmits) { r_log(NR_LOG_STUN,LOG_INFO,"STUN-CLIENT(%s): Too many retransmit attempts",ctx->label); ABORT(R_FAILED); } /* if there is a scheduled retransimt, get rid of the scheduled retransmit * and retransmit immediately */ if (ctx->timer_handle) { NR_async_timer_cancel(ctx->timer_handle); ctx->timer_handle=0; if (r=nr_stun_client_send_request(ctx)) ABORT(r); } _status=0; abort: return(_status); }
/* This takes ownership of nrsock whether it fails or not. */ static int nr_tcp_socket_ctx_create(nr_socket *nrsock, int is_framed, int max_pending, nr_tcp_socket_ctx **sockp) { int r, _status; nr_tcp_socket_ctx *sock = 0; nr_socket *tcpsock; if (!(sock = RCALLOC(sizeof(nr_tcp_socket_ctx)))) { nr_socket_destroy(&nrsock); ABORT(R_NO_MEMORY); } if ((r=nr_socket_buffered_stun_create(nrsock, max_pending, is_framed ? ICE_TCP_FRAMING : TURN_TCP_FRAMING, &tcpsock))){ nr_socket_destroy(&nrsock); ABORT(r); } sock->inner=tcpsock; sock->is_framed=is_framed; if ((r=nr_ip4_port_to_transport_addr(ntohl(INADDR_ANY), 0, IPPROTO_TCP, &sock->remote_addr))) ABORT(r); *sockp=sock; _status=0; abort: if (_status) { r_log(LOG_ICE,LOG_DEBUG,"%s:%d function %s failed with error %d",__FILE__,__LINE__,__FUNCTION__,_status); nr_tcp_socket_ctx_destroy(&sock); } return(_status); }
/* TODO([email protected]): We currently don't support channels. We might in the future. Mozilla bug 857736 */ int nr_turn_client_send_indication(nr_turn_client_ctx *ctx, const UCHAR *msg, size_t len, int flags, nr_transport_addr *remote_addr) { int r,_status; nr_stun_client_send_indication_params params = { { 0 } }; nr_stun_message *ind = 0; if (ctx->state != NR_TURN_CLIENT_STATE_ALLOCATED) ABORT(R_FAILED); r_log(NR_LOG_TURN, LOG_DEBUG, "TURN(%s): Send indication len=%zu", ctx->label, len); if ((r=nr_turn_client_ensure_perm(ctx, remote_addr))) ABORT(r); if ((r=nr_transport_addr_copy(¶ms.remote_addr, remote_addr))) ABORT(r); params.data.data = (UCHAR*)msg; params.data.len = len; if ((r=nr_stun_build_send_indication(¶ms, &ind))) ABORT(r); if ((r=nr_turn_client_send_stun_request(ctx, ind, flags))) ABORT(r); _status=0; abort: nr_stun_message_destroy(&ind); return(_status); }
static void nr_stun_client_timer_expired_cb(NR_SOCKET s, int b, void *cb_arg) { int _status; nr_stun_client_ctx *ctx=cb_arg; struct timeval now; INT8 ms_waited; /* Prevent this timer from being cancelled later */ ctx->timer_handle=0; /* Shouldn't happen */ if(ctx->state==NR_STUN_CLIENT_STATE_CANCELLED) ABORT(R_REJECTED); gettimeofday(&now, 0); if (r_timeval_diff_ms(&now, &ctx->timer_set, &ms_waited)) { r_log(NR_LOG_STUN,LOG_DEBUG,"STUN-CLIENT(%s): Timer expired",ctx->label); } else { r_log(NR_LOG_STUN,LOG_DEBUG,"STUN-CLIENT(%s): Timer expired (after %llu ms)",ctx->label, ms_waited); } if (ctx->request_ct >= ctx->maximum_transmits) { r_log(NR_LOG_STUN,LOG_INFO,"STUN-CLIENT(%s): Timed out",ctx->label); ctx->state=NR_STUN_CLIENT_STATE_TIMED_OUT; ABORT(R_FAILED); } if (ctx->state != NR_STUN_CLIENT_STATE_RUNNING) ABORT(R_NOT_PERMITTED); /* as a side effect will reset the timer */ nr_stun_client_send_request(ctx); _status = 0; abort: if (ctx->state != NR_STUN_CLIENT_STATE_RUNNING) { /* Cancel the timer firing */ if (ctx->timer_handle){ NR_async_timer_cancel(ctx->timer_handle); ctx->timer_handle=0; } nr_stun_client_fire_finished_cb(ctx); } return; }
int TestNrSocket::listen(int backlog) { MOZ_ASSERT(internal_socket_->my_addr().protocol == IPPROTO_TCP); r_log(LOG_GENERIC, LOG_DEBUG, "TestNrSocket %s listening", internal_socket_->my_addr().as_string); return internal_socket_->listen(backlog); }
void TestNrSocket::fire_readable_callback() { MOZ_ASSERT(poll_flags() & PR_POLL_READ); // Stop listening on all mapped sockets; we will start listening again // if the app starts listening to us again. cancel_port_mapping_async_wait(NR_ASYNC_WAIT_READ); r_log(LOG_GENERIC, LOG_DEBUG, "TestNrSocket %s ready for read", my_addr_.as_string); fire_callback(NR_ASYNC_WAIT_READ); }
int TestNrSocket::PortMapping::cancel(int how) { r_log(LOG_GENERIC, LOG_DEBUG, "PortMapping %s -> %s stop waiting for %s", external_socket_->my_addr().as_string, remote_address_.as_string, how == NR_ASYNC_WAIT_READ ? "read" : "write"); return external_socket_->cancel(how); }
static void nr_turn_client_error_cb(NR_SOCKET s, int how, void *arg) { nr_turn_stun_ctx *ctx = (nr_turn_stun_ctx *)arg; r_log(NR_LOG_TURN, LOG_WARNING, "TURN(%s): mode %d, %s", ctx->tctx->label, ctx->mode, __FUNCTION__); nr_turn_client_failed(ctx->tctx); }
int nr_turn_client_cancel(nr_turn_client_ctx *ctx) { nr_turn_stun_ctx *stun = 0; if (ctx->state == NR_TURN_CLIENT_STATE_CANCELLED || ctx->state == NR_TURN_CLIENT_STATE_FAILED) return 0; if (ctx->label) r_log(NR_LOG_TURN, LOG_INFO, "TURN(%s): cancelling", ctx->label); /* If we are waiting for connect, we need to stop waiting for writability */ if (ctx->state == NR_TURN_CLIENT_STATE_INITTED || ctx->state == NR_TURN_CLIENT_STATE_ALLOCATION_WAIT) { NR_SOCKET fd; int r; r = nr_socket_getfd(ctx->sock, &fd); if (r) { /* We should be able to get the fd, but if we get an error, we shouldn't cancel. */ r_log(NR_LOG_TURN, LOG_ERR, "TURN: Couldn't get internal fd"); } else { NR_ASYNC_CANCEL(fd, NR_ASYNC_WAIT_WRITE); } } /* Cancel the STUN client ctxs */ stun = STAILQ_FIRST(&ctx->stun_ctxs); while (stun) { nr_stun_client_cancel(stun->stun); stun = STAILQ_NEXT(stun, entry); } /* Cancel the timers, if not already cancelled */ NR_async_timer_cancel(ctx->connected_timer_handle); NR_async_timer_cancel(ctx->refresh_timer_handle); ctx->state = NR_TURN_CLIENT_STATE_CANCELLED; return(0); }
int TestNrSocket::write(const void *msg, size_t len, size_t *written) { UCHAR *buf = static_cast<UCHAR*>(const_cast<void*>(msg)); if (nat_->block_stun_ && nr_is_stun_message(buf, len)) { // Should cause this socket to be abandoned r_log(LOG_GENERIC, LOG_DEBUG, "TestNrSocket %s dropping outgoing TCP " "because it is configured to drop STUN", my_addr().as_string); return R_INTERNAL; } if (nat_->block_tcp_ && !tls_) { // Should cause this socket to be abandoned r_log(LOG_GENERIC, LOG_DEBUG, "TestNrSocket %s dropping outgoing TCP " "because it is configured to drop TCP", my_addr().as_string); return R_INTERNAL; } if (port_mappings_.empty()) { // The no-nat case, just pass call through. r_log(LOG_GENERIC, LOG_DEBUG, "TestNrSocket %s writing", my_addr().as_string); return internal_socket_->write(msg, len, written); } destroy_stale_port_mappings(); if (port_mappings_.empty()) { r_log(LOG_GENERIC, LOG_DEBUG, "TestNrSocket %s dropping outgoing TCP " "because the port mapping was stale", my_addr().as_string); return R_INTERNAL; } // This is TCP only MOZ_ASSERT(port_mappings_.size() == 1); r_log(LOG_GENERIC, LOG_DEBUG, "PortMapping %s -> %s writing", port_mappings_.front()->external_socket_->my_addr().as_string, port_mappings_.front()->remote_address_.as_string); port_mappings_.front()->last_used_ = PR_IntervalNow(); return port_mappings_.front()->external_socket_->write(msg, len, written); }
static int nr_win32_get_adapter_friendly_name(char *adapter_GUID, char **friendly_name) { int r,_status; HKEY adapter_reg; TCHAR adapter_key[_NR_MAX_KEY_LENGTH]; TCHAR keyval_buf[_NR_MAX_KEY_LENGTH]; TCHAR adapter_GUID_tchar[_NR_MAX_NAME_LENGTH]; DWORD keyval_len, key_type; size_t converted_chars, newlen; char *my_fn = 0; #ifdef _UNICODE mbstowcs_s(&converted_chars, adapter_GUID_tchar, strlen(adapter_GUID)+1, adapter_GUID, _TRUNCATE); #else strlcpy(adapter_GUID_tchar, adapter_GUID, _NR_MAX_NAME_LENGTH); #endif _tcscpy_s(adapter_key, _NR_MAX_KEY_LENGTH, TEXT(_ADAPTERS_BASE_REG)); _tcscat_s(adapter_key, _NR_MAX_KEY_LENGTH, TEXT("\\")); _tcscat_s(adapter_key, _NR_MAX_KEY_LENGTH, adapter_GUID_tchar); _tcscat_s(adapter_key, _NR_MAX_KEY_LENGTH, TEXT("\\Connection")); r = RegOpenKeyEx(HKEY_LOCAL_MACHINE, adapter_key, 0, KEY_READ, &adapter_reg); if (r != ERROR_SUCCESS) { r_log(NR_LOG_STUN, LOG_ERR, "Got error %d opening adapter reg key\n", r); ABORT(R_INTERNAL); } keyval_len = sizeof(keyval_buf); r = RegQueryValueEx(adapter_reg, TEXT("Name"), NULL, &key_type, (BYTE *)keyval_buf, &keyval_len); RegCloseKey(adapter_reg); #ifdef UNICODE newlen = wcslen(keyval_buf)+1; my_fn = (char *) RCALLOC(newlen); if (!my_fn) { ABORT(R_NO_MEMORY); } wcstombs_s(&converted_chars, my_fn, newlen, keyval_buf, _TRUNCATE); #else my_fn = r_strdup(keyval_buf); #endif *friendly_name = my_fn; _status=0; abort: if (_status) { if (my_fn) free(my_fn); } return(_status); }
static void nr_ice_candidate_pair_restart_stun_role_change_cb(NR_SOCKET s, int how, void *cb_arg) { nr_ice_cand_pair *pair=cb_arg; pair->restart_role_change_cb_timer=0; r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s)/STREAM(%s)/CAND-PAIR(%s):COMP(%d): Restarting pair as %s: %s",pair->pctx->label,pair->local->stream->label,pair->codeword,pair->remote->component->component_id,pair->pctx->controlling ? "CONTROLLING" : "CONTROLLED",pair->as_string); nr_ice_candidate_pair_restart(pair->pctx, pair); }
int TestNrSocket::PortMapping::async_wait(int how, NR_async_cb cb, void *cb_arg, char *function, int line) { r_log(LOG_GENERIC, LOG_DEBUG, "PortMapping %s -> %s waiting for %s", external_socket_->my_addr().as_string, remote_address_.as_string, how == NR_ASYNC_WAIT_READ ? "read" : "write"); return external_socket_->async_wait(how, cb, cb_arg, function, line); }
TestNrSocket::PortMapping* TestNrSocket::create_port_mapping( const nr_transport_addr &remote_address, const RefPtr<NrSocketBase> &external_socket) const { r_log(LOG_GENERIC, LOG_INFO, "TestNrSocket %s creating port mapping %s -> %s", internal_socket_->my_addr().as_string, external_socket->my_addr().as_string, remote_address.as_string); return new PortMapping(remote_address, external_socket); }