nsresult NrIceTurnServer::ToNicerTurnStruct(nr_ice_turn_server *server) const { memset(server, 0, sizeof(nr_ice_turn_server)); nsresult rv = ToNicerStunStruct(&server->turn_server); if (NS_FAILED(rv)) return rv; if (username_.empty()) return NS_ERROR_INVALID_ARG; if (password_.empty()) return NS_ERROR_INVALID_ARG; if (!(server->username=r_strdup(username_.c_str()))) return NS_ERROR_OUT_OF_MEMORY; // TODO([email protected]): handle non-ASCII passwords somehow? // STUN requires they be SASLpreped, but we don't know if // they are at this point. // C++03 23.2.4, Paragraph 1 stipulates that the elements // in std::vector must be contiguous, and can therefore be // used as input to functions expecting C arrays. int r = r_data_create(&server->password, const_cast<UCHAR *>(&password_[0]), password_.size()); if (r) { RFREE(server->username); return NS_ERROR_OUT_OF_MEMORY; } return NS_OK; }
void NicerConnection::setupTurnServer() { if (ice_config_.turn_server.empty()) { return; } auto servers = std::unique_ptr<nr_ice_turn_server[]>(new nr_ice_turn_server[1]); nr_ice_turn_server *server = &servers[0]; nr_ice_stun_server *stun_server = &server->turn_server; memset(server, 0, sizeof(nr_ice_turn_server)); stun_server->transport = IPPROTO_UDP; stun_server->type = NR_ICE_STUN_SERVER_TYPE_ADDR; nr_transport_addr addr; nr_str_port_to_transport_addr(ice_config_.turn_server.c_str(), ice_config_.turn_port, IPPROTO_UDP, &addr); stun_server->u.addr = addr; server->username = r_strdup(const_cast<char*>(ice_config_.turn_username.c_str())); int r = r_data_create(&server->password, reinterpret_cast<UCHAR*>(const_cast<char *>(&ice_config_.turn_pass[0])), ice_config_.turn_pass.size()); if (r) { RFREE(server->username); return; } r = nicer_->IceContextSetTurnServers(ctx_, servers.get(), 1); if (r) { ELOG_WARN("%s message: Could not setup Turn", toLog()); } ELOG_DEBUG("%s message: TURN server configured", toLog()); }
static int 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) { int r,_status; nr_stun_client_allocate_request1_params *allocate_request1 = 0; nr_stun_client_allocate_request2_params *allocate_request2 = 0; nr_stun_client_allocate_response1_results *allocate_response1 = 0; // nr_stun_client_allocate_response2_results *allocate_response2; if (ctx->state != NR_TURN_CLIENT_STATE_INITTED) ABORT(R_NOT_PERMITTED); assert(ctx->phase == NR_TURN_CLIENT_PHASE_INITIALIZED); allocate_request1 = &ctx->stun_ctx[NR_TURN_CLIENT_PHASE_ALLOCATE_REQUEST1]->params.allocate_request1; allocate_response1 = &ctx->stun_ctx[NR_TURN_CLIENT_PHASE_ALLOCATE_REQUEST1]->results.allocate_response1; allocate_request2 = &ctx->stun_ctx[NR_TURN_CLIENT_PHASE_ALLOCATE_REQUEST2]->params.allocate_request2; ctx->state=NR_TURN_CLIENT_STATE_RUNNING; ctx->finished_cb=finished_cb; ctx->cb_arg=cb_arg; ctx->username = r_strdup(username); if (!ctx->username) ABORT(R_NO_MEMORY); if ((r=r_data_create(&ctx->password, password->data, password->len))) ABORT(r); allocate_request1->username = ctx->username; allocate_request2->username = ctx->username; allocate_request2->password = ctx->password; allocate_request2->realm = allocate_response1->realm; allocate_request2->nonce = allocate_response1->nonce; allocate_request2->bandwidth_kbps = bandwidth_kbps; allocate_request2->lifetime_secs = lifetime_secs; _status=0; abort: if (_status) ctx->state = NR_TURN_CLIENT_STATE_FAILED; if (ctx->state != NR_TURN_CLIENT_STATE_RUNNING) { 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,cb_arg); } return(_status); }
/* nr_turn_client_ctx functions */ int nr_turn_client_ctx_create(const char *label, nr_socket *sock, const char *username, Data *password, nr_transport_addr *addr, nr_turn_client_ctx **ctxp) { nr_turn_client_ctx *ctx=0; int r,_status; if ((r=r_log_register("turn", &NR_LOG_TURN))) ABORT(r); if(!(ctx=RCALLOC(sizeof(nr_turn_client_ctx)))) ABORT(R_NO_MEMORY); STAILQ_INIT(&ctx->stun_ctxs); STAILQ_INIT(&ctx->permissions); if(!(ctx->label=r_strdup(label))) ABORT(R_NO_MEMORY); ctx->sock=sock; ctx->username = r_strdup(username); if (!ctx->username) ABORT(R_NO_MEMORY); if ((r=r_data_create(&ctx->password, password->data, password->len))) ABORT(r); if ((r=nr_transport_addr_copy(&ctx->turn_server_addr, addr))) ABORT(r); if (addr->protocol == IPPROTO_UDP) { ctx->state = NR_TURN_CLIENT_STATE_CONNECTED; } else { assert(addr->protocol == IPPROTO_TCP); ctx->state = NR_TURN_CLIENT_STATE_INITTED; if (r=nr_turn_client_connect(ctx)) { if (r != R_WOULDBLOCK) ABORT(r); } } *ctxp=ctx; _status=0; abort: if(_status){ nr_turn_client_ctx_destroy(&ctx); } return(_status); }