summaryrefslogtreecommitdiff
path: root/p2p
diff options
context:
space:
mode:
authorPrimiano Tucci <primiano@google.com>2014-09-30 14:46:33 +0100
committerPrimiano Tucci <primiano@google.com>2014-09-30 14:46:33 +0100
commitda0509e3087cc5ee9adc0fe1abb85112ea6529a5 (patch)
tree532416c2f3025131e902ab655f3d404945485a6b /p2p
parent67bbc8e3efef31646fec91b0b422a78708a3f4aa (diff)
parent6fd722a3e5cdf933ad206ec7cd697ce95a5630cd (diff)
downloadtalk-da0509e3087cc5ee9adc0fe1abb85112ea6529a5.tar.gz
This commit was generated by merge_to_master.py. Change-Id: I3cccc8f04ad0036aecdb7eefe316a059ebcefaf9
Diffstat (limited to 'p2p')
-rw-r--r--p2p/base/asyncstuntcpsocket.h6
-rw-r--r--p2p/base/basicpacketsocketfactory.h6
-rw-r--r--p2p/base/constants.cc2
-rw-r--r--p2p/base/constants.h2
-rw-r--r--p2p/base/p2ptransport.cc4
-rw-r--r--p2p/base/packetsocketfactory.h6
-rw-r--r--p2p/base/parsing.h2
-rw-r--r--p2p/base/port.cc2
-rw-r--r--p2p/base/port.h1
-rw-r--r--p2p/base/portallocator.h44
-rw-r--r--p2p/base/rawtransport.cc4
-rw-r--r--p2p/base/rawtransportchannel.cc4
-rw-r--r--p2p/base/session.h2
-rw-r--r--p2p/base/session_unittest.cc4
-rw-r--r--p2p/base/sessiondescription.cc2
-rw-r--r--p2p/base/sessionmessages.cc2
-rw-r--r--p2p/base/sessionmessages.h2
-rw-r--r--p2p/base/stun.cc3
-rw-r--r--p2p/base/stun.h3
-rw-r--r--p2p/base/stunport.h2
-rw-r--r--p2p/base/testturnserver.h26
-rw-r--r--p2p/base/transport.cc2
-rw-r--r--p2p/base/transport_unittest.cc2
-rw-r--r--p2p/base/turnport.cc134
-rw-r--r--p2p/base/turnport.h18
-rw-r--r--p2p/base/turnport_unittest.cc185
-rw-r--r--p2p/base/turnserver.cc56
-rw-r--r--p2p/base/turnserver.h20
-rw-r--r--p2p/client/autoportallocator.h6
-rw-r--r--p2p/client/basicportallocator.cc156
-rw-r--r--p2p/client/basicportallocator.h3
-rw-r--r--p2p/client/connectivitychecker.cc95
-rw-r--r--p2p/client/connectivitychecker_unittest.cc60
-rw-r--r--p2p/client/fakeportallocator.h45
-rw-r--r--p2p/client/portallocator_unittest.cc174
-rw-r--r--p2p/client/sessionmanagertask.h6
36 files changed, 888 insertions, 203 deletions
diff --git a/p2p/base/asyncstuntcpsocket.h b/p2p/base/asyncstuntcpsocket.h
index b63c0b5..136b4df 100644
--- a/p2p/base/asyncstuntcpsocket.h
+++ b/p2p/base/asyncstuntcpsocket.h
@@ -25,8 +25,8 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef TALK_BASE_ASYNCSTUNTCPSOCKET_H_
-#define TALK_BASE_ASYNCSTUNTCPSOCKET_H_
+#ifndef TALK_P2P_BASE_ASYNCSTUNTCPSOCKET_H_
+#define TALK_P2P_BASE_ASYNCSTUNTCPSOCKET_H_
#include "webrtc/base/asynctcpsocket.h"
#include "webrtc/base/scoped_ptr.h"
@@ -64,4 +64,4 @@ class AsyncStunTCPSocket : public rtc::AsyncTCPSocketBase {
} // namespace cricket
-#endif // TALK_BASE_ASYNCSTUNTCPSOCKET_H_
+#endif // TALK_P2P_BASE_ASYNCSTUNTCPSOCKET_H_
diff --git a/p2p/base/basicpacketsocketfactory.h b/p2p/base/basicpacketsocketfactory.h
index b1bae35..77b1652 100644
--- a/p2p/base/basicpacketsocketfactory.h
+++ b/p2p/base/basicpacketsocketfactory.h
@@ -25,8 +25,8 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef TALK_BASE_BASICPACKETSOCKETFACTORY_H_
-#define TALK_BASE_BASICPACKETSOCKETFACTORY_H_
+#ifndef TALK_P2P_BASE_BASICPACKETSOCKETFACTORY_H_
+#define TALK_P2P_BASE_BASICPACKETSOCKETFACTORY_H_
#include "talk/p2p/base/packetsocketfactory.h"
@@ -65,4 +65,4 @@ class BasicPacketSocketFactory : public PacketSocketFactory {
} // namespace rtc
-#endif // TALK_BASE_BASICPACKETSOCKETFACTORY_H_
+#endif // TALK_P2P_BASE_BASICPACKETSOCKETFACTORY_H_
diff --git a/p2p/base/constants.cc b/p2p/base/constants.cc
index 2e57d9d..278a615 100644
--- a/p2p/base/constants.cc
+++ b/p2p/base/constants.cc
@@ -29,7 +29,7 @@
#include <string>
-#include "talk/xmllite/qname.h"
+#include "webrtc/libjingle/xmllite/qname.h"
namespace cricket {
diff --git a/p2p/base/constants.h b/p2p/base/constants.h
index 61dd815..4cd1166 100644
--- a/p2p/base/constants.h
+++ b/p2p/base/constants.h
@@ -29,7 +29,7 @@
#define TALK_P2P_BASE_CONSTANTS_H_
#include <string>
-#include "talk/xmllite/qname.h"
+#include "webrtc/libjingle/xmllite/qname.h"
// This file contains constants related to signaling that are used in various
// classes in this directory.
diff --git a/p2p/base/p2ptransport.cc b/p2p/base/p2ptransport.cc
index b992cc0..06941ac 100644
--- a/p2p/base/p2ptransport.cc
+++ b/p2p/base/p2ptransport.cc
@@ -35,8 +35,8 @@
#include "talk/p2p/base/parsing.h"
#include "talk/p2p/base/sessionmanager.h"
#include "talk/p2p/base/sessionmessages.h"
-#include "talk/xmllite/qname.h"
-#include "talk/xmllite/xmlelement.h"
+#include "webrtc/libjingle/xmllite/qname.h"
+#include "webrtc/libjingle/xmllite/xmlelement.h"
#include "talk/xmpp/constants.h"
#include "webrtc/base/base64.h"
#include "webrtc/base/common.h"
diff --git a/p2p/base/packetsocketfactory.h b/p2p/base/packetsocketfactory.h
index 6b82682..46767c2 100644
--- a/p2p/base/packetsocketfactory.h
+++ b/p2p/base/packetsocketfactory.h
@@ -25,8 +25,8 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef TALK_BASE_PACKETSOCKETFACTORY_H_
-#define TALK_BASE_PACKETSOCKETFACTORY_H_
+#ifndef TALK_P2P_BASE_PACKETSOCKETFACTORY_H_
+#define TALK_P2P_BASE_PACKETSOCKETFACTORY_H_
#include "webrtc/base/proxyinfo.h"
@@ -66,4 +66,4 @@ class PacketSocketFactory {
} // namespace rtc
-#endif // TALK_BASE_PACKETSOCKETFACTORY_H_
+#endif // TALK_P2P_BASE_PACKETSOCKETFACTORY_H_
diff --git a/p2p/base/parsing.h b/p2p/base/parsing.h
index 635b122..2aab2f8 100644
--- a/p2p/base/parsing.h
+++ b/p2p/base/parsing.h
@@ -30,7 +30,7 @@
#include <string>
#include <vector>
-#include "talk/xmllite/xmlelement.h" // Needed to delete ParseError.extra.
+#include "webrtc/libjingle/xmllite/xmlelement.h" // Needed to delete ParseError.extra.
#include "webrtc/base/basictypes.h"
#include "webrtc/base/stringencode.h"
diff --git a/p2p/base/port.cc b/p2p/base/port.cc
index 3820154..0cf46eb 100644
--- a/p2p/base/port.cc
+++ b/p2p/base/port.cc
@@ -1212,7 +1212,7 @@ std::string Connection::ToString() const {
<< ":" << local.type() << ":" << local.protocol()
<< ":" << local.address().ToSensitiveString()
<< "->" << remote.id() << ":" << remote.component()
- << ":" << remote.preference()
+ << ":" << remote.priority()
<< ":" << remote.type() << ":"
<< remote.protocol() << ":" << remote.address().ToSensitiveString() << "|"
<< CONNECT_STATE_ABBREV[connected()]
diff --git a/p2p/base/port.h b/p2p/base/port.h
index cccfdad..4893586 100644
--- a/p2p/base/port.h
+++ b/p2p/base/port.h
@@ -155,6 +155,7 @@ class Port : public PortInterface, public rtc::MessageHandler,
uint64 IceTiebreaker() const { return tiebreaker_; }
virtual bool SharedSocket() const { return shared_socket_; }
+ void ResetSharedSocket() { shared_socket_ = false; }
// The thread on which this port performs its I/O.
rtc::Thread* thread() { return thread_; }
diff --git a/p2p/base/portallocator.h b/p2p/base/portallocator.h
index 84e5fea..5bc389e 100644
--- a/p2p/base/portallocator.h
+++ b/p2p/base/portallocator.h
@@ -44,17 +44,18 @@ namespace cricket {
// Clients can override this class to control port allocation, including
// what kinds of ports are allocated.
-const uint32 PORTALLOCATOR_DISABLE_UDP = 0x01;
-const uint32 PORTALLOCATOR_DISABLE_STUN = 0x02;
-const uint32 PORTALLOCATOR_DISABLE_RELAY = 0x04;
-const uint32 PORTALLOCATOR_DISABLE_TCP = 0x08;
-const uint32 PORTALLOCATOR_ENABLE_SHAKER = 0x10;
-const uint32 PORTALLOCATOR_ENABLE_BUNDLE = 0x20;
-const uint32 PORTALLOCATOR_ENABLE_IPV6 = 0x40;
-const uint32 PORTALLOCATOR_ENABLE_SHARED_UFRAG = 0x80;
-const uint32 PORTALLOCATOR_ENABLE_SHARED_SOCKET = 0x100;
-const uint32 PORTALLOCATOR_ENABLE_STUN_RETRANSMIT_ATTRIBUTE = 0x200;
-const uint32 PORTALLOCATOR_ENABLE_TURN_SHARED_SOCKET = 0x400;
+enum {
+ PORTALLOCATOR_DISABLE_UDP = 0x01,
+ PORTALLOCATOR_DISABLE_STUN = 0x02,
+ PORTALLOCATOR_DISABLE_RELAY = 0x04,
+ PORTALLOCATOR_DISABLE_TCP = 0x08,
+ PORTALLOCATOR_ENABLE_SHAKER = 0x10,
+ PORTALLOCATOR_ENABLE_BUNDLE = 0x20,
+ PORTALLOCATOR_ENABLE_IPV6 = 0x40,
+ PORTALLOCATOR_ENABLE_SHARED_UFRAG = 0x80,
+ PORTALLOCATOR_ENABLE_SHARED_SOCKET = 0x100,
+ PORTALLOCATOR_ENABLE_STUN_RETRANSMIT_ATTRIBUTE = 0x200,
+};
const uint32 kDefaultPortAllocatorFlags = 0;
@@ -63,6 +64,15 @@ const uint32 kDefaultStepDelay = 1000; // 1 sec step delay.
// internal. Less than 20ms is not acceptable. We choose 50ms as our default.
const uint32 kMinimumStepDelay = 50;
+// CF = CANDIDATE FILTER
+enum {
+ CF_NONE = 0x0,
+ CF_HOST = 0x1,
+ CF_REFLEXIVE = 0x2,
+ CF_RELAY = 0x4,
+ CF_ALL = 0x7,
+};
+
class PortAllocatorSessionMuxer;
class PortAllocatorSession : public sigslot::has_slots<> {
@@ -118,7 +128,8 @@ class PortAllocator : public sigslot::has_slots<> {
min_port_(0),
max_port_(0),
step_delay_(kDefaultStepDelay),
- allow_tcp_listen_(true) {
+ allow_tcp_listen_(true),
+ candidate_filter_(CF_ALL) {
// This will allow us to have old behavior on non webrtc clients.
}
virtual ~PortAllocator();
@@ -158,7 +169,6 @@ class PortAllocator : public sigslot::has_slots<> {
uint32 step_delay() const { return step_delay_; }
void set_step_delay(uint32 delay) {
- ASSERT(delay >= kMinimumStepDelay);
step_delay_ = delay;
}
@@ -167,6 +177,13 @@ class PortAllocator : public sigslot::has_slots<> {
allow_tcp_listen_ = allow_tcp_listen;
}
+ uint32 candidate_filter() { return candidate_filter_; }
+ bool set_candidate_filter(uint32 filter) {
+ // TODO(mallinath) - Do transition check?
+ candidate_filter_ = filter;
+ return true;
+ }
+
protected:
virtual PortAllocatorSession* CreateSessionInternal(
const std::string& content_name,
@@ -184,6 +201,7 @@ class PortAllocator : public sigslot::has_slots<> {
uint32 step_delay_;
SessionMuxerMap muxers_;
bool allow_tcp_listen_;
+ uint32 candidate_filter_;
};
} // namespace cricket
diff --git a/p2p/base/rawtransport.cc b/p2p/base/rawtransport.cc
index 5913177..2af1864 100644
--- a/p2p/base/rawtransport.cc
+++ b/p2p/base/rawtransport.cc
@@ -32,8 +32,8 @@
#include "talk/p2p/base/rawtransport.h"
#include "talk/p2p/base/rawtransportchannel.h"
#include "talk/p2p/base/sessionmanager.h"
-#include "talk/xmllite/qname.h"
-#include "talk/xmllite/xmlelement.h"
+#include "webrtc/libjingle/xmllite/qname.h"
+#include "webrtc/libjingle/xmllite/xmlelement.h"
#include "talk/xmpp/constants.h"
#include "webrtc/base/common.h"
diff --git a/p2p/base/rawtransportchannel.cc b/p2p/base/rawtransportchannel.cc
index ef0a532..ae268e3 100644
--- a/p2p/base/rawtransportchannel.cc
+++ b/p2p/base/rawtransportchannel.cc
@@ -36,8 +36,8 @@
#include "talk/p2p/base/relayport.h"
#include "talk/p2p/base/sessionmanager.h"
#include "talk/p2p/base/stunport.h"
-#include "talk/xmllite/qname.h"
-#include "talk/xmllite/xmlelement.h"
+#include "webrtc/libjingle/xmllite/qname.h"
+#include "webrtc/libjingle/xmllite/xmlelement.h"
#include "talk/xmpp/constants.h"
#include "webrtc/base/common.h"
diff --git a/p2p/base/session.h b/p2p/base/session.h
index 756bbe0..e06cf00 100644
--- a/p2p/base/session.h
+++ b/p2p/base/session.h
@@ -39,7 +39,7 @@
#include "talk/p2p/base/sessionmanager.h"
#include "talk/p2p/base/sessionmessages.h"
#include "talk/p2p/base/transport.h"
-#include "talk/xmllite/xmlelement.h"
+#include "webrtc/libjingle/xmllite/xmlelement.h"
#include "talk/xmpp/constants.h"
#include "webrtc/base/refcount.h"
#include "webrtc/base/scoped_ptr.h"
diff --git a/p2p/base/session_unittest.cc b/p2p/base/session_unittest.cc
index 90cd06d..4674d2c 100644
--- a/p2p/base/session_unittest.cc
+++ b/p2p/base/session_unittest.cc
@@ -601,8 +601,7 @@ class TestPortAllocatorSession : public cricket::PortAllocatorSession {
network_("network", "unittest",
rtc::IPAddress(INADDR_LOOPBACK), 8),
socket_factory_(rtc::Thread::Current()),
- running_(false),
- port_(28653) {
+ running_(false) {
network_.AddIP(address_.ipaddr());
}
@@ -655,7 +654,6 @@ class TestPortAllocatorSession : public cricket::PortAllocatorSession {
rtc::Network network_;
rtc::BasicPacketSocketFactory socket_factory_;
bool running_;
- int port_;
};
class TestPortAllocator : public cricket::PortAllocator {
diff --git a/p2p/base/sessiondescription.cc b/p2p/base/sessiondescription.cc
index 7009aa8..7ad3d48 100644
--- a/p2p/base/sessiondescription.cc
+++ b/p2p/base/sessiondescription.cc
@@ -27,7 +27,7 @@
#include "talk/p2p/base/sessiondescription.h"
-#include "talk/xmllite/xmlelement.h"
+#include "webrtc/libjingle/xmllite/xmlelement.h"
namespace cricket {
diff --git a/p2p/base/sessionmessages.cc b/p2p/base/sessionmessages.cc
index bfba273..b2fd9d6 100644
--- a/p2p/base/sessionmessages.cc
+++ b/p2p/base/sessionmessages.cc
@@ -36,7 +36,7 @@
#include "talk/p2p/base/sessionclient.h"
#include "talk/p2p/base/sessiondescription.h"
#include "talk/p2p/base/transport.h"
-#include "talk/xmllite/xmlconstants.h"
+#include "webrtc/libjingle/xmllite/xmlconstants.h"
#include "talk/xmpp/constants.h"
#include "webrtc/base/logging.h"
#include "webrtc/base/scoped_ptr.h"
diff --git a/p2p/base/sessionmessages.h b/p2p/base/sessionmessages.h
index 38fca98..7e1f8ac 100644
--- a/p2p/base/sessionmessages.h
+++ b/p2p/base/sessionmessages.h
@@ -36,7 +36,7 @@
#include "talk/p2p/base/parsing.h"
#include "talk/p2p/base/sessiondescription.h" // Needed to delete contents.
#include "talk/p2p/base/transportinfo.h"
-#include "talk/xmllite/xmlelement.h"
+#include "webrtc/libjingle/xmllite/xmlelement.h"
#include "webrtc/base/basictypes.h"
namespace cricket {
diff --git a/p2p/base/stun.cc b/p2p/base/stun.cc
index be96b76..061fd9a 100644
--- a/p2p/base/stun.cc
+++ b/p2p/base/stun.cc
@@ -41,6 +41,7 @@ using rtc::ByteBuffer;
namespace cricket {
+const char STUN_ERROR_REASON_TRY_ALTERNATE_SERVER[] = "Try Alternate Server";
const char STUN_ERROR_REASON_BAD_REQUEST[] = "Bad Request";
const char STUN_ERROR_REASON_UNAUTHORIZED[] = "Unauthorized";
const char STUN_ERROR_REASON_FORBIDDEN[] = "Forbidden";
@@ -401,7 +402,7 @@ StunAttributeValueType StunMessage::GetAttributeValueType(int type) const {
case STUN_ATTR_NONCE: return STUN_VALUE_BYTE_STRING;
case STUN_ATTR_XOR_MAPPED_ADDRESS: return STUN_VALUE_XOR_ADDRESS;
case STUN_ATTR_SOFTWARE: return STUN_VALUE_BYTE_STRING;
- case STUN_ATTR_ALTERNATE_SERVER: return STUN_VALUE_BYTE_STRING;
+ case STUN_ATTR_ALTERNATE_SERVER: return STUN_VALUE_ADDRESS;
case STUN_ATTR_FINGERPRINT: return STUN_VALUE_UINT32;
case STUN_ATTR_RETRANSMIT_COUNT: return STUN_VALUE_UINT32;
default: return STUN_VALUE_UNKNOWN;
diff --git a/p2p/base/stun.h b/p2p/base/stun.h
index b22b51e..c4f522b 100644
--- a/p2p/base/stun.h
+++ b/p2p/base/stun.h
@@ -63,7 +63,7 @@ enum StunAttributeType {
STUN_ATTR_NONCE = 0x0015, // ByteString
STUN_ATTR_XOR_MAPPED_ADDRESS = 0x0020, // XorAddress
STUN_ATTR_SOFTWARE = 0x8022, // ByteString
- STUN_ATTR_ALTERNATE_SERVER = 0x8023, // ByteString
+ STUN_ATTR_ALTERNATE_SERVER = 0x8023, // Address
STUN_ATTR_FINGERPRINT = 0x8028, // UInt32
STUN_ATTR_RETRANSMIT_COUNT = 0xFF00 // UInt32
};
@@ -104,6 +104,7 @@ enum StunErrorCode {
};
// Strings for the error codes above.
+extern const char STUN_ERROR_REASON_TRY_ALTERNATE_SERVER[];
extern const char STUN_ERROR_REASON_BAD_REQUEST[];
extern const char STUN_ERROR_REASON_UNAUTHORIZED[];
extern const char STUN_ERROR_REASON_UNKNOWN_ATTRIBUTE[];
diff --git a/p2p/base/stunport.h b/p2p/base/stunport.h
index 0a49b67..b3b6d5b 100644
--- a/p2p/base/stunport.h
+++ b/p2p/base/stunport.h
@@ -82,7 +82,7 @@ class UDPPort : public Port {
return socket_->GetLocalAddress();
}
- const ServerAddresses server_addresses() const {
+ const ServerAddresses& server_addresses() const {
return server_addresses_;
}
void
diff --git a/p2p/base/testturnserver.h b/p2p/base/testturnserver.h
index e2c0ccb..6c30afe 100644
--- a/p2p/base/testturnserver.h
+++ b/p2p/base/testturnserver.h
@@ -29,6 +29,7 @@
#define TALK_P2P_BASE_TESTTURNSERVER_H_
#include <string>
+#include <vector>
#include "talk/p2p/base/basicpacketsocketfactory.h"
#include "talk/p2p/base/stun.h"
@@ -41,6 +42,27 @@ namespace cricket {
static const char kTestRealm[] = "example.org";
static const char kTestSoftware[] = "TestTurnServer";
+class TestTurnRedirector : public TurnRedirectInterface {
+ public:
+ explicit TestTurnRedirector(const std::vector<rtc::SocketAddress>& addresses)
+ : alternate_server_addresses_(addresses),
+ iter_(alternate_server_addresses_.begin()) {
+ }
+
+ virtual bool ShouldRedirect(const rtc::SocketAddress&,
+ rtc::SocketAddress* out) {
+ if (!out || iter_ == alternate_server_addresses_.end()) {
+ return false;
+ }
+ *out = *iter_++;
+ return true;
+ }
+
+ private:
+ const std::vector<rtc::SocketAddress>& alternate_server_addresses_;
+ std::vector<rtc::SocketAddress>::const_iterator iter_;
+};
+
class TestTurnServer : public TurnAuthInterface {
public:
TestTurnServer(rtc::Thread* thread,
@@ -61,6 +83,10 @@ class TestTurnServer : public TurnAuthInterface {
TurnServer* server() { return &server_; }
+ void set_redirect_hook(TurnRedirectInterface* redirect_hook) {
+ server_.set_redirect_hook(redirect_hook);
+ }
+
void AddInternalSocket(const rtc::SocketAddress& int_addr,
ProtocolType proto) {
rtc::Thread* thread = rtc::Thread::Current();
diff --git a/p2p/base/transport.cc b/p2p/base/transport.cc
index 6ee7b2a..d88f5e7 100644
--- a/p2p/base/transport.cc
+++ b/p2p/base/transport.cc
@@ -33,7 +33,7 @@
#include "talk/p2p/base/port.h"
#include "talk/p2p/base/sessionmanager.h"
#include "talk/p2p/base/transportchannelimpl.h"
-#include "talk/xmllite/xmlelement.h"
+#include "webrtc/libjingle/xmllite/xmlelement.h"
#include "talk/xmpp/constants.h"
#include "webrtc/base/bind.h"
#include "webrtc/base/common.h"
diff --git a/p2p/base/transport_unittest.cc b/p2p/base/transport_unittest.cc
index fa2c116..8f7dae2 100644
--- a/p2p/base/transport_unittest.cc
+++ b/p2p/base/transport_unittest.cc
@@ -31,7 +31,7 @@
#include "talk/p2p/base/parsing.h"
#include "talk/p2p/base/rawtransport.h"
#include "talk/p2p/base/sessionmessages.h"
-#include "talk/xmllite/xmlelement.h"
+#include "webrtc/libjingle/xmllite/xmlelement.h"
#include "talk/xmpp/constants.h"
#include "webrtc/base/fakesslidentity.h"
#include "webrtc/base/gunit.h"
diff --git a/p2p/base/turnport.cc b/p2p/base/turnport.cc
index 3faacd1..2908d71 100644
--- a/p2p/base/turnport.cc
+++ b/p2p/base/turnport.cc
@@ -51,6 +51,10 @@ static const int TURN_PERMISSION_TIMEOUT = 5 * 60 * 1000; // 5 minutes
static const size_t TURN_CHANNEL_HEADER_SIZE = 4U;
+// Retry at most twice (i.e. three different ALLOCATE requests) on
+// STUN_ERROR_ALLOCATION_MISMATCH error per rfc5766.
+static const size_t MAX_ALLOCATE_MISMATCH_RETRIES = 2;
+
inline bool IsTurnChannelData(uint16 msg_type) {
return ((msg_type & 0xC000) == 0x4000); // MSB are 0b01
}
@@ -78,6 +82,7 @@ class TurnAllocateRequest : public StunRequest {
private:
// Handles authentication challenge from the server.
void OnAuthChallenge(StunMessage* response, int code);
+ void OnTryAlternate(StunMessage* response, int code);
void OnUnknownAttribute(StunMessage* response);
TurnPort* port_;
@@ -187,7 +192,8 @@ TurnPort::TurnPort(rtc::Thread* thread,
request_manager_(thread),
next_channel_number_(TURN_CHANNEL_NUMBER_START),
connected_(false),
- server_priority_(server_priority) {
+ server_priority_(server_priority),
+ allocate_mismatch_retries_(0) {
request_manager_.SignalSendPacket.connect(this, &TurnPort::OnSendStunPacket);
}
@@ -211,7 +217,8 @@ TurnPort::TurnPort(rtc::Thread* thread,
request_manager_(thread),
next_channel_number_(TURN_CHANNEL_NUMBER_START),
connected_(false),
- server_priority_(server_priority) {
+ server_priority_(server_priority),
+ allocate_mismatch_retries_(0) {
request_manager_.SignalSendPacket.connect(this, &TurnPort::OnSendStunPacket);
}
@@ -253,6 +260,9 @@ void TurnPort::PrepareAddress() {
return;
}
+ // Insert the current address to prevent redirection pingpong.
+ attempted_server_addresses_.insert(server_address_.address);
+
LOG_J(LS_INFO, this) << "Trying to connect to TURN server via "
<< ProtoToString(server_address_.proto) << " @ "
<< server_address_.address.ToSensitiveString();
@@ -267,6 +277,8 @@ void TurnPort::PrepareAddress() {
}
bool TurnPort::CreateTurnClientSocket() {
+ ASSERT(!socket_ || SharedSocket());
+
if (server_address_.proto == PROTO_UDP && !SharedSocket()) {
socket_ = socket_factory()->CreateUdpSocket(
rtc::SocketAddress(ip(), 0), min_port(), max_port());
@@ -336,6 +348,29 @@ void TurnPort::OnSocketClose(rtc::AsyncPacketSocket* socket, int error) {
}
}
+void TurnPort::OnAllocateMismatch() {
+ if (allocate_mismatch_retries_ >= MAX_ALLOCATE_MISMATCH_RETRIES) {
+ LOG_J(LS_WARNING, this) << "Giving up on the port after "
+ << allocate_mismatch_retries_
+ << " retries for STUN_ERROR_ALLOCATION_MISMATCH";
+ OnAllocateError();
+ return;
+ }
+
+ LOG_J(LS_INFO, this) << "Allocating a new socket after "
+ << "STUN_ERROR_ALLOCATION_MISMATCH, retry = "
+ << allocate_mismatch_retries_ + 1;
+ if (SharedSocket()) {
+ ResetSharedSocket();
+ } else {
+ delete socket_;
+ }
+ socket_ = NULL;
+
+ PrepareAddress();
+ ++allocate_mismatch_retries_;
+}
+
Connection* TurnPort::CreateConnection(const Candidate& address,
CandidateOrigin origin) {
// TURN-UDP can only connect to UDP candidates.
@@ -458,6 +493,38 @@ void TurnPort::OnReadyToSend(rtc::AsyncPacketSocket* socket) {
}
}
+
+// Update current server address port with the alternate server address port.
+bool TurnPort::SetAlternateServer(const rtc::SocketAddress& address) {
+ // Check if we have seen this address before and reject if we did.
+ AttemptedServerSet::iterator iter = attempted_server_addresses_.find(address);
+ if (iter != attempted_server_addresses_.end()) {
+ LOG_J(LS_WARNING, this) << "Redirection to ["
+ << address.ToSensitiveString()
+ << "] ignored, allocation failed.";
+ return false;
+ }
+
+ // If protocol family of server address doesn't match with local, return.
+ if (!IsCompatibleAddress(address)) {
+ LOG(LS_WARNING) << "Server IP address family does not match with "
+ << "local host address family type";
+ return false;
+ }
+
+ LOG_J(LS_INFO, this) << "Redirecting from TURN server ["
+ << server_address_.address.ToSensitiveString()
+ << "] to TURN server ["
+ << address.ToSensitiveString()
+ << "]";
+ server_address_ = ProtocolAddress(address, server_address_.proto,
+ server_address_.secure);
+
+ // Insert the current address to prevent redirection pingpong.
+ attempted_server_addresses_.insert(server_address_.address);
+ return true;
+}
+
void TurnPort::ResolveTurnAddress(const rtc::SocketAddress& address) {
if (resolver_)
return;
@@ -544,6 +611,9 @@ void TurnPort::OnMessage(rtc::Message* message) {
if (message->message_id == MSG_ERROR) {
SignalPortError(this);
return;
+ } else if (message->message_id == MSG_ALLOCATE_MISMATCH) {
+ OnAllocateMismatch();
+ return;
}
Port::OnMessage(message);
@@ -805,6 +875,14 @@ void TurnAllocateRequest::OnErrorResponse(StunMessage* response) {
case STUN_ERROR_UNAUTHORIZED: // Unauthrorized.
OnAuthChallenge(response, error_code->code());
break;
+ case STUN_ERROR_TRY_ALTERNATE:
+ OnTryAlternate(response, error_code->code());
+ break;
+ case STUN_ERROR_ALLOCATION_MISMATCH:
+ // We must handle this error async because trying to delete the socket in
+ // OnErrorResponse will cause a deadlock on the socket.
+ port_->thread()->Post(port_, TurnPort::MSG_ALLOCATE_MISMATCH);
+ break;
default:
LOG_J(LS_WARNING, port_) << "Allocate response error, code="
<< error_code->code();
@@ -849,6 +927,57 @@ void TurnAllocateRequest::OnAuthChallenge(StunMessage* response, int code) {
port_->SendRequest(new TurnAllocateRequest(port_), 0);
}
+void TurnAllocateRequest::OnTryAlternate(StunMessage* response, int code) {
+ // TODO(guoweis): Currently, we only support UDP redirect
+ if (port_->server_address().proto != PROTO_UDP) {
+ LOG_J(LS_WARNING, port_) << "Receiving 300 Alternate Server on non-UDP "
+ << "allocating request from ["
+ << port_->server_address().address.ToSensitiveString()
+ << "], failed as currently not supported";
+ port_->OnAllocateError();
+ return;
+ }
+
+ // According to RFC 5389 section 11, there are use cases where
+ // authentication of response is not possible, we're not validating
+ // message integrity.
+
+ // Get the alternate server address attribute value.
+ const StunAddressAttribute* alternate_server_attr =
+ response->GetAddress(STUN_ATTR_ALTERNATE_SERVER);
+ if (!alternate_server_attr) {
+ LOG_J(LS_WARNING, port_) << "Missing STUN_ATTR_ALTERNATE_SERVER "
+ << "attribute in try alternate error response";
+ port_->OnAllocateError();
+ return;
+ }
+ if (!port_->SetAlternateServer(alternate_server_attr->GetAddress())) {
+ port_->OnAllocateError();
+ return;
+ }
+
+ // Check the attributes.
+ const StunByteStringAttribute* realm_attr =
+ response->GetByteString(STUN_ATTR_REALM);
+ if (realm_attr) {
+ LOG_J(LS_INFO, port_) << "Applying STUN_ATTR_REALM attribute in "
+ << "try alternate error response.";
+ port_->set_realm(realm_attr->GetString());
+ }
+
+ const StunByteStringAttribute* nonce_attr =
+ response->GetByteString(STUN_ATTR_NONCE);
+ if (nonce_attr) {
+ LOG_J(LS_INFO, port_) << "Applying STUN_ATTR_NONCE attribute in "
+ << "try alternate error response.";
+ port_->set_nonce(nonce_attr->GetString());
+ }
+
+ // Send another allocate request to alternate server,
+ // with the received realm and nonce values.
+ port_->SendRequest(new TurnAllocateRequest(port_), 0);
+}
+
TurnRefreshRequest::TurnRefreshRequest(TurnPort* port)
: StunRequest(new TurnMessage()),
port_(port) {
@@ -876,7 +1005,6 @@ void TurnRefreshRequest::OnResponse(StunMessage* response) {
}
void TurnRefreshRequest::OnErrorResponse(StunMessage* response) {
- // TODO(juberti): Handle 437 error response as a success.
const StunErrorCodeAttribute* error_code = response->GetErrorCode();
LOG_J(LS_WARNING, port_) << "Refresh response error, code="
<< error_code->code();
diff --git a/p2p/base/turnport.h b/p2p/base/turnport.h
index d73b11d..ab7d4e7 100644
--- a/p2p/base/turnport.h
+++ b/p2p/base/turnport.h
@@ -30,6 +30,7 @@
#include <stdio.h>
#include <list>
+#include <set>
#include <string>
#include "talk/p2p/base/port.h"
@@ -119,6 +120,12 @@ class TurnPort : public Port {
int error() const { return error_; }
+ void OnAllocateMismatch();
+
+ rtc::AsyncPacketSocket* socket() const {
+ return socket_;
+ }
+
// Signal with resolved server address.
// Parameters are port, server address and resolved server address.
// This signal will be sent only if server address is resolved successfully.
@@ -153,10 +160,14 @@ class TurnPort : public Port {
int server_priority);
private:
- enum { MSG_ERROR = MSG_FIRST_AVAILABLE };
+ enum {
+ MSG_ERROR = MSG_FIRST_AVAILABLE,
+ MSG_ALLOCATE_MISMATCH
+ };
typedef std::list<TurnEntry*> EntryList;
typedef std::map<rtc::Socket::Option, int> SocketOptionsMap;
+ typedef std::set<rtc::SocketAddress> AttemptedServerSet;
virtual void OnMessage(rtc::Message* pmsg);
@@ -170,6 +181,7 @@ class TurnPort : public Port {
}
}
+ bool SetAlternateServer(const rtc::SocketAddress& address);
void ResolveTurnAddress(const rtc::SocketAddress& address);
void OnResolveResult(rtc::AsyncResolverInterface* resolver);
@@ -207,6 +219,7 @@ class TurnPort : public Port {
ProtocolAddress server_address_;
RelayCredentials credentials_;
+ AttemptedServerSet attempted_server_addresses_;
rtc::AsyncPacketSocket* socket_;
SocketOptionsMap socket_options_;
@@ -226,6 +239,9 @@ class TurnPort : public Port {
// calculating the candidate priority.
int server_priority_;
+ // The number of retries made due to allocate mismatch error.
+ size_t allocate_mismatch_retries_;
+
friend class TurnEntry;
friend class TurnAllocateRequest;
friend class TurnRefreshRequest;
diff --git a/p2p/base/turnport_unittest.cc b/p2p/base/turnport_unittest.cc
index 44dc64f..d895cbd 100644
--- a/p2p/base/turnport_unittest.cc
+++ b/p2p/base/turnport_unittest.cc
@@ -64,6 +64,8 @@ static const SocketAddress kTurnUdpIntAddr("99.99.99.3",
static const SocketAddress kTurnTcpIntAddr("99.99.99.4",
cricket::TURN_SERVER_PORT);
static const SocketAddress kTurnUdpExtAddr("99.99.99.5", 0);
+static const SocketAddress kTurnAlternateUdpIntAddr(
+ "99.99.99.6", cricket::TURN_SERVER_PORT);
static const SocketAddress kTurnUdpIPv6IntAddr(
"2400:4030:1:2c00:be30:abcd:efab:cdef", cricket::TURN_SERVER_PORT);
static const SocketAddress kTurnUdpIPv6ExtAddr(
@@ -208,10 +210,13 @@ class TurnPortTest : public testing::Test,
const cricket::ProtocolAddress& server_address) {
ASSERT(server_address.proto == cricket::PROTO_UDP);
- socket_.reset(socket_factory_.CreateUdpSocket(
- rtc::SocketAddress(kLocalAddr1.ipaddr(), 0), 0, 0));
- ASSERT_TRUE(socket_ != NULL);
- socket_->SignalReadPacket.connect(this, &TurnPortTest::OnSocketReadPacket);
+ if (!socket_) {
+ socket_.reset(socket_factory_.CreateUdpSocket(
+ rtc::SocketAddress(kLocalAddr1.ipaddr(), 0), 0, 0));
+ ASSERT_TRUE(socket_ != NULL);
+ socket_->SignalReadPacket.connect(
+ this, &TurnPortTest::OnSocketReadPacket);
+ }
cricket::RelayCredentials credentials(username, password);
turn_port_.reset(cricket::TurnPort::Create(
@@ -411,6 +416,80 @@ TEST_F(TurnPortTest, TestTurnAllocateBadPassword) {
ASSERT_EQ(0U, turn_port_->Candidates().size());
}
+// Tests that a new local address is created after
+// STUN_ERROR_ALLOCATION_MISMATCH.
+TEST_F(TurnPortTest, TestTurnAllocateMismatch) {
+ // Do a normal allocation first.
+ CreateTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr);
+ turn_port_->PrepareAddress();
+ EXPECT_TRUE_WAIT(turn_ready_, kTimeout);
+ rtc::SocketAddress first_addr(turn_port_->socket()->GetLocalAddress());
+
+ // Forces the socket server to assign the same port.
+ ss_->SetNextPortForTesting(first_addr.port());
+
+ turn_ready_ = false;
+ CreateTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr);
+ turn_port_->PrepareAddress();
+
+ // Verifies that the new port has the same address.
+ EXPECT_EQ(first_addr, turn_port_->socket()->GetLocalAddress());
+
+ EXPECT_TRUE_WAIT(turn_ready_, kTimeout);
+
+ // Verifies that the new port has a different address now.
+ EXPECT_NE(first_addr, turn_port_->socket()->GetLocalAddress());
+}
+
+// Tests that a shared-socket-TurnPort creates its own socket after
+// STUN_ERROR_ALLOCATION_MISMATCH.
+TEST_F(TurnPortTest, TestSharedSocketAllocateMismatch) {
+ // Do a normal allocation first.
+ CreateSharedTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr);
+ turn_port_->PrepareAddress();
+ EXPECT_TRUE_WAIT(turn_ready_, kTimeout);
+ rtc::SocketAddress first_addr(turn_port_->socket()->GetLocalAddress());
+
+ turn_ready_ = false;
+ CreateSharedTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr);
+
+ // Verifies that the new port has the same address.
+ EXPECT_EQ(first_addr, turn_port_->socket()->GetLocalAddress());
+ EXPECT_TRUE(turn_port_->SharedSocket());
+
+ turn_port_->PrepareAddress();
+ EXPECT_TRUE_WAIT(turn_ready_, kTimeout);
+
+ // Verifies that the new port has a different address now.
+ EXPECT_NE(first_addr, turn_port_->socket()->GetLocalAddress());
+ EXPECT_FALSE(turn_port_->SharedSocket());
+}
+
+TEST_F(TurnPortTest, TestTurnTcpAllocateMismatch) {
+ turn_server_.AddInternalSocket(kTurnTcpIntAddr, cricket::PROTO_TCP);
+ CreateTurnPort(kTurnUsername, kTurnPassword, kTurnTcpProtoAddr);
+
+ // Do a normal allocation first.
+ turn_port_->PrepareAddress();
+ EXPECT_TRUE_WAIT(turn_ready_, kTimeout);
+ rtc::SocketAddress first_addr(turn_port_->socket()->GetLocalAddress());
+
+ // Forces the socket server to assign the same port.
+ ss_->SetNextPortForTesting(first_addr.port());
+
+ turn_ready_ = false;
+ CreateTurnPort(kTurnUsername, kTurnPassword, kTurnTcpProtoAddr);
+ turn_port_->PrepareAddress();
+
+ // Verifies that the new port has the same address.
+ EXPECT_EQ(first_addr, turn_port_->socket()->GetLocalAddress());
+
+ EXPECT_TRUE_WAIT(turn_ready_, kTimeout);
+
+ // Verifies that the new port has a different address now.
+ EXPECT_NE(first_addr, turn_port_->socket()->GetLocalAddress());
+}
+
// Do a TURN allocation and try to send a packet to it from the outside.
// The packet should be dropped. Then, try to send a packet from TURN to the
// outside. It should reach its destination. Finally, try again from the
@@ -445,6 +524,103 @@ TEST_F(TurnPortTest, TestTurnTlsTcpConnectionFails) {
ASSERT_EQ(0U, turn_port_->Candidates().size());
}
+// Test try-alternate-server feature.
+TEST_F(TurnPortTest, TestTurnAlternateServer) {
+ std::vector<rtc::SocketAddress> redirect_addresses;
+ redirect_addresses.push_back(kTurnAlternateUdpIntAddr);
+
+ cricket::TestTurnRedirector redirector(redirect_addresses);
+ turn_server_.AddInternalSocket(kTurnAlternateUdpIntAddr,
+ cricket::PROTO_UDP);
+ turn_server_.set_redirect_hook(&redirector);
+ CreateTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr);
+
+ // Retrieve the address before we run the state machine.
+ const SocketAddress old_addr = turn_port_->server_address().address;
+
+ turn_port_->PrepareAddress();
+ EXPECT_TRUE_WAIT(turn_ready_, kTimeout);
+ // Retrieve the address again, the turn port's address should be
+ // changed.
+ const SocketAddress new_addr = turn_port_->server_address().address;
+ EXPECT_NE(old_addr, new_addr);
+ ASSERT_EQ(1U, turn_port_->Candidates().size());
+ EXPECT_EQ(kTurnUdpExtAddr.ipaddr(),
+ turn_port_->Candidates()[0].address().ipaddr());
+ EXPECT_NE(0, turn_port_->Candidates()[0].address().port());
+}
+
+// Test that we fail when we redirect to an address different from
+// current IP family.
+TEST_F(TurnPortTest, TestTurnAlternateServerV4toV6) {
+ std::vector<rtc::SocketAddress> redirect_addresses;
+ redirect_addresses.push_back(kTurnUdpIPv6IntAddr);
+
+ cricket::TestTurnRedirector redirector(redirect_addresses);
+ turn_server_.AddInternalSocket(kTurnAlternateUdpIntAddr,
+ cricket::PROTO_UDP);
+ turn_server_.set_redirect_hook(&redirector);
+ CreateTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr);
+ turn_port_->PrepareAddress();
+ EXPECT_TRUE_WAIT(turn_error_, kTimeout);
+}
+
+// Test that we fail to handle alternate-server response over TCP protocol.
+TEST_F(TurnPortTest, TestTurnAlternateServerTcp) {
+ std::vector<rtc::SocketAddress> redirect_addresses;
+ redirect_addresses.push_back(kTurnAlternateUdpIntAddr);
+
+ cricket::TestTurnRedirector redirector(redirect_addresses);
+ turn_server_.set_redirect_hook(&redirector);
+ turn_server_.AddInternalSocket(kTurnTcpIntAddr, cricket::PROTO_TCP);
+ CreateTurnPort(kTurnUsername, kTurnPassword, kTurnTcpProtoAddr);
+
+ turn_server_.AddInternalSocket(kTurnAlternateUdpIntAddr, cricket::PROTO_TCP);
+ turn_port_->PrepareAddress();
+ EXPECT_TRUE_WAIT(turn_error_, kTimeout);
+}
+
+// Test try-alternate-server catches the case of pingpong.
+TEST_F(TurnPortTest, TestTurnAlternateServerPingPong) {
+ std::vector<rtc::SocketAddress> redirect_addresses;
+ redirect_addresses.push_back(kTurnAlternateUdpIntAddr);
+ redirect_addresses.push_back(kTurnUdpIntAddr);
+
+ cricket::TestTurnRedirector redirector(redirect_addresses);
+
+ turn_server_.AddInternalSocket(kTurnAlternateUdpIntAddr,
+ cricket::PROTO_UDP);
+ turn_server_.set_redirect_hook(&redirector);
+ CreateTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr);
+
+ turn_port_->PrepareAddress();
+ EXPECT_TRUE_WAIT(turn_error_, kTimeout);
+ ASSERT_EQ(0U, turn_port_->Candidates().size());
+ rtc::SocketAddress address;
+ // Verify that we have exhausted all alternate servers instead of
+ // failure caused by other errors.
+ EXPECT_FALSE(redirector.ShouldRedirect(address, &address));
+}
+
+// Test try-alternate-server catch the case of repeated server.
+TEST_F(TurnPortTest, TestTurnAlternateServerDetectRepetition) {
+ std::vector<rtc::SocketAddress> redirect_addresses;
+ redirect_addresses.push_back(kTurnAlternateUdpIntAddr);
+ redirect_addresses.push_back(kTurnAlternateUdpIntAddr);
+
+ cricket::TestTurnRedirector redirector(redirect_addresses);
+
+ turn_server_.AddInternalSocket(kTurnAlternateUdpIntAddr,
+ cricket::PROTO_UDP);
+ turn_server_.set_redirect_hook(&redirector);
+ CreateTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr);
+
+ turn_port_->PrepareAddress();
+ EXPECT_TRUE_WAIT(turn_error_, kTimeout);
+ ASSERT_EQ(0U, turn_port_->Candidates().size());
+}
+
+
// Run TurnConnectionTest with one-time-use nonce feature.
// Here server will send a 438 STALE_NONCE error message for
// every TURN transaction.
@@ -515,4 +691,3 @@ TEST_F(TurnPortTest, TestResolverShutdown) {
EXPECT_EQ(last_fd_count, GetFDCount());
}
#endif
-
diff --git a/p2p/base/turnserver.cc b/p2p/base/turnserver.cc
index abc065a..dbcbcd4 100644
--- a/p2p/base/turnserver.cc
+++ b/p2p/base/turnserver.cc
@@ -62,9 +62,9 @@ inline bool IsTurnChannelData(uint16 msg_type) {
return ((msg_type & 0xC000) == 0x4000);
}
-// IDs used for posted messages.
+// IDs used for posted messages for TurnServer::Allocation.
enum {
- MSG_TIMEOUT,
+ MSG_ALLOCATION_TIMEOUT,
};
// Encapsulates a TURN allocation.
@@ -208,6 +208,7 @@ TurnServer::TurnServer(rtc::Thread* thread)
: thread_(thread),
nonce_key_(rtc::CreateRandomString(kNonceKeySize)),
auth_hook_(NULL),
+ redirect_hook_(NULL),
enable_otu_nonce_(false) {
}
@@ -316,6 +317,15 @@ void TurnServer::HandleStunMessage(Connection* conn, const char* data,
return;
}
+ if (redirect_hook_ != NULL && msg.type() == STUN_ALLOCATE_REQUEST) {
+ rtc::SocketAddress address;
+ if (redirect_hook_->ShouldRedirect(conn->src(), &address)) {
+ SendErrorResponseWithAlternateServer(
+ conn, &msg, address);
+ return;
+ }
+ }
+
// Look up the key that we'll use to validate the M-I. If we have an
// existing allocation, the key will already be cached.
Allocation* allocation = FindAllocation(conn);
@@ -334,7 +344,6 @@ void TurnServer::HandleStunMessage(Connection* conn, const char* data,
}
if (!allocation && msg.type() == STUN_ALLOCATE_REQUEST) {
- // This is a new allocate request.
HandleAllocateRequest(conn, &msg, key);
} else if (allocation &&
(msg.type() != STUN_ALLOCATE_REQUEST ||
@@ -551,6 +560,17 @@ void TurnServer::SendErrorResponseWithRealmAndNonce(
SendStun(conn, &resp);
}
+void TurnServer::SendErrorResponseWithAlternateServer(
+ Connection* conn, const StunMessage* msg,
+ const rtc::SocketAddress& addr) {
+ TurnMessage resp;
+ InitErrorResponse(msg, STUN_ERROR_TRY_ALTERNATE,
+ STUN_ERROR_REASON_TRY_ALTERNATE_SERVER, &resp);
+ VERIFY(resp.AddAttribute(new StunAddressAttribute(
+ STUN_ATTR_ALTERNATE_SERVER, addr)));
+ SendStun(conn, &resp);
+}
+
void TurnServer::SendStun(Connection* conn, StunMessage* msg) {
rtc::ByteBuffer buf;
// Add a SOFTWARE attribute if one is set.
@@ -588,7 +608,9 @@ void TurnServer::DestroyInternalSocket(rtc::AsyncPacketSocket* socket) {
InternalSocketMap::iterator iter = server_sockets_.find(socket);
if (iter != server_sockets_.end()) {
rtc::AsyncPacketSocket* socket = iter->first;
- delete socket;
+ // We must destroy the socket async to avoid invalidating the sigslot
+ // callback list iterator inside a sigslot callback.
+ rtc::Thread::Current()->Dispose(socket);
server_sockets_.erase(iter);
}
}
@@ -642,7 +664,7 @@ TurnServer::Allocation::~Allocation() {
it != perms_.end(); ++it) {
delete *it;
}
- thread_->Clear(this, MSG_TIMEOUT);
+ thread_->Clear(this, MSG_ALLOCATION_TIMEOUT);
LOG_J(LS_INFO, this) << "Allocation destroyed";
}
@@ -687,7 +709,7 @@ void TurnServer::Allocation::HandleAllocateRequest(const TurnMessage* msg) {
// Figure out the lifetime and start the allocation timer.
int lifetime_secs = ComputeLifetime(msg);
- thread_->PostDelayed(lifetime_secs * 1000, this, MSG_TIMEOUT);
+ thread_->PostDelayed(lifetime_secs * 1000, this, MSG_ALLOCATION_TIMEOUT);
LOG_J(LS_INFO, this) << "Created allocation, lifetime=" << lifetime_secs;
@@ -714,8 +736,8 @@ void TurnServer::Allocation::HandleRefreshRequest(const TurnMessage* msg) {
int lifetime_secs = ComputeLifetime(msg);
// Reset the expiration timer.
- thread_->Clear(this, MSG_TIMEOUT);
- thread_->PostDelayed(lifetime_secs * 1000, this, MSG_TIMEOUT);
+ thread_->Clear(this, MSG_ALLOCATION_TIMEOUT);
+ thread_->PostDelayed(lifetime_secs * 1000, this, MSG_ALLOCATION_TIMEOUT);
LOG_J(LS_INFO, this) << "Refreshed allocation, lifetime=" << lifetime_secs;
@@ -943,7 +965,7 @@ void TurnServer::Allocation::SendExternal(const void* data, size_t size,
}
void TurnServer::Allocation::OnMessage(rtc::Message* msg) {
- ASSERT(msg->message_id == MSG_TIMEOUT);
+ ASSERT(msg->message_id == MSG_ALLOCATION_TIMEOUT);
SignalDestroyed(this);
delete this;
}
@@ -968,16 +990,16 @@ TurnServer::Permission::Permission(rtc::Thread* thread,
}
TurnServer::Permission::~Permission() {
- thread_->Clear(this, MSG_TIMEOUT);
+ thread_->Clear(this, MSG_ALLOCATION_TIMEOUT);
}
void TurnServer::Permission::Refresh() {
- thread_->Clear(this, MSG_TIMEOUT);
- thread_->PostDelayed(kPermissionTimeout, this, MSG_TIMEOUT);
+ thread_->Clear(this, MSG_ALLOCATION_TIMEOUT);
+ thread_->PostDelayed(kPermissionTimeout, this, MSG_ALLOCATION_TIMEOUT);
}
void TurnServer::Permission::OnMessage(rtc::Message* msg) {
- ASSERT(msg->message_id == MSG_TIMEOUT);
+ ASSERT(msg->message_id == MSG_ALLOCATION_TIMEOUT);
SignalDestroyed(this);
delete this;
}
@@ -989,16 +1011,16 @@ TurnServer::Channel::Channel(rtc::Thread* thread, int id,
}
TurnServer::Channel::~Channel() {
- thread_->Clear(this, MSG_TIMEOUT);
+ thread_->Clear(this, MSG_ALLOCATION_TIMEOUT);
}
void TurnServer::Channel::Refresh() {
- thread_->Clear(this, MSG_TIMEOUT);
- thread_->PostDelayed(kChannelTimeout, this, MSG_TIMEOUT);
+ thread_->Clear(this, MSG_ALLOCATION_TIMEOUT);
+ thread_->PostDelayed(kChannelTimeout, this, MSG_ALLOCATION_TIMEOUT);
}
void TurnServer::Channel::OnMessage(rtc::Message* msg) {
- ASSERT(msg->message_id == MSG_TIMEOUT);
+ ASSERT(msg->message_id == MSG_ALLOCATION_TIMEOUT);
SignalDestroyed(this);
delete this;
}
diff --git a/p2p/base/turnserver.h b/p2p/base/turnserver.h
index 4798232..553d00c 100644
--- a/p2p/base/turnserver.h
+++ b/p2p/base/turnserver.h
@@ -63,6 +63,14 @@ class TurnAuthInterface {
std::string* key) = 0;
};
+// An interface enables Turn Server to control redirection behavior.
+class TurnRedirectInterface {
+ public:
+ virtual bool ShouldRedirect(const rtc::SocketAddress& address,
+ rtc::SocketAddress* out) = 0;
+ virtual ~TurnRedirectInterface() {}
+};
+
// The core TURN server class. Give it a socket to listen on via
// AddInternalServerSocket, and a factory to create external sockets via
// SetExternalSocketFactory, and it's ready to go.
@@ -83,6 +91,10 @@ class TurnServer : public sigslot::has_slots<> {
// Sets the authentication callback; does not take ownership.
void set_auth_hook(TurnAuthInterface* auth_hook) { auth_hook_ = auth_hook; }
+ void set_redirect_hook(TurnRedirectInterface* redirect_hook) {
+ redirect_hook_ = redirect_hook;
+ }
+
void set_enable_otu_nonce(bool enable) { enable_otu_nonce_ = enable; }
// Starts listening for packets from internal clients.
@@ -155,6 +167,11 @@ class TurnServer : public sigslot::has_slots<> {
const StunMessage* req,
int code,
const std::string& reason);
+
+ void SendErrorResponseWithAlternateServer(Connection* conn,
+ const StunMessage* req,
+ const rtc::SocketAddress& addr);
+
void SendStun(Connection* conn, StunMessage* msg);
void Send(Connection* conn, const rtc::ByteBuffer& buf);
@@ -171,14 +188,17 @@ class TurnServer : public sigslot::has_slots<> {
std::string realm_;
std::string software_;
TurnAuthInterface* auth_hook_;
+ TurnRedirectInterface* redirect_hook_;
// otu - one-time-use. Server will respond with 438 if it's
// sees the same nonce in next transaction.
bool enable_otu_nonce_;
+
InternalSocketMap server_sockets_;
ServerSocketMap server_listen_sockets_;
rtc::scoped_ptr<rtc::PacketSocketFactory>
external_socket_factory_;
rtc::SocketAddress external_addr_;
+
AllocationMap allocations_;
};
diff --git a/p2p/client/autoportallocator.h b/p2p/client/autoportallocator.h
index 298f829..ed87162 100644
--- a/p2p/client/autoportallocator.h
+++ b/p2p/client/autoportallocator.h
@@ -25,8 +25,8 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef TALK_EXAMPLES_LOGIN_AUTOPORTALLOCATOR_H_
-#define TALK_EXAMPLES_LOGIN_AUTOPORTALLOCATOR_H_
+#ifndef TALK_P2P_CLIENT_AUTOPORTALLOCATOR_H_
+#define TALK_P2P_CLIENT_AUTOPORTALLOCATOR_H_
#include <string>
#include <vector>
@@ -66,4 +66,4 @@ class AutoPortAllocator : public cricket::HttpPortAllocator {
}
};
-#endif // TALK_EXAMPLES_LOGIN_AUTOPORTALLOCATOR_H_
+#endif // TALK_P2P_CLIENT_AUTOPORTALLOCATOR_H_
diff --git a/p2p/client/basicportallocator.cc b/p2p/client/basicportallocator.cc
index d39db8f..0ec13e7 100644
--- a/p2p/client/basicportallocator.cc
+++ b/p2p/client/basicportallocator.cc
@@ -47,13 +47,15 @@ using rtc::CreateRandomString;
namespace {
-const uint32 MSG_CONFIG_START = 1;
-const uint32 MSG_CONFIG_READY = 2;
-const uint32 MSG_ALLOCATE = 3;
-const uint32 MSG_ALLOCATION_PHASE = 4;
-const uint32 MSG_SHAKE = 5;
-const uint32 MSG_SEQUENCEOBJECTS_CREATED = 6;
-const uint32 MSG_CONFIG_STOP = 7;
+enum {
+ MSG_CONFIG_START,
+ MSG_CONFIG_READY,
+ MSG_ALLOCATE,
+ MSG_ALLOCATION_PHASE,
+ MSG_SHAKE,
+ MSG_SEQUENCEOBJECTS_CREATED,
+ MSG_CONFIG_STOP,
+};
const int PHASE_UDP = 0;
const int PHASE_RELAY = 1;
@@ -147,9 +149,6 @@ class AllocationSequence : public rtc::MessageHandler,
const rtc::PacketTime& packet_time);
void OnPortDestroyed(PortInterface* port);
- void OnResolvedTurnServerAddress(
- TurnPort* port, const rtc::SocketAddress& server_address,
- const rtc::SocketAddress& resolved_server_address);
BasicPortAllocatorSession* session_;
rtc::Network* network_;
@@ -161,8 +160,7 @@ class AllocationSequence : public rtc::MessageHandler,
rtc::scoped_ptr<rtc::AsyncPacketSocket> udp_socket_;
// There will be only one udp port per AllocationSequence.
UDPPort* udp_port_;
- // Keeping a map for turn ports keyed with server addresses.
- std::map<rtc::SocketAddress, Port*> turn_ports_;
+ std::vector<TurnPort*> turn_ports_;
int phase_;
};
@@ -228,10 +226,11 @@ BasicPortAllocator::~BasicPortAllocator() {
PortAllocatorSession *BasicPortAllocator::CreateSessionInternal(
const std::string& content_name, int component,
const std::string& ice_ufrag, const std::string& ice_pwd) {
- return new BasicPortAllocatorSession(this, content_name, component,
- ice_ufrag, ice_pwd);
+ return new BasicPortAllocatorSession(
+ this, content_name, component, ice_ufrag, ice_pwd);
}
+
// BasicPortAllocatorSession
BasicPortAllocatorSession::BasicPortAllocatorSession(
BasicPortAllocator *allocator,
@@ -432,7 +431,11 @@ void BasicPortAllocatorSession::DoAllocate() {
}
if (!(sequence_flags & PORTALLOCATOR_ENABLE_IPV6) &&
+#ifdef USE_WEBRTC_DEV_BRANCH
+ networks[i]->GetBestIP().family() == AF_INET6) {
+#else // USE_WEBRTC_DEV_BRANCH
networks[i]->ip().family() == AF_INET6) {
+#endif // USE_WEBRTC_DEV_BRANCH
// Skip IPv6 networks unless the flag's been set.
continue;
}
@@ -530,8 +533,10 @@ void BasicPortAllocatorSession::OnCandidateReady(
// Send candidates whose protocol is enabled.
std::vector<Candidate> candidates;
ProtocolType pvalue;
+ bool candidate_allowed_to_send = CheckCandidateFilter(c);
if (StringToProto(c.protocol().c_str(), &pvalue) &&
- data->sequence()->ProtocolEnabled(pvalue)) {
+ data->sequence()->ProtocolEnabled(pvalue) &&
+ candidate_allowed_to_send) {
candidates.push_back(c);
}
@@ -542,7 +547,9 @@ void BasicPortAllocatorSession::OnCandidateReady(
// Moving to READY state as we have atleast one candidate from the port.
// Since this port has atleast one candidate we should forward this port
// to listners, to allow connections from this port.
- if (!data->ready()) {
+ // Also we should make sure that candidate gathered from this port is allowed
+ // to send outside.
+ if (!data->ready() && candidate_allowed_to_send) {
data->set_ready();
SignalPortReady(this, port);
}
@@ -588,6 +595,8 @@ void BasicPortAllocatorSession::OnProtocolEnabled(AllocationSequence* seq,
const std::vector<Candidate>& potentials = it->port()->Candidates();
for (size_t i = 0; i < potentials.size(); ++i) {
+ if (!CheckCandidateFilter(potentials[i]))
+ continue;
ProtocolType pvalue;
if (!StringToProto(potentials[i].protocol().c_str(), &pvalue))
continue;
@@ -602,6 +611,31 @@ void BasicPortAllocatorSession::OnProtocolEnabled(AllocationSequence* seq,
}
}
+bool BasicPortAllocatorSession::CheckCandidateFilter(const Candidate& c) {
+ uint32 filter = allocator_->candidate_filter();
+ bool allowed = false;
+ if (filter & CF_RELAY) {
+ allowed |= (c.type() == RELAY_PORT_TYPE);
+ }
+
+ if (filter & CF_REFLEXIVE) {
+ // We allow host candidates if the filter allows server-reflexive candidates
+ // and the candidate is a public IP. Because we don't generate
+ // server-reflexive candidates if they have the same IP as the host
+ // candidate (i.e. when the host candidate is a public IP), filtering to
+ // only server-reflexive candidates won't work right when the host
+ // candidates have public IPs.
+ allowed |= (c.type() == STUN_PORT_TYPE) ||
+ (c.type() == LOCAL_PORT_TYPE && !c.address().IsPrivateIP());
+ }
+
+ if (filter & CF_HOST) {
+ allowed |= (c.type() == LOCAL_PORT_TYPE);
+ }
+
+ return allowed;
+}
+
void BasicPortAllocatorSession::OnPortAllocationComplete(
AllocationSequence* seq) {
// Send candidate allocation complete signal if all ports are done.
@@ -698,7 +732,12 @@ AllocationSequence::AllocationSequence(BasicPortAllocatorSession* session,
uint32 flags)
: session_(session),
network_(network),
+
+#ifdef USE_WEBRTC_DEV_BRANCH
+ ip_(network->GetBestIP()),
+#else // USE_WEBRTC_DEV_BRANCH
ip_(network->ip()),
+#endif // USE_WEBRTC_DEV_BRANCH
config_(config),
state_(kInit),
flags_(flags),
@@ -741,7 +780,11 @@ AllocationSequence::~AllocationSequence() {
void AllocationSequence::DisableEquivalentPhases(rtc::Network* network,
PortConfiguration* config, uint32* flags) {
+#ifdef USE_WEBRTC_DEV_BRANCH
+ if (!((network == network_) && (ip_ == network->GetBestIP()))) {
+#else // USE_WEBRTC_DEV_BRANCH
if (!((network == network_) && (ip_ == network->ip()))) {
+#endif // USE_WEBRTC_DEV_BRANCH
// Different network setup; nothing is equivalent.
return;
}
@@ -1020,26 +1063,15 @@ void AllocationSequence::CreateTurnPort(const RelayServerConfig& config) {
// don't pass shared socket for ports which will create TCP sockets.
// TODO(mallinath) - Enable shared socket mode for TURN ports. Disabled
// due to webrtc bug https://code.google.com/p/webrtc/issues/detail?id=3537
- if (IsFlagSet(PORTALLOCATOR_ENABLE_TURN_SHARED_SOCKET) &&
+ if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET) &&
relay_port->proto == PROTO_UDP) {
port = TurnPort::Create(session_->network_thread(),
session_->socket_factory(),
network_, udp_socket_.get(),
session_->username(), session_->password(),
*relay_port, config.credentials, config.priority);
- // If we are using shared socket for TURN and udp ports, we need to
- // find a way to demux the packets to the correct port when received.
- // Mapping against server_address is one way of doing this. When packet
- // is received the remote_address will be checked against the map.
- // If server address is not resolved, a signal will be sent from the port
- // after the address is resolved. The map entry will updated with the
- // resolved address when the signal is received from the port.
- if ((*relay_port).address.IsUnresolved()) {
- // If server address is not resolved then listen for signal from port.
- port->SignalResolvedServerAddress.connect(
- this, &AllocationSequence::OnResolvedTurnServerAddress);
- }
- turn_ports_[(*relay_port).address] = port;
+
+ turn_ports_.push_back(port);
// Listen to the port destroyed signal, to allow AllocationSequence to
// remove entrt from it's map.
port->SignalDestroyed.connect(this, &AllocationSequence::OnPortDestroyed);
@@ -1063,51 +1095,45 @@ void AllocationSequence::OnReadPacket(
const rtc::SocketAddress& remote_addr,
const rtc::PacketTime& packet_time) {
ASSERT(socket == udp_socket_.get());
- // If the packet is received from one of the TURN server in the config, then
- // pass down the packet to that port, otherwise it will be handed down to
- // the local udp port.
- Port* port = NULL;
- std::map<rtc::SocketAddress, Port*>::iterator iter =
- turn_ports_.find(remote_addr);
- if (iter != turn_ports_.end()) {
- port = iter->second;
- } else if (udp_port_) {
- port = udp_port_;
+
+ bool turn_port_found = false;
+
+ // Try to find the TurnPort that matches the remote address. Note that the
+ // message could be a STUN binding response if the TURN server is also used as
+ // a STUN server. We don't want to parse every message here to check if it is
+ // a STUN binding response, so we pass the message to TurnPort regardless of
+ // the message type. The TurnPort will just ignore the message since it will
+ // not find any request by transaction ID.
+ for (std::vector<TurnPort*>::const_iterator it = turn_ports_.begin();
+ it != turn_ports_.end(); ++it) {
+ TurnPort* port = *it;
+ if (port->server_address().address == remote_addr) {
+ port->HandleIncomingPacket(socket, data, size, remote_addr, packet_time);
+ turn_port_found = true;
+ break;
+ }
}
- ASSERT(port != NULL);
- if (port) {
- port->HandleIncomingPacket(socket, data, size, remote_addr, packet_time);
+
+ if (udp_port_) {
+ const ServerAddresses& stun_servers = udp_port_->server_addresses();
+
+ // Pass the packet to the UdpPort if there is no matching TurnPort, or if
+ // the TURN server is also a STUN server.
+ if (!turn_port_found ||
+ stun_servers.find(remote_addr) != stun_servers.end()) {
+ udp_port_->HandleIncomingPacket(
+ socket, data, size, remote_addr, packet_time);
+ }
}
}
void AllocationSequence::OnPortDestroyed(PortInterface* port) {
if (udp_port_ == port) {
udp_port_ = NULL;
- } else {
- std::map<rtc::SocketAddress, Port*>::iterator iter;
- for (iter = turn_ports_.begin(); iter != turn_ports_.end(); ++iter) {
- if (iter->second == port) {
- turn_ports_.erase(iter);
- break;
- }
- }
- }
-}
-
-void AllocationSequence::OnResolvedTurnServerAddress(
- TurnPort* port, const rtc::SocketAddress& server_address,
- const rtc::SocketAddress& resolved_server_address) {
- std::map<rtc::SocketAddress, Port*>::iterator iter;
- iter = turn_ports_.find(server_address);
- if (iter == turn_ports_.end()) {
- LOG(LS_INFO) << "TurnPort entry is not found in the map.";
return;
}
- ASSERT(iter->second == port);
- // Remove old entry and then insert using the resolved address as key.
- turn_ports_.erase(iter);
- turn_ports_[resolved_server_address] = port;
+ turn_ports_.erase(std::find(turn_ports_.begin(), turn_ports_.end(), port));
}
// PortConfiguration
diff --git a/p2p/client/basicportallocator.h b/p2p/client/basicportallocator.h
index 5f43880..d424772 100644
--- a/p2p/client/basicportallocator.h
+++ b/p2p/client/basicportallocator.h
@@ -160,7 +160,6 @@ class BasicPortAllocatorSession : public PortAllocatorSession,
void set_ready() { ASSERT(state_ == STATE_INIT); state_ = STATE_READY; }
void set_complete() {
- ASSERT(state_ == STATE_READY);
state_ = STATE_COMPLETE;
}
void set_error() {
@@ -201,6 +200,8 @@ class BasicPortAllocatorSession : public PortAllocatorSession,
void OnPortAllocationComplete(AllocationSequence* seq);
PortData* FindPort(Port* port);
+ bool CheckCandidateFilter(const Candidate& c);
+
BasicPortAllocator* allocator_;
rtc::Thread* network_thread_;
rtc::scoped_ptr<rtc::PacketSocketFactory> owned_socket_factory_;
diff --git a/p2p/client/connectivitychecker.cc b/p2p/client/connectivitychecker.cc
index 06de5e4..723c5a1 100644
--- a/p2p/client/connectivitychecker.cc
+++ b/p2p/client/connectivitychecker.cc
@@ -1,5 +1,29 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-
+/*
+ * libjingle
+ * Copyright 2011, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
#include <string>
@@ -214,7 +238,12 @@ void ConnectivityChecker::OnRequestDone(rtc::AsyncHttpRequest* request) {
return;
}
rtc::ProxyInfo proxy_info = request->proxy();
- NicMap::iterator i = nics_.find(NicId(networks[0]->ip(), proxy_info.address));
+ NicMap::iterator i =
+#ifdef USE_WEBRTC_DEV_BRANCH
+ nics_.find(NicId(networks[0]->GetBestIP(), proxy_info.address));
+#else // USE_WEBRTC_DEV_BRANCH
+ nics_.find(NicId(networks[0]->ip(), proxy_info.address));
+#endif // USE_WEBRTC_DEV_BRANCH
if (i != nics_.end()) {
int port = request->port();
uint32 now = rtc::Time();
@@ -247,7 +276,11 @@ void ConnectivityChecker::OnRelayPortComplete(Port* port) {
ASSERT(worker_ == rtc::Thread::Current());
RelayPort* relay_port = reinterpret_cast<RelayPort*>(port);
const ProtocolAddress* address = relay_port->ServerAddress(0);
+#ifdef USE_WEBRTC_DEV_BRANCH
+ rtc::IPAddress ip = port->Network()->GetBestIP();
+#else // USE_WEBRTC_DEV_BRANCH
rtc::IPAddress ip = port->Network()->ip();
+#endif // USE_WEBRTC_DEV_BRANCH
NicMap::iterator i = nics_.find(NicId(ip, port->proxy().address));
if (i != nics_.end()) {
// We have it already, add the new information.
@@ -281,7 +314,11 @@ void ConnectivityChecker::OnStunPortComplete(Port* port) {
ASSERT(worker_ == rtc::Thread::Current());
const std::vector<Candidate> candidates = port->Candidates();
Candidate c = candidates[0];
+#ifdef USE_WEBRTC_DEV_BRANCH
+ rtc::IPAddress ip = port->Network()->GetBestIP();
+#else // USE_WEBRTC_DEV_BRANCH
rtc::IPAddress ip = port->Network()->ip();
+#endif // USE_WEBRTC_DEV_BRANCH
NicMap::iterator i = nics_.find(NicId(ip, port->proxy().address));
if (i != nics_.end()) {
// We have it already, add the new information.
@@ -300,7 +337,11 @@ void ConnectivityChecker::OnStunPortComplete(Port* port) {
void ConnectivityChecker::OnStunPortError(Port* port) {
ASSERT(worker_ == rtc::Thread::Current());
LOG(LS_ERROR) << "Stun address error.";
+#ifdef USE_WEBRTC_DEV_BRANCH
+ rtc::IPAddress ip = port->Network()->GetBestIP();
+#else // USE_WEBRTC_DEV_BRANCH
rtc::IPAddress ip = port->Network()->ip();
+#endif // USE_WEBRTC_DEV_BRANCH
NicMap::iterator i = nics_.find(NicId(ip, port->proxy().address));
if (i != nics_.end()) {
// We have it already, add the new information.
@@ -337,19 +378,36 @@ HttpPortAllocator* ConnectivityChecker::CreatePortAllocator(
StunPort* ConnectivityChecker::CreateStunPort(
const std::string& username, const std::string& password,
const PortConfiguration* config, rtc::Network* network) {
- return StunPort::Create(worker_, socket_factory_.get(),
- network, network->ip(), 0, 0,
- username, password, config->stun_servers);
+ return StunPort::Create(worker_,
+ socket_factory_.get(),
+ network,
+#ifdef USE_WEBRTC_DEV_BRANCH
+ network->GetBestIP(),
+#else // USE_WEBRTC_DEV_BRANCH
+ network->ip(),
+#endif // USE_WEBRTC_DEV_BRANCH
+ 0,
+ 0,
+ username,
+ password,
+ config->stun_servers);
}
RelayPort* ConnectivityChecker::CreateRelayPort(
const std::string& username, const std::string& password,
const PortConfiguration* config, rtc::Network* network) {
- return RelayPort::Create(worker_, socket_factory_.get(),
- network, network->ip(),
+ return RelayPort::Create(worker_,
+ socket_factory_.get(),
+ network,
+#ifdef USE_WEBRTC_DEV_BRANCH
+ network->GetBestIP(),
+#else // USE_WEBRTC_DEV_BRANCH
+ network->ip(),
+#endif // USE_WEBRTC_DEV_BRANCH
port_allocator_->min_port(),
port_allocator_->max_port(),
- username, password);
+ username,
+ password);
}
void ConnectivityChecker::CreateRelayPorts(
@@ -365,8 +423,12 @@ void ConnectivityChecker::CreateRelayPorts(
for (relay = config->relays.begin();
relay != config->relays.end(); ++relay) {
for (uint32 i = 0; i < networks.size(); ++i) {
- NicMap::iterator iter = nics_.find(NicId(networks[i]->ip(),
- proxy_info.address));
+ NicMap::iterator iter =
+#ifdef USE_WEBRTC_DEV_BRANCH
+ nics_.find(NicId(networks[i]->GetBestIP(), proxy_info.address));
+#else // USE_WEBRTC_DEV_BRANCH
+ nics_.find(NicId(networks[i]->ip(), proxy_info.address));
+#endif // USE_WEBRTC_DEV_BRANCH
if (iter != nics_.end()) {
// TODO: Now setting the same start time for all protocols.
// This might affect accuracy, but since we are mainly looking for
@@ -423,7 +485,11 @@ void ConnectivityChecker::AllocatePorts() {
rtc::ProxyInfo proxy_info = GetProxyInfo();
bool allocate_relay_ports = false;
for (uint32 i = 0; i < networks.size(); ++i) {
+#ifdef USE_WEBRTC_DEV_BRANCH
+ if (AddNic(networks[i]->GetBestIP(), proxy_info.address)) {
+#else // USE_WEBRTC_DEV_BRANCH
if (AddNic(networks[i]->ip(), proxy_info.address)) {
+#endif // USE_WEBRTC_DEV_BRANCH
Port* port = CreateStunPort(username, password, &config, networks[i]);
if (port) {
@@ -500,7 +566,12 @@ void ConnectivityChecker::RegisterHttpStart(int port) {
return;
}
rtc::ProxyInfo proxy_info = GetProxyInfo();
- NicMap::iterator i = nics_.find(NicId(networks[0]->ip(), proxy_info.address));
+ NicMap::iterator i =
+#ifdef USE_WEBRTC_DEV_BRANCH
+ nics_.find(NicId(networks[0]->GetBestIP(), proxy_info.address));
+#else // USE_WEBRTC_DEV_BRANCH
+ nics_.find(NicId(networks[0]->ip(), proxy_info.address));
+#endif // USE_WEBRTC_DEV_BRANCH
if (i != nics_.end()) {
uint32 now = rtc::Time();
NicInfo* nic_info = &i->second;
diff --git a/p2p/client/connectivitychecker_unittest.cc b/p2p/client/connectivitychecker_unittest.cc
index b96cf17..187505a 100644
--- a/p2p/client/connectivitychecker_unittest.cc
+++ b/p2p/client/connectivitychecker_unittest.cc
@@ -1,5 +1,29 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-
+/*
+ * libjingle
+ * Copyright 2011, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
#include <string>
@@ -211,19 +235,35 @@ class ConnectivityCheckerForTest : public ConnectivityChecker {
virtual StunPort* CreateStunPort(
const std::string& username, const std::string& password,
const PortConfiguration* config, rtc::Network* network) {
- return new FakeStunPort(worker(), socket_factory_,
- network, network->ip(),
- kMinPort, kMaxPort,
- username, password,
+ return new FakeStunPort(worker(),
+ socket_factory_,
+ network,
+#ifdef USE_WEBRTC_DEV_BRANCH
+ network->GetBestIP(),
+#else // USE_WEBRTC_DEV_BRANCH
+ network->ip(),
+#endif // USE_WEBRTC_DEV_BRANCH
+ kMinPort,
+ kMaxPort,
+ username,
+ password,
config->stun_servers);
}
virtual RelayPort* CreateRelayPort(
const std::string& username, const std::string& password,
const PortConfiguration* config, rtc::Network* network) {
- return new FakeRelayPort(worker(), socket_factory_,
- network, network->ip(),
- kMinPort, kMaxPort,
- username, password);
+ return new FakeRelayPort(worker(),
+ socket_factory_,
+ network,
+#ifdef USE_WEBRTC_DEV_BRANCH
+ network->GetBestIP(),
+#else // USE_WEBRTC_DEV_BRANCH
+ network->ip(),
+#endif // USE_WEBRTC_DEV_BRANCH
+ kMinPort,
+ kMaxPort,
+ username,
+ password);
}
virtual void InitiateProxyDetection() {
if (!proxy_initiated_) {
diff --git a/p2p/client/fakeportallocator.h b/p2p/client/fakeportallocator.h
index 6c36c4e..e1a04dd 100644
--- a/p2p/client/fakeportallocator.h
+++ b/p2p/client/fakeportallocator.h
@@ -1,6 +1,29 @@
-// Copyright 2010 Google Inc. All Rights Reserved,
-//
-// Author: Justin Uberti (juberti@google.com)
+/*
+ * libjingle
+ * Copyright 2010, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
#ifndef TALK_P2P_CLIENT_FAKEPORTALLOCATOR_H_
#define TALK_P2P_CLIENT_FAKEPORTALLOCATOR_H_
@@ -39,10 +62,18 @@ class FakePortAllocatorSession : public PortAllocatorSession {
virtual void StartGettingPorts() {
if (!port_) {
- port_.reset(cricket::UDPPort::Create(worker_thread_, factory_,
- &network_, network_.ip(), 0, 0,
- username(),
- password()));
+ port_.reset(cricket::UDPPort::Create(worker_thread_,
+ factory_,
+ &network_,
+#ifdef USE_WEBRTC_DEV_BRANCH
+ network_.GetBestIP(),
+#else // USE_WEBRTC_DEV_BRANCH
+ network_.ip(),
+#endif // USE_WEBRTC_DEV_BRANCH
+ 0,
+ 0,
+ username(),
+ password()));
AddPort(port_.get());
}
++port_config_count_;
diff --git a/p2p/client/portallocator_unittest.cc b/p2p/client/portallocator_unittest.cc
index 57cfbe3..e793064 100644
--- a/p2p/client/portallocator_unittest.cc
+++ b/p2p/client/portallocator_unittest.cc
@@ -53,6 +53,7 @@ using rtc::SocketAddress;
using rtc::Thread;
static const SocketAddress kClientAddr("11.11.11.11", 0);
+static const SocketAddress kPrivateAddr("192.168.1.11", 0);
static const SocketAddress kClientIPv6Addr(
"2401:fa00:4:1000:be30:5bff:fee5:c3", 0);
static const SocketAddress kClientAddr2("22.22.22.22", 0);
@@ -132,9 +133,32 @@ class PortAllocatorTest : public testing::Test, public sigslot::has_slots<> {
bool SetPortRange(int min_port, int max_port) {
return allocator_->SetPortRange(min_port, max_port);
}
- rtc::NATServer* CreateNatServer(const SocketAddress& addr,
- rtc::NATType type) {
- return new rtc::NATServer(type, vss_.get(), addr, vss_.get(), addr);
+ void ResetWithNatServer(const rtc::SocketAddress& stun_server) {
+ nat_server_.reset(new rtc::NATServer(
+ rtc::NAT_OPEN_CONE, vss_.get(), kNatAddr, vss_.get(), kNatAddr));
+
+ ServerAddresses stun_servers;
+ stun_servers.insert(stun_server);
+ allocator_.reset(new cricket::BasicPortAllocator(
+ &network_manager_, &nat_socket_factory_, stun_servers));
+ allocator().set_step_delay(cricket::kMinimumStepDelay);
+ }
+
+ void AddTurnServers(const rtc::SocketAddress& udp_turn,
+ const rtc::SocketAddress& tcp_turn) {
+ cricket::RelayServerConfig relay_server(cricket::RELAY_TURN);
+ cricket::RelayCredentials credentials(kTurnUsername, kTurnPassword);
+ relay_server.credentials = credentials;
+
+ if (!udp_turn.IsNil()) {
+ relay_server.ports.push_back(cricket::ProtocolAddress(
+ kTurnUdpIntAddr, cricket::PROTO_UDP, false));
+ }
+ if (!tcp_turn.IsNil()) {
+ relay_server.ports.push_back(cricket::ProtocolAddress(
+ kTurnTcpIntAddr, cricket::PROTO_TCP, false));
+ }
+ allocator_->AddRelay(relay_server);
}
bool CreateSession(int component) {
@@ -253,6 +277,7 @@ class PortAllocatorTest : public testing::Test, public sigslot::has_slots<> {
rtc::scoped_ptr<rtc::VirtualSocketServer> vss_;
rtc::scoped_ptr<rtc::FirewallSocketServer> fss_;
rtc::SocketServerScope ss_scope_;
+ rtc::scoped_ptr<rtc::NATServer> nat_server_;
rtc::NATSocketFactory nat_factory_;
rtc::BasicPacketSocketFactory nat_socket_factory_;
cricket::TestStunServer stun_server_;
@@ -538,7 +563,7 @@ TEST_F(PortAllocatorTest, TestCandidatePriorityOfMultipleInterfaces) {
// Test to verify ICE restart process.
TEST_F(PortAllocatorTest, TestGetAllPortsRestarts) {
AddInterface(kClientAddr);
- EXPECT_TRUE(CreateSession(1));
+ EXPECT_TRUE(CreateSession(cricket::ICE_CANDIDATE_COMPONENT_RTP));
session_->StartGettingPorts();
EXPECT_EQ_WAIT(7U, candidates_.size(), kDefaultAllocationTimeout);
EXPECT_EQ(4U, ports_.size());
@@ -546,6 +571,73 @@ TEST_F(PortAllocatorTest, TestGetAllPortsRestarts) {
// TODO - Extend this to verify ICE restart.
}
+// Test ICE candidate filter mechanism with options Relay/Host/Reflexive.
+TEST_F(PortAllocatorTest, TestCandidateFilterWithRelayOnly) {
+ AddInterface(kClientAddr);
+ allocator().set_candidate_filter(cricket::CF_RELAY);
+ EXPECT_TRUE(CreateSession(cricket::ICE_CANDIDATE_COMPONENT_RTP));
+ session_->StartGettingPorts();
+ EXPECT_TRUE_WAIT(candidate_allocation_done_, kDefaultAllocationTimeout);
+ // Using GTURN, we will have 4 candidates.
+ EXPECT_EQ(4U, candidates_.size());
+ EXPECT_EQ(1U, ports_.size()); // Only Relay port will be in ready state.
+ for (size_t i = 0; i < candidates_.size(); ++i) {
+ EXPECT_EQ(std::string(cricket::RELAY_PORT_TYPE), candidates_[i].type());
+ }
+}
+
+TEST_F(PortAllocatorTest, TestCandidateFilterWithHostOnly) {
+ AddInterface(kClientAddr);
+ allocator().set_flags(cricket::PORTALLOCATOR_ENABLE_SHARED_UFRAG |
+ cricket::PORTALLOCATOR_ENABLE_SHARED_SOCKET);
+ allocator().set_candidate_filter(cricket::CF_HOST);
+ EXPECT_TRUE(CreateSession(cricket::ICE_CANDIDATE_COMPONENT_RTP));
+ session_->StartGettingPorts();
+ EXPECT_TRUE_WAIT(candidate_allocation_done_, kDefaultAllocationTimeout);
+ EXPECT_EQ(2U, candidates_.size()); // Host UDP/TCP candidates only.
+ EXPECT_EQ(2U, ports_.size()); // UDP/TCP ports only.
+ for (size_t i = 0; i < candidates_.size(); ++i) {
+ EXPECT_EQ(std::string(cricket::LOCAL_PORT_TYPE), candidates_[i].type());
+ }
+}
+
+// Host is behind the NAT.
+TEST_F(PortAllocatorTest, TestCandidateFilterWithReflexiveOnly) {
+ AddInterface(kPrivateAddr);
+ ResetWithNatServer(kStunAddr);
+
+ allocator().set_flags(cricket::PORTALLOCATOR_ENABLE_SHARED_UFRAG |
+ cricket::PORTALLOCATOR_ENABLE_SHARED_SOCKET);
+ allocator().set_candidate_filter(cricket::CF_REFLEXIVE);
+ EXPECT_TRUE(CreateSession(cricket::ICE_CANDIDATE_COMPONENT_RTP));
+ session_->StartGettingPorts();
+ EXPECT_TRUE_WAIT(candidate_allocation_done_, kDefaultAllocationTimeout);
+ // Host is behind NAT, no private address will be exposed. Hence only UDP
+ // port with STUN candidate will be sent outside.
+ EXPECT_EQ(1U, candidates_.size()); // Only STUN candidate.
+ EXPECT_EQ(1U, ports_.size()); // Only UDP port will be in ready state.
+ for (size_t i = 0; i < candidates_.size(); ++i) {
+ EXPECT_EQ(std::string(cricket::STUN_PORT_TYPE), candidates_[i].type());
+ }
+}
+
+// Host is not behind the NAT.
+TEST_F(PortAllocatorTest, TestCandidateFilterWithReflexiveOnlyAndNoNAT) {
+ AddInterface(kClientAddr);
+ allocator().set_flags(cricket::PORTALLOCATOR_ENABLE_SHARED_UFRAG |
+ cricket::PORTALLOCATOR_ENABLE_SHARED_SOCKET);
+ allocator().set_candidate_filter(cricket::CF_REFLEXIVE);
+ EXPECT_TRUE(CreateSession(cricket::ICE_CANDIDATE_COMPONENT_RTP));
+ session_->StartGettingPorts();
+ EXPECT_TRUE_WAIT(candidate_allocation_done_, kDefaultAllocationTimeout);
+ // Host has a public address, both UDP and TCP candidates will be exposed.
+ EXPECT_EQ(2U, candidates_.size()); // Local UDP + TCP candidate.
+ EXPECT_EQ(2U, ports_.size()); // UDP and TCP ports will be in ready state.
+ for (size_t i = 0; i < candidates_.size(); ++i) {
+ EXPECT_EQ(std::string(cricket::LOCAL_PORT_TYPE), candidates_[i].type());
+ }
+}
+
TEST_F(PortAllocatorTest, TestBasicMuxFeatures) {
AddInterface(kClientAddr);
allocator().set_flags(cricket::PORTALLOCATOR_ENABLE_BUNDLE);
@@ -698,13 +790,8 @@ TEST_F(PortAllocatorTest, TestSharedSocketWithoutNat) {
// local candidates as client behind a nat.
TEST_F(PortAllocatorTest, TestSharedSocketWithNat) {
AddInterface(kClientAddr);
- rtc::scoped_ptr<rtc::NATServer> nat_server(
- CreateNatServer(kNatAddr, rtc::NAT_OPEN_CONE));
- ServerAddresses stun_servers;
- stun_servers.insert(kStunAddr);
- allocator_.reset(new cricket::BasicPortAllocator(
- &network_manager_, &nat_socket_factory_, stun_servers));
- allocator_->set_step_delay(cricket::kMinimumStepDelay);
+ ResetWithNatServer(kStunAddr);
+
allocator_->set_flags(allocator().flags() |
cricket::PORTALLOCATOR_ENABLE_SHARED_UFRAG |
cricket::PORTALLOCATOR_ENABLE_SHARED_SOCKET);
@@ -726,14 +813,8 @@ TEST_F(PortAllocatorTest, TestSharedSocketWithoutNatUsingTurn) {
turn_server_.AddInternalSocket(kTurnTcpIntAddr, cricket::PROTO_TCP);
AddInterface(kClientAddr);
allocator_.reset(new cricket::BasicPortAllocator(&network_manager_));
- cricket::RelayServerConfig relay_server(cricket::RELAY_TURN);
- cricket::RelayCredentials credentials(kTurnUsername, kTurnPassword);
- relay_server.credentials = credentials;
- relay_server.ports.push_back(cricket::ProtocolAddress(
- kTurnUdpIntAddr, cricket::PROTO_UDP, false));
- relay_server.ports.push_back(cricket::ProtocolAddress(
- kTurnTcpIntAddr, cricket::PROTO_TCP, false));
- allocator_->AddRelay(relay_server);
+
+ AddTurnServers(kTurnUdpIntAddr, kTurnTcpIntAddr);
allocator_->set_step_delay(cricket::kMinimumStepDelay);
allocator_->set_flags(allocator().flags() |
@@ -790,20 +871,10 @@ TEST_F(PortAllocatorTest, TestSharedSocketWithServerAddressResolve) {
// stun and turn candidates.
TEST_F(PortAllocatorTest, TestSharedSocketWithNatUsingTurn) {
AddInterface(kClientAddr);
- rtc::scoped_ptr<rtc::NATServer> nat_server(
- CreateNatServer(kNatAddr, rtc::NAT_OPEN_CONE));
- ServerAddresses stun_servers;
- stun_servers.insert(kStunAddr);
- allocator_.reset(new cricket::BasicPortAllocator(
- &network_manager_, &nat_socket_factory_, stun_servers));
- cricket::RelayServerConfig relay_server(cricket::RELAY_TURN);
- cricket::RelayCredentials credentials(kTurnUsername, kTurnPassword);
- relay_server.credentials = credentials;
- relay_server.ports.push_back(cricket::ProtocolAddress(
- kTurnUdpIntAddr, cricket::PROTO_UDP, false));
- allocator_->AddRelay(relay_server);
+ ResetWithNatServer(kStunAddr);
+
+ AddTurnServers(kTurnUdpIntAddr, rtc::SocketAddress());
- allocator_->set_step_delay(cricket::kMinimumStepDelay);
allocator_->set_flags(allocator().flags() |
cricket::PORTALLOCATOR_ENABLE_SHARED_UFRAG |
cricket::PORTALLOCATOR_ENABLE_SHARED_SOCKET |
@@ -829,6 +900,45 @@ TEST_F(PortAllocatorTest, TestSharedSocketWithNatUsingTurn) {
EXPECT_EQ(1U, ports_[1]->Candidates().size());
}
+// Test that when PORTALLOCATOR_ENABLE_SHARED_SOCKET is enabled and the TURN
+// server is also used as the STUN server, we should get 'local', 'stun', and
+// 'relay' candidates.
+TEST_F(PortAllocatorTest, TestSharedSocketWithNatUsingTurnAsStun) {
+ AddInterface(kClientAddr);
+ ResetWithNatServer(kTurnUdpIntAddr);
+ AddTurnServers(kTurnUdpIntAddr, rtc::SocketAddress());
+
+ // Must set the step delay to 0 to make sure the relay allocation phase is
+ // started before the STUN candidates are obtained, so that the STUN binding
+ // response is processed when both StunPort and TurnPort exist to reproduce
+ // webrtc issue 3537.
+ allocator_->set_step_delay(0);
+ allocator_->set_flags(allocator().flags() |
+ cricket::PORTALLOCATOR_ENABLE_SHARED_UFRAG |
+ cricket::PORTALLOCATOR_ENABLE_SHARED_SOCKET |
+ cricket::PORTALLOCATOR_DISABLE_TCP);
+
+ EXPECT_TRUE(CreateSession(cricket::ICE_CANDIDATE_COMPONENT_RTP));
+ session_->StartGettingPorts();
+
+ ASSERT_EQ_WAIT(3U, candidates_.size(), kDefaultAllocationTimeout);
+ EXPECT_PRED5(CheckCandidate, candidates_[0],
+ cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "udp", kClientAddr);
+ EXPECT_PRED5(CheckCandidate, candidates_[1],
+ cricket::ICE_CANDIDATE_COMPONENT_RTP, "stun", "udp",
+ rtc::SocketAddress(kNatAddr.ipaddr(), 0));
+ EXPECT_PRED5(CheckCandidate, candidates_[2],
+ cricket::ICE_CANDIDATE_COMPONENT_RTP, "relay", "udp",
+ rtc::SocketAddress(kTurnUdpExtAddr.ipaddr(), 0));
+ EXPECT_EQ(candidates_[2].related_address(), candidates_[1].address());
+
+ EXPECT_TRUE_WAIT(candidate_allocation_done_, kDefaultAllocationTimeout);
+ EXPECT_EQ(3U, candidates_.size());
+ // Local port will be created first and then TURN port.
+ EXPECT_EQ(2U, ports_[0]->Candidates().size());
+ EXPECT_EQ(1U, ports_[1]->Candidates().size());
+}
+
// This test verifies when PORTALLOCATOR_ENABLE_SHARED_SOCKET flag is enabled
// and fail to generate STUN candidate, local UDP candidate is generated
// properly.
diff --git a/p2p/client/sessionmanagertask.h b/p2p/client/sessionmanagertask.h
index d7d9733..e16d9d6 100644
--- a/p2p/client/sessionmanagertask.h
+++ b/p2p/client/sessionmanagertask.h
@@ -25,8 +25,8 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef _SESSIONMANAGERTASK_H_
-#define _SESSIONMANAGERTASK_H_
+#ifndef TALK_P2P_CLIENT_SESSIONMANAGERTASK_H_
+#define TALK_P2P_CLIENT_SESSIONMANAGERTASK_H_
#include "talk/p2p/base/sessionmanager.h"
#include "talk/p2p/client/sessionsendtask.h"
@@ -90,4 +90,4 @@ class SessionManagerTask : public buzz::XmppTask {
} // namespace cricket
-#endif // _SESSIONMANAGERTASK_H_
+#endif // TALK_P2P_CLIENT_SESSIONMANAGERTASK_H_