Bug 909179 - Add ability to disable ICE components r=abr

This commit is contained in:
EKR 2013-08-25 19:35:21 -07:00
parent 1073f298a1
commit a4d6a811cc
9 changed files with 197 additions and 26 deletions

View File

@ -197,6 +197,7 @@ nsresult NrIceMediaStream::ParseTrickleCandidate(const std::string& candidate) {
return NS_OK;
}
// Returns NS_ERROR_NOT_AVAILABLE if component is unpaired or disabled.
nsresult NrIceMediaStream::GetActivePair(int component,
NrIceCandidate **localp,
NrIceCandidate **remotep) {
@ -208,6 +209,10 @@ nsresult NrIceMediaStream::GetActivePair(int component,
stream_,
component,
&local_int, &remote_int);
// If result is R_REJECTED then component is unpaired or disabled.
if (r == R_REJECTED)
return NS_ERROR_NOT_AVAILABLE;
if (r)
return NS_ERROR_FAILURE;
@ -304,6 +309,21 @@ std::vector<std::string> NrIceMediaStream::GetCandidates() const {
return ret;
}
nsresult NrIceMediaStream::DisableComponent(int component_id) {
if (!stream_)
return NS_ERROR_FAILURE;
int r = nr_ice_media_stream_disable_component(stream_,
component_id);
if (r) {
MOZ_MTLOG(ML_ERROR, "Couldn't disable '" << name_ << "':" <<
component_id);
return NS_ERROR_FAILURE;
}
return NS_OK;
}
nsresult NrIceMediaStream::SendPacket(int component_id,
const unsigned char *data,
size_t len) {

View File

@ -104,6 +104,9 @@ class NrIceMediaStream {
// Parse trickle ICE candidate
nsresult ParseTrickleCandidate(const std::string& candidate);
// Disable a component
nsresult DisableComponent(int component);
// Get the candidate pair currently active. It's the
// caller's responsibility to free these.
nsresult GetActivePair(int component,

View File

@ -168,10 +168,16 @@ class IceTestPeer : public sigslot::has_slots<> {
return ice_ctx_->GetGlobalAttributes();
}
std::vector<std::string> GetCandidates(const std::string &name) {
std::vector<std::string> candidates_in = candidates_[name];
std::vector<std::string> GetCandidates(size_t stream) {
std::vector<std::string> candidates;
if (stream >= streams_.size())
return candidates;
std::vector<std::string> candidates_in =
streams_[stream]->GetCandidates();
for (size_t i=0; i < candidates_in.size(); i++) {
if ((!candidate_filter_) || candidate_filter_(candidates_in[i])) {
std::cerr << "Returning candidate: " << candidates_in[i] << std::endl;
@ -213,7 +219,7 @@ class IceTestPeer : public sigslot::has_slots<> {
for (size_t i=0; i<streams_.size(); ++i) {
test_utils->sts_target()->Dispatch(
WrapRunnableRet(streams_[i], &NrIceMediaStream::ParseAttributes,
remote->GetCandidates(remote->streams_[i]->name()),
remote->GetCandidates(i),
&res), NS_DISPATCH_SYNC);
ASSERT_TRUE(NS_SUCCEEDED(res));
@ -249,7 +255,7 @@ class IceTestPeer : public sigslot::has_slots<> {
ASSERT_GT(remote_->streams_.size(), stream);
std::vector<std::string> candidates =
remote_->GetCandidates(remote_->streams_[stream]->name());
remote_->GetCandidates(stream);
for (size_t j=0; j<candidates.size(); j++) {
test_utils->sts_target()->Dispatch(
@ -302,13 +308,17 @@ class IceTestPeer : public sigslot::has_slots<> {
NrIceCandidate *remote;
nsresult res = streams_[i]->GetActivePair(j+1, &local, &remote);
ASSERT_TRUE(NS_SUCCEEDED(res));
DumpCandidate("Local ", *local);
ASSERT_EQ(expected_local_type_, local->type);
DumpCandidate("Remote ", *remote);
ASSERT_EQ(expected_remote_type_, remote->type);
delete local;
delete remote;
if (res == NS_ERROR_NOT_AVAILABLE) {
std::cerr << "Component unpaired or disabled." << std::endl;
} else {
ASSERT_TRUE(NS_SUCCEEDED(res));
DumpCandidate("Local ", *local);
ASSERT_EQ(expected_local_type_, local->type);
DumpCandidate("Remote ", *remote);
ASSERT_EQ(expected_remote_type_, remote->type);
delete local;
delete remote;
}
}
}
}
@ -379,6 +389,12 @@ class IceTestPeer : public sigslot::has_slots<> {
streams_[i]->ParseAttributes(attributes);
}
void DisableComponent(int stream, int component_id) {
ASSERT_LT(stream, streams_.size());
nsresult res = streams_[stream]->DisableComponent(component_id);
ASSERT_TRUE(NS_SUCCEEDED(res));
}
private:
std::string name_;
nsRefPtr<NrIceCtx> ice_ctx_;
@ -661,6 +677,21 @@ TEST_F(IceGatherTest, TestGatherTurn) {
Gather();
}
TEST_F(IceGatherTest, TestGatherDisableComponent) {
peer_->SetStunServer(kDefaultStunServerHostname, kDefaultStunServerPort);
peer_->AddStream(2);
peer_->DisableComponent(1, 2);
Gather();
std::vector<std::string> candidates =
peer_->GetCandidates(1);
for (size_t i=0; i<candidates.size(); ++i) {
size_t sp1 = candidates[i].find(' ');
ASSERT_EQ(0, candidates[i].compare(sp1+1, 1, "1", 1));
}
}
// Verify that a bogus candidate doesn't cause crashes on the
// main thread. See bug 856433.
TEST_F(IceGatherTest, TestBogusCandidate) {
@ -686,6 +717,21 @@ TEST_F(IceConnectTest, TestConnect) {
Connect();
}
TEST_F(IceConnectTest, TestConnectTwoComponents) {
AddStream("first", 2);
ASSERT_TRUE(Gather(true));
Connect();
}
TEST_F(IceConnectTest, TestConnectTwoComponentsDisableSecond) {
AddStream("first", 2);
ASSERT_TRUE(Gather(true));
p1_->DisableComponent(0, 2);
p2_->DisableComponent(0, 2);
Connect();
}
TEST_F(IceConnectTest, TestConnectP2ThenP1) {
AddStream("first", 1);
ASSERT_TRUE(Gather(true));

View File

@ -415,6 +415,9 @@ static int nr_ice_component_process_incoming_check(nr_ice_component *comp, nr_tr
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);
if (comp->state == NR_ICE_COMPONENT_DISABLED)
ABORT(R_REJECTED);
/* Check for role conficts (7.2.1.1) */
if(comp->stream->pctx->controlling){
if(nr_stun_message_has_attribute(sreq,NR_STUN_ATTR_ICE_CONTROLLING,&attr)){

View File

@ -55,6 +55,7 @@ struct nr_ice_component_ {
#define NR_ICE_COMPONENT_RUNNING 1
#define NR_ICE_COMPONENT_NOMINATED 2
#define NR_ICE_COMPONENT_FAILED 3
#define NR_ICE_COMPONENT_DISABLED 4
struct nr_ice_ctx_ *ctx;
struct nr_ice_media_stream_ *stream;
nr_ice_component *local_component;

View File

@ -155,10 +155,12 @@ int nr_ice_media_stream_get_attributes(nr_ice_media_stream *stream, char ***attr
/* First find out how many attributes we need */
comp=STAILQ_FIRST(&stream->components);
while(comp){
if(r=nr_ice_component_prune_candidates(stream->ctx,comp))
ABORT(r);
if (comp->state != NR_ICE_COMPONENT_DISABLED) {
if(r=nr_ice_component_prune_candidates(stream->ctx,comp))
ABORT(r);
attrct+=comp->candidate_ct;
attrct+=comp->candidate_ct;
}
comp=STAILQ_NEXT(comp,entry);
}
@ -180,18 +182,20 @@ int nr_ice_media_stream_get_attributes(nr_ice_media_stream *stream, char ***attr
/* Now format the attributes */
comp=STAILQ_FIRST(&stream->components);
while(comp){
nr_ice_candidate *cand;
if (comp->state != NR_ICE_COMPONENT_DISABLED) {
nr_ice_candidate *cand;
cand=TAILQ_FIRST(&comp->candidates);
while(cand){
assert(index < attrct);
cand=TAILQ_FIRST(&comp->candidates);
while(cand){
assert(index < attrct);
if(r=nr_ice_format_candidate_attribute(cand, attrs[index],MAX_ATTRIBUTE_SIZE))
ABORT(r);
if(r=nr_ice_format_candidate_attribute(cand, attrs[index],MAX_ATTRIBUTE_SIZE))
ABORT(r);
index++;
index++;
cand=TAILQ_NEXT(cand,entry_comp);
cand=TAILQ_NEXT(cand,entry_comp);
}
}
comp=STAILQ_NEXT(comp,entry);
}
@ -274,8 +278,11 @@ int nr_ice_media_stream_pair_candidates(nr_ice_peer_ctx *pctx,nr_ice_media_strea
pcomp=STAILQ_FIRST(&pstream->components);
lcomp=STAILQ_FIRST(&lstream->components);
while(pcomp){
if(r=nr_ice_component_pair_candidates(pctx,lcomp,pcomp))
ABORT(r);
if ((lcomp->state != NR_ICE_COMPONENT_DISABLED) &&
(pcomp->state != NR_ICE_COMPONENT_DISABLED)) {
if(r=nr_ice_component_pair_candidates(pctx,lcomp,pcomp))
ABORT(r);
}
lcomp=STAILQ_NEXT(lcomp,entry);
pcomp=STAILQ_NEXT(pcomp,entry);
@ -567,7 +574,9 @@ int nr_ice_media_stream_component_nominated(nr_ice_media_stream *stream,nr_ice_c
comp=STAILQ_FIRST(&stream->components);
while(comp){
if(!comp->nominated)
if((comp->state != NR_ICE_COMPONENT_DISABLED) &&
(comp->local_component->state != NR_ICE_COMPONENT_DISABLED) &&
!comp->nominated)
break;
comp=STAILQ_NEXT(comp,entry);
@ -578,7 +587,7 @@ int nr_ice_media_stream_component_nominated(nr_ice_media_stream *stream,nr_ice_c
goto done;
/* All done... */
r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s)/ICE-STREAM(%s): all components have nominated candidate pairs",stream->pctx->label,stream->label);
r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s)/ICE-STREAM(%s): all active components have nominated candidate pairs",stream->pctx->label,stream->label);
nr_ice_media_stream_set_state(stream,NR_ICE_MEDIA_STREAM_CHECKS_COMPLETED);
/* Cancel our timer */
@ -724,6 +733,7 @@ int nr_ice_media_stream_send(nr_ice_peer_ctx *pctx, nr_ice_media_stream *str, in
return(_status);
}
/* Returns R_REJECTED if the component is unpaired or has been disabled. */
int nr_ice_media_stream_get_active(nr_ice_peer_ctx *pctx, nr_ice_media_stream *str, int component, nr_ice_candidate **local, nr_ice_candidate **remote)
{
int r,_status;
@ -733,6 +743,10 @@ int nr_ice_media_stream_get_active(nr_ice_peer_ctx *pctx, nr_ice_media_stream *s
if(r=nr_ice_peer_ctx_find_component(pctx, str, component, &comp))
ABORT(r);
if (comp->state == NR_ICE_COMPONENT_UNPAIRED ||
comp->state == NR_ICE_COMPONENT_DISABLED)
ABORT(R_REJECTED);
if(!comp->active)
ABORT(R_NOT_FOUND);
@ -797,3 +811,26 @@ int nr_ice_media_stream_finalize(nr_ice_media_stream *lstr,nr_ice_media_stream *
return(0);
}
int nr_ice_media_stream_disable_component(nr_ice_media_stream *stream, int component_id)
{
int r,_status;
nr_ice_component *comp;
if (stream->ice_state != NR_ICE_MEDIA_STREAM_UNPAIRED)
ABORT(R_FAILED);
if ((r=nr_ice_media_stream_find_component(stream, component_id, &comp)))
ABORT(r);
/* Can only disable before pairing */
if (comp->state != NR_ICE_COMPONENT_UNPAIRED)
ABORT(R_FAILED);
comp->state = NR_ICE_COMPONENT_DISABLED;
_status=0;
abort:
return(_status);
}

View File

@ -94,6 +94,7 @@ int nr_ice_media_stream_find_component(nr_ice_media_stream *str, int comp_id, nr
int nr_ice_media_stream_addrs(nr_ice_peer_ctx *pctx, nr_ice_media_stream *str, int component, nr_transport_addr *local, nr_transport_addr *remote);
int
nr_ice_peer_ctx_parse_media_stream_attribute(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, char *attr);
int nr_ice_media_stream_disable_component(nr_ice_media_stream *stream, int component_id);
#ifdef __cplusplus

View File

@ -208,6 +208,15 @@ static int nr_ice_ctx_parse_candidate(nr_ice_peer_ctx *pctx, nr_ice_media_stream
ABORT(R_BAD_DATA);
}
if (comp->state == NR_ICE_COMPONENT_DISABLED) {
r_log(LOG_ICE,LOG_ERR,"Peer offered candidates for disabled remote component");
ABORT(R_BAD_DATA);
}
if (comp->local_component->state == NR_ICE_COMPONENT_DISABLED) {
r_log(LOG_ICE,LOG_ERR,"Peer offered candidates for disabled local component");
ABORT(R_BAD_DATA);
}
cand->component=comp;
TAILQ_INSERT_TAIL(&comp->candidates,cand,entry_comp);
@ -220,7 +229,31 @@ static int nr_ice_ctx_parse_candidate(nr_ice_peer_ctx *pctx, nr_ice_media_stream
return(_status);
}
static int nr_ice_peer_ctx_find_pstream(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, nr_ice_media_stream **pstreamp)
{
int _status;
nr_ice_media_stream *pstream;
/* Because we don't have forward pointers, iterate through all the
peer streams to find one that matches us */
pstream=STAILQ_FIRST(&pctx->peer_streams);
while(pstream) {
if (pstream->local_stream == stream)
break;
pstream = STAILQ_NEXT(pstream, entry);
}
if (!pstream) {
r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) has no stream matching stream %s",pctx->ctx->label,pctx->label,stream->label);
ABORT(R_NOT_FOUND);
}
*pstreamp = pstream;
_status=0;
abort:
return(_status);
}
int nr_ice_peer_ctx_parse_trickle_candidate(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, char *candidate)
{
@ -326,6 +359,31 @@ int nr_ice_peer_ctx_pair_candidates(nr_ice_peer_ctx *pctx)
return(_status);
}
int nr_ice_peer_ctx_disable_component(nr_ice_peer_ctx *pctx, nr_ice_media_stream *lstream, int component_id)
{
int r, _status;
nr_ice_media_stream *pstream;
nr_ice_component *component;
int j;
if ((r=nr_ice_peer_ctx_find_pstream(pctx, lstream, &pstream)))
ABORT(r);
/* We shouldn't be calling this after we have started pairing */
if (pstream->ice_state != NR_ICE_MEDIA_STREAM_UNPAIRED)
ABORT(R_FAILED);
if ((r=nr_ice_media_stream_find_component(pstream, component_id,
&component)))
ABORT(r);
component->state = NR_ICE_COMPONENT_DISABLED;
_status=0;
abort:
return(_status);
}
static void nr_ice_peer_ctx_destroy_cb(NR_SOCKET s, int how, void *cb_arg)
{
nr_ice_peer_ctx *pctx=cb_arg;

View File

@ -78,6 +78,8 @@ int nr_ice_peer_ctx_log_state(nr_ice_peer_ctx *pctx);
int nr_ice_peer_ctx_stream_done(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream);
int nr_ice_peer_ctx_find_component(nr_ice_peer_ctx *pctx, nr_ice_media_stream *str, int component_id, nr_ice_component **compp);
int nr_ice_peer_ctx_deliver_packet_maybe(nr_ice_peer_ctx *pctx, nr_ice_component *comp, nr_transport_addr *source_addr, UCHAR *data, int len);
int nr_ice_peer_ctx_disable_component(nr_ice_peer_ctx *pctx, nr_ice_media_stream *lstream, int component_id);
#ifdef __cplusplus
}
#endif /* __cplusplus */