Accept incoming pings before remote answer is set to reduce connection latency.
BUG=4068 R=juberti@webrtc.org Review URL: https://webrtc-codereview.appspot.com/33509004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@7980 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
@@ -354,7 +354,8 @@ class WebRtcSessionTest : public testing::Test {
|
|||||||
SocketAddress(), SocketAddress(), SocketAddress()));
|
SocketAddress(), SocketAddress(), SocketAddress()));
|
||||||
allocator_->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP |
|
allocator_->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP |
|
||||||
cricket::PORTALLOCATOR_DISABLE_RELAY |
|
cricket::PORTALLOCATOR_DISABLE_RELAY |
|
||||||
cricket::PORTALLOCATOR_ENABLE_BUNDLE);
|
cricket::PORTALLOCATOR_ENABLE_BUNDLE |
|
||||||
|
cricket::PORTALLOCATOR_ENABLE_SHARED_UFRAG);
|
||||||
EXPECT_TRUE(channel_manager_->Init());
|
EXPECT_TRUE(channel_manager_->Init());
|
||||||
desc_factory_->set_add_legacy_streams(false);
|
desc_factory_->set_add_legacy_streams(false);
|
||||||
allocator_->set_step_delay(cricket::kMinimumStepDelay);
|
allocator_->set_step_delay(cricket::kMinimumStepDelay);
|
||||||
@@ -1212,7 +1213,8 @@ class WebRtcSessionTest : public testing::Test {
|
|||||||
allocator_->AddRelay(relay_server);
|
allocator_->AddRelay(relay_server);
|
||||||
allocator_->set_step_delay(cricket::kMinimumStepDelay);
|
allocator_->set_step_delay(cricket::kMinimumStepDelay);
|
||||||
allocator_->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP |
|
allocator_->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP |
|
||||||
cricket::PORTALLOCATOR_ENABLE_BUNDLE);
|
cricket::PORTALLOCATOR_ENABLE_BUNDLE |
|
||||||
|
cricket::PORTALLOCATOR_ENABLE_SHARED_UFRAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
cricket::FakeMediaEngine* media_engine_;
|
cricket::FakeMediaEngine* media_engine_;
|
||||||
|
|||||||
@@ -303,6 +303,12 @@ void P2PTransportChannel::SetRemoteIceCredentials(const std::string& ice_ufrag,
|
|||||||
remote_ice_ufrag_ = ice_ufrag;
|
remote_ice_ufrag_ = ice_ufrag;
|
||||||
remote_ice_pwd_ = ice_pwd;
|
remote_ice_pwd_ = ice_pwd;
|
||||||
|
|
||||||
|
// We need to update the credentials for any peer reflexive candidates.
|
||||||
|
std::vector<Connection*>::iterator it = connections_.begin();
|
||||||
|
for (; it != connections_.end(); ++it) {
|
||||||
|
(*it)->MaybeSetRemoteIceCredentials(ice_ufrag, ice_pwd);
|
||||||
|
}
|
||||||
|
|
||||||
if (ice_restart) {
|
if (ice_restart) {
|
||||||
// |candidate.generation()| is not signaled in ICEPROTO_RFC5245.
|
// |candidate.generation()| is not signaled in ICEPROTO_RFC5245.
|
||||||
// Therefore we need to keep track of the remote ice restart so
|
// Therefore we need to keep track of the remote ice restart so
|
||||||
@@ -450,12 +456,10 @@ void P2PTransportChannel::OnUnknownAddress(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Candidate* candidate = NULL;
|
const Candidate* candidate = NULL;
|
||||||
bool known_username = false;
|
|
||||||
std::string remote_password;
|
std::string remote_password;
|
||||||
for (it = remote_candidates_.begin(); it != remote_candidates_.end(); ++it) {
|
for (it = remote_candidates_.begin(); it != remote_candidates_.end(); ++it) {
|
||||||
if (it->username() == remote_username) {
|
if (it->username() == remote_username) {
|
||||||
remote_password = it->password();
|
remote_password = it->password();
|
||||||
known_username = true;
|
|
||||||
if (ufrag_per_port ||
|
if (ufrag_per_port ||
|
||||||
(it->address() == address &&
|
(it->address() == address &&
|
||||||
it->protocol() == ProtoToString(proto))) {
|
it->protocol() == ProtoToString(proto))) {
|
||||||
@@ -467,19 +471,11 @@ void P2PTransportChannel::OnUnknownAddress(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!known_username) {
|
// The STUN binding request may arrive after setRemoteDescription and before
|
||||||
if (port_muxed) {
|
// adding remote candidate, so we need to set the password to the shared
|
||||||
// When Ports are muxed, SignalUnknownAddress is delivered to all
|
// password if the user name matches.
|
||||||
// P2PTransportChannel belong to a session. Return from here will
|
if (remote_password.empty() && remote_username == remote_ice_ufrag_) {
|
||||||
// save us from sending stun binding error message from incorrect channel.
|
remote_password = remote_ice_pwd_;
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Don't know about this username, the request is bogus
|
|
||||||
// This sometimes happens if a binding response comes in before the ACCEPT
|
|
||||||
// message. It is totally valid; the retry state machine will try again.
|
|
||||||
port->SendBindingErrorResponse(stun_msg, address,
|
|
||||||
STUN_ERROR_STALE_CREDENTIALS, STUN_ERROR_REASON_STALE_CREDENTIALS);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Candidate new_remote_candidate;
|
Candidate new_remote_candidate;
|
||||||
@@ -569,6 +565,8 @@ void P2PTransportChannel::OnUnknownAddress(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOG(LS_INFO) << "Adding connection from peer reflexive candidate: "
|
||||||
|
<< new_remote_candidate.ToString();
|
||||||
AddConnection(connection);
|
AddConnection(connection);
|
||||||
connection->ReceivedPing();
|
connection->ReceivedPing();
|
||||||
|
|
||||||
@@ -716,6 +714,8 @@ bool P2PTransportChannel::CreateConnection(PortInterface* port,
|
|||||||
// found, then we can create a new connection for this address.
|
// found, then we can create a new connection for this address.
|
||||||
Connection* connection = port->GetConnection(remote_candidate.address());
|
Connection* connection = port->GetConnection(remote_candidate.address());
|
||||||
if (connection != NULL) {
|
if (connection != NULL) {
|
||||||
|
connection->MaybeUpdatePeerReflexiveCandidate(remote_candidate);
|
||||||
|
|
||||||
// It is not legal to try to change any of the parameters of an existing
|
// It is not legal to try to change any of the parameters of an existing
|
||||||
// connection; however, the other side can send a duplicate candidate.
|
// connection; however, the other side can send a duplicate candidate.
|
||||||
if (!remote_candidate.IsEquivalent(connection->remote_candidate())) {
|
if (!remote_candidate.IsEquivalent(connection->remote_candidate())) {
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
using cricket::kDefaultPortAllocatorFlags;
|
using cricket::kDefaultPortAllocatorFlags;
|
||||||
using cricket::kMinimumStepDelay;
|
using cricket::kMinimumStepDelay;
|
||||||
using cricket::kDefaultStepDelay;
|
using cricket::kDefaultStepDelay;
|
||||||
|
using cricket::PORTALLOCATOR_ENABLE_BUNDLE;
|
||||||
using cricket::PORTALLOCATOR_ENABLE_SHARED_UFRAG;
|
using cricket::PORTALLOCATOR_ENABLE_SHARED_UFRAG;
|
||||||
using cricket::PORTALLOCATOR_ENABLE_SHARED_SOCKET;
|
using cricket::PORTALLOCATOR_ENABLE_SHARED_SOCKET;
|
||||||
using cricket::ServerAddresses;
|
using cricket::ServerAddresses;
|
||||||
@@ -96,6 +97,10 @@ static const char* kIcePwd[4] = {"TESTICEPWD00000000000000",
|
|||||||
static const uint64 kTiebreaker1 = 11111;
|
static const uint64 kTiebreaker1 = 11111;
|
||||||
static const uint64 kTiebreaker2 = 22222;
|
static const uint64 kTiebreaker2 = 22222;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
MSG_CANDIDATE
|
||||||
|
};
|
||||||
|
|
||||||
// This test simulates 2 P2P endpoints that want to establish connectivity
|
// This test simulates 2 P2P endpoints that want to establish connectivity
|
||||||
// with each other over various network topologies and conditions, which can be
|
// with each other over various network topologies and conditions, which can be
|
||||||
// specified in each individial test.
|
// specified in each individial test.
|
||||||
@@ -199,10 +204,21 @@ class P2PTransportChannelTestBase : public testing::Test,
|
|||||||
rtc::scoped_ptr<cricket::P2PTransportChannel> ch_;
|
rtc::scoped_ptr<cricket::P2PTransportChannel> ch_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CandidateData : public rtc::MessageData {
|
||||||
|
CandidateData(cricket::TransportChannel* ch, const cricket::Candidate& c)
|
||||||
|
: channel(ch), candidate(c) {
|
||||||
|
}
|
||||||
|
cricket::TransportChannel* channel;
|
||||||
|
cricket::Candidate candidate;
|
||||||
|
};
|
||||||
|
|
||||||
struct Endpoint {
|
struct Endpoint {
|
||||||
Endpoint() : signaling_delay_(0), role_(cricket::ICEROLE_UNKNOWN),
|
Endpoint()
|
||||||
tiebreaker_(0), role_conflict_(false),
|
: role_(cricket::ICEROLE_UNKNOWN),
|
||||||
protocol_type_(cricket::ICEPROTO_GOOGLE) {}
|
tiebreaker_(0),
|
||||||
|
role_conflict_(false),
|
||||||
|
save_candidates_(false),
|
||||||
|
protocol_type_(cricket::ICEPROTO_GOOGLE) {}
|
||||||
bool HasChannel(cricket::TransportChannel* ch) {
|
bool HasChannel(cricket::TransportChannel* ch) {
|
||||||
return (ch == cd1_.ch_.get() || ch == cd2_.ch_.get());
|
return (ch == cd1_.ch_.get() || ch == cd2_.ch_.get());
|
||||||
}
|
}
|
||||||
@@ -213,7 +229,6 @@ class P2PTransportChannelTestBase : public testing::Test,
|
|||||||
else
|
else
|
||||||
return &cd2_;
|
return &cd2_;
|
||||||
}
|
}
|
||||||
void SetSignalingDelay(int delay) { signaling_delay_ = delay; }
|
|
||||||
|
|
||||||
void SetIceRole(cricket::IceRole role) { role_ = role; }
|
void SetIceRole(cricket::IceRole role) { role_ = role; }
|
||||||
cricket::IceRole ice_role() { return role_; }
|
cricket::IceRole ice_role() { return role_; }
|
||||||
@@ -236,19 +251,12 @@ class P2PTransportChannelTestBase : public testing::Test,
|
|||||||
rtc::scoped_ptr<cricket::BasicPortAllocator> allocator_;
|
rtc::scoped_ptr<cricket::BasicPortAllocator> allocator_;
|
||||||
ChannelData cd1_;
|
ChannelData cd1_;
|
||||||
ChannelData cd2_;
|
ChannelData cd2_;
|
||||||
int signaling_delay_;
|
|
||||||
cricket::IceRole role_;
|
cricket::IceRole role_;
|
||||||
uint64 tiebreaker_;
|
uint64 tiebreaker_;
|
||||||
bool role_conflict_;
|
bool role_conflict_;
|
||||||
|
bool save_candidates_;
|
||||||
cricket::IceProtocolType protocol_type_;
|
cricket::IceProtocolType protocol_type_;
|
||||||
};
|
std::vector<CandidateData*> saved_candidates_;
|
||||||
|
|
||||||
struct CandidateData : public rtc::MessageData {
|
|
||||||
CandidateData(cricket::TransportChannel* ch, const cricket::Candidate& c)
|
|
||||||
: channel(ch), candidate(c) {
|
|
||||||
}
|
|
||||||
cricket::TransportChannel* channel;
|
|
||||||
cricket::Candidate candidate;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ChannelData* GetChannelData(cricket::TransportChannel* channel) {
|
ChannelData* GetChannelData(cricket::TransportChannel* channel) {
|
||||||
@@ -277,11 +285,11 @@ class P2PTransportChannelTestBase : public testing::Test,
|
|||||||
std::string ice_ufrag_ep2_cd2_ch = kIceUfrag[3];
|
std::string ice_ufrag_ep2_cd2_ch = kIceUfrag[3];
|
||||||
std::string ice_pwd_ep2_cd2_ch = kIcePwd[3];
|
std::string ice_pwd_ep2_cd2_ch = kIcePwd[3];
|
||||||
// In BUNDLE each endpoint must share common ICE credentials.
|
// In BUNDLE each endpoint must share common ICE credentials.
|
||||||
if (ep1_.allocator_->flags() & cricket::PORTALLOCATOR_ENABLE_BUNDLE) {
|
if (ep1_.allocator_->flags() & PORTALLOCATOR_ENABLE_BUNDLE) {
|
||||||
ice_ufrag_ep1_cd2_ch = ice_ufrag_ep1_cd1_ch;
|
ice_ufrag_ep1_cd2_ch = ice_ufrag_ep1_cd1_ch;
|
||||||
ice_pwd_ep1_cd2_ch = ice_pwd_ep1_cd1_ch;
|
ice_pwd_ep1_cd2_ch = ice_pwd_ep1_cd1_ch;
|
||||||
}
|
}
|
||||||
if (ep2_.allocator_->flags() & cricket::PORTALLOCATOR_ENABLE_BUNDLE) {
|
if (ep2_.allocator_->flags() & PORTALLOCATOR_ENABLE_BUNDLE) {
|
||||||
ice_ufrag_ep2_cd2_ch = ice_ufrag_ep2_cd1_ch;
|
ice_ufrag_ep2_cd2_ch = ice_ufrag_ep2_cd1_ch;
|
||||||
ice_pwd_ep2_cd2_ch = ice_pwd_ep2_cd1_ch;
|
ice_pwd_ep2_cd2_ch = ice_pwd_ep2_cd1_ch;
|
||||||
}
|
}
|
||||||
@@ -380,9 +388,6 @@ class P2PTransportChannelTestBase : public testing::Test,
|
|||||||
void SetAllocatorFlags(int endpoint, int flags) {
|
void SetAllocatorFlags(int endpoint, int flags) {
|
||||||
GetAllocator(endpoint)->set_flags(flags);
|
GetAllocator(endpoint)->set_flags(flags);
|
||||||
}
|
}
|
||||||
void SetSignalingDelay(int endpoint, int delay) {
|
|
||||||
GetEndpoint(endpoint)->SetSignalingDelay(delay);
|
|
||||||
}
|
|
||||||
void SetIceProtocol(int endpoint, cricket::IceProtocolType type) {
|
void SetIceProtocol(int endpoint, cricket::IceProtocolType type) {
|
||||||
GetEndpoint(endpoint)->SetIceProtocolType(type);
|
GetEndpoint(endpoint)->SetIceProtocolType(type);
|
||||||
}
|
}
|
||||||
@@ -629,23 +634,44 @@ class P2PTransportChannelTestBase : public testing::Test,
|
|||||||
if (force_relay_ && c.type() != cricket::RELAY_PORT_TYPE)
|
if (force_relay_ && c.type() != cricket::RELAY_PORT_TYPE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
main_->PostDelayed(GetEndpoint(ch)->signaling_delay_, this, 0,
|
if (GetEndpoint(ch)->save_candidates_) {
|
||||||
new CandidateData(ch, c));
|
GetEndpoint(ch)->saved_candidates_.push_back(new CandidateData(ch, c));
|
||||||
}
|
} else {
|
||||||
void OnMessage(rtc::Message* msg) {
|
main_->Post(this, MSG_CANDIDATE, new CandidateData(ch, c));
|
||||||
rtc::scoped_ptr<CandidateData> data(
|
}
|
||||||
static_cast<CandidateData*>(msg->pdata));
|
}
|
||||||
cricket::P2PTransportChannel* rch = GetRemoteChannel(data->channel);
|
|
||||||
cricket::Candidate c = data->candidate;
|
void PauseCandidates(int endpoint) {
|
||||||
if (clear_remote_candidates_ufrag_pwd_) {
|
GetEndpoint(endpoint)->save_candidates_ = true;
|
||||||
c.set_username("");
|
}
|
||||||
c.set_password("");
|
|
||||||
|
void ResumeCandidates(int endpoint) {
|
||||||
|
Endpoint* ed = GetEndpoint(endpoint);
|
||||||
|
std::vector<CandidateData*>::iterator it = ed->saved_candidates_.begin();
|
||||||
|
for (; it != ed->saved_candidates_.end(); ++it) {
|
||||||
|
main_->Post(this, MSG_CANDIDATE, *it);
|
||||||
|
}
|
||||||
|
ed->saved_candidates_.clear();
|
||||||
|
ed->save_candidates_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnMessage(rtc::Message* msg) {
|
||||||
|
switch (msg->message_id) {
|
||||||
|
case MSG_CANDIDATE: {
|
||||||
|
rtc::scoped_ptr<CandidateData> data(
|
||||||
|
static_cast<CandidateData*>(msg->pdata));
|
||||||
|
cricket::P2PTransportChannel* rch = GetRemoteChannel(data->channel);
|
||||||
|
cricket::Candidate c = data->candidate;
|
||||||
|
if (clear_remote_candidates_ufrag_pwd_) {
|
||||||
|
c.set_username("");
|
||||||
|
c.set_password("");
|
||||||
|
}
|
||||||
|
LOG(LS_INFO) << "Candidate(" << data->channel->component() << "->"
|
||||||
|
<< rch->component() << "): " << c.ToString();
|
||||||
|
rch->OnCandidate(c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
LOG(LS_INFO) << "Candidate(" << data->channel->component() << "->"
|
|
||||||
<< rch->component() << "): " << c.type() << ", " << c.protocol()
|
|
||||||
<< ", " << c.address().ToString() << ", " << c.username()
|
|
||||||
<< ", " << c.generation();
|
|
||||||
rch->OnCandidate(c);
|
|
||||||
}
|
}
|
||||||
void OnReadPacket(cricket::TransportChannel* channel, const char* data,
|
void OnReadPacket(cricket::TransportChannel* channel, const char* data,
|
||||||
size_t len, const rtc::PacketTime& packet_time,
|
size_t len, const rtc::PacketTime& packet_time,
|
||||||
@@ -822,6 +848,10 @@ class P2PTransportChannelTest : public P2PTransportChannelTestBase {
|
|||||||
SetIceProtocol(1, type);
|
SetIceProtocol(1, type);
|
||||||
SetAllocatorFlags(1, allocator_flags2);
|
SetAllocatorFlags(1, allocator_flags2);
|
||||||
SetAllocationStepDelay(1, delay2);
|
SetAllocationStepDelay(1, delay2);
|
||||||
|
|
||||||
|
if (type == cricket::ICEPROTO_RFC5245) {
|
||||||
|
set_clear_remote_candidates_ufrag_pwd(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void ConfigureEndpoint(int endpoint, Config config) {
|
void ConfigureEndpoint(int endpoint, Config config) {
|
||||||
switch (config) {
|
switch (config) {
|
||||||
@@ -1163,14 +1193,12 @@ TEST_F(P2PTransportChannelTest, HandleUfragPwdChangeAsIce) {
|
|||||||
// Test that we restart candidate allocation when local ufrag&pwd changed.
|
// Test that we restart candidate allocation when local ufrag&pwd changed.
|
||||||
// Standard Ice protocol is used.
|
// Standard Ice protocol is used.
|
||||||
TEST_F(P2PTransportChannelTest, HandleUfragPwdChangeBundleAsIce) {
|
TEST_F(P2PTransportChannelTest, HandleUfragPwdChangeBundleAsIce) {
|
||||||
ConfigureEndpoints(OPEN, OPEN,
|
ConfigureEndpoints(
|
||||||
PORTALLOCATOR_ENABLE_SHARED_UFRAG,
|
OPEN, OPEN,
|
||||||
PORTALLOCATOR_ENABLE_SHARED_UFRAG,
|
PORTALLOCATOR_ENABLE_BUNDLE | PORTALLOCATOR_ENABLE_SHARED_UFRAG,
|
||||||
kMinimumStepDelay, kMinimumStepDelay,
|
PORTALLOCATOR_ENABLE_BUNDLE | PORTALLOCATOR_ENABLE_SHARED_UFRAG,
|
||||||
cricket::ICEPROTO_RFC5245);
|
kMinimumStepDelay, kMinimumStepDelay,
|
||||||
SetAllocatorFlags(0, cricket::PORTALLOCATOR_ENABLE_BUNDLE);
|
cricket::ICEPROTO_RFC5245);
|
||||||
SetAllocatorFlags(1, cricket::PORTALLOCATOR_ENABLE_BUNDLE);
|
|
||||||
|
|
||||||
CreateChannels(2);
|
CreateChannels(2);
|
||||||
TestHandleIceUfragPasswordChanged();
|
TestHandleIceUfragPasswordChanged();
|
||||||
DestroyChannels();
|
DestroyChannels();
|
||||||
@@ -1192,14 +1220,12 @@ TEST_F(P2PTransportChannelTest, HandleUfragPwdChangeAsGice) {
|
|||||||
// Test that ICE restart works when bundle is enabled.
|
// Test that ICE restart works when bundle is enabled.
|
||||||
// Google Ice protocol is used.
|
// Google Ice protocol is used.
|
||||||
TEST_F(P2PTransportChannelTest, HandleUfragPwdChangeBundleAsGice) {
|
TEST_F(P2PTransportChannelTest, HandleUfragPwdChangeBundleAsGice) {
|
||||||
ConfigureEndpoints(OPEN, OPEN,
|
ConfigureEndpoints(
|
||||||
PORTALLOCATOR_ENABLE_SHARED_UFRAG,
|
OPEN, OPEN,
|
||||||
PORTALLOCATOR_ENABLE_SHARED_UFRAG,
|
PORTALLOCATOR_ENABLE_BUNDLE | PORTALLOCATOR_ENABLE_SHARED_UFRAG,
|
||||||
kDefaultStepDelay, kDefaultStepDelay,
|
PORTALLOCATOR_ENABLE_BUNDLE | PORTALLOCATOR_ENABLE_SHARED_UFRAG,
|
||||||
cricket::ICEPROTO_GOOGLE);
|
kDefaultStepDelay, kDefaultStepDelay,
|
||||||
SetAllocatorFlags(0, cricket::PORTALLOCATOR_ENABLE_BUNDLE);
|
cricket::ICEPROTO_GOOGLE);
|
||||||
SetAllocatorFlags(1, cricket::PORTALLOCATOR_ENABLE_BUNDLE);
|
|
||||||
|
|
||||||
CreateChannels(2);
|
CreateChannels(2);
|
||||||
TestHandleIceUfragPasswordChanged();
|
TestHandleIceUfragPasswordChanged();
|
||||||
DestroyChannels();
|
DestroyChannels();
|
||||||
@@ -1233,25 +1259,68 @@ TEST_F(P2PTransportChannelTest, GetStats) {
|
|||||||
DestroyChannels();
|
DestroyChannels();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that we properly handle getting a STUN error due to slow signaling.
|
// Test that we properly create a connection on a STUN ping from unknown address
|
||||||
TEST_F(P2PTransportChannelTest, DISABLED_SlowSignaling) {
|
// when the signaling is slow.
|
||||||
ConfigureEndpoints(OPEN, NAT_SYMMETRIC,
|
TEST_F(P2PTransportChannelTest, PeerReflexiveCandidateBeforeSignaling) {
|
||||||
kDefaultPortAllocatorFlags,
|
ConfigureEndpoints(OPEN, OPEN,
|
||||||
kDefaultPortAllocatorFlags,
|
PORTALLOCATOR_ENABLE_SHARED_UFRAG,
|
||||||
|
PORTALLOCATOR_ENABLE_SHARED_UFRAG,
|
||||||
kDefaultStepDelay, kDefaultStepDelay,
|
kDefaultStepDelay, kDefaultStepDelay,
|
||||||
cricket::ICEPROTO_GOOGLE);
|
cricket::ICEPROTO_RFC5245);
|
||||||
// Make signaling from the callee take 500ms, so that the initial STUN pings
|
|
||||||
// from the callee beat the signaling, and so the caller responds with a
|
|
||||||
// unknown username error. We should just eat that and carry on; mishandling
|
|
||||||
// this will instead cause all the callee's connections to be discarded.
|
|
||||||
SetSignalingDelay(1, 1000);
|
|
||||||
CreateChannels(1);
|
CreateChannels(1);
|
||||||
|
|
||||||
|
// Pause sending ep2's candidates to ep1 until ep1 receives the peer reflexive
|
||||||
|
// candidate.
|
||||||
|
PauseCandidates(1);
|
||||||
|
|
||||||
|
// The caller should have the best connection connected to the peer reflexive
|
||||||
|
// candidate.
|
||||||
const cricket::Connection* best_connection = NULL;
|
const cricket::Connection* best_connection = NULL;
|
||||||
// Wait until the callee's connections are created.
|
WAIT((best_connection = ep1_ch1()->best_connection()) != NULL, 2000);
|
||||||
WAIT((best_connection = ep2_ch1()->best_connection()) != NULL, 1000);
|
EXPECT_EQ("prflx", ep1_ch1()->best_connection()->remote_candidate().type());
|
||||||
// Wait to see if they get culled; they shouldn't.
|
|
||||||
WAIT(ep2_ch1()->best_connection() != best_connection, 1000);
|
ep1_ch1()->SetRemoteIceCredentials(kIceUfrag[1], kIcePwd[1]);
|
||||||
EXPECT_TRUE(ep2_ch1()->best_connection() == best_connection);
|
ResumeCandidates(1);
|
||||||
|
|
||||||
|
WAIT(ep2_ch1()->best_connection() != NULL, 2000);
|
||||||
|
|
||||||
|
// Verify ep1's best connection is updated to use the 'local' candidate.
|
||||||
|
EXPECT_EQ_WAIT(
|
||||||
|
"local",
|
||||||
|
ep1_ch1()->best_connection()->remote_candidate().type(),
|
||||||
|
2000);
|
||||||
|
EXPECT_EQ(best_connection, ep1_ch1()->best_connection());
|
||||||
|
DestroyChannels();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that we properly create a connection on a STUN ping from unknown address
|
||||||
|
// when the signaling is slow and the end points are behind NAT.
|
||||||
|
TEST_F(P2PTransportChannelTest, PeerReflexiveCandidateBeforeSignalingWithNAT) {
|
||||||
|
ConfigureEndpoints(OPEN, NAT_SYMMETRIC,
|
||||||
|
PORTALLOCATOR_ENABLE_SHARED_UFRAG,
|
||||||
|
PORTALLOCATOR_ENABLE_SHARED_UFRAG,
|
||||||
|
kDefaultStepDelay, kDefaultStepDelay,
|
||||||
|
cricket::ICEPROTO_RFC5245);
|
||||||
|
CreateChannels(1);
|
||||||
|
// Pause sending ep2's candidates to ep1 until ep1 receives the peer reflexive
|
||||||
|
// candidate.
|
||||||
|
PauseCandidates(1);
|
||||||
|
|
||||||
|
// The caller should have the best connection connected to the peer reflexive
|
||||||
|
// candidate.
|
||||||
|
WAIT(ep1_ch1()->best_connection() != NULL, 2000);
|
||||||
|
EXPECT_EQ("prflx", ep1_ch1()->best_connection()->remote_candidate().type());
|
||||||
|
|
||||||
|
ep1_ch1()->SetRemoteIceCredentials(kIceUfrag[1], kIcePwd[1]);
|
||||||
|
ResumeCandidates(1);
|
||||||
|
|
||||||
|
const cricket::Connection* best_connection = NULL;
|
||||||
|
WAIT((best_connection = ep2_ch1()->best_connection()) != NULL, 2000);
|
||||||
|
|
||||||
|
// Wait to verify the connection is not culled.
|
||||||
|
WAIT(ep1_ch1()->writable(), 2000);
|
||||||
|
EXPECT_EQ(ep2_ch1()->best_connection(), best_connection);
|
||||||
|
EXPECT_EQ("prflx", ep1_ch1()->best_connection()->remote_candidate().type());
|
||||||
DestroyChannels();
|
DestroyChannels();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1359,8 +1428,10 @@ TEST_F(P2PTransportChannelTest, TestTcpConnectionsFromActiveToPassive) {
|
|||||||
TEST_F(P2PTransportChannelTest, TestBundleAllocatorToBundleAllocator) {
|
TEST_F(P2PTransportChannelTest, TestBundleAllocatorToBundleAllocator) {
|
||||||
AddAddress(0, kPublicAddrs[0]);
|
AddAddress(0, kPublicAddrs[0]);
|
||||||
AddAddress(1, kPublicAddrs[1]);
|
AddAddress(1, kPublicAddrs[1]);
|
||||||
SetAllocatorFlags(0, cricket::PORTALLOCATOR_ENABLE_BUNDLE);
|
SetAllocatorFlags(
|
||||||
SetAllocatorFlags(1, cricket::PORTALLOCATOR_ENABLE_BUNDLE);
|
0, PORTALLOCATOR_ENABLE_BUNDLE | PORTALLOCATOR_ENABLE_SHARED_UFRAG);
|
||||||
|
SetAllocatorFlags(
|
||||||
|
1, PORTALLOCATOR_ENABLE_BUNDLE | PORTALLOCATOR_ENABLE_SHARED_UFRAG);
|
||||||
|
|
||||||
CreateChannels(2);
|
CreateChannels(2);
|
||||||
|
|
||||||
@@ -1385,7 +1456,8 @@ TEST_F(P2PTransportChannelTest, TestBundleAllocatorToNonBundleAllocator) {
|
|||||||
AddAddress(0, kPublicAddrs[0]);
|
AddAddress(0, kPublicAddrs[0]);
|
||||||
AddAddress(1, kPublicAddrs[1]);
|
AddAddress(1, kPublicAddrs[1]);
|
||||||
// Enable BUNDLE flag at one side.
|
// Enable BUNDLE flag at one side.
|
||||||
SetAllocatorFlags(0, cricket::PORTALLOCATOR_ENABLE_BUNDLE);
|
SetAllocatorFlags(
|
||||||
|
0, PORTALLOCATOR_ENABLE_BUNDLE | PORTALLOCATOR_ENABLE_SHARED_UFRAG);
|
||||||
|
|
||||||
CreateChannels(2);
|
CreateChannels(2);
|
||||||
|
|
||||||
@@ -1418,8 +1490,10 @@ TEST_F(P2PTransportChannelTest, TestIceRoleConflictWithoutBundle) {
|
|||||||
TEST_F(P2PTransportChannelTest, TestIceRoleConflictWithBundle) {
|
TEST_F(P2PTransportChannelTest, TestIceRoleConflictWithBundle) {
|
||||||
AddAddress(0, kPublicAddrs[0]);
|
AddAddress(0, kPublicAddrs[0]);
|
||||||
AddAddress(1, kPublicAddrs[1]);
|
AddAddress(1, kPublicAddrs[1]);
|
||||||
SetAllocatorFlags(0, cricket::PORTALLOCATOR_ENABLE_BUNDLE);
|
SetAllocatorFlags(
|
||||||
SetAllocatorFlags(1, cricket::PORTALLOCATOR_ENABLE_BUNDLE);
|
0, PORTALLOCATOR_ENABLE_BUNDLE | PORTALLOCATOR_ENABLE_SHARED_UFRAG);
|
||||||
|
SetAllocatorFlags(
|
||||||
|
1, PORTALLOCATOR_ENABLE_BUNDLE | PORTALLOCATOR_ENABLE_SHARED_UFRAG);
|
||||||
TestSignalRoleConflict();
|
TestSignalRoleConflict();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -418,7 +418,8 @@ bool Port::GetStunMessage(const char* data, size_t size,
|
|||||||
if (IsStandardIce() &&
|
if (IsStandardIce() &&
|
||||||
!stun_msg->ValidateMessageIntegrity(data, size, password_)) {
|
!stun_msg->ValidateMessageIntegrity(data, size, password_)) {
|
||||||
LOG_J(LS_ERROR, this) << "Received STUN request with bad M-I "
|
LOG_J(LS_ERROR, this) << "Received STUN request with bad M-I "
|
||||||
<< "from " << addr.ToSensitiveString();
|
<< "from " << addr.ToSensitiveString()
|
||||||
|
<< ", password_=" << password_;
|
||||||
SendBindingErrorResponse(stun_msg.get(), addr, STUN_ERROR_UNAUTHORIZED,
|
SendBindingErrorResponse(stun_msg.get(), addr, STUN_ERROR_UNAUTHORIZED,
|
||||||
STUN_ERROR_REASON_UNAUTHORIZED);
|
STUN_ERROR_REASON_UNAUTHORIZED);
|
||||||
return true;
|
return true;
|
||||||
@@ -1348,6 +1349,27 @@ void Connection::HandleRoleConflictFromPeer() {
|
|||||||
port_->SignalRoleConflict(port_);
|
port_->SignalRoleConflict(port_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Connection::MaybeSetRemoteIceCredentials(const std::string& ice_ufrag,
|
||||||
|
const std::string& ice_pwd) {
|
||||||
|
if (remote_candidate_.username() == ice_ufrag &&
|
||||||
|
remote_candidate_.password().empty()) {
|
||||||
|
remote_candidate_.set_password(ice_pwd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Connection::MaybeUpdatePeerReflexiveCandidate(
|
||||||
|
const Candidate& new_candidate) {
|
||||||
|
if (remote_candidate_.type() == PRFLX_PORT_TYPE &&
|
||||||
|
new_candidate.type() != PRFLX_PORT_TYPE &&
|
||||||
|
remote_candidate_.protocol() == new_candidate.protocol() &&
|
||||||
|
remote_candidate_.address() == new_candidate.address() &&
|
||||||
|
remote_candidate_.username() == new_candidate.username() &&
|
||||||
|
remote_candidate_.password() == new_candidate.password() &&
|
||||||
|
remote_candidate_.generation() == new_candidate.generation()) {
|
||||||
|
remote_candidate_ = new_candidate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Connection::OnMessage(rtc::Message *pmsg) {
|
void Connection::OnMessage(rtc::Message *pmsg) {
|
||||||
ASSERT(pmsg->message_id == MSG_DELETE);
|
ASSERT(pmsg->message_id == MSG_DELETE);
|
||||||
|
|
||||||
|
|||||||
@@ -535,6 +535,16 @@ class Connection : public rtc::MessageHandler,
|
|||||||
|
|
||||||
IceMode remote_ice_mode() const { return remote_ice_mode_; }
|
IceMode remote_ice_mode() const { return remote_ice_mode_; }
|
||||||
|
|
||||||
|
// Update the ICE password of the remote candidate if |ice_ufrag| matches
|
||||||
|
// the candidate's ufrag, and the candidate's passwrod has not been set.
|
||||||
|
void MaybeSetRemoteIceCredentials(const std::string& ice_ufrag,
|
||||||
|
const std::string& ice_pwd);
|
||||||
|
|
||||||
|
// If |remote_candidate_| is peer reflexive and is equivalent to
|
||||||
|
// |new_candidate| except the type, update |remote_candidate_| to
|
||||||
|
// |new_candidate|.
|
||||||
|
void MaybeUpdatePeerReflexiveCandidate(const Candidate& new_candidate);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Constructs a new connection to the given remote port.
|
// Constructs a new connection to the given remote port.
|
||||||
Connection(Port* port, size_t index, const Candidate& candidate);
|
Connection(Port* port, size_t index, const Candidate& candidate);
|
||||||
|
|||||||
@@ -28,6 +28,9 @@ PortAllocatorSession::PortAllocatorSession(const std::string& content_name,
|
|||||||
// by itself.
|
// by itself.
|
||||||
username_(flags_ & PORTALLOCATOR_ENABLE_SHARED_UFRAG ? ice_ufrag : ""),
|
username_(flags_ & PORTALLOCATOR_ENABLE_SHARED_UFRAG ? ice_ufrag : ""),
|
||||||
password_(flags_ & PORTALLOCATOR_ENABLE_SHARED_UFRAG ? ice_pwd : "") {
|
password_(flags_ & PORTALLOCATOR_ENABLE_SHARED_UFRAG ? ice_pwd : "") {
|
||||||
|
// If bundle is enabled, shared ufrag must be enabled too.
|
||||||
|
ASSERT((!(flags_ & PORTALLOCATOR_ENABLE_BUNDLE)) ||
|
||||||
|
(flags_ & PORTALLOCATOR_ENABLE_SHARED_UFRAG));
|
||||||
}
|
}
|
||||||
|
|
||||||
PortAllocator::~PortAllocator() {
|
PortAllocator::~PortAllocator() {
|
||||||
|
|||||||
@@ -644,7 +644,8 @@ TEST_F(PortAllocatorTest, TestCandidateFilterWithReflexiveOnlyAndNoNAT) {
|
|||||||
|
|
||||||
TEST_F(PortAllocatorTest, TestBasicMuxFeatures) {
|
TEST_F(PortAllocatorTest, TestBasicMuxFeatures) {
|
||||||
AddInterface(kClientAddr);
|
AddInterface(kClientAddr);
|
||||||
allocator().set_flags(cricket::PORTALLOCATOR_ENABLE_BUNDLE);
|
allocator().set_flags(cricket::PORTALLOCATOR_ENABLE_BUNDLE |
|
||||||
|
cricket::PORTALLOCATOR_ENABLE_SHARED_UFRAG);
|
||||||
// Session ID - session1.
|
// Session ID - session1.
|
||||||
rtc::scoped_ptr<cricket::PortAllocatorSession> session1(
|
rtc::scoped_ptr<cricket::PortAllocatorSession> session1(
|
||||||
CreateSession("session1", cricket::ICE_CANDIDATE_COMPONENT_RTP));
|
CreateSession("session1", cricket::ICE_CANDIDATE_COMPONENT_RTP));
|
||||||
@@ -671,7 +672,8 @@ TEST_F(PortAllocatorTest, TestBasicMuxFeatures) {
|
|||||||
// set of candidates.
|
// set of candidates.
|
||||||
TEST_F(PortAllocatorTest, TestBundleIceRestart) {
|
TEST_F(PortAllocatorTest, TestBundleIceRestart) {
|
||||||
AddInterface(kClientAddr);
|
AddInterface(kClientAddr);
|
||||||
allocator().set_flags(cricket::PORTALLOCATOR_ENABLE_BUNDLE);
|
allocator().set_flags(cricket::PORTALLOCATOR_ENABLE_BUNDLE |
|
||||||
|
cricket::PORTALLOCATOR_ENABLE_SHARED_UFRAG);
|
||||||
// Session ID - session1.
|
// Session ID - session1.
|
||||||
rtc::scoped_ptr<cricket::PortAllocatorSession> session1(
|
rtc::scoped_ptr<cricket::PortAllocatorSession> session1(
|
||||||
CreateSession("session1", kContentName,
|
CreateSession("session1", kContentName,
|
||||||
|
|||||||
Reference in New Issue
Block a user