mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 886120 - Make ICE respond before receiving peer credentials r=abr
This commit is contained in:
parent
64a655c353
commit
7fa772890f
@ -280,17 +280,17 @@ class IceTestPeer : public sigslot::has_slots<> {
|
||||
}
|
||||
|
||||
void GotCandidate(NrIceMediaStream *stream, const std::string &candidate) {
|
||||
std::cout << "Got candidate " << candidate << std::endl;
|
||||
std::cerr << "Got candidate " << candidate << std::endl;
|
||||
candidates_[stream->name()].push_back(candidate);
|
||||
}
|
||||
|
||||
void StreamReady(NrIceMediaStream *stream) {
|
||||
std::cout << "Stream ready " << stream->name() << std::endl;
|
||||
std::cerr << "Stream ready " << stream->name() << std::endl;
|
||||
++ready_ct_;
|
||||
}
|
||||
|
||||
void IceCompleted(NrIceCtx *ctx) {
|
||||
std::cout << "ICE completed " << name_ << std::endl;
|
||||
std::cerr << "ICE completed " << name_ << std::endl;
|
||||
ice_complete_ = true;
|
||||
}
|
||||
|
||||
@ -413,6 +413,21 @@ class IceConnectTest : public ::testing::Test {
|
||||
ASSERT_TRUE_WAIT(p1_->ice_complete() && p2_->ice_complete(), 5000);
|
||||
}
|
||||
|
||||
|
||||
void ConnectP1(TrickleMode mode = TRICKLE_NONE) {
|
||||
p1_->Connect(p2_, mode);
|
||||
}
|
||||
|
||||
void ConnectP2(TrickleMode mode = TRICKLE_NONE) {
|
||||
p2_->Connect(p1_, mode);
|
||||
}
|
||||
|
||||
void WaitForComplete(int expected_streams = 1) {
|
||||
ASSERT_TRUE_WAIT(p1_->ready_ct() == expected_streams &&
|
||||
p2_->ready_ct() == expected_streams, 5000);
|
||||
ASSERT_TRUE_WAIT(p1_->ice_complete() && p2_->ice_complete(), 5000);
|
||||
}
|
||||
|
||||
void ConnectTrickle() {
|
||||
p1_->Connect(p2_, TRICKLE_DEFERRED);
|
||||
p2_->Connect(p1_, TRICKLE_DEFERRED);
|
||||
@ -425,6 +440,14 @@ class IceConnectTest : public ::testing::Test {
|
||||
ASSERT_TRUE_WAIT(p2_->is_ready(stream), 5000);
|
||||
}
|
||||
|
||||
void DoTrickleP1(size_t stream) {
|
||||
p1_->DoTrickle(stream);
|
||||
}
|
||||
|
||||
void DoTrickleP2(size_t stream) {
|
||||
p2_->DoTrickle(stream);
|
||||
}
|
||||
|
||||
void VerifyConnected() {
|
||||
}
|
||||
|
||||
@ -539,6 +562,40 @@ TEST_F(IceConnectTest, TestConnect) {
|
||||
Connect();
|
||||
}
|
||||
|
||||
TEST_F(IceConnectTest, TestConnectP2ThenP1) {
|
||||
AddStream("first", 1);
|
||||
ASSERT_TRUE(Gather(true));
|
||||
ConnectP2();
|
||||
PR_Sleep(1000);
|
||||
ConnectP1();
|
||||
WaitForComplete();
|
||||
}
|
||||
|
||||
TEST_F(IceConnectTest, TestConnectP2ThenP1Trickle) {
|
||||
AddStream("first", 1);
|
||||
ASSERT_TRUE(Gather(true));
|
||||
ConnectP2();
|
||||
PR_Sleep(1000);
|
||||
ConnectP1(TRICKLE_DEFERRED);
|
||||
DoTrickleP1(0);
|
||||
WaitForComplete();
|
||||
}
|
||||
|
||||
TEST_F(IceConnectTest, TestConnectP2ThenP1TrickleTwoComponents) {
|
||||
AddStream("first", 1);
|
||||
AddStream("second", 2);
|
||||
ASSERT_TRUE(Gather(true));
|
||||
ConnectP2();
|
||||
PR_Sleep(1000);
|
||||
ConnectP1(TRICKLE_DEFERRED);
|
||||
DoTrickleP1(0);
|
||||
std::cerr << "Sleeping between trickle streams" << std::endl;
|
||||
PR_Sleep(1000); // Give this some time to settle but not complete
|
||||
// all of ICE.
|
||||
DoTrickleP1(1);
|
||||
WaitForComplete(2);
|
||||
}
|
||||
|
||||
TEST_F(IceConnectTest, TestConnectAutoPrioritize) {
|
||||
Init(false);
|
||||
AddStream("first", 1);
|
||||
|
@ -53,9 +53,6 @@ int nr_ice_candidate_pair_create(nr_ice_peer_ctx *pctx, nr_ice_candidate *lcand,
|
||||
{
|
||||
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;
|
||||
@ -98,17 +95,6 @@ int nr_ice_candidate_pair_create(nr_ice_peer_ctx *pctx, nr_ice_candidate *lcand,
|
||||
rcand->foundation,NULL))
|
||||
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;
|
||||
assert(lufrag);
|
||||
assert(lpwd);
|
||||
rufrag=rcand->stream->ufrag?rcand->stream->ufrag:pctx->peer_ufrag;
|
||||
rpwd=rcand->stream->pwd?rcand->stream->pwd:pctx->peer_pwd;
|
||||
if (!rufrag || !rpwd)
|
||||
ABORT(R_BAD_DATA);
|
||||
|
||||
/* Compute the RTO per S 16 */
|
||||
RTO = MAX(100, (pctx->ctx->Ta * pctx->waiting_pairs));
|
||||
|
||||
@ -121,38 +107,27 @@ int nr_ice_candidate_pair_create(nr_ice_peer_ctx *pctx, nr_ice_candidate *lcand,
|
||||
t_priority = tmpcand.priority;
|
||||
|
||||
/* Our sending context */
|
||||
if(r=nr_concat_strings(&l2ruser,rufrag,":",lufrag,NULL))
|
||||
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)))
|
||||
if(!(pair->stun_client->params.ice_binding_request.username=r_strdup(rcand->stream->l2r_user)))
|
||||
ABORT(R_NO_MEMORY);
|
||||
if(r=r_data_make(&pair->stun_client->params.ice_binding_request.password,(UCHAR *)rpwd,strlen(rpwd)))
|
||||
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(ekr@rtfm.com): 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;
|
||||
|
||||
/* Our receiving username/passwords. Stash these for later
|
||||
injection into the stun server ctx*/
|
||||
if(r=nr_concat_strings(&pair->r2l_user,lufrag,":",rufrag,NULL))
|
||||
ABORT(r);
|
||||
if(!(r2lpass=r_strdup(lpwd)))
|
||||
ABORT(R_NO_MEMORY);
|
||||
INIT_DATA(pair->r2l_pwd,(UCHAR *)r2lpass,strlen(r2lpass));
|
||||
// Give up ownership of r2lpass
|
||||
r2lpass=0;
|
||||
|
||||
*pairp=pair;
|
||||
|
||||
_status=0;
|
||||
abort:
|
||||
RFREE(l2ruser);
|
||||
RFREE(r2lpass);
|
||||
if(_status){
|
||||
nr_ice_candidate_pair_destroy(&pair);
|
||||
}
|
||||
@ -178,9 +153,6 @@ int nr_ice_candidate_pair_destroy(nr_ice_cand_pair **pairp)
|
||||
nr_stun_client_ctx_destroy(&pair->stun_client);
|
||||
}
|
||||
|
||||
RFREE(pair->r2l_user);
|
||||
RFREE(pair->r2l_pwd.data);
|
||||
|
||||
NR_async_timer_cancel(pair->stun_cb_timer);
|
||||
NR_async_timer_cancel(pair->restart_controlled_cb_timer);
|
||||
NR_async_timer_cancel(pair->restart_nominated_cb_timer);
|
||||
@ -559,7 +531,6 @@ void nr_ice_candidate_pair_restart_stun_nominated_cb(NR_SOCKET s, int how, void
|
||||
r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/STREAM(%s):%d: Restarting pair %s as nominated",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_CONTROLLING;
|
||||
|
||||
if(r=nr_stun_client_start(pair->stun_client,NR_ICE_CLIENT_MODE_USE_CANDIDATE,nr_ice_candidate_pair_stun_cb,pair))
|
||||
ABORT(r);
|
||||
|
@ -61,9 +61,6 @@ struct nr_ice_cand_pair_ {
|
||||
nr_ice_candidate *remote; /* The remote candidate */
|
||||
char *foundation; /* The combined foundations */
|
||||
|
||||
char *r2l_user; /* Stashed username */
|
||||
Data r2l_pwd; /* Stashed password */
|
||||
|
||||
nr_stun_client_ctx *stun_client; /* STUN context when acting as a client */
|
||||
void *stun_client_handle;
|
||||
|
||||
|
@ -46,6 +46,59 @@ static char *RCSSTRING __UNUSED__="$Id: ice_component.c,v 1.2 2008/04/28 17:59:0
|
||||
#include "nr_socket_turn.h"
|
||||
#include "ice_reg.h"
|
||||
|
||||
static int nr_ice_component_stun_server_default_cb(void *cb_arg,nr_stun_server_ctx *stun_ctx,nr_socket *sock, nr_stun_server_request *req, int *dont_free, int *error);
|
||||
static int nr_ice_pre_answer_request_destroy(nr_ice_pre_answer_request **parp);
|
||||
|
||||
/* This function takes ownership of the contents of req (but not req itself) */
|
||||
static int nr_ice_pre_answer_request_create(nr_socket *sock, nr_stun_server_request *req, nr_ice_pre_answer_request **parp)
|
||||
{
|
||||
int r, _status;
|
||||
nr_ice_pre_answer_request *par = 0;
|
||||
nr_stun_message_attribute *attr;
|
||||
|
||||
if (!(par = RCALLOC(sizeof(nr_ice_pre_answer_request))))
|
||||
ABORT(R_NO_MEMORY);
|
||||
|
||||
par->req = *req; /* Struct assignment */
|
||||
memset(req, 0, sizeof(*req)); /* Zero contents to avoid confusion */
|
||||
|
||||
if (r=nr_socket_getaddr(sock, &par->local_addr))
|
||||
ABORT(r);
|
||||
if (!nr_stun_message_has_attribute(par->req.request, NR_STUN_ATTR_USERNAME, &attr))
|
||||
ABORT(R_INTERNAL);
|
||||
if (!(par->username = r_strdup(attr->u.username)))
|
||||
ABORT(R_NO_MEMORY);
|
||||
|
||||
*parp=par;
|
||||
_status=0;
|
||||
abort:
|
||||
if (_status) {
|
||||
/* Erase the request so we don't free it */
|
||||
memset(&par->req, 0, sizeof(nr_stun_server_request));
|
||||
nr_ice_pre_answer_request_destroy(&par);
|
||||
}
|
||||
|
||||
return(_status);
|
||||
}
|
||||
|
||||
static int nr_ice_pre_answer_request_destroy(nr_ice_pre_answer_request **parp)
|
||||
{
|
||||
nr_ice_pre_answer_request *par;
|
||||
|
||||
if (!parp || !*parp)
|
||||
return(0);
|
||||
|
||||
par = *parp;
|
||||
*parp = 0;
|
||||
|
||||
nr_stun_message_destroy(&par->req.request);
|
||||
nr_stun_message_destroy(&par->req.response);
|
||||
|
||||
RFREE(par->username);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int nr_ice_component_create(nr_ice_media_stream *stream, int component_id, nr_ice_component **componentp)
|
||||
{
|
||||
int _status;
|
||||
@ -54,13 +107,15 @@ int nr_ice_component_create(nr_ice_media_stream *stream, int component_id, nr_ic
|
||||
if(!(comp=RCALLOC(sizeof(nr_ice_component))))
|
||||
ABORT(R_NO_MEMORY);
|
||||
|
||||
comp->state=NR_ICE_COMPONENT_RUNNING;
|
||||
comp->state=NR_ICE_COMPONENT_UNPAIRED;
|
||||
comp->component_id=component_id;
|
||||
comp->stream=stream;
|
||||
comp->ctx=stream->ctx;
|
||||
|
||||
STAILQ_INIT(&comp->sockets);
|
||||
TAILQ_INIT(&comp->candidates);
|
||||
STAILQ_INIT(&comp->pre_answer_reqs);
|
||||
|
||||
STAILQ_INSERT_TAIL(&stream->components,comp,entry);
|
||||
|
||||
_status=0;
|
||||
@ -73,6 +128,7 @@ int nr_ice_component_destroy(nr_ice_component **componentp)
|
||||
nr_ice_component *component;
|
||||
nr_ice_socket *s1,*s2;
|
||||
nr_ice_candidate *c1,*c2;
|
||||
nr_ice_pre_answer_request *r1,*r2;
|
||||
|
||||
if(!componentp || !*componentp)
|
||||
return(0);
|
||||
@ -89,7 +145,6 @@ int nr_ice_component_destroy(nr_ice_component **componentp)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* candidates MUST be destroyed before the sockets so that
|
||||
they can deregister */
|
||||
TAILQ_FOREACH_SAFE(c1, &component->candidates, entry_comp, c2){
|
||||
@ -102,6 +157,11 @@ int nr_ice_component_destroy(nr_ice_component **componentp)
|
||||
nr_ice_socket_destroy(&s1);
|
||||
}
|
||||
|
||||
STAILQ_FOREACH_SAFE(r1, &component->pre_answer_reqs, entry, r2){
|
||||
STAILQ_REMOVE(&component->pre_answer_reqs,r1,nr_ice_pre_answer_request_, entry);
|
||||
nr_ice_pre_answer_request_destroy(&r1);
|
||||
}
|
||||
|
||||
if(component->keepalive_timer)
|
||||
NR_async_timer_cancel(component->keepalive_timer);
|
||||
nr_stun_client_ctx_destroy(&component->keepalive_ctx);
|
||||
@ -119,6 +179,9 @@ int nr_ice_component_initialize(struct nr_ice_ctx_ *ctx,nr_ice_component *compon
|
||||
nr_socket *sock;
|
||||
nr_ice_socket *isock=0;
|
||||
nr_ice_candidate *cand=0;
|
||||
char *lufrag;
|
||||
char *lpwd;
|
||||
Data pwd;
|
||||
int addr_ct;
|
||||
int i;
|
||||
int j;
|
||||
@ -221,6 +284,22 @@ int nr_ice_component_initialize(struct nr_ice_ctx_ *ctx,nr_ice_component *compon
|
||||
ABORT(r);
|
||||
if(r=nr_ice_socket_register_stun_server(isock,isock->stun_server,&isock->stun_server_handle))
|
||||
ABORT(r);
|
||||
/* Add the default STUN credentials so that we can respond before
|
||||
we hear about the peer. Note: we need to recompute these because
|
||||
we have not yet computed the values in the peer media stream.*/
|
||||
lufrag=component->stream->ufrag ? component->stream->ufrag : ctx->ufrag;
|
||||
assert(lufrag);
|
||||
if (!lufrag)
|
||||
ABORT(R_INTERNAL);
|
||||
lpwd=component->stream->pwd ? component->stream->pwd :ctx->pwd;
|
||||
assert(lpwd);
|
||||
if (!lpwd)
|
||||
ABORT(R_INTERNAL);
|
||||
|
||||
INIT_DATA(pwd, (UCHAR *)lpwd, strlen(lpwd));
|
||||
|
||||
if(r=nr_stun_server_add_default_client(isock->stun_server, lufrag, &pwd, nr_ice_component_stun_server_default_cb, component))
|
||||
ABORT(r);
|
||||
|
||||
STAILQ_INSERT_TAIL(&component->sockets,isock,entry);
|
||||
}
|
||||
@ -329,12 +408,10 @@ int nr_ice_component_prune_candidates(nr_ice_ctx *ctx, nr_ice_component *comp)
|
||||
}
|
||||
|
||||
/* Section 7.2.1 */
|
||||
static int nr_ice_component_stun_server_cb(void *cb_arg,nr_stun_server_ctx *stun_ctx,nr_socket *sock, nr_stun_server_request *req, int *error)
|
||||
static int nr_ice_component_process_incoming_check(nr_ice_component *comp, nr_transport_addr *local_addr, nr_stun_server_request *req, int *error)
|
||||
{
|
||||
nr_ice_component *comp=cb_arg;
|
||||
nr_ice_cand_pair *pair;
|
||||
nr_ice_candidate *pcand=0;
|
||||
nr_transport_addr local_addr;
|
||||
nr_stun_message *sreq=req->request;
|
||||
nr_stun_message_attribute *attr;
|
||||
int component_id_matched;
|
||||
@ -343,8 +420,6 @@ static int nr_ice_component_stun_server_cb(void *cb_arg,nr_stun_server_ctx *stun
|
||||
nr_ice_cand_pair *found_invalid=0;
|
||||
int r=0,_status;
|
||||
|
||||
assert(sock!=0);
|
||||
|
||||
r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/STREAM(%s)(%d): received request from %s",comp->stream->pctx->label,comp->stream->label,comp->component_id,req->src_addr.as_string);
|
||||
|
||||
/* Check for role conficts (7.2.1.1) */
|
||||
@ -389,13 +464,7 @@ static int nr_ice_component_stun_server_cb(void *cb_arg,nr_stun_server_ctx *stun
|
||||
}
|
||||
}
|
||||
|
||||
/* Find the candidate pair that this maps to */
|
||||
if(r=nr_socket_getaddr(sock,&local_addr)) {
|
||||
*error=500;
|
||||
ABORT(r);
|
||||
}
|
||||
|
||||
r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): This STUN request appears to map to local addr %s",comp->stream->pctx->label,local_addr.as_string);
|
||||
r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): This STUN request appears to map to local addr %s",comp->stream->pctx->label,local_addr->as_string);
|
||||
|
||||
pair=TAILQ_FIRST(&comp->stream->check_list);
|
||||
while(pair){
|
||||
@ -407,7 +476,7 @@ static int nr_ice_component_stun_server_cb(void *cb_arg,nr_stun_server_ctx *stun
|
||||
goto next_pair;
|
||||
component_id_matched = 1;
|
||||
|
||||
if(nr_transport_addr_cmp(&pair->local->base,&local_addr,NR_TRANSPORT_ADDR_CMP_MODE_ALL))
|
||||
if(nr_transport_addr_cmp(&pair->local->base,local_addr,NR_TRANSPORT_ADDR_CMP_MODE_ALL))
|
||||
goto next_pair;
|
||||
local_addr_matched=1;
|
||||
|
||||
@ -438,7 +507,7 @@ static int nr_ice_component_stun_server_cb(void *cb_arg,nr_stun_server_ctx *stun
|
||||
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))
|
||||
if(!nr_transport_addr_cmp(&cand->addr,local_addr,NR_TRANSPORT_ADDR_CMP_MODE_ALL))
|
||||
break;
|
||||
|
||||
cand=TAILQ_NEXT(cand,entry_comp);
|
||||
@ -447,7 +516,7 @@ static int nr_ice_component_stun_server_cb(void *cb_arg,nr_stun_server_ctx *stun
|
||||
/* 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);
|
||||
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);
|
||||
@ -536,6 +605,57 @@ static int nr_ice_component_stun_server_cb(void *cb_arg,nr_stun_server_ctx *stun
|
||||
return(_status);
|
||||
}
|
||||
|
||||
static int nr_ice_component_stun_server_cb(void *cb_arg,nr_stun_server_ctx *stun_ctx,nr_socket *sock, nr_stun_server_request *req, int *dont_free, int *error)
|
||||
{
|
||||
nr_ice_component *comp=cb_arg;
|
||||
nr_transport_addr local_addr;
|
||||
int r,_status;
|
||||
|
||||
/* Find the candidate pair that this maps to */
|
||||
if(r=nr_socket_getaddr(sock,&local_addr)) {
|
||||
*error=500;
|
||||
ABORT(r);
|
||||
}
|
||||
|
||||
if (r=nr_ice_component_process_incoming_check(comp, &local_addr, req, error))
|
||||
ABORT(r);
|
||||
|
||||
_status=0;
|
||||
abort:
|
||||
return(_status);
|
||||
}
|
||||
|
||||
int nr_ice_component_service_pre_answer_requests(nr_ice_peer_ctx *pctx, nr_ice_component *pcomp, char *username, int *serviced)
|
||||
{
|
||||
nr_ice_pre_answer_request *r1,*r2;
|
||||
nr_ice_component *comp = pcomp->local_component;
|
||||
int r,_status;
|
||||
|
||||
if (serviced)
|
||||
*serviced = 0;
|
||||
|
||||
r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/STREAM(%s)/comp(%d): looking for pre-answer requests",pctx->label,comp->stream->label,comp->component_id);
|
||||
|
||||
STAILQ_FOREACH_SAFE(r1, &comp->pre_answer_reqs, entry, r2) {
|
||||
if (!strcmp(r1->username, username)) {
|
||||
int error = 0;
|
||||
|
||||
r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/STREAM(%s)/comp(%d): found pre-answer request",pctx->label,comp->stream->label,comp->component_id);
|
||||
r = nr_ice_component_process_incoming_check(pcomp, &r1->local_addr, &r1->req, &error);
|
||||
if (r) {
|
||||
r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s)/STREAM(%s)/comp(%d): error processing pre-answer request. Would have returned %d",pctx->label,comp->stream->label,comp->component_id, error);
|
||||
}
|
||||
(*serviced)++;
|
||||
STAILQ_REMOVE(&comp->pre_answer_reqs,r1,nr_ice_pre_answer_request_, entry);
|
||||
nr_ice_pre_answer_request_destroy(&r1);
|
||||
}
|
||||
}
|
||||
|
||||
_status=0;
|
||||
abort:
|
||||
return(_status);
|
||||
}
|
||||
|
||||
int nr_ice_component_pair_candidates(nr_ice_peer_ctx *pctx, nr_ice_component *lcomp,nr_ice_component *pcomp)
|
||||
{
|
||||
nr_ice_candidate *lcand,*pcand;
|
||||
@ -603,21 +723,6 @@ int nr_ice_component_pair_candidates(nr_ice_peer_ctx *pctx, nr_ice_component *lc
|
||||
if(!pair)
|
||||
goto next_cand;
|
||||
|
||||
if (!was_paired) {
|
||||
/* Add the stun username/password pair from the last pair (any
|
||||
would do) to the stun contexts, but only if we haven't already
|
||||
done so (was_paired) */
|
||||
isock=STAILQ_FIRST(&lcomp->sockets);
|
||||
while(isock){
|
||||
if(r=nr_stun_server_add_client(isock->stun_server,pctx->label,
|
||||
pair->r2l_user,&pair->r2l_pwd,nr_ice_component_stun_server_cb,pcomp)) {
|
||||
ABORT(r);
|
||||
}
|
||||
|
||||
isock=STAILQ_NEXT(isock,entry);
|
||||
}
|
||||
}
|
||||
|
||||
next_cand:
|
||||
lcand=TAILQ_NEXT(lcand,entry_comp);
|
||||
}
|
||||
@ -628,13 +733,55 @@ int nr_ice_component_pair_candidates(nr_ice_peer_ctx *pctx, nr_ice_component *lc
|
||||
pcand->state = NR_ICE_CAND_PEER_CANDIDATE_PAIRED;
|
||||
|
||||
pcand=TAILQ_NEXT(pcand,entry_comp);
|
||||
|
||||
}
|
||||
|
||||
/* Now register the STUN server callback for this component.
|
||||
Note that this is a per-component CB so we only need to
|
||||
do this once.
|
||||
*/
|
||||
if (pcomp->state != NR_ICE_COMPONENT_RUNNING) {
|
||||
isock=STAILQ_FIRST(&lcomp->sockets);
|
||||
while(isock){
|
||||
if(r=nr_stun_server_add_client(isock->stun_server,pctx->label,
|
||||
pcomp->stream->r2l_user,&pcomp->stream->r2l_pass,nr_ice_component_stun_server_cb,pcomp)) {
|
||||
ABORT(r);
|
||||
}
|
||||
isock=STAILQ_NEXT(isock,entry);
|
||||
}
|
||||
}
|
||||
|
||||
pcomp->state = NR_ICE_COMPONENT_RUNNING;
|
||||
|
||||
_status=0;
|
||||
abort:
|
||||
return(_status);
|
||||
}
|
||||
|
||||
/* Fires when we have an incoming candidate that doesn't correspond to an existing
|
||||
remote peer. This is either pre-answer or just spurious. Store it in the
|
||||
component for use when we see the actual answer, at which point we need
|
||||
to do the procedures from S 7.2.1 in nr_ice_component_stun_server_cb.
|
||||
*/
|
||||
static int nr_ice_component_stun_server_default_cb(void *cb_arg,nr_stun_server_ctx *stun_ctx,nr_socket *sock, nr_stun_server_request *req, int *dont_free, int *error)
|
||||
{
|
||||
int r, _status;
|
||||
nr_ice_component *comp = (nr_ice_component *)cb_arg;
|
||||
nr_ice_pre_answer_request *par = 0;
|
||||
r_log(LOG_ICE,LOG_DEBUG,"ICE(%s)/STREAM(%s)/comp(%d): Received STUN request pre-answer from %s",
|
||||
comp->ctx->label, comp->stream->label, comp->component_id, req->src_addr.as_string);
|
||||
|
||||
if (r=nr_ice_pre_answer_request_create(sock, req, &par))
|
||||
ABORT(r);
|
||||
|
||||
*dont_free = 1;
|
||||
STAILQ_INSERT_TAIL(&comp->pre_answer_reqs, par, entry);
|
||||
|
||||
_status=0;
|
||||
abort:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nr_ice_component_nominated_pair(nr_ice_component *comp, nr_ice_cand_pair *pair)
|
||||
{
|
||||
int r,_status;
|
||||
|
@ -39,8 +39,19 @@ using namespace std;
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef struct nr_ice_pre_answer_request_ {
|
||||
nr_stun_server_request req;
|
||||
char *username;
|
||||
nr_transport_addr local_addr;
|
||||
|
||||
STAILQ_ENTRY(nr_ice_pre_answer_request_) entry;
|
||||
} nr_ice_pre_answer_request;
|
||||
|
||||
typedef STAILQ_HEAD(nr_ice_pre_answer_request_head_, nr_ice_pre_answer_request_) nr_ice_pre_answer_request_head;
|
||||
|
||||
struct nr_ice_component_ {
|
||||
int state;
|
||||
#define NR_ICE_COMPONENT_UNPAIRED 0
|
||||
#define NR_ICE_COMPONENT_RUNNING 1
|
||||
#define NR_ICE_COMPONENT_NOMINATED 2
|
||||
#define NR_ICE_COMPONENT_FAILED 3
|
||||
@ -52,6 +63,7 @@ struct nr_ice_component_ {
|
||||
nr_ice_socket_head sockets;
|
||||
nr_ice_candidate_head candidates;
|
||||
int candidate_ct;
|
||||
nr_ice_pre_answer_request_head pre_answer_reqs;
|
||||
|
||||
int valid_pairs;
|
||||
struct nr_ice_cand_pair_ *nominated; /* Highest priority nomninated pair */
|
||||
@ -71,6 +83,7 @@ int nr_ice_component_destroy(nr_ice_component **componentp);
|
||||
int nr_ice_component_initialize(struct nr_ice_ctx_ *ctx,nr_ice_component *component);
|
||||
int nr_ice_component_prune_candidates(nr_ice_ctx *ctx, nr_ice_component *comp);
|
||||
int nr_ice_component_pair_candidates(nr_ice_peer_ctx *pctx, nr_ice_component *lcomp,nr_ice_component *pcomp);
|
||||
int nr_ice_component_service_pre_answer_requests(nr_ice_peer_ctx *pctx, nr_ice_component *pcomp, char *username, int *serviced);
|
||||
int nr_ice_component_nominated_pair(nr_ice_component *comp, nr_ice_cand_pair *pair);
|
||||
int nr_ice_component_failed_pair(nr_ice_component *comp, nr_ice_cand_pair *pair);
|
||||
int nr_ice_component_select_pair(nr_ice_peer_ctx *pctx, nr_ice_component *comp);
|
||||
|
@ -39,6 +39,7 @@ static char *RCSSTRING __UNUSED__="$Id: ice_media_stream.c,v 1.2 2008/04/28 17:5
|
||||
#include <nr_api.h>
|
||||
#include <r_assoc.h>
|
||||
#include <async_timer.h>
|
||||
#include "ice_util.h"
|
||||
#include "ice_ctx.h"
|
||||
|
||||
static char *nr_ice_media_stream_states[]={"INVALID",
|
||||
@ -109,6 +110,10 @@ int nr_ice_media_stream_destroy(nr_ice_media_stream **streamp)
|
||||
|
||||
RFREE(stream->ufrag);
|
||||
RFREE(stream->pwd);
|
||||
RFREE(stream->r2l_user);
|
||||
RFREE(stream->l2r_user);
|
||||
r_data_zfree(&stream->r2l_pass);
|
||||
r_data_zfree(&stream->l2r_pass);
|
||||
|
||||
if(stream->timer)
|
||||
NR_async_timer_cancel(stream->timer);
|
||||
@ -277,8 +282,7 @@ int nr_ice_media_stream_pair_candidates(nr_ice_peer_ctx *pctx,nr_ice_media_strea
|
||||
};
|
||||
|
||||
if (pstream->ice_state == NR_ICE_MEDIA_STREAM_UNPAIRED) {
|
||||
r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): unfreezing stream %s",pstream->pctx->label,pstream->label);
|
||||
pstream->ice_state = NR_ICE_MEDIA_STREAM_CHECKS_FROZEN;
|
||||
nr_ice_media_stream_set_state(pstream, NR_ICE_MEDIA_STREAM_CHECKS_FROZEN);
|
||||
}
|
||||
|
||||
_status=0;
|
||||
@ -286,6 +290,35 @@ int nr_ice_media_stream_pair_candidates(nr_ice_peer_ctx *pctx,nr_ice_media_strea
|
||||
return(_status);
|
||||
}
|
||||
|
||||
int nr_ice_media_stream_service_pre_answer_requests(nr_ice_peer_ctx *pctx, nr_ice_media_stream *lstream, nr_ice_media_stream *pstream, int *serviced)
|
||||
{
|
||||
nr_ice_component *pcomp;
|
||||
int r,_status;
|
||||
char *user = 0;
|
||||
char *lufrag, *rufrag;
|
||||
|
||||
if (serviced)
|
||||
*serviced = 0;
|
||||
|
||||
pcomp=STAILQ_FIRST(&pstream->components);
|
||||
while(pcomp){
|
||||
int serviced_inner=0;
|
||||
|
||||
/* Flush all the pre-answer requests */
|
||||
if(r=nr_ice_component_service_pre_answer_requests(pctx, pcomp, pstream->r2l_user, &serviced_inner))
|
||||
ABORT(r);
|
||||
if (serviced)
|
||||
*serviced += serviced_inner;
|
||||
|
||||
pcomp=STAILQ_NEXT(pcomp,entry);
|
||||
}
|
||||
|
||||
_status=0;
|
||||
abort:
|
||||
RFREE(user);
|
||||
return(_status);
|
||||
}
|
||||
|
||||
/* S 5.8 -- run the highest priority WAITING pair or if not available
|
||||
FROZEN pair */
|
||||
static void nr_ice_media_stream_check_timer_cb(NR_SOCKET s, int h, void *cb_arg)
|
||||
|
@ -50,7 +50,10 @@ struct nr_ice_media_stream_ {
|
||||
|
||||
char *ufrag; /* ICE username */
|
||||
char *pwd; /* ICE password */
|
||||
|
||||
char *r2l_user; /* The username for incoming requests */
|
||||
char *l2r_user; /* The username for outgoing requests */
|
||||
Data r2l_pass; /* The password for incoming requests */
|
||||
Data l2r_pass; /* The password for outcoming requests */
|
||||
int ice_state;
|
||||
|
||||
#define NR_ICE_MEDIA_STREAM_UNPAIRED 1
|
||||
@ -77,6 +80,7 @@ int nr_ice_media_stream_get_attributes(nr_ice_media_stream *stream, char ***attr
|
||||
int nr_ice_media_stream_get_default_candidate(nr_ice_media_stream *stream, int component, nr_ice_candidate **candp);
|
||||
int nr_ice_media_stream_pair_candidates(nr_ice_peer_ctx *pctx,nr_ice_media_stream *lstream,nr_ice_media_stream *pstream);
|
||||
int nr_ice_media_stream_start_checks(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream);
|
||||
int nr_ice_media_stream_service_pre_answer_requests(nr_ice_peer_ctx *pctx,nr_ice_media_stream *lstream,nr_ice_media_stream *pstream, int *serviced);
|
||||
int nr_ice_media_stream_unfreeze_pairs(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream);
|
||||
int nr_ice_media_stream_unfreeze_pairs_foundation(nr_ice_media_stream *stream, char *foundation);
|
||||
int nr_ice_media_stream_dump_state(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream,FILE *out);
|
||||
|
@ -39,6 +39,8 @@ static char *RCSSTRING __UNUSED__="$Id: ice_peer_ctx.c,v 1.2 2008/04/28 17:59:01
|
||||
#include <nr_api.h>
|
||||
#include "ice_ctx.h"
|
||||
#include "ice_peer_ctx.h"
|
||||
#include "ice_media_stream.h"
|
||||
#include "ice_util.h"
|
||||
#include "nr_crypto.h"
|
||||
#include "async_timer.h"
|
||||
|
||||
@ -98,6 +100,8 @@ int nr_ice_peer_ctx_parse_stream_attributes(nr_ice_peer_ctx *pctx, nr_ice_media_
|
||||
{
|
||||
nr_ice_media_stream *pstream=0;
|
||||
nr_ice_component *comp,*comp2;
|
||||
char *lufrag,*rufrag;
|
||||
char *lpwd,*rpwd;
|
||||
int r,_status;
|
||||
|
||||
/*
|
||||
@ -122,6 +126,25 @@ int nr_ice_peer_ctx_parse_stream_attributes(nr_ice_peer_ctx *pctx, nr_ice_media_
|
||||
if (r=nr_ice_peer_ctx_parse_stream_attributes_int(pctx,stream,pstream,attrs,attr_ct))
|
||||
ABORT(r);
|
||||
|
||||
/* Now that we have the ufrag and password, compute all the username/password
|
||||
pairs */
|
||||
lufrag=stream->ufrag?stream->ufrag:pctx->ctx->ufrag;
|
||||
lpwd=stream->pwd?stream->pwd:pctx->ctx->pwd;
|
||||
assert(lufrag);
|
||||
assert(lpwd);
|
||||
rufrag=pstream->ufrag?pstream->ufrag:pctx->peer_ufrag;
|
||||
rpwd=pstream->pwd?pstream->pwd:pctx->peer_pwd;
|
||||
if (!rufrag || !rpwd)
|
||||
ABORT(R_BAD_DATA);
|
||||
|
||||
if(r=nr_concat_strings(&pstream->r2l_user,lufrag,":",rufrag,NULL))
|
||||
ABORT(r);
|
||||
if(r=nr_concat_strings(&pstream->l2r_user,rufrag,":",lufrag,NULL))
|
||||
ABORT(r);
|
||||
if(r=r_data_make(&pstream->r2l_pass, (UCHAR *)lpwd, strlen(lpwd)))
|
||||
ABORT(r);
|
||||
if(r=r_data_make(&pstream->l2r_pass, (UCHAR *)rpwd, strlen(rpwd)))
|
||||
ABORT(r);
|
||||
|
||||
STAILQ_INSERT_TAIL(&pctx->peer_streams,pstream,entry);
|
||||
|
||||
@ -207,6 +230,8 @@ int nr_ice_peer_ctx_parse_trickle_candidate(nr_ice_peer_ctx *pctx, nr_ice_media_
|
||||
int r,_status;
|
||||
int needs_pairing = 0;
|
||||
|
||||
r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) parsing trickle ICE candidate %s",pctx->ctx->label,pctx->label,candidate);
|
||||
|
||||
pstream=STAILQ_FIRST(&pctx->peer_streams);
|
||||
while(pstream) {
|
||||
if (pstream->local_stream == stream)
|
||||
@ -279,6 +304,9 @@ int nr_ice_peer_ctx_pair_candidates(nr_ice_peer_ctx *pctx)
|
||||
nr_ice_media_stream *stream;
|
||||
int r,_status;
|
||||
|
||||
|
||||
r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) pairing candidates",pctx->ctx->label,pctx->label);
|
||||
|
||||
if(STAILQ_EMPTY(&pctx->peer_streams)) {
|
||||
r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) received no media stream attribributes",pctx->ctx->label,pctx->label);
|
||||
ABORT(R_FAILED);
|
||||
@ -356,6 +384,7 @@ int nr_ice_peer_ctx_start_checks2(nr_ice_peer_ctx *pctx, int allow_non_first)
|
||||
{
|
||||
int r,_status;
|
||||
nr_ice_media_stream *stream;
|
||||
int started = 0;
|
||||
|
||||
stream=STAILQ_FIRST(&pctx->peer_streams);
|
||||
if(!stream)
|
||||
@ -366,6 +395,16 @@ int nr_ice_peer_ctx_start_checks2(nr_ice_peer_ctx *pctx, int allow_non_first)
|
||||
break;
|
||||
|
||||
if(!allow_non_first){
|
||||
/* This test applies if:
|
||||
|
||||
1. allow_non_first is 0 (i.e., non-trickle ICE)
|
||||
2. the first stream has an empty check list.
|
||||
|
||||
But in the non-trickle ICE case, the other side should have provided
|
||||
some candidates or ICE is pretty much not going to work and we're
|
||||
just going to fail. Hence R_FAILED as opposed to R_NOT_FOUND and
|
||||
immediate termination here.
|
||||
*/
|
||||
r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) first stream has empty check list",pctx->ctx->label,pctx->label);
|
||||
ABORT(R_FAILED);
|
||||
}
|
||||
@ -374,15 +413,36 @@ int nr_ice_peer_ctx_start_checks2(nr_ice_peer_ctx *pctx, int allow_non_first)
|
||||
}
|
||||
|
||||
if (!stream) {
|
||||
r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) no streams with non-empty check lists",pctx->ctx->label,pctx->label);
|
||||
ABORT(R_NOT_FOUND);
|
||||
r_log(LOG_ICE,LOG_NOTICE,"ICE(%s): peer (%s) no streams with non-empty check lists",pctx->ctx->label,pctx->label);
|
||||
}
|
||||
|
||||
if (stream->ice_state == NR_ICE_MEDIA_STREAM_CHECKS_FROZEN) {
|
||||
else if (stream->ice_state == NR_ICE_MEDIA_STREAM_CHECKS_FROZEN) {
|
||||
if(r=nr_ice_media_stream_unfreeze_pairs(pctx,stream))
|
||||
ABORT(r);
|
||||
if(r=nr_ice_media_stream_start_checks(pctx,stream))
|
||||
ABORT(r);
|
||||
++started;
|
||||
}
|
||||
|
||||
stream=STAILQ_FIRST(&pctx->peer_streams);
|
||||
while (stream) {
|
||||
int serviced = 0;
|
||||
if (r=nr_ice_media_stream_service_pre_answer_requests(pctx, stream->local_stream, stream, &serviced))
|
||||
ABORT(r);
|
||||
|
||||
if (serviced) {
|
||||
++started;
|
||||
}
|
||||
else {
|
||||
r_log(LOG_ICE,LOG_NOTICE,"ICE(%s): peer (%s) no streams with pre-answer requests",pctx->ctx->label,pctx->label);
|
||||
}
|
||||
|
||||
|
||||
stream=STAILQ_NEXT(stream, entry);
|
||||
}
|
||||
|
||||
if (!started) {
|
||||
r_log(LOG_ICE,LOG_NOTICE,"ICE(%s): peer (%s) no checks to start",pctx->ctx->label,pctx->label);
|
||||
ABORT(R_NOT_FOUND);
|
||||
}
|
||||
|
||||
_status=0;
|
||||
|
@ -239,6 +239,9 @@ nr_stun_build_use_candidate(nr_stun_client_ice_use_candidate_params *params, nr_
|
||||
if ((r=nr_stun_message_add_priority_attribute(req, params->priority)))
|
||||
ABORT(r);
|
||||
|
||||
if ((r=nr_stun_message_add_ice_controlling_attribute(req, params->tiebreaker)))
|
||||
ABORT(r);
|
||||
|
||||
*msg = req;
|
||||
|
||||
_status=0;
|
||||
@ -274,6 +277,9 @@ nr_stun_build_req_ice(nr_stun_client_ice_binding_request_params *params, nr_stun
|
||||
if ((r=nr_stun_message_add_ice_controlled_attribute(req, params->tiebreaker)))
|
||||
ABORT(r);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
ABORT(R_INTERNAL);
|
||||
}
|
||||
|
||||
*msg = req;
|
||||
|
@ -79,6 +79,7 @@ typedef struct nr_stun_client_ice_use_candidate_params_ {
|
||||
char *username;
|
||||
Data password;
|
||||
UINT4 priority;
|
||||
UINT8 tiebreaker;
|
||||
} nr_stun_client_ice_use_candidate_params;
|
||||
|
||||
int nr_stun_build_use_candidate(nr_stun_client_ice_use_candidate_params *params, nr_stun_message **msg);
|
||||
|
@ -84,17 +84,18 @@ int nr_stun_server_ctx_destroy(nr_stun_server_ctx **ctxp)
|
||||
nr_stun_server_destroy_client(clnt1);
|
||||
}
|
||||
|
||||
nr_stun_server_destroy_client(ctx->default_client);
|
||||
|
||||
RFREE(ctx->label);
|
||||
RFREE(ctx);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int nr_stun_server_add_client(nr_stun_server_ctx *ctx, char *client_label, char *user, Data *pass, int (*stun_server_cb)(void *cb_arg, nr_stun_server_ctx *ctx,nr_socket *sock, nr_stun_server_request *req, int *error), void *cb_arg)
|
||||
static int nr_stun_server_client_create(nr_stun_server_ctx *ctx, char *client_label, char *user, Data *pass, nr_stun_server_cb cb, void *cb_arg, nr_stun_server_client **clntp)
|
||||
{
|
||||
int r,_status;
|
||||
|
||||
nr_stun_server_client *clnt=0;
|
||||
int r,_status;
|
||||
|
||||
if(!(clnt=RCALLOC(sizeof(nr_stun_server_client))))
|
||||
ABORT(R_NO_MEMORY);
|
||||
@ -108,16 +109,49 @@ int nr_stun_server_add_client(nr_stun_server_ctx *ctx, char *client_label, char
|
||||
if(r=r_data_copy(&clnt->password,pass))
|
||||
ABORT(r);
|
||||
|
||||
clnt->stun_server_cb=stun_server_cb;
|
||||
clnt->stun_server_cb=cb;
|
||||
clnt->cb_arg=cb_arg;
|
||||
|
||||
*clntp = clnt;
|
||||
_status=0;
|
||||
abort:
|
||||
if(_status){
|
||||
nr_stun_server_destroy_client(clnt);
|
||||
}
|
||||
return(_status);
|
||||
}
|
||||
|
||||
int nr_stun_server_add_client(nr_stun_server_ctx *ctx, char *client_label, char *user, Data *pass, nr_stun_server_cb cb, void *cb_arg)
|
||||
{
|
||||
int r,_status;
|
||||
nr_stun_server_client *clnt;
|
||||
|
||||
if (r=nr_stun_server_client_create(ctx, client_label, user, pass, cb, cb_arg, &clnt))
|
||||
ABORT(r);
|
||||
|
||||
STAILQ_INSERT_TAIL(&ctx->clients,clnt,entry);
|
||||
|
||||
_status=0;
|
||||
abort:
|
||||
if(_status){
|
||||
nr_stun_server_destroy_client(clnt);
|
||||
}
|
||||
return(_status);
|
||||
}
|
||||
|
||||
int nr_stun_server_add_default_client(nr_stun_server_ctx *ctx, char *ufrag, Data *pass, nr_stun_server_cb cb, void *cb_arg)
|
||||
{
|
||||
int r,_status;
|
||||
nr_stun_server_client *clnt;
|
||||
|
||||
assert(!ctx->default_client);
|
||||
if (ctx->default_client)
|
||||
ABORT(R_INTERNAL);
|
||||
|
||||
if (r=nr_stun_server_client_create(ctx, "default_client", ufrag, pass, cb, cb_arg, &clnt))
|
||||
ABORT(r);
|
||||
|
||||
ctx->default_client = clnt;
|
||||
|
||||
_status=0;
|
||||
abort:
|
||||
return(_status);
|
||||
}
|
||||
|
||||
@ -200,6 +234,7 @@ int nr_stun_server_process_request(nr_stun_server_ctx *ctx, nr_socket *sock, cha
|
||||
nr_stun_server_client *clnt = 0;
|
||||
nr_stun_server_request info;
|
||||
int error;
|
||||
int dont_free;
|
||||
|
||||
r_log(NR_LOG_STUN,LOG_DEBUG,"STUN-SERVER(%s): Received(my_addr=%s,peer_addr=%s)",ctx->label,ctx->my_addr.as_string,peer_addr->as_string);
|
||||
|
||||
@ -291,7 +326,8 @@ int nr_stun_server_process_request(nr_stun_server_ctx *ctx, nr_socket *sock, cha
|
||||
info.response = res;
|
||||
|
||||
error = 0;
|
||||
if (clnt->stun_server_cb(clnt->cb_arg,ctx,sock,&info,&error)) {
|
||||
dont_free = 0;
|
||||
if (clnt->stun_server_cb(clnt->cb_arg,ctx,sock,&info,&dont_free,&error)) {
|
||||
if (error == 0)
|
||||
error = 500;
|
||||
|
||||
@ -335,8 +371,10 @@ int nr_stun_server_process_request(nr_stun_server_ctx *ctx, nr_socket *sock, cha
|
||||
_status = 0;
|
||||
}
|
||||
|
||||
nr_stun_message_destroy(&res);
|
||||
nr_stun_message_destroy(&req);
|
||||
if (!dont_free) {
|
||||
nr_stun_message_destroy(&res);
|
||||
nr_stun_message_destroy(&req);
|
||||
}
|
||||
|
||||
return(_status);
|
||||
}
|
||||
@ -375,6 +413,9 @@ static int nr_stun_server_send_response(nr_stun_server_ctx *ctx, nr_socket *sock
|
||||
|
||||
static int nr_stun_server_destroy_client(nr_stun_server_client *clnt)
|
||||
{
|
||||
if (!clnt)
|
||||
return 0;
|
||||
|
||||
RFREE(clnt->label);
|
||||
RFREE(clnt->username);
|
||||
r_data_zfree(&clnt->password);
|
||||
@ -399,6 +440,20 @@ int nr_stun_get_message_client(nr_stun_server_ctx *ctx, nr_stun_message *req, nr
|
||||
sizeof(attr->u.username)))
|
||||
break;
|
||||
}
|
||||
|
||||
if (!clnt && ctx->default_client) {
|
||||
/* If we can't find a specific client see if this matches the default,
|
||||
which means that the username starts with our ufrag.
|
||||
*/
|
||||
char *colon = strchr(attr->u.username, ':');
|
||||
if (colon && !strncmp(ctx->default_client->username,
|
||||
attr->u.username,
|
||||
colon - attr->u.username)) {
|
||||
clnt = ctx->default_client;
|
||||
r_log(NR_LOG_STUN,LOG_DEBUG,"STUN-SERVER(%s): Falling back to default client, username=: %s",ctx->label,attr->u.username);
|
||||
}
|
||||
}
|
||||
|
||||
if (!clnt) {
|
||||
r_log(NR_LOG_STUN,LOG_NOTICE,"STUN-SERVER(%s): Request from unknown user: %s",ctx->label,attr->u.username);
|
||||
ABORT(R_NOT_FOUND);
|
||||
|
@ -47,11 +47,13 @@ typedef struct nr_stun_server_request_{
|
||||
nr_stun_message *response;
|
||||
} nr_stun_server_request;
|
||||
|
||||
typedef int (*nr_stun_server_cb)(void *cb_arg, struct nr_stun_server_ctx_ *ctx,nr_socket *sock,nr_stun_server_request *req, int *dont_free, int *error);
|
||||
|
||||
struct nr_stun_server_client_ {
|
||||
char *label;
|
||||
char *username;
|
||||
Data password;
|
||||
int (*stun_server_cb)(void *cb_arg, nr_stun_server_ctx *ctx,nr_socket *sock, nr_stun_server_request *req, int *error);
|
||||
nr_stun_server_cb stun_server_cb;
|
||||
void *cb_arg;
|
||||
char nonce[NR_STUN_MAX_NONCE_BYTES+1]; /* +1 for \0 */
|
||||
STAILQ_ENTRY(nr_stun_server_client_) entry;
|
||||
@ -64,13 +66,15 @@ struct nr_stun_server_ctx_ {
|
||||
nr_socket *sock;
|
||||
nr_transport_addr my_addr;
|
||||
nr_stun_server_client_head clients;
|
||||
nr_stun_server_client *default_client;
|
||||
};
|
||||
|
||||
|
||||
int nr_stun_server_ctx_create(char *label, nr_socket *sock, nr_stun_server_ctx **ctxp);
|
||||
int nr_stun_server_ctx_destroy(nr_stun_server_ctx **ctxp);
|
||||
int nr_stun_server_add_client(nr_stun_server_ctx *ctx, char *client_label, char *user, Data *pass, int (*stun_server_cb)(void *cb_arg, nr_stun_server_ctx *ctx,nr_socket *sock,nr_stun_server_request *req, int *error), void *cb_arg);
|
||||
int nr_stun_server_add_client(nr_stun_server_ctx *ctx, char *client_label, char *user, Data *pass, nr_stun_server_cb cb, void *cb_arg);
|
||||
int nr_stun_server_remove_client(nr_stun_server_ctx *ctx, void *cb_arg);
|
||||
int nr_stun_server_add_default_client(nr_stun_server_ctx *ctx, char *ufrag, Data *pass, nr_stun_server_cb cb, void *cb_arg);
|
||||
int nr_stun_server_process_request(nr_stun_server_ctx *ctx, nr_socket *sock, char *msg, int len, nr_transport_addr *peer_addr, int auth_rule);
|
||||
int nr_stun_get_message_client(nr_stun_server_ctx *ctx, nr_stun_message *req, nr_stun_server_client **clnt);
|
||||
|
||||
|
@ -2283,12 +2283,15 @@ TEST_F(SignalingTest, missingUfrag)
|
||||
// FSM. This may change in the future.
|
||||
a1_.CreateOffer(constraints, OFFER_AV, SHOULD_SENDRECV_AV);
|
||||
a1_.SetLocal(TestObserver::OFFER, offer, true);
|
||||
// Really we should detect failure at the SetRemote point,
|
||||
// since without a ufrag, we aren't going to be successful.
|
||||
// But for now, this isn't detected till SIPCC tries to impose
|
||||
// the parameters on the ICE stack in SetLocal. Bug 892161.
|
||||
a2_.SetRemote(TestObserver::OFFER, offer, true);
|
||||
a2_.CreateAnswer(constraints, offer, OFFER_AV | ANSWER_AV);
|
||||
a2_.SetLocal(TestObserver::ANSWER, a2_.answer(), true);
|
||||
a1_.SetRemote(TestObserver::ANSWER, a2_.answer(), true);
|
||||
// We don't check anything in particular for success here -- simply not
|
||||
// crashing by now is enough to declare success.
|
||||
a2_.SetLocal(TestObserver::ANSWER, a2_.answer(),
|
||||
true, sipcc::PeerConnectionImpl::kSignalingHaveRemoteOffer);
|
||||
// Since things have now failed, just stop.
|
||||
}
|
||||
|
||||
} // End namespace test.
|
||||
|
Loading…
Reference in New Issue
Block a user