diff options
-rw-r--r-- | examples/BUILD.gn | 14 | ||||
-rw-r--r-- | examples/relayserver/relayserver_main.cc | 66 | ||||
-rw-r--r-- | p2p/BUILD.gn | 7 | ||||
-rw-r--r-- | p2p/base/p2p_transport_channel_unittest.cc | 7 | ||||
-rw-r--r-- | p2p/base/port.h | 5 | ||||
-rw-r--r-- | p2p/base/port_allocator.cc | 4 | ||||
-rw-r--r-- | p2p/base/port_allocator.h | 5 | ||||
-rw-r--r-- | p2p/base/port_unittest.cc | 190 | ||||
-rw-r--r-- | p2p/base/regathering_controller_unittest.cc | 2 | ||||
-rw-r--r-- | p2p/base/relay_port.cc | 860 | ||||
-rw-r--r-- | p2p/base/relay_port.h | 118 | ||||
-rw-r--r-- | p2p/base/relay_port_unittest.cc | 272 | ||||
-rw-r--r-- | p2p/base/relay_server.cc | 741 | ||||
-rw-r--r-- | p2p/base/relay_server.h | 235 | ||||
-rw-r--r-- | p2p/base/relay_server_unittest.cc | 511 | ||||
-rw-r--r-- | p2p/base/test_relay_server.h | 101 | ||||
-rw-r--r-- | p2p/client/basic_port_allocator.cc | 48 | ||||
-rw-r--r-- | p2p/client/basic_port_allocator.h | 6 | ||||
-rw-r--r-- | p2p/client/basic_port_allocator_unittest.cc | 5 |
19 files changed, 52 insertions, 3145 deletions
diff --git a/examples/BUILD.gn b/examples/BUILD.gn index 7b69c2b85c..6c3c6581f1 100644 --- a/examples/BUILD.gn +++ b/examples/BUILD.gn @@ -47,7 +47,6 @@ group("examples") { if (is_linux || is_win) { deps += [ ":peerconnection_server", - ":relayserver", ":stunserver", ":turnserver", ] @@ -740,19 +739,6 @@ if (is_linux || is_win) { "//third_party/abseil-cpp/absl/flags:usage", ] } - rtc_executable("relayserver") { - testonly = true - sources = [ - "relayserver/relayserver_main.cc", - ] - deps = [ - "../p2p:p2p_server_utils", - "../p2p:rtc_p2p", - "../pc:rtc_pc", - "../rtc_base", - "../rtc_base:rtc_base_approved", - ] - } rtc_executable("turnserver") { testonly = true sources = [ diff --git a/examples/relayserver/relayserver_main.cc b/examples/relayserver/relayserver_main.cc deleted file mode 100644 index 2045cb4031..0000000000 --- a/examples/relayserver/relayserver_main.cc +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include <iostream> // NOLINT -#include <memory> - -#include "p2p/base/relay_server.h" -#include "rtc_base/async_udp_socket.h" -#include "rtc_base/socket_address.h" -#include "rtc_base/socket_server.h" -#include "rtc_base/thread.h" - -int main(int argc, char** argv) { - if (argc != 3) { - std::cerr << "usage: relayserver internal-address external-address" - << std::endl; - return 1; - } - - rtc::SocketAddress int_addr; - if (!int_addr.FromString(argv[1])) { - std::cerr << "Unable to parse IP address: " << argv[1]; - return 1; - } - - rtc::SocketAddress ext_addr; - if (!ext_addr.FromString(argv[2])) { - std::cerr << "Unable to parse IP address: " << argv[2]; - return 1; - } - - rtc::Thread* pthMain = rtc::Thread::Current(); - - std::unique_ptr<rtc::AsyncUDPSocket> int_socket( - rtc::AsyncUDPSocket::Create(pthMain->socketserver(), int_addr)); - if (!int_socket) { - std::cerr << "Failed to create a UDP socket bound at" << int_addr.ToString() - << std::endl; - return 1; - } - - std::unique_ptr<rtc::AsyncUDPSocket> ext_socket( - rtc::AsyncUDPSocket::Create(pthMain->socketserver(), ext_addr)); - if (!ext_socket) { - std::cerr << "Failed to create a UDP socket bound at" << ext_addr.ToString() - << std::endl; - return 1; - } - - cricket::RelayServer server(pthMain); - server.AddInternalSocket(int_socket.get()); - server.AddExternalSocket(ext_socket.get()); - - std::cout << "Listening internally at " << int_addr.ToString() << std::endl; - std::cout << "Listening externally at " << ext_addr.ToString() << std::endl; - - pthMain->Run(); - return 0; -} diff --git a/p2p/BUILD.gn b/p2p/BUILD.gn index 0b3d28c404..8c4b6f636b 100644 --- a/p2p/BUILD.gn +++ b/p2p/BUILD.gn @@ -70,8 +70,6 @@ rtc_library("rtc_p2p") { "base/pseudo_tcp.h", "base/regathering_controller.cc", "base/regathering_controller.h", - "base/relay_port.cc", - "base/relay_port.h", "base/stun_port.cc", "base/stun_port.h", "base/stun_request.cc", @@ -160,7 +158,6 @@ if (rtc_include_tests) { "base/fake_packet_transport.h", "base/mock_async_resolver.h", "base/mock_ice_transport.h", - "base/test_relay_server.h", "base/test_stun_server.cc", "base/test_stun_server.h", "base/test_turn_customizer.h", @@ -200,8 +197,6 @@ if (rtc_include_tests) { "base/port_unittest.cc", "base/pseudo_tcp_unittest.cc", "base/regathering_controller_unittest.cc", - "base/relay_port_unittest.cc", - "base/relay_server_unittest.cc", "base/stun_port_unittest.cc", "base/stun_request_unittest.cc", "base/stun_server_unittest.cc", @@ -244,8 +239,6 @@ if (rtc_include_tests) { rtc_library("p2p_server_utils") { testonly = true sources = [ - "base/relay_server.cc", - "base/relay_server.h", "base/stun_server.cc", "base/stun_server.h", "base/turn_server.cc", diff --git a/p2p/base/p2p_transport_channel_unittest.cc b/p2p/base/p2p_transport_channel_unittest.cc index 3919b3f068..76030189ff 100644 --- a/p2p/base/p2p_transport_channel_unittest.cc +++ b/p2p/base/p2p_transport_channel_unittest.cc @@ -19,7 +19,6 @@ #include "p2p/base/ice_transport_internal.h" #include "p2p/base/mock_async_resolver.h" #include "p2p/base/packet_transport_internal.h" -#include "p2p/base/test_relay_server.h" #include "p2p/base/test_stun_server.h" #include "p2p/base/test_turn_server.h" #include "p2p/client/basic_port_allocator.h" @@ -156,7 +155,7 @@ cricket::BasicPortAllocator* CreateBasicPortAllocator( const cricket::ServerAddresses& stun_servers, const rtc::SocketAddress& turn_server_udp, const rtc::SocketAddress& turn_server_tcp) { - cricket::RelayServerConfig turn_server(cricket::RELAY_TURN); + cricket::RelayServerConfig turn_server; turn_server.credentials = kRelayCredentials; if (!turn_server_udp.IsNil()) { turn_server.ports.push_back( @@ -2578,7 +2577,7 @@ TEST_F(P2PTransportChannelMultihomedTest, TestFailoverControllingSide) { TEST_F(P2PTransportChannelMultihomedTest, TestFailoverWithManyConnections) { rtc::ScopedFakeClock clock; test_turn_server()->AddInternalSocket(kTurnTcpIntAddr, PROTO_TCP); - RelayServerConfig turn_server(RELAY_TURN); + RelayServerConfig turn_server; turn_server.credentials = kRelayCredentials; turn_server.ports.push_back(ProtocolAddress(kTurnTcpIntAddr, PROTO_TCP)); GetAllocator(0)->AddTurnServer(turn_server); @@ -4757,7 +4756,7 @@ TEST_F(P2PTransportChannelMostLikelyToWorkFirstTest, TEST_F(P2PTransportChannelMostLikelyToWorkFirstTest, TestTcpTurn) { // Add a Tcp Turn server. turn_server()->AddInternalSocket(kTurnTcpIntAddr, PROTO_TCP); - RelayServerConfig config(RELAY_TURN); + RelayServerConfig config; config.credentials = kRelayCredentials; config.ports.push_back(ProtocolAddress(kTurnTcpIntAddr, PROTO_TCP)); allocator()->AddTurnServer(config); diff --git a/p2p/base/port.h b/p2p/base/port.h index dde991aa98..5bd59d0e4d 100644 --- a/p2p/base/port.h +++ b/p2p/base/port.h @@ -57,11 +57,6 @@ extern const char TCPTYPE_ACTIVE_STR[]; extern const char TCPTYPE_PASSIVE_STR[]; extern const char TCPTYPE_SIMOPEN_STR[]; -enum RelayType { - RELAY_GTURN, // Legacy google relay service. - RELAY_TURN // Standard (TURN) relay service. -}; - enum IcePriorityValue { ICE_TYPE_PREFERENCE_RELAY_TLS = 0, ICE_TYPE_PREFERENCE_RELAY_TCP = 1, diff --git a/p2p/base/port_allocator.cc b/p2p/base/port_allocator.cc index b30416fdd3..b13896c4bc 100644 --- a/p2p/base/port_allocator.cc +++ b/p2p/base/port_allocator.cc @@ -20,13 +20,13 @@ namespace cricket { -RelayServerConfig::RelayServerConfig(RelayType type) : type(type) {} +RelayServerConfig::RelayServerConfig() {} RelayServerConfig::RelayServerConfig(const rtc::SocketAddress& address, const std::string& username, const std::string& password, ProtocolType proto) - : type(RELAY_TURN), credentials(username, password) { + : credentials(username, password) { ports.push_back(ProtocolAddress(address, proto)); } diff --git a/p2p/base/port_allocator.h b/p2p/base/port_allocator.h index eb04cc2a1f..2fe8db2c97 100644 --- a/p2p/base/port_allocator.h +++ b/p2p/base/port_allocator.h @@ -149,7 +149,7 @@ struct RelayCredentials { typedef std::vector<ProtocolAddress> PortList; // TODO(deadbeef): Rename to TurnServerConfig. struct RTC_EXPORT RelayServerConfig { - explicit RelayServerConfig(RelayType type); + RelayServerConfig(); RelayServerConfig(const rtc::SocketAddress& address, const std::string& username, const std::string& password, @@ -170,12 +170,11 @@ struct RTC_EXPORT RelayServerConfig { ~RelayServerConfig(); bool operator==(const RelayServerConfig& o) const { - return type == o.type && ports == o.ports && credentials == o.credentials && + return ports == o.ports && credentials == o.credentials && priority == o.priority; } bool operator!=(const RelayServerConfig& o) const { return !(*this == o); } - RelayType type; PortList ports; RelayCredentials credentials; int priority = 0; diff --git a/p2p/base/port_unittest.cc b/p2p/base/port_unittest.cc index 3556e3102a..4103ba41b3 100644 --- a/p2p/base/port_unittest.cc +++ b/p2p/base/port_unittest.cc @@ -27,12 +27,10 @@ #include "p2p/base/p2p_constants.h" #include "p2p/base/port_allocator.h" #include "p2p/base/port_interface.h" -#include "p2p/base/relay_port.h" #include "p2p/base/stun.h" #include "p2p/base/stun_port.h" #include "p2p/base/stun_server.h" #include "p2p/base/tcp_port.h" -#include "p2p/base/test_relay_server.h" #include "p2p/base/test_stun_server.h" #include "p2p/base/test_turn_server.h" #include "p2p/base/transport_description.h" @@ -90,12 +88,6 @@ const SocketAddress kLocalAddr2("192.168.1.3", 0); const SocketAddress kNatAddr1("77.77.77.77", rtc::NAT_SERVER_UDP_PORT); const SocketAddress kNatAddr2("88.88.88.88", rtc::NAT_SERVER_UDP_PORT); const SocketAddress kStunAddr("99.99.99.1", STUN_SERVER_PORT); -const SocketAddress kRelayUdpIntAddr("99.99.99.2", 5000); -const SocketAddress kRelayUdpExtAddr("99.99.99.3", 5001); -const SocketAddress kRelayTcpIntAddr("99.99.99.2", 5002); -const SocketAddress kRelayTcpExtAddr("99.99.99.3", 5003); -const SocketAddress kRelaySslTcpIntAddr("99.99.99.2", 5004); -const SocketAddress kRelaySslTcpExtAddr("99.99.99.3", 5005); const SocketAddress kTurnUdpIntAddr("99.99.99.4", STUN_SERVER_PORT); const SocketAddress kTurnTcpIntAddr("99.99.99.4", 5010); const SocketAddress kTurnUdpExtAddr("99.99.99.5", 0); @@ -112,8 +104,6 @@ constexpr int kTiebreaker2 = 22222; const char* data = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; -constexpr int kGturnUserNameLength = 16; - Candidate GetCandidate(Port* port) { RTC_DCHECK_GE(port->Candidates().size(), 1); return port->Candidates()[0]; @@ -410,13 +400,6 @@ class PortTest : public ::testing::Test, public sigslot::has_slots<> { nat_socket_factory2_(&nat_factory2_), stun_server_(TestStunServer::Create(&main_, kStunAddr)), turn_server_(&main_, kTurnUdpIntAddr, kTurnUdpExtAddr), - relay_server_(&main_, - kRelayUdpIntAddr, - kRelayUdpExtAddr, - kRelayTcpIntAddr, - kRelayTcpExtAddr, - kRelaySslTcpIntAddr, - kRelaySslTcpExtAddr), username_(rtc::CreateRandomString(ICE_UFRAG_LENGTH)), password_(rtc::CreateRandomString(ICE_PWD_LENGTH)), role_conflict_(false), @@ -441,13 +424,13 @@ class PortTest : public ::testing::Test, public sigslot::has_slots<> { ntype == NAT_OPEN_CONE, true, ntype != NAT_SYMMETRIC, true); } - void TestLocalToRelay(RelayType rtype, ProtocolType proto) { + void TestLocalToRelay(ProtocolType proto) { auto port1 = CreateUdpPort(kLocalAddr1); port1->SetIceRole(cricket::ICEROLE_CONTROLLING); - auto port2 = CreateRelayPort(kLocalAddr2, rtype, proto, PROTO_UDP); + auto port2 = CreateRelayPort(kLocalAddr2, proto, PROTO_UDP); port2->SetIceRole(cricket::ICEROLE_CONTROLLED); - TestConnectivity("udp", std::move(port1), RelayName(rtype, proto), - std::move(port2), rtype == RELAY_GTURN, true, true, true); + TestConnectivity("udp", std::move(port1), RelayName(proto), + std::move(port2), false, true, true, true); } void TestStunToLocal(NATType ntype) { nat_server1_ = CreateNatServer(kNatAddr1, ntype); @@ -470,15 +453,15 @@ class PortTest : public ::testing::Test, public sigslot::has_slots<> { ntype1 != NAT_SYMMETRIC, ntype2 != NAT_SYMMETRIC, ntype1 + ntype2 < (NAT_PORT_RESTRICTED + NAT_SYMMETRIC)); } - void TestStunToRelay(NATType ntype, RelayType rtype, ProtocolType proto) { + void TestStunToRelay(NATType ntype, ProtocolType proto) { nat_server1_ = CreateNatServer(kNatAddr1, ntype); auto port1 = CreateStunPort(kLocalAddr1, &nat_socket_factory1_); port1->SetIceRole(cricket::ICEROLE_CONTROLLING); - auto port2 = CreateRelayPort(kLocalAddr2, rtype, proto, PROTO_UDP); + auto port2 = CreateRelayPort(kLocalAddr2, proto, PROTO_UDP); port2->SetIceRole(cricket::ICEROLE_CONTROLLED); - TestConnectivity(StunName(ntype), std::move(port1), RelayName(rtype, proto), - std::move(port2), rtype == RELAY_GTURN, - ntype != NAT_SYMMETRIC, true, true); + TestConnectivity(StunName(ntype), std::move(port1), RelayName(proto), + std::move(port2), false, ntype != NAT_SYMMETRIC, true, + true); } void TestTcpToTcp() { auto port1 = CreateTcpPort(kLocalAddr1); @@ -488,21 +471,21 @@ class PortTest : public ::testing::Test, public sigslot::has_slots<> { TestConnectivity("tcp", std::move(port1), "tcp", std::move(port2), true, false, true, true); } - void TestTcpToRelay(RelayType rtype, ProtocolType proto) { + void TestTcpToRelay(ProtocolType proto) { auto port1 = CreateTcpPort(kLocalAddr1); port1->SetIceRole(cricket::ICEROLE_CONTROLLING); - auto port2 = CreateRelayPort(kLocalAddr2, rtype, proto, PROTO_TCP); + auto port2 = CreateRelayPort(kLocalAddr2, proto, PROTO_TCP); port2->SetIceRole(cricket::ICEROLE_CONTROLLED); - TestConnectivity("tcp", std::move(port1), RelayName(rtype, proto), - std::move(port2), rtype == RELAY_GTURN, false, true, true); + TestConnectivity("tcp", std::move(port1), RelayName(proto), + std::move(port2), false, false, true, true); } - void TestSslTcpToRelay(RelayType rtype, ProtocolType proto) { + void TestSslTcpToRelay(ProtocolType proto) { auto port1 = CreateTcpPort(kLocalAddr1); port1->SetIceRole(cricket::ICEROLE_CONTROLLING); - auto port2 = CreateRelayPort(kLocalAddr2, rtype, proto, PROTO_SSLTCP); + auto port2 = CreateRelayPort(kLocalAddr2, proto, PROTO_SSLTCP); port2->SetIceRole(cricket::ICEROLE_CONTROLLED); - TestConnectivity("ssltcp", std::move(port1), RelayName(rtype, proto), - std::move(port2), rtype == RELAY_GTURN, false, true, true); + TestConnectivity("ssltcp", std::move(port1), RelayName(proto), + std::move(port2), false, false, true, true); } rtc::Network* MakeNetwork(const SocketAddress& addr) { @@ -538,14 +521,9 @@ class PortTest : public ::testing::Test, public sigslot::has_slots<> { absl::nullopt); } std::unique_ptr<Port> CreateRelayPort(const SocketAddress& addr, - RelayType rtype, ProtocolType int_proto, ProtocolType ext_proto) { - if (rtype == RELAY_TURN) { - return CreateTurnPort(addr, &socket_factory_, int_proto, ext_proto); - } else { - return CreateGturnPort(addr, int_proto, ext_proto); - } + return CreateTurnPort(addr, &socket_factory_, int_proto, ext_proto); } std::unique_ptr<TurnPort> CreateTurnPort(const SocketAddress& addr, PacketSocketFactory* socket_factory, @@ -567,24 +545,6 @@ class PortTest : public ::testing::Test, public sigslot::has_slots<> { ProtocolAddress(server_addr, int_proto), kRelayCredentials, 0, "", {}, {}, nullptr, nullptr); } - std::unique_ptr<RelayPort> CreateGturnPort(const SocketAddress& addr, - ProtocolType int_proto, - ProtocolType ext_proto) { - std::unique_ptr<RelayPort> port = CreateGturnPort(addr); - SocketAddress addrs[] = {kRelayUdpIntAddr, kRelayTcpIntAddr, - kRelaySslTcpIntAddr}; - port->AddServerAddress(ProtocolAddress(addrs[int_proto], int_proto)); - return port; - } - std::unique_ptr<RelayPort> CreateGturnPort(const SocketAddress& addr) { - // TODO(pthatcher): Remove GTURN. - // Generate a username with length of 16 for Gturn only. - std::string username = rtc::CreateRandomString(kGturnUserNameLength); - return RelayPort::Create(&main_, &socket_factory_, MakeNetwork(addr), 0, 0, - username, password_); - // TODO(?): Add an external address for ext_proto, so that the - // other side can connect to this port using a non-UDP protocol. - } std::unique_ptr<rtc::NATServer> CreateNatServer(const SocketAddress& addr, rtc::NATType type) { return std::make_unique<rtc::NATServer>(type, ss_.get(), addr, addr, @@ -604,33 +564,18 @@ class PortTest : public ::testing::Test, public sigslot::has_slots<> { return "stun(?)"; } } - static const char* RelayName(RelayType type, ProtocolType proto) { - if (type == RELAY_TURN) { - switch (proto) { - case PROTO_UDP: - return "turn(udp)"; - case PROTO_TCP: - return "turn(tcp)"; - case PROTO_SSLTCP: - return "turn(ssltcp)"; - case PROTO_TLS: - return "turn(tls)"; - default: - return "turn(?)"; - } - } else { - switch (proto) { - case PROTO_UDP: - return "gturn(udp)"; - case PROTO_TCP: - return "gturn(tcp)"; - case PROTO_SSLTCP: - return "gturn(ssltcp)"; - case PROTO_TLS: - return "gturn(tls)"; - default: - return "gturn(?)"; - } + static const char* RelayName(ProtocolType proto) { + switch (proto) { + case PROTO_UDP: + return "turn(udp)"; + case PROTO_TCP: + return "turn(tcp)"; + case PROTO_SSLTCP: + return "turn(ssltcp)"; + case PROTO_TLS: + return "turn(tls)"; + default: + return "turn(?)"; } } @@ -856,7 +801,6 @@ class PortTest : public ::testing::Test, public sigslot::has_slots<> { rtc::BasicPacketSocketFactory nat_socket_factory2_; std::unique_ptr<TestStunServer> stun_server_; TestTurnServer turn_server_; - TestRelayServer relay_server_; std::string username_; std::string password_; bool role_conflict_; @@ -1120,19 +1064,7 @@ TEST_F(PortTest, TestLocalToSymNat) { // Flaky: https://code.google.com/p/webrtc/issues/detail?id=3316. TEST_F(PortTest, DISABLED_TestLocalToTurn) { - TestLocalToRelay(RELAY_TURN, PROTO_UDP); -} - -TEST_F(PortTest, TestLocalToGturn) { - TestLocalToRelay(RELAY_GTURN, PROTO_UDP); -} - -TEST_F(PortTest, TestLocalToTcpGturn) { - TestLocalToRelay(RELAY_GTURN, PROTO_TCP); -} - -TEST_F(PortTest, TestLocalToSslTcpGturn) { - TestLocalToRelay(RELAY_GTURN, PROTO_SSLTCP); + TestLocalToRelay(PROTO_UDP); } // Cone NAT -> XXXX @@ -1157,15 +1089,7 @@ TEST_F(PortTest, TestConeNatToSymNat) { } TEST_F(PortTest, TestConeNatToTurn) { - TestStunToRelay(NAT_OPEN_CONE, RELAY_TURN, PROTO_UDP); -} - -TEST_F(PortTest, TestConeNatToGturn) { - TestStunToRelay(NAT_OPEN_CONE, RELAY_GTURN, PROTO_UDP); -} - -TEST_F(PortTest, TestConeNatToTcpGturn) { - TestStunToRelay(NAT_OPEN_CONE, RELAY_GTURN, PROTO_TCP); + TestStunToRelay(NAT_OPEN_CONE, PROTO_UDP); } // Address-restricted NAT -> XXXX @@ -1190,15 +1114,7 @@ TEST_F(PortTest, TestARNatToSymNat) { } TEST_F(PortTest, TestARNatToTurn) { - TestStunToRelay(NAT_ADDR_RESTRICTED, RELAY_TURN, PROTO_UDP); -} - -TEST_F(PortTest, TestARNatToGturn) { - TestStunToRelay(NAT_ADDR_RESTRICTED, RELAY_GTURN, PROTO_UDP); -} - -TEST_F(PortTest, TestARNATNatToTcpGturn) { - TestStunToRelay(NAT_ADDR_RESTRICTED, RELAY_GTURN, PROTO_TCP); + TestStunToRelay(NAT_ADDR_RESTRICTED, PROTO_UDP); } // Port-restricted NAT -> XXXX @@ -1224,15 +1140,7 @@ TEST_F(PortTest, TestPRNatToSymNat) { } TEST_F(PortTest, TestPRNatToTurn) { - TestStunToRelay(NAT_PORT_RESTRICTED, RELAY_TURN, PROTO_UDP); -} - -TEST_F(PortTest, TestPRNatToGturn) { - TestStunToRelay(NAT_PORT_RESTRICTED, RELAY_GTURN, PROTO_UDP); -} - -TEST_F(PortTest, TestPRNatToTcpGturn) { - TestStunToRelay(NAT_PORT_RESTRICTED, RELAY_GTURN, PROTO_TCP); + TestStunToRelay(NAT_PORT_RESTRICTED, PROTO_UDP); } // Symmetric NAT -> XXXX @@ -1259,15 +1167,7 @@ TEST_F(PortTest, TestSymNatToSymNat) { } TEST_F(PortTest, TestSymNatToTurn) { - TestStunToRelay(NAT_SYMMETRIC, RELAY_TURN, PROTO_UDP); -} - -TEST_F(PortTest, TestSymNatToGturn) { - TestStunToRelay(NAT_SYMMETRIC, RELAY_GTURN, PROTO_UDP); -} - -TEST_F(PortTest, TestSymNatToTcpGturn) { - TestStunToRelay(NAT_SYMMETRIC, RELAY_GTURN, PROTO_TCP); + TestStunToRelay(NAT_SYMMETRIC, PROTO_UDP); } // Outbound TCP -> XXXX @@ -2394,16 +2294,6 @@ TEST_F(PortTest, TestCandidateFoundation) { stunport->Candidates()[0].foundation()); EXPECT_NE(udpport2->Candidates()[0].foundation(), stunport->Candidates()[0].foundation()); - // Verify GTURN candidate foundation. - auto relayport = CreateGturnPort(kLocalAddr1); - relayport->AddServerAddress( - cricket::ProtocolAddress(kRelayUdpIntAddr, cricket::PROTO_UDP)); - relayport->PrepareAddress(); - ASSERT_EQ_WAIT(1U, relayport->Candidates().size(), kDefaultTimeout); - EXPECT_NE(udpport1->Candidates()[0].foundation(), - relayport->Candidates()[0].foundation()); - EXPECT_NE(udpport2->Candidates()[0].foundation(), - relayport->Candidates()[0].foundation()); // Verifying TURN candidate foundation. auto turnport1 = CreateTurnPort(kLocalAddr1, nat_socket_factory1(), PROTO_UDP, PROTO_UDP); @@ -2465,16 +2355,6 @@ TEST_F(PortTest, TestCandidateRelatedAddress) { // Check STUN candidate related address. EXPECT_EQ(stunport->Candidates()[0].related_address(), stunport->GetLocalAddress()); - // Verifying the related address for the GTURN candidates. - // NOTE: In case of GTURN related address will be equal to the mapped - // address, but address(mapped) will not be XOR. - auto relayport = CreateGturnPort(kLocalAddr1); - relayport->AddServerAddress( - cricket::ProtocolAddress(kRelayUdpIntAddr, cricket::PROTO_UDP)); - relayport->PrepareAddress(); - ASSERT_EQ_WAIT(1U, relayport->Candidates().size(), kDefaultTimeout); - // For Gturn related address is set to "0.0.0.0:0" - EXPECT_EQ(rtc::SocketAddress(), relayport->Candidates()[0].related_address()); // Verifying the related address for TURN candidate. // For TURN related address must be equal to the mapped address. auto turnport = diff --git a/p2p/base/regathering_controller_unittest.cc b/p2p/base/regathering_controller_unittest.cc index cee4a67b0a..e9da576667 100644 --- a/p2p/base/regathering_controller_unittest.cc +++ b/p2p/base/regathering_controller_unittest.cc @@ -63,7 +63,7 @@ class RegatheringControllerTest : public ::testing::Test, void InitializeAndGatherOnce() { cricket::ServerAddresses stun_servers; stun_servers.insert(kStunAddr); - cricket::RelayServerConfig turn_server(cricket::RELAY_TURN); + cricket::RelayServerConfig turn_server; turn_server.credentials = kRelayCredentials; turn_server.ports.push_back( cricket::ProtocolAddress(kTurnUdpIntAddr, cricket::PROTO_UDP)); diff --git a/p2p/base/relay_port.cc b/p2p/base/relay_port.cc deleted file mode 100644 index 808d6cec75..0000000000 --- a/p2p/base/relay_port.cc +++ /dev/null @@ -1,860 +0,0 @@ -/* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ -#include "p2p/base/relay_port.h" - -#include <errno.h> -#include <string.h> - -#include <algorithm> - -#include "p2p/base/connection.h" -#include "p2p/base/stun.h" -#include "p2p/base/stun_request.h" -#include "rtc_base/async_packet_socket.h" -#include "rtc_base/byte_buffer.h" -#include "rtc_base/checks.h" -#include "rtc_base/dscp.h" -#include "rtc_base/location.h" -#include "rtc_base/logging.h" -#include "rtc_base/message_handler.h" -#include "rtc_base/message_queue.h" -#include "rtc_base/net_helper.h" -#include "rtc_base/proxy_info.h" -#include "rtc_base/time_utils.h" - -namespace cricket { - -static const int kMessageConnectTimeout = 1; -static const int kKeepAliveDelay = 10 * 60 * 1000; -static const int kRetryTimeout = 50 * 1000; // ICE says 50 secs -// How long to wait for a socket to connect to remote host in milliseconds -// before trying another connection. -static const int kSoftConnectTimeoutMs = 3 * 1000; - -// Handles a connection to one address/port/protocol combination for a -// particular RelayEntry. -class RelayConnection : public sigslot::has_slots<> { - public: - RelayConnection(const ProtocolAddress* protocol_address, - rtc::AsyncPacketSocket* socket, - rtc::Thread* thread); - ~RelayConnection() override; - rtc::AsyncPacketSocket* socket() const { return socket_; } - - const ProtocolAddress* protocol_address() { return protocol_address_; } - - rtc::SocketAddress GetAddress() const { return protocol_address_->address; } - - ProtocolType GetProtocol() const { return protocol_address_->proto; } - - int SetSocketOption(rtc::Socket::Option opt, int value); - - // Validates a response to a STUN allocate request. - bool CheckResponse(StunMessage* msg); - - // Sends data to the relay server. - int Send(const void* pv, size_t cb, const rtc::PacketOptions& options); - - // Sends a STUN allocate request message to the relay server. - void SendAllocateRequest(RelayEntry* entry, int delay); - - // Return the latest error generated by the socket. - int GetError() { return socket_->GetError(); } - - // Called on behalf of a StunRequest to write data to the socket. This is - // already STUN intended for the server, so no wrapping is necessary. - void OnSendPacket(const void* data, size_t size, StunRequest* req); - - private: - rtc::AsyncPacketSocket* socket_; - const ProtocolAddress* protocol_address_; - StunRequestManager* request_manager_; - rtc::DiffServCodePoint dscp_; -}; - -// Manages a number of connections to the relayserver, one for each -// available protocol. We aim to use each connection for only a -// specific destination address so that we can avoid wrapping every -// packet in a STUN send / data indication. -class RelayEntry : public rtc::MessageHandler, public sigslot::has_slots<> { - public: - RelayEntry(RelayPort* port, const rtc::SocketAddress& ext_addr); - ~RelayEntry() override; - - RelayPort* port() { return port_; } - - const rtc::SocketAddress& address() const { return ext_addr_; } - void set_address(const rtc::SocketAddress& addr) { ext_addr_ = addr; } - - bool connected() const { return connected_; } - bool locked() const { return locked_; } - - // Returns the last error on the socket of this entry. - int GetError(); - - // Returns the most preferred connection of the given - // ones. Connections are rated based on protocol in the order of: - // UDP, TCP and SSLTCP, where UDP is the most preferred protocol - static RelayConnection* GetBestConnection(RelayConnection* conn1, - RelayConnection* conn2); - - // Sends the STUN requests to the server to initiate this connection. - void Connect(); - - // Called when this entry becomes connected. The address given is the one - // exposed to the outside world on the relay server. - void OnConnect(const rtc::SocketAddress& mapped_addr, - RelayConnection* socket); - - // Sends a packet to the given destination address using the socket of this - // entry. This will wrap the packet in STUN if necessary. - int SendTo(const void* data, - size_t size, - const rtc::SocketAddress& addr, - const rtc::PacketOptions& options); - - // Schedules a keep-alive allocate request. - void ScheduleKeepAlive(); - - void SetServerIndex(size_t sindex) { server_index_ = sindex; } - - // Sets this option on the socket of each connection. - int SetSocketOption(rtc::Socket::Option opt, int value); - - size_t ServerIndex() const { return server_index_; } - - // Try a different server address - void HandleConnectFailure(rtc::AsyncPacketSocket* socket); - - // Implementation of the MessageHandler Interface. - void OnMessage(rtc::Message* pmsg) override; - - private: - RelayPort* port_; - rtc::SocketAddress ext_addr_; - size_t server_index_; - bool connected_; - bool locked_; - RelayConnection* current_connection_; - - // Called when a TCP connection is established or fails - void OnSocketConnect(rtc::AsyncPacketSocket* socket); - void OnSocketClose(rtc::AsyncPacketSocket* socket, int error); - - // Called when a packet is received on this socket. - void OnReadPacket(rtc::AsyncPacketSocket* socket, - const char* data, - size_t size, - const rtc::SocketAddress& remote_addr, - const int64_t& packet_time_us); - - void OnSentPacket(rtc::AsyncPacketSocket* socket, - const rtc::SentPacket& sent_packet); - - // Called when the socket is currently able to send. - void OnReadyToSend(rtc::AsyncPacketSocket* socket); - - // Sends the given data on the socket to the server with no wrapping. This - // returns the number of bytes written or -1 if an error occurred. - int SendPacket(const void* data, - size_t size, - const rtc::PacketOptions& options); -}; - -// Handles an allocate request for a particular RelayEntry. -class AllocateRequest : public StunRequest { - public: - AllocateRequest(RelayEntry* entry, RelayConnection* connection); - ~AllocateRequest() override = default; - - void Prepare(StunMessage* request) override; - - void OnSent() override; - int resend_delay() override; - - void OnResponse(StunMessage* response) override; - void OnErrorResponse(StunMessage* response) override; - void OnTimeout() override; - - private: - RelayEntry* entry_; - RelayConnection* connection_; - int64_t start_time_; -}; - -RelayPort::RelayPort(rtc::Thread* thread, - rtc::PacketSocketFactory* factory, - rtc::Network* network, - uint16_t min_port, - uint16_t max_port, - const std::string& username, - const std::string& password) - : Port(thread, - RELAY_PORT_TYPE, - factory, - network, - min_port, - max_port, - username, - password), - ready_(false), - error_(0) { - entries_.push_back(new RelayEntry(this, rtc::SocketAddress())); - // TODO(?): set local preference value for TCP based candidates. -} - -RelayPort::~RelayPort() { - for (size_t i = 0; i < entries_.size(); ++i) - delete entries_[i]; - thread()->Clear(this); -} - -void RelayPort::AddServerAddress(const ProtocolAddress& addr) { - // Since HTTP proxies usually only allow 443, - // let's up the priority on PROTO_SSLTCP - if (addr.proto == PROTO_SSLTCP && (proxy().type == rtc::PROXY_HTTPS || - proxy().type == rtc::PROXY_UNKNOWN)) { - server_addr_.push_front(addr); - } else { - server_addr_.push_back(addr); - } -} - -void RelayPort::AddExternalAddress(const ProtocolAddress& addr) { - std::string proto_name = ProtoToString(addr.proto); - for (std::vector<ProtocolAddress>::iterator it = external_addr_.begin(); - it != external_addr_.end(); ++it) { - if ((it->address == addr.address) && (it->proto == addr.proto)) { - RTC_LOG(INFO) << "Redundant relay address: " << proto_name << " @ " - << addr.address.ToSensitiveString(); - return; - } - } - external_addr_.push_back(addr); -} - -void RelayPort::SetReady() { - if (!ready_) { - std::vector<ProtocolAddress>::iterator iter; - for (iter = external_addr_.begin(); iter != external_addr_.end(); ++iter) { - std::string proto_name = ProtoToString(iter->proto); - // In case of Gturn, related address is set to null socket address. - // This is due to as mapped address stun attribute is used for allocated - // address. - AddAddress(iter->address, iter->address, rtc::SocketAddress(), proto_name, - proto_name, "", RELAY_PORT_TYPE, ICE_TYPE_PREFERENCE_RELAY_UDP, - 0, "", false); - } - ready_ = true; - SignalPortComplete(this); - } -} - -const ProtocolAddress* RelayPort::ServerAddress(size_t index) const { - if (index < server_addr_.size()) - return &server_addr_[index]; - return NULL; -} - -bool RelayPort::HasMagicCookie(const char* data, size_t size) { - if (size < 24 + sizeof(TURN_MAGIC_COOKIE_VALUE)) { - return false; - } else { - return memcmp(data + 24, TURN_MAGIC_COOKIE_VALUE, - sizeof(TURN_MAGIC_COOKIE_VALUE)) == 0; - } -} - -void RelayPort::PrepareAddress() { - // We initiate a connect on the first entry. If this completes, it will fill - // in the server address as the address of this port. - RTC_DCHECK(entries_.size() == 1); - entries_[0]->Connect(); - ready_ = false; -} - -Connection* RelayPort::CreateConnection(const Candidate& address, - CandidateOrigin origin) { - // We only create conns to non-udp sockets if they are incoming on this port - if ((address.protocol() != UDP_PROTOCOL_NAME) && - (origin != ORIGIN_THIS_PORT)) { - return 0; - } - - // We don't support loopback on relays - if (address.type() == Type()) { - return 0; - } - - if (!IsCompatibleAddress(address.address())) { - return 0; - } - - size_t index = 0; - for (size_t i = 0; i < Candidates().size(); ++i) { - const Candidate& local = Candidates()[i]; - if (local.protocol() == address.protocol()) { - index = i; - break; - } - } - - Connection* conn = new ProxyConnection(this, index, address); - AddOrReplaceConnection(conn); - return conn; -} - -int RelayPort::SendTo(const void* data, - size_t size, - const rtc::SocketAddress& addr, - const rtc::PacketOptions& options, - bool payload) { - // Try to find an entry for this specific address. Note that the first entry - // created was not given an address initially, so it can be set to the first - // address that comes along. - RelayEntry* entry = 0; - - for (size_t i = 0; i < entries_.size(); ++i) { - if (entries_[i]->address().IsNil() && payload) { - entry = entries_[i]; - entry->set_address(addr); - break; - } else if (entries_[i]->address() == addr) { - entry = entries_[i]; - break; - } - } - - // If we did not find one, then we make a new one. This will not be useable - // until it becomes connected, however. - if (!entry && payload) { - entry = new RelayEntry(this, addr); - if (!entries_.empty()) { - entry->SetServerIndex(entries_[0]->ServerIndex()); - } - entry->Connect(); - entries_.push_back(entry); - } - - // If the entry is connected, then we can send on it (though wrapping may - // still be necessary). Otherwise, we can't yet use this connection, so we - // default to the first one. - if (!entry || !entry->connected()) { - RTC_DCHECK(!entries_.empty()); - entry = entries_[0]; - if (!entry->connected()) { - error_ = ENOTCONN; - return SOCKET_ERROR; - } - } - - // Send the actual contents to the server using the usual mechanism. - rtc::PacketOptions modified_options(options); - CopyPortInformationToPacketInfo(&modified_options.info_signaled_after_sent); - int sent = entry->SendTo(data, size, addr, modified_options); - if (sent <= 0) { - RTC_DCHECK(sent < 0); - error_ = entry->GetError(); - return SOCKET_ERROR; - } - // The caller of the function is expecting the number of user data bytes, - // rather than the size of the packet. - return static_cast<int>(size); -} - -int RelayPort::SetOption(rtc::Socket::Option opt, int value) { - int result = 0; - for (size_t i = 0; i < entries_.size(); ++i) { - if (entries_[i]->SetSocketOption(opt, value) < 0) { - result = -1; - error_ = entries_[i]->GetError(); - } - } - options_.push_back(OptionValue(opt, value)); - return result; -} - -int RelayPort::GetOption(rtc::Socket::Option opt, int* value) { - std::vector<OptionValue>::iterator it; - for (it = options_.begin(); it < options_.end(); ++it) { - if (it->first == opt) { - *value = it->second; - return 0; - } - } - return SOCKET_ERROR; -} - -int RelayPort::GetError() { - return error_; -} - -bool RelayPort::SupportsProtocol(const std::string& protocol) const { - // Relay port may create both TCP and UDP connections. - return true; -} - -ProtocolType RelayPort::GetProtocol() const { - // We shouldn't be using RelayPort, but we need to provide an implementation - // here. - return PROTO_UDP; -} - -void RelayPort::OnReadPacket(const char* data, - size_t size, - const rtc::SocketAddress& remote_addr, - ProtocolType proto, - int64_t packet_time_us) { - if (Connection* conn = GetConnection(remote_addr)) { - conn->OnReadPacket(data, size, packet_time_us); - } else { - Port::OnReadPacket(data, size, remote_addr, proto); - } -} - -RelayConnection::RelayConnection(const ProtocolAddress* protocol_address, - rtc::AsyncPacketSocket* socket, - rtc::Thread* thread) - : socket_(socket), - protocol_address_(protocol_address), - dscp_(rtc::DSCP_NO_CHANGE) { - request_manager_ = new StunRequestManager(thread); - request_manager_->SignalSendPacket.connect(this, - &RelayConnection::OnSendPacket); -} - -RelayConnection::~RelayConnection() { - delete request_manager_; - delete socket_; -} - -int RelayConnection::SetSocketOption(rtc::Socket::Option opt, int value) { - if (opt == rtc::Socket::OPT_DSCP) { - dscp_ = static_cast<rtc::DiffServCodePoint>(value); - } - if (socket_) { - return socket_->SetOption(opt, value); - } - return 0; -} - -bool RelayConnection::CheckResponse(StunMessage* msg) { - return request_manager_->CheckResponse(msg); -} - -void RelayConnection::OnSendPacket(const void* data, - size_t size, - StunRequest* req) { - rtc::PacketOptions options(dscp_); - int sent = socket_->SendTo(data, size, GetAddress(), options); - if (sent <= 0) { - RTC_LOG(LS_VERBOSE) << "OnSendPacket: failed sending to " - << GetAddress().ToSensitiveString() - << strerror(socket_->GetError()); - RTC_DCHECK(sent < 0); - } -} - -int RelayConnection::Send(const void* pv, - size_t cb, - const rtc::PacketOptions& options) { - return socket_->SendTo(pv, cb, GetAddress(), options); -} - -void RelayConnection::SendAllocateRequest(RelayEntry* entry, int delay) { - request_manager_->SendDelayed(new AllocateRequest(entry, this), delay); -} - -RelayEntry::RelayEntry(RelayPort* port, const rtc::SocketAddress& ext_addr) - : port_(port), - ext_addr_(ext_addr), - server_index_(0), - connected_(false), - locked_(false), - current_connection_(NULL) {} - -RelayEntry::~RelayEntry() { - // Remove all RelayConnections and dispose sockets. - delete current_connection_; - current_connection_ = NULL; -} - -void RelayEntry::Connect() { - // If we're already connected, return. - if (connected_) - return; - - // If we've exhausted all options, bail out. - const ProtocolAddress* ra = port()->ServerAddress(server_index_); - if (!ra) { - RTC_LOG(LS_WARNING) << "No more relay addresses left to try"; - return; - } - - // Remove any previous connection. - if (current_connection_) { - port()->thread()->Dispose(current_connection_); - current_connection_ = NULL; - } - - // Try to set up our new socket. - RTC_LOG(LS_INFO) << "Connecting to relay via " << ProtoToString(ra->proto) - << " @ " << ra->address.ToSensitiveString(); - - rtc::AsyncPacketSocket* socket = NULL; - - if (ra->proto == PROTO_UDP) { - // UDP sockets are simple. - socket = port_->socket_factory()->CreateUdpSocket( - rtc::SocketAddress(port_->Network()->GetBestIP(), 0), port_->min_port(), - port_->max_port()); - } else if (ra->proto == PROTO_TCP || ra->proto == PROTO_SSLTCP) { - int opts = (ra->proto == PROTO_SSLTCP) - ? rtc::PacketSocketFactory::OPT_TLS_FAKE - : 0; - rtc::PacketSocketTcpOptions tcp_opts; - tcp_opts.opts = opts; - socket = port_->socket_factory()->CreateClientTcpSocket( - rtc::SocketAddress(port_->Network()->GetBestIP(), 0), ra->address, - port_->proxy(), port_->user_agent(), tcp_opts); - } else { - RTC_LOG(LS_WARNING) << "Unknown protocol: " << ra->proto; - } - - // If we failed to get a socket, move on to the next protocol. - if (!socket) { - RTC_LOG(LS_WARNING) << "Socket creation failed"; - port()->thread()->Post(RTC_FROM_HERE, this, kMessageConnectTimeout); - return; - } - - // Otherwise, create the new connection and configure any socket options. - socket->SignalReadPacket.connect(this, &RelayEntry::OnReadPacket); - socket->SignalSentPacket.connect(this, &RelayEntry::OnSentPacket); - socket->SignalReadyToSend.connect(this, &RelayEntry::OnReadyToSend); - current_connection_ = new RelayConnection(ra, socket, port()->thread()); - for (size_t i = 0; i < port_->options().size(); ++i) { - current_connection_->SetSocketOption(port_->options()[i].first, - port_->options()[i].second); - } - - // If we're trying UDP, start binding requests. - // If we're trying TCP, wait for connection with a fixed timeout. - if ((ra->proto == PROTO_TCP) || (ra->proto == PROTO_SSLTCP)) { - socket->SignalClose.connect(this, &RelayEntry::OnSocketClose); - socket->SignalConnect.connect(this, &RelayEntry::OnSocketConnect); - port()->thread()->PostDelayed(RTC_FROM_HERE, kSoftConnectTimeoutMs, this, - kMessageConnectTimeout); - } else { - current_connection_->SendAllocateRequest(this, 0); - } -} - -int RelayEntry::GetError() { - if (current_connection_ != NULL) { - return current_connection_->GetError(); - } - return 0; -} - -RelayConnection* RelayEntry::GetBestConnection(RelayConnection* conn1, - RelayConnection* conn2) { - return conn1->GetProtocol() <= conn2->GetProtocol() ? conn1 : conn2; -} - -void RelayEntry::OnConnect(const rtc::SocketAddress& mapped_addr, - RelayConnection* connection) { - // We are connected, notify our parent. - ProtocolType proto = PROTO_UDP; - RTC_LOG(INFO) << "Relay allocate succeeded: " << ProtoToString(proto) << " @ " - << mapped_addr.ToSensitiveString(); - connected_ = true; - - port_->AddExternalAddress(ProtocolAddress(mapped_addr, proto)); - port_->SetReady(); -} - -int RelayEntry::SendTo(const void* data, - size_t size, - const rtc::SocketAddress& addr, - const rtc::PacketOptions& options) { - // If this connection is locked to the address given, then we can send the - // packet with no wrapper. - if (locked_ && (ext_addr_ == addr)) - return SendPacket(data, size, options); - - // Otherwise, we must wrap the given data in a STUN SEND request so that we - // can communicate the destination address to the server. - // - // Note that we do not use a StunRequest here. This is because there is - // likely no reason to resend this packet. If it is late, we just drop it. - // The next send to this address will try again. - - RelayMessage request; - request.SetType(STUN_SEND_REQUEST); - - auto magic_cookie_attr = - StunAttribute::CreateByteString(STUN_ATTR_MAGIC_COOKIE); - magic_cookie_attr->CopyBytes(TURN_MAGIC_COOKIE_VALUE, - sizeof(TURN_MAGIC_COOKIE_VALUE)); - request.AddAttribute(std::move(magic_cookie_attr)); - - auto username_attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME); - username_attr->CopyBytes(port_->username_fragment().c_str(), - port_->username_fragment().size()); - request.AddAttribute(std::move(username_attr)); - - auto addr_attr = StunAttribute::CreateAddress(STUN_ATTR_DESTINATION_ADDRESS); - addr_attr->SetIP(addr.ipaddr()); - addr_attr->SetPort(addr.port()); - request.AddAttribute(std::move(addr_attr)); - - // Attempt to lock - if (ext_addr_ == addr) { - auto options_attr = StunAttribute::CreateUInt32(STUN_ATTR_OPTIONS); - options_attr->SetValue(0x1); - request.AddAttribute(std::move(options_attr)); - } - - auto data_attr = StunAttribute::CreateByteString(STUN_ATTR_DATA); - data_attr->CopyBytes(data, size); - request.AddAttribute(std::move(data_attr)); - - // TODO(?): compute the HMAC. - - rtc::ByteBufferWriter buf; - request.Write(&buf); - - return SendPacket(buf.Data(), buf.Length(), options); -} - -void RelayEntry::ScheduleKeepAlive() { - if (current_connection_) { - current_connection_->SendAllocateRequest(this, kKeepAliveDelay); - } -} - -int RelayEntry::SetSocketOption(rtc::Socket::Option opt, int value) { - // Set the option on all available sockets. - int socket_error = 0; - if (current_connection_) { - socket_error = current_connection_->SetSocketOption(opt, value); - } - return socket_error; -} - -void RelayEntry::HandleConnectFailure(rtc::AsyncPacketSocket* socket) { - // Make sure it's the current connection that has failed, it might - // be an old socked that has not yet been disposed. - if (!socket || - (current_connection_ && socket == current_connection_->socket())) { - if (current_connection_) - port()->SignalConnectFailure(current_connection_->protocol_address()); - - // Try to connect to the next server address. - server_index_ += 1; - Connect(); - } -} - -void RelayEntry::OnMessage(rtc::Message* pmsg) { - RTC_DCHECK(pmsg->message_id == kMessageConnectTimeout); - if (current_connection_) { - const ProtocolAddress* ra = current_connection_->protocol_address(); - RTC_LOG(LS_WARNING) << "Relay " << ra->proto << " connection to " - << ra->address.ToSensitiveString() << " timed out"; - - // Currently we connect to each server address in sequence. If we - // have more addresses to try, treat this is an error and move on to - // the next address, otherwise give this connection more time and - // await the real timeout. - // - // TODO(?): Connect to servers in parallel to speed up connect time - // and to avoid giving up too early. - port_->SignalSoftTimeout(ra); - HandleConnectFailure(current_connection_->socket()); - } else { - HandleConnectFailure(NULL); - } -} - -void RelayEntry::OnSocketConnect(rtc::AsyncPacketSocket* socket) { - RTC_LOG(INFO) << "relay tcp connected to " - << socket->GetRemoteAddress().ToSensitiveString(); - if (current_connection_ != NULL) { - current_connection_->SendAllocateRequest(this, 0); - } -} - -void RelayEntry::OnSocketClose(rtc::AsyncPacketSocket* socket, int error) { - RTC_LOG_ERR_EX(LERROR, error) << "Relay connection failed: socket closed"; - HandleConnectFailure(socket); -} - -void RelayEntry::OnReadPacket(rtc::AsyncPacketSocket* socket, - const char* data, - size_t size, - const rtc::SocketAddress& remote_addr, - const int64_t& packet_time_us) { - // RTC_DCHECK(remote_addr == port_->server_addr()); - // TODO(?): are we worried about this? - - if (current_connection_ == NULL || socket != current_connection_->socket()) { - // This packet comes from an unknown address. - RTC_LOG(WARNING) << "Dropping packet: unknown address"; - return; - } - - // If the magic cookie is not present, then this is an unwrapped packet sent - // by the server, The actual remote address is the one we recorded. - if (!port_->HasMagicCookie(data, size)) { - if (locked_) { - port_->OnReadPacket(data, size, ext_addr_, PROTO_UDP, packet_time_us); - } else { - RTC_LOG(WARNING) << "Dropping packet: entry not locked"; - } - return; - } - - rtc::ByteBufferReader buf(data, size); - RelayMessage msg; - if (!msg.Read(&buf)) { - RTC_LOG(INFO) << "Incoming packet was not STUN"; - return; - } - - // The incoming packet should be a STUN ALLOCATE response, SEND response, or - // DATA indication. - if (current_connection_->CheckResponse(&msg)) { - return; - } else if (msg.type() == STUN_SEND_RESPONSE) { - if (const StunUInt32Attribute* options_attr = - msg.GetUInt32(STUN_ATTR_OPTIONS)) { - if (options_attr->value() & 0x1) { - locked_ = true; - } - } - return; - } else if (msg.type() != STUN_DATA_INDICATION) { - RTC_LOG(INFO) << "Received BAD stun type from server: " << msg.type(); - return; - } - - // This must be a data indication. - - const StunAddressAttribute* addr_attr = - msg.GetAddress(STUN_ATTR_SOURCE_ADDRESS2); - if (!addr_attr) { - RTC_LOG(INFO) << "Data indication has no source address"; - return; - } else if (addr_attr->family() != 1) { - RTC_LOG(INFO) << "Source address has bad family"; - return; - } - - rtc::SocketAddress remote_addr2(addr_attr->ipaddr(), addr_attr->port()); - - const StunByteStringAttribute* data_attr = msg.GetByteString(STUN_ATTR_DATA); - if (!data_attr) { - RTC_LOG(INFO) << "Data indication has no data"; - return; - } - - // Process the actual data and remote address in the normal manner. - port_->OnReadPacket(data_attr->bytes(), data_attr->length(), remote_addr2, - PROTO_UDP, packet_time_us); -} - -void RelayEntry::OnSentPacket(rtc::AsyncPacketSocket* socket, - const rtc::SentPacket& sent_packet) { - port_->OnSentPacket(socket, sent_packet); -} - -void RelayEntry::OnReadyToSend(rtc::AsyncPacketSocket* socket) { - if (connected()) { - port_->OnReadyToSend(); - } -} - -int RelayEntry::SendPacket(const void* data, - size_t size, - const rtc::PacketOptions& options) { - int sent = 0; - if (current_connection_) { - // We are connected, no need to send packets anywere else than to - // the current connection. - sent = current_connection_->Send(data, size, options); - } - return sent; -} - -AllocateRequest::AllocateRequest(RelayEntry* entry, RelayConnection* connection) - : StunRequest(new RelayMessage()), entry_(entry), connection_(connection) { - start_time_ = rtc::TimeMillis(); -} - -void AllocateRequest::Prepare(StunMessage* request) { - request->SetType(STUN_ALLOCATE_REQUEST); - - auto username_attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME); - username_attr->CopyBytes(entry_->port()->username_fragment().c_str(), - entry_->port()->username_fragment().size()); - request->AddAttribute(std::move(username_attr)); -} - -void AllocateRequest::OnSent() { - count_ += 1; - if (count_ == 5) - timeout_ = true; -} - -int AllocateRequest::resend_delay() { - if (count_ == 0) { - return 0; - } - return 100 * std::max(1 << (count_ - 1), 2); -} - -void AllocateRequest::OnResponse(StunMessage* response) { - const StunAddressAttribute* addr_attr = - response->GetAddress(STUN_ATTR_MAPPED_ADDRESS); - if (!addr_attr) { - RTC_LOG(INFO) << "Allocate response missing mapped address."; - } else if (addr_attr->family() != 1) { - RTC_LOG(INFO) << "Mapped address has bad family"; - } else { - rtc::SocketAddress addr(addr_attr->ipaddr(), addr_attr->port()); - entry_->OnConnect(addr, connection_); - } - - // We will do a keep-alive regardless of whether this request suceeds. - // This should have almost no impact on network usage. - entry_->ScheduleKeepAlive(); -} - -void AllocateRequest::OnErrorResponse(StunMessage* response) { - const StunErrorCodeAttribute* attr = response->GetErrorCode(); - if (!attr) { - RTC_LOG(LS_ERROR) << "Missing allocate response error code."; - } else { - RTC_LOG(INFO) << "Allocate error response: code=" << attr->code() - << " reason=" << attr->reason(); - } - - if (rtc::TimeMillis() - start_time_ <= kRetryTimeout) - entry_->ScheduleKeepAlive(); -} - -void AllocateRequest::OnTimeout() { - RTC_LOG(INFO) << "Allocate request timed out"; - entry_->HandleConnectFailure(connection_->socket()); -} - -} // namespace cricket diff --git a/p2p/base/relay_port.h b/p2p/base/relay_port.h deleted file mode 100644 index f9121ad1d4..0000000000 --- a/p2p/base/relay_port.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef P2P_BASE_RELAY_PORT_H_ -#define P2P_BASE_RELAY_PORT_H_ - -#include <deque> -#include <memory> -#include <string> -#include <utility> -#include <vector> - -#include "absl/memory/memory.h" -#include "p2p/base/port.h" -#include "p2p/base/stun_request.h" - -namespace cricket { - -class RelayEntry; -class RelayConnection; - -// Communicates using an allocated port on the relay server. For each -// remote candidate that we try to send data to a RelayEntry instance -// is created. The RelayEntry will try to reach the remote destination -// by connecting to all available server addresses in a pre defined -// order with a small delay in between. When a connection is -// successful all other connection attempts are aborted. -class RelayPort : public Port { - public: - typedef std::pair<rtc::Socket::Option, int> OptionValue; - - // RelayPort doesn't yet do anything fancy in the ctor. - static std::unique_ptr<RelayPort> Create(rtc::Thread* thread, - rtc::PacketSocketFactory* factory, - rtc::Network* network, - uint16_t min_port, - uint16_t max_port, - const std::string& username, - const std::string& password) { - // Using `new` to access a non-public constructor. - return absl::WrapUnique(new RelayPort(thread, factory, network, min_port, - max_port, username, password)); - } - ~RelayPort() override; - - void AddServerAddress(const ProtocolAddress& addr); - void AddExternalAddress(const ProtocolAddress& addr); - - const std::vector<OptionValue>& options() const { return options_; } - bool HasMagicCookie(const char* data, size_t size); - - void PrepareAddress() override; - Connection* CreateConnection(const Candidate& address, - CandidateOrigin origin) override; - int SetOption(rtc::Socket::Option opt, int value) override; - int GetOption(rtc::Socket::Option opt, int* value) override; - int GetError() override; - bool SupportsProtocol(const std::string& protocol) const override; - ProtocolType GetProtocol() const override; - - const ProtocolAddress* ServerAddress(size_t index) const; - bool IsReady() { return ready_; } - - // Used for testing. - sigslot::signal1<const ProtocolAddress*> SignalConnectFailure; - sigslot::signal1<const ProtocolAddress*> SignalSoftTimeout; - - protected: - RelayPort(rtc::Thread* thread, - rtc::PacketSocketFactory* factory, - rtc::Network*, - uint16_t min_port, - uint16_t max_port, - const std::string& username, - const std::string& password); - bool Init(); - - void SetReady(); - - int SendTo(const void* data, - size_t size, - const rtc::SocketAddress& addr, - const rtc::PacketOptions& options, - bool payload) override; - - // Dispatches the given packet to the port or connection as appropriate. - void OnReadPacket(const char* data, - size_t size, - const rtc::SocketAddress& remote_addr, - ProtocolType proto, - int64_t packet_time_us); - - // The OnSentPacket callback is left empty here since they are handled by - // RelayEntry. - void OnSentPacket(rtc::AsyncPacketSocket* socket, - const rtc::SentPacket& sent_packet) override {} - - private: - friend class RelayEntry; - - std::deque<ProtocolAddress> server_addr_; - std::vector<ProtocolAddress> external_addr_; - bool ready_; - std::vector<RelayEntry*> entries_; - std::vector<OptionValue> options_; - int error_; -}; - -} // namespace cricket - -#endif // P2P_BASE_RELAY_PORT_H_ diff --git a/p2p/base/relay_port_unittest.cc b/p2p/base/relay_port_unittest.cc deleted file mode 100644 index 1b2236aae0..0000000000 --- a/p2p/base/relay_port_unittest.cc +++ /dev/null @@ -1,272 +0,0 @@ -/* - * Copyright 2009 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "p2p/base/relay_port.h" - -#include <map> -#include <memory> - -#include "p2p/base/basic_packet_socket_factory.h" -#include "p2p/base/relay_server.h" -#include "rtc_base/gunit.h" -#include "rtc_base/helpers.h" -#include "rtc_base/logging.h" -#include "rtc_base/socket_adapters.h" -#include "rtc_base/socket_address.h" -#include "rtc_base/ssl_adapter.h" -#include "rtc_base/thread.h" -#include "rtc_base/virtual_socket_server.h" - -using rtc::SocketAddress; - -static const SocketAddress kLocalAddress = SocketAddress("192.168.1.2", 0); -static const SocketAddress kRelayUdpAddr = SocketAddress("99.99.99.1", 5000); -static const SocketAddress kRelayTcpAddr = SocketAddress("99.99.99.2", 5001); -static const SocketAddress kRelaySslAddr = SocketAddress("99.99.99.3", 443); -static const SocketAddress kRelayExtAddr = SocketAddress("99.99.99.3", 5002); - -static const int kTimeoutMs = 1000; -static const int kMaxTimeoutMs = 5000; - -// Tests connecting a RelayPort to a fake relay server -// (cricket::RelayServer) using all currently available protocols. The -// network layer is faked out by using a VirtualSocketServer for -// creating sockets. The test will monitor the current state of the -// RelayPort and created sockets by listening for signals such as, -// SignalConnectFailure, SignalConnectTimeout, SignalSocketClosed and -// SignalReadPacket. -class RelayPortTest : public ::testing::Test, public sigslot::has_slots<> { - public: - RelayPortTest() - : virtual_socket_server_(new rtc::VirtualSocketServer()), - main_(virtual_socket_server_.get()), - network_("unittest", "unittest", kLocalAddress.ipaddr(), 32), - socket_factory_(rtc::Thread::Current()), - username_(rtc::CreateRandomString(16)), - password_(rtc::CreateRandomString(16)), - relay_port_(cricket::RelayPort::Create(&main_, - &socket_factory_, - &network_, - 0, - 0, - username_, - password_)), - relay_server_(new cricket::RelayServer(&main_)) { - network_.AddIP(kLocalAddress.ipaddr()); - } - - void OnReadPacket(rtc::AsyncPacketSocket* socket, - const char* /* data */, - size_t /* size */, - const rtc::SocketAddress& /* remote_addr */, - const int64_t& /* packet_time_us */) { - received_packet_count_[socket]++; - } - - void OnConnectFailure(const cricket::ProtocolAddress* addr) { - failed_connections_.push_back(*addr); - } - - void OnSoftTimeout(const cricket::ProtocolAddress* addr) { - soft_timedout_connections_.push_back(*addr); - } - - protected: - virtual void SetUp() { - // The relay server needs an external socket to work properly. - rtc::AsyncUDPSocket* ext_socket = CreateAsyncUdpSocket(kRelayExtAddr); - relay_server_->AddExternalSocket(ext_socket); - - // Listen for failures. - relay_port_->SignalConnectFailure.connect(this, - &RelayPortTest::OnConnectFailure); - - // Listen for soft timeouts. - relay_port_->SignalSoftTimeout.connect(this, &RelayPortTest::OnSoftTimeout); - } - - // Udp has the highest 'goodness' value of the three different - // protocols used for connecting to the relay server. As soon as - // PrepareAddress is called, the RelayPort will start trying to - // connect to the given UDP address. As soon as a response to the - // sent STUN allocate request message has been received, the - // RelayPort will consider the connection to be complete and will - // abort any other connection attempts. - void TestConnectUdp() { - // Add a UDP socket to the relay server. - rtc::AsyncUDPSocket* internal_udp_socket = - CreateAsyncUdpSocket(kRelayUdpAddr); - rtc::AsyncSocket* server_socket = CreateServerSocket(kRelayTcpAddr); - - relay_server_->AddInternalSocket(internal_udp_socket); - relay_server_->AddInternalServerSocket(server_socket, cricket::PROTO_TCP); - - // Now add our relay addresses to the relay port and let it start. - relay_port_->AddServerAddress( - cricket::ProtocolAddress(kRelayUdpAddr, cricket::PROTO_UDP)); - relay_port_->AddServerAddress( - cricket::ProtocolAddress(kRelayTcpAddr, cricket::PROTO_TCP)); - relay_port_->PrepareAddress(); - - // Should be connected. - EXPECT_TRUE_WAIT(relay_port_->IsReady(), kTimeoutMs); - - // Make sure that we are happy with UDP, ie. not continuing with - // TCP, SSLTCP, etc. - WAIT(relay_server_->HasConnection(kRelayTcpAddr), kTimeoutMs); - - // Should have only one connection. - EXPECT_EQ(1, relay_server_->GetConnectionCount()); - - // Should be the UDP address. - EXPECT_TRUE(relay_server_->HasConnection(kRelayUdpAddr)); - } - - // TCP has the second best 'goodness' value, and as soon as UDP - // connection has failed, the RelayPort will attempt to connect via - // TCP. Here we add a fake UDP address together with a real TCP - // address to simulate an UDP failure. As soon as UDP has failed the - // RelayPort will try the TCP adress and succed. - void TestConnectTcp() { - // Create a fake UDP address for relay port to simulate a failure. - cricket::ProtocolAddress fake_protocol_address = - cricket::ProtocolAddress(kRelayUdpAddr, cricket::PROTO_UDP); - - // Create a server socket for the RelayServer. - rtc::AsyncSocket* server_socket = CreateServerSocket(kRelayTcpAddr); - relay_server_->AddInternalServerSocket(server_socket, cricket::PROTO_TCP); - - // Add server addresses to the relay port and let it start. - relay_port_->AddServerAddress( - cricket::ProtocolAddress(fake_protocol_address)); - relay_port_->AddServerAddress( - cricket::ProtocolAddress(kRelayTcpAddr, cricket::PROTO_TCP)); - relay_port_->PrepareAddress(); - - EXPECT_FALSE(relay_port_->IsReady()); - - // Should have timed out in 200 + 200 + 400 + 800 + 1600 ms = 3200ms. - // Add some margin of error for slow bots. - // TODO(deadbeef): Use simulated clock instead of just increasing timeouts - // to fix flaky tests. - EXPECT_TRUE_WAIT(HasFailed(&fake_protocol_address), 5000); - - // Wait until relayport is ready. - EXPECT_TRUE_WAIT(relay_port_->IsReady(), kMaxTimeoutMs); - - // Should have only one connection. - EXPECT_EQ(1, relay_server_->GetConnectionCount()); - - // Should be the TCP address. - EXPECT_TRUE(relay_server_->HasConnection(kRelayTcpAddr)); - } - - void TestConnectSslTcp() { - // Create a fake TCP address for relay port to simulate a failure. - // We skip UDP here since transition from UDP to TCP has been - // tested above. - cricket::ProtocolAddress fake_protocol_address = - cricket::ProtocolAddress(kRelayTcpAddr, cricket::PROTO_TCP); - - // Create a ssl server socket for the RelayServer. - rtc::AsyncSocket* ssl_server_socket = CreateServerSocket(kRelaySslAddr); - relay_server_->AddInternalServerSocket(ssl_server_socket, - cricket::PROTO_SSLTCP); - - // Create a tcp server socket that listens on the fake address so - // the relay port can attempt to connect to it. - std::unique_ptr<rtc::AsyncSocket> tcp_server_socket( - CreateServerSocket(kRelayTcpAddr)); - - // Add server addresses to the relay port and let it start. - relay_port_->AddServerAddress(fake_protocol_address); - relay_port_->AddServerAddress( - cricket::ProtocolAddress(kRelaySslAddr, cricket::PROTO_SSLTCP)); - relay_port_->PrepareAddress(); - EXPECT_FALSE(relay_port_->IsReady()); - - // Should have timed out in 3000 ms(relayport.cc, kSoftConnectTimeoutMs). - EXPECT_TRUE_WAIT_MARGIN(HasTimedOut(&fake_protocol_address), 3000, 100); - - // Wait until relayport is ready. - EXPECT_TRUE_WAIT(relay_port_->IsReady(), kMaxTimeoutMs); - - // Should have only one connection. - EXPECT_EQ(1, relay_server_->GetConnectionCount()); - - // Should be the SSLTCP address. - EXPECT_TRUE(relay_server_->HasConnection(kRelaySslAddr)); - } - - private: - rtc::AsyncUDPSocket* CreateAsyncUdpSocket(const SocketAddress addr) { - rtc::AsyncSocket* socket = - virtual_socket_server_->CreateAsyncSocket(AF_INET, SOCK_DGRAM); - rtc::AsyncUDPSocket* packet_socket = - rtc::AsyncUDPSocket::Create(socket, addr); - EXPECT_TRUE(packet_socket != NULL); - packet_socket->SignalReadPacket.connect(this, &RelayPortTest::OnReadPacket); - return packet_socket; - } - - rtc::AsyncSocket* CreateServerSocket(const SocketAddress addr) { - rtc::AsyncSocket* socket = - virtual_socket_server_->CreateAsyncSocket(AF_INET, SOCK_STREAM); - EXPECT_GE(socket->Bind(addr), 0); - EXPECT_GE(socket->Listen(5), 0); - return socket; - } - - bool HasFailed(cricket::ProtocolAddress* addr) { - for (size_t i = 0; i < failed_connections_.size(); i++) { - if (failed_connections_[i].address == addr->address && - failed_connections_[i].proto == addr->proto) { - return true; - } - } - return false; - } - - bool HasTimedOut(cricket::ProtocolAddress* addr) { - for (size_t i = 0; i < soft_timedout_connections_.size(); i++) { - if (soft_timedout_connections_[i].address == addr->address && - soft_timedout_connections_[i].proto == addr->proto) { - return true; - } - } - return false; - } - - typedef std::map<rtc::AsyncPacketSocket*, int> PacketMap; - - std::unique_ptr<rtc::VirtualSocketServer> virtual_socket_server_; - rtc::AutoSocketServerThread main_; - rtc::Network network_; - rtc::BasicPacketSocketFactory socket_factory_; - std::string username_; - std::string password_; - std::unique_ptr<cricket::RelayPort> relay_port_; - std::unique_ptr<cricket::RelayServer> relay_server_; - std::vector<cricket::ProtocolAddress> failed_connections_; - std::vector<cricket::ProtocolAddress> soft_timedout_connections_; - PacketMap received_packet_count_; -}; - -TEST_F(RelayPortTest, ConnectUdp) { - TestConnectUdp(); -} - -TEST_F(RelayPortTest, ConnectTcp) { - TestConnectTcp(); -} - -TEST_F(RelayPortTest, ConnectSslTcp) { - TestConnectSslTcp(); -} diff --git a/p2p/base/relay_server.cc b/p2p/base/relay_server.cc deleted file mode 100644 index 7214fa1022..0000000000 --- a/p2p/base/relay_server.cc +++ /dev/null @@ -1,741 +0,0 @@ -/* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "p2p/base/relay_server.h" - -#ifdef WEBRTC_POSIX -#include <errno.h> -#endif // WEBRTC_POSIX - -#include <algorithm> -#include <utility> - -#include "absl/algorithm/container.h" -#include "rtc_base/async_tcp_socket.h" -#include "rtc_base/checks.h" -#include "rtc_base/helpers.h" -#include "rtc_base/logging.h" -#include "rtc_base/numerics/safe_conversions.h" -#include "rtc_base/server_socket_adapters.h" - -namespace cricket { - -// By default, we require a ping every 90 seconds. -const int MAX_LIFETIME = 15 * 60 * 1000; - -// The number of bytes in each of the usernames we use. -const uint32_t USERNAME_LENGTH = 16; - -// Calls SendTo on the given socket and logs any bad results. -void Send(rtc::AsyncPacketSocket* socket, - const char* bytes, - size_t size, - const rtc::SocketAddress& addr) { - rtc::PacketOptions options; - int result = socket->SendTo(bytes, size, addr, options); - if (result < static_cast<int>(size)) { - RTC_LOG(LS_ERROR) << "SendTo wrote only " << result << " of " << size - << " bytes"; - } else if (result < 0) { - RTC_LOG_ERR(LS_ERROR) << "SendTo"; - } -} - -// Sends the given STUN message on the given socket. -void SendStun(const StunMessage& msg, - rtc::AsyncPacketSocket* socket, - const rtc::SocketAddress& addr) { - rtc::ByteBufferWriter buf; - msg.Write(&buf); - Send(socket, buf.Data(), buf.Length(), addr); -} - -// Constructs a STUN error response and sends it on the given socket. -void SendStunError(const StunMessage& msg, - rtc::AsyncPacketSocket* socket, - const rtc::SocketAddress& remote_addr, - int error_code, - const char* error_desc, - const std::string& magic_cookie) { - RelayMessage err_msg; - err_msg.SetType(GetStunErrorResponseType(msg.type())); - err_msg.SetTransactionID(msg.transaction_id()); - - auto magic_cookie_attr = - StunAttribute::CreateByteString(cricket::STUN_ATTR_MAGIC_COOKIE); - if (magic_cookie.size() == 0) { - magic_cookie_attr->CopyBytes(cricket::TURN_MAGIC_COOKIE_VALUE, - sizeof(cricket::TURN_MAGIC_COOKIE_VALUE)); - } else { - magic_cookie_attr->CopyBytes(magic_cookie.c_str(), magic_cookie.size()); - } - err_msg.AddAttribute(std::move(magic_cookie_attr)); - - auto err_code = StunAttribute::CreateErrorCode(); - err_code->SetClass(error_code / 100); - err_code->SetNumber(error_code % 100); - err_code->SetReason(error_desc); - err_msg.AddAttribute(std::move(err_code)); - - SendStun(err_msg, socket, remote_addr); -} - -RelayServer::RelayServer(rtc::Thread* thread) - : thread_(thread), random_(rtc::SystemTimeNanos()), log_bindings_(true) {} - -RelayServer::~RelayServer() { - // Deleting the binding will cause it to be removed from the map. - while (!bindings_.empty()) - delete bindings_.begin()->second; - for (size_t i = 0; i < internal_sockets_.size(); ++i) - delete internal_sockets_[i]; - for (size_t i = 0; i < external_sockets_.size(); ++i) - delete external_sockets_[i]; - for (size_t i = 0; i < removed_sockets_.size(); ++i) - delete removed_sockets_[i]; - while (!server_sockets_.empty()) { - rtc::AsyncSocket* socket = server_sockets_.begin()->first; - server_sockets_.erase(server_sockets_.begin()->first); - delete socket; - } -} - -void RelayServer::AddInternalSocket(rtc::AsyncPacketSocket* socket) { - RTC_DCHECK(!absl::c_linear_search(internal_sockets_, socket)); - internal_sockets_.push_back(socket); - socket->SignalReadPacket.connect(this, &RelayServer::OnInternalPacket); -} - -void RelayServer::RemoveInternalSocket(rtc::AsyncPacketSocket* socket) { - auto iter = absl::c_find(internal_sockets_, socket); - RTC_DCHECK(iter != internal_sockets_.end()); - internal_sockets_.erase(iter); - removed_sockets_.push_back(socket); - socket->SignalReadPacket.disconnect(this); -} - -void RelayServer::AddExternalSocket(rtc::AsyncPacketSocket* socket) { - RTC_DCHECK(!absl::c_linear_search(external_sockets_, socket)); - external_sockets_.push_back(socket); - socket->SignalReadPacket.connect(this, &RelayServer::OnExternalPacket); -} - -void RelayServer::RemoveExternalSocket(rtc::AsyncPacketSocket* socket) { - auto iter = absl::c_find(external_sockets_, socket); - RTC_DCHECK(iter != external_sockets_.end()); - external_sockets_.erase(iter); - removed_sockets_.push_back(socket); - socket->SignalReadPacket.disconnect(this); -} - -void RelayServer::AddInternalServerSocket(rtc::AsyncSocket* socket, - cricket::ProtocolType proto) { - RTC_DCHECK(server_sockets_.end() == server_sockets_.find(socket)); - server_sockets_[socket] = proto; - socket->SignalReadEvent.connect(this, &RelayServer::OnReadEvent); -} - -void RelayServer::RemoveInternalServerSocket(rtc::AsyncSocket* socket) { - auto iter = server_sockets_.find(socket); - RTC_DCHECK(iter != server_sockets_.end()); - server_sockets_.erase(iter); - socket->SignalReadEvent.disconnect(this); -} - -int RelayServer::GetConnectionCount() const { - return static_cast<int>(connections_.size()); -} - -rtc::SocketAddressPair RelayServer::GetConnection(int connection) const { - int i = 0; - for (const auto& entry : connections_) { - if (i == connection) { - return entry.second->addr_pair(); - } - ++i; - } - return rtc::SocketAddressPair(); -} - -bool RelayServer::HasConnection(const rtc::SocketAddress& address) const { - for (const auto& entry : connections_) { - if (entry.second->addr_pair().destination() == address) { - return true; - } - } - return false; -} - -void RelayServer::OnReadEvent(rtc::AsyncSocket* socket) { - RTC_DCHECK(server_sockets_.find(socket) != server_sockets_.end()); - AcceptConnection(socket); -} - -void RelayServer::OnInternalPacket(rtc::AsyncPacketSocket* socket, - const char* bytes, - size_t size, - const rtc::SocketAddress& remote_addr, - const int64_t& /* packet_time_us */) { - // Get the address of the connection we just received on. - rtc::SocketAddressPair ap(remote_addr, socket->GetLocalAddress()); - RTC_DCHECK(!ap.destination().IsNil()); - - // If this did not come from an existing connection, it should be a STUN - // allocate request. - auto piter = connections_.find(ap); - if (piter == connections_.end()) { - HandleStunAllocate(bytes, size, ap, socket); - return; - } - - RelayServerConnection* int_conn = piter->second; - - // Handle STUN requests to the server itself. - if (int_conn->binding()->HasMagicCookie(bytes, size)) { - HandleStun(int_conn, bytes, size); - return; - } - - // Otherwise, this is a non-wrapped packet that we are to forward. Make sure - // that this connection has been locked. (Otherwise, we would not know what - // address to forward to.) - if (!int_conn->locked()) { - RTC_LOG(LS_WARNING) << "Dropping packet: connection not locked"; - return; - } - - // Forward this to the destination address into the connection. - RelayServerConnection* ext_conn = int_conn->binding()->GetExternalConnection( - int_conn->default_destination()); - if (ext_conn && ext_conn->locked()) { - // TODO(?): Check the HMAC. - ext_conn->Send(bytes, size); - } else { - // This happens very often and is not an error. - RTC_LOG(LS_INFO) << "Dropping packet: no external connection"; - } -} - -void RelayServer::OnExternalPacket(rtc::AsyncPacketSocket* socket, - const char* bytes, - size_t size, - const rtc::SocketAddress& remote_addr, - const int64_t& /* packet_time_us */) { - // Get the address of the connection we just received on. - rtc::SocketAddressPair ap(remote_addr, socket->GetLocalAddress()); - RTC_DCHECK(!ap.destination().IsNil()); - - // If this connection already exists, then forward the traffic. - auto piter = connections_.find(ap); - if (piter != connections_.end()) { - // TODO(?): Check the HMAC. - RelayServerConnection* ext_conn = piter->second; - RelayServerConnection* int_conn = - ext_conn->binding()->GetInternalConnection( - ext_conn->addr_pair().source()); - RTC_DCHECK(int_conn != NULL); - int_conn->Send(bytes, size, ext_conn->addr_pair().source()); - ext_conn->Lock(); // allow outgoing packets - return; - } - - // The first packet should always be a STUN / TURN packet. If it isn't, then - // we should just ignore this packet. - RelayMessage msg; - rtc::ByteBufferReader buf(bytes, size); - if (!msg.Read(&buf)) { - RTC_LOG(LS_WARNING) << "Dropping packet: first packet not STUN"; - return; - } - - // The initial packet should have a username (which identifies the binding). - const StunByteStringAttribute* username_attr = - msg.GetByteString(STUN_ATTR_USERNAME); - if (!username_attr) { - RTC_LOG(LS_WARNING) << "Dropping packet: no username"; - return; - } - - uint32_t length = - std::min(static_cast<uint32_t>(username_attr->length()), USERNAME_LENGTH); - std::string username(username_attr->bytes(), length); - // TODO(?): Check the HMAC. - - // The binding should already be present. - auto biter = bindings_.find(username); - if (biter == bindings_.end()) { - RTC_LOG(LS_WARNING) << "Dropping packet: no binding with username"; - return; - } - - // Add this authenticted connection to the binding. - RelayServerConnection* ext_conn = - new RelayServerConnection(biter->second, ap, socket); - ext_conn->binding()->AddExternalConnection(ext_conn); - AddConnection(ext_conn); - - // We always know where external packets should be forwarded, so we can lock - // them from the beginning. - ext_conn->Lock(); - - // Send this message on the appropriate internal connection. - RelayServerConnection* int_conn = ext_conn->binding()->GetInternalConnection( - ext_conn->addr_pair().source()); - RTC_DCHECK(int_conn != NULL); - int_conn->Send(bytes, size, ext_conn->addr_pair().source()); -} - -bool RelayServer::HandleStun(const char* bytes, - size_t size, - const rtc::SocketAddress& remote_addr, - rtc::AsyncPacketSocket* socket, - std::string* username, - StunMessage* msg) { - // Parse this into a stun message. Eat the message if this fails. - rtc::ByteBufferReader buf(bytes, size); - if (!msg->Read(&buf)) { - return false; - } - - // The initial packet should have a username (which identifies the binding). - const StunByteStringAttribute* username_attr = - msg->GetByteString(STUN_ATTR_USERNAME); - if (!username_attr) { - SendStunError(*msg, socket, remote_addr, 432, "Missing Username", ""); - return false; - } - - // Record the username if requested. - if (username) - username->append(username_attr->bytes(), username_attr->length()); - - // TODO(?): Check for unknown attributes (<= 0x7fff) - - return true; -} - -void RelayServer::HandleStunAllocate(const char* bytes, - size_t size, - const rtc::SocketAddressPair& ap, - rtc::AsyncPacketSocket* socket) { - // Make sure this is a valid STUN request. - RelayMessage request; - std::string username; - if (!HandleStun(bytes, size, ap.source(), socket, &username, &request)) - return; - - // Make sure this is a an allocate request. - if (request.type() != STUN_ALLOCATE_REQUEST) { - SendStunError(request, socket, ap.source(), 600, "Operation Not Supported", - ""); - return; - } - - // TODO(?): Check the HMAC. - - // Find or create the binding for this username. - - RelayServerBinding* binding; - - auto biter = bindings_.find(username); - if (biter != bindings_.end()) { - binding = biter->second; - } else { - // NOTE: In the future, bindings will be created by the bot only. This - // else-branch will then disappear. - - // Compute the appropriate lifetime for this binding. - int lifetime = MAX_LIFETIME; - const StunUInt32Attribute* lifetime_attr = - request.GetUInt32(STUN_ATTR_LIFETIME); - if (lifetime_attr) - lifetime = - std::min(lifetime, static_cast<int>(lifetime_attr->value() * 1000)); - - binding = new RelayServerBinding(this, username, "0", lifetime); - binding->SignalTimeout.connect(this, &RelayServer::OnTimeout); - bindings_[username] = binding; - - if (log_bindings_) { - RTC_LOG(LS_INFO) << "Added new binding " << username << ", " - << bindings_.size() << " total"; - } - } - - // Add this connection to the binding. It starts out unlocked. - RelayServerConnection* int_conn = - new RelayServerConnection(binding, ap, socket); - binding->AddInternalConnection(int_conn); - AddConnection(int_conn); - - // Now that we have a connection, this other method takes over. - HandleStunAllocate(int_conn, request); -} - -void RelayServer::HandleStun(RelayServerConnection* int_conn, - const char* bytes, - size_t size) { - // Make sure this is a valid STUN request. - RelayMessage request; - std::string username; - if (!HandleStun(bytes, size, int_conn->addr_pair().source(), - int_conn->socket(), &username, &request)) - return; - - // Make sure the username is the one were were expecting. - if (username != int_conn->binding()->username()) { - int_conn->SendStunError(request, 430, "Stale Credentials"); - return; - } - - // TODO(?): Check the HMAC. - - // Send this request to the appropriate handler. - if (request.type() == STUN_SEND_REQUEST) - HandleStunSend(int_conn, request); - else if (request.type() == STUN_ALLOCATE_REQUEST) - HandleStunAllocate(int_conn, request); - else - int_conn->SendStunError(request, 600, "Operation Not Supported"); -} - -void RelayServer::HandleStunAllocate(RelayServerConnection* int_conn, - const StunMessage& request) { - // Create a response message that includes an address with which external - // clients can communicate. - - RelayMessage response; - response.SetType(STUN_ALLOCATE_RESPONSE); - response.SetTransactionID(request.transaction_id()); - - auto magic_cookie_attr = - StunAttribute::CreateByteString(cricket::STUN_ATTR_MAGIC_COOKIE); - magic_cookie_attr->CopyBytes(int_conn->binding()->magic_cookie().c_str(), - int_conn->binding()->magic_cookie().size()); - response.AddAttribute(std::move(magic_cookie_attr)); - - RTC_DCHECK_GT(external_sockets_.size(), 0); - size_t index = - random_.Rand(rtc::dchecked_cast<uint32_t>(external_sockets_.size() - 1)); - rtc::SocketAddress ext_addr = external_sockets_[index]->GetLocalAddress(); - - auto addr_attr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS); - addr_attr->SetIP(ext_addr.ipaddr()); - addr_attr->SetPort(ext_addr.port()); - response.AddAttribute(std::move(addr_attr)); - - auto res_lifetime_attr = StunAttribute::CreateUInt32(STUN_ATTR_LIFETIME); - res_lifetime_attr->SetValue(int_conn->binding()->lifetime() / 1000); - response.AddAttribute(std::move(res_lifetime_attr)); - - // TODO(?): Support transport-prefs (preallocate RTCP port). - // TODO(?): Support bandwidth restrictions. - // TODO(?): Add message integrity check. - - // Send a response to the caller. - int_conn->SendStun(response); -} - -void RelayServer::HandleStunSend(RelayServerConnection* int_conn, - const StunMessage& request) { - const StunAddressAttribute* addr_attr = - request.GetAddress(STUN_ATTR_DESTINATION_ADDRESS); - if (!addr_attr) { - int_conn->SendStunError(request, 400, "Bad Request"); - return; - } - - const StunByteStringAttribute* data_attr = - request.GetByteString(STUN_ATTR_DATA); - if (!data_attr) { - int_conn->SendStunError(request, 400, "Bad Request"); - return; - } - - rtc::SocketAddress ext_addr(addr_attr->ipaddr(), addr_attr->port()); - RelayServerConnection* ext_conn = - int_conn->binding()->GetExternalConnection(ext_addr); - if (!ext_conn) { - // Create a new connection to establish the relationship with this binding. - RTC_DCHECK(external_sockets_.size() == 1); - rtc::AsyncPacketSocket* socket = external_sockets_[0]; - rtc::SocketAddressPair ap(ext_addr, socket->GetLocalAddress()); - ext_conn = new RelayServerConnection(int_conn->binding(), ap, socket); - ext_conn->binding()->AddExternalConnection(ext_conn); - AddConnection(ext_conn); - } - - // If this connection has pinged us, then allow outgoing traffic. - if (ext_conn->locked()) - ext_conn->Send(data_attr->bytes(), data_attr->length()); - - const StunUInt32Attribute* options_attr = - request.GetUInt32(STUN_ATTR_OPTIONS); - if (options_attr && (options_attr->value() & 0x01)) { - int_conn->set_default_destination(ext_addr); - int_conn->Lock(); - - RelayMessage response; - response.SetType(STUN_SEND_RESPONSE); - response.SetTransactionID(request.transaction_id()); - - auto magic_cookie_attr = - StunAttribute::CreateByteString(cricket::STUN_ATTR_MAGIC_COOKIE); - magic_cookie_attr->CopyBytes(int_conn->binding()->magic_cookie().c_str(), - int_conn->binding()->magic_cookie().size()); - response.AddAttribute(std::move(magic_cookie_attr)); - - auto options2_attr = - StunAttribute::CreateUInt32(cricket::STUN_ATTR_OPTIONS); - options2_attr->SetValue(0x01); - response.AddAttribute(std::move(options2_attr)); - - int_conn->SendStun(response); - } -} - -void RelayServer::AddConnection(RelayServerConnection* conn) { - RTC_DCHECK(connections_.find(conn->addr_pair()) == connections_.end()); - connections_[conn->addr_pair()] = conn; -} - -void RelayServer::RemoveConnection(RelayServerConnection* conn) { - auto iter = connections_.find(conn->addr_pair()); - RTC_DCHECK(iter != connections_.end()); - connections_.erase(iter); -} - -void RelayServer::RemoveBinding(RelayServerBinding* binding) { - auto iter = bindings_.find(binding->username()); - RTC_DCHECK(iter != bindings_.end()); - bindings_.erase(iter); - - if (log_bindings_) { - RTC_LOG(LS_INFO) << "Removed binding " << binding->username() << ", " - << bindings_.size() << " remaining"; - } -} - -void RelayServer::OnMessage(rtc::Message* pmsg) { - static const uint32_t kMessageAcceptConnection = 1; - RTC_DCHECK(pmsg->message_id == kMessageAcceptConnection); - - rtc::MessageData* data = pmsg->pdata; - rtc::AsyncSocket* socket = - static_cast<rtc::TypedMessageData<rtc::AsyncSocket*>*>(data)->data(); - AcceptConnection(socket); - delete data; -} - -void RelayServer::OnTimeout(RelayServerBinding* binding) { - // This call will result in all of the necessary clean-up. We can't call - // delete here, because you can't delete an object that is signaling you. - thread_->Dispose(binding); -} - -void RelayServer::AcceptConnection(rtc::AsyncSocket* server_socket) { - // Check if someone is trying to connect to us. - rtc::SocketAddress accept_addr; - rtc::AsyncSocket* accepted_socket = server_socket->Accept(&accept_addr); - if (accepted_socket != NULL) { - // We had someone trying to connect, now check which protocol to - // use and create a packet socket. - RTC_DCHECK(server_sockets_[server_socket] == cricket::PROTO_TCP || - server_sockets_[server_socket] == cricket::PROTO_SSLTCP); - if (server_sockets_[server_socket] == cricket::PROTO_SSLTCP) { - accepted_socket = new rtc::AsyncSSLServerSocket(accepted_socket); - } - rtc::AsyncTCPSocket* tcp_socket = - new rtc::AsyncTCPSocket(accepted_socket, false); - - // Finally add the socket so it can start communicating with the client. - AddInternalSocket(tcp_socket); - } -} - -RelayServerConnection::RelayServerConnection( - RelayServerBinding* binding, - const rtc::SocketAddressPair& addrs, - rtc::AsyncPacketSocket* socket) - : binding_(binding), addr_pair_(addrs), socket_(socket), locked_(false) { - // The creation of a new connection constitutes a use of the binding. - binding_->NoteUsed(); -} - -RelayServerConnection::~RelayServerConnection() { - // Remove this connection from the server's map (if it exists there). - binding_->server()->RemoveConnection(this); -} - -void RelayServerConnection::Send(const char* data, size_t size) { - // Note that the binding has been used again. - binding_->NoteUsed(); - - cricket::Send(socket_, data, size, addr_pair_.source()); -} - -void RelayServerConnection::Send(const char* data, - size_t size, - const rtc::SocketAddress& from_addr) { - // If the from address is known to the client, we don't need to send it. - if (locked() && (from_addr == default_dest_)) { - Send(data, size); - return; - } - - // Wrap the given data in a data-indication packet. - - RelayMessage msg; - msg.SetType(STUN_DATA_INDICATION); - - auto magic_cookie_attr = - StunAttribute::CreateByteString(cricket::STUN_ATTR_MAGIC_COOKIE); - magic_cookie_attr->CopyBytes(binding_->magic_cookie().c_str(), - binding_->magic_cookie().size()); - msg.AddAttribute(std::move(magic_cookie_attr)); - - auto addr_attr = StunAttribute::CreateAddress(STUN_ATTR_SOURCE_ADDRESS2); - addr_attr->SetIP(from_addr.ipaddr()); - addr_attr->SetPort(from_addr.port()); - msg.AddAttribute(std::move(addr_attr)); - - auto data_attr = StunAttribute::CreateByteString(STUN_ATTR_DATA); - RTC_DCHECK(size <= 65536); - data_attr->CopyBytes(data, uint16_t(size)); - msg.AddAttribute(std::move(data_attr)); - - SendStun(msg); -} - -void RelayServerConnection::SendStun(const StunMessage& msg) { - // Note that the binding has been used again. - binding_->NoteUsed(); - - cricket::SendStun(msg, socket_, addr_pair_.source()); -} - -void RelayServerConnection::SendStunError(const StunMessage& request, - int error_code, - const char* error_desc) { - // An error does not indicate use. If no legitimate use off the binding - // occurs, we want it to be cleaned up even if errors are still occuring. - - cricket::SendStunError(request, socket_, addr_pair_.source(), error_code, - error_desc, binding_->magic_cookie()); -} - -void RelayServerConnection::Lock() { - locked_ = true; -} - -void RelayServerConnection::Unlock() { - locked_ = false; -} - -// IDs used for posted messages: -const uint32_t MSG_LIFETIME_TIMER = 1; - -RelayServerBinding::RelayServerBinding(RelayServer* server, - const std::string& username, - const std::string& password, - int lifetime) - : server_(server), - username_(username), - password_(password), - lifetime_(lifetime) { - // For now, every connection uses the standard magic cookie value. - magic_cookie_.append(reinterpret_cast<const char*>(TURN_MAGIC_COOKIE_VALUE), - sizeof(TURN_MAGIC_COOKIE_VALUE)); - - // Initialize the last-used time to now. - NoteUsed(); - - // Set the first timeout check. - server_->thread()->PostDelayed(RTC_FROM_HERE, lifetime_, this, - MSG_LIFETIME_TIMER); -} - -RelayServerBinding::~RelayServerBinding() { - // Clear the outstanding timeout check. - server_->thread()->Clear(this); - - // Clean up all of the connections. - for (size_t i = 0; i < internal_connections_.size(); ++i) - delete internal_connections_[i]; - for (size_t i = 0; i < external_connections_.size(); ++i) - delete external_connections_[i]; - - // Remove this binding from the server's map. - server_->RemoveBinding(this); -} - -void RelayServerBinding::AddInternalConnection(RelayServerConnection* conn) { - internal_connections_.push_back(conn); -} - -void RelayServerBinding::AddExternalConnection(RelayServerConnection* conn) { - external_connections_.push_back(conn); -} - -void RelayServerBinding::NoteUsed() { - last_used_ = rtc::TimeMillis(); -} - -bool RelayServerBinding::HasMagicCookie(const char* bytes, size_t size) const { - if (size < 24 + magic_cookie_.size()) { - return false; - } else { - return memcmp(bytes + 24, magic_cookie_.c_str(), magic_cookie_.size()) == 0; - } -} - -RelayServerConnection* RelayServerBinding::GetInternalConnection( - const rtc::SocketAddress& ext_addr) { - // Look for an internal connection that is locked to this address. - for (size_t i = 0; i < internal_connections_.size(); ++i) { - if (internal_connections_[i]->locked() && - (ext_addr == internal_connections_[i]->default_destination())) - return internal_connections_[i]; - } - - // If one was not found, we send to the first connection. - RTC_DCHECK(internal_connections_.size() > 0); - return internal_connections_[0]; -} - -RelayServerConnection* RelayServerBinding::GetExternalConnection( - const rtc::SocketAddress& ext_addr) { - for (size_t i = 0; i < external_connections_.size(); ++i) { - if (ext_addr == external_connections_[i]->addr_pair().source()) - return external_connections_[i]; - } - return 0; -} - -void RelayServerBinding::OnMessage(rtc::Message* pmsg) { - if (pmsg->message_id == MSG_LIFETIME_TIMER) { - RTC_DCHECK(!pmsg->pdata); - - // If the lifetime timeout has been exceeded, then send a signal. - // Otherwise, just keep waiting. - if (rtc::TimeMillis() >= last_used_ + lifetime_) { - RTC_LOG(LS_INFO) << "Expiring binding " << username_; - SignalTimeout(this); - } else { - server_->thread()->PostDelayed(RTC_FROM_HERE, lifetime_, this, - MSG_LIFETIME_TIMER); - } - - } else { - RTC_NOTREACHED(); - } -} - -} // namespace cricket diff --git a/p2p/base/relay_server.h b/p2p/base/relay_server.h deleted file mode 100644 index 3b9e9be1cb..0000000000 --- a/p2p/base/relay_server.h +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef P2P_BASE_RELAY_SERVER_H_ -#define P2P_BASE_RELAY_SERVER_H_ - -#include <map> -#include <string> -#include <vector> - -#include "p2p/base/port.h" -#include "p2p/base/stun.h" -#include "rtc_base/async_udp_socket.h" -#include "rtc_base/random.h" -#include "rtc_base/socket_address_pair.h" -#include "rtc_base/thread.h" -#include "rtc_base/time_utils.h" - -namespace cricket { - -class RelayServerBinding; -class RelayServerConnection; - -// Relays traffic between connections to the server that are "bound" together. -// All connections created with the same username/password are bound together. -class RelayServer : public rtc::MessageHandler, public sigslot::has_slots<> { - public: - // Creates a server, which will use this thread to post messages to itself. - explicit RelayServer(rtc::Thread* thread); - ~RelayServer() override; - - rtc::Thread* thread() { return thread_; } - - // Indicates whether we will print updates of the number of bindings. - bool log_bindings() const { return log_bindings_; } - void set_log_bindings(bool log_bindings) { log_bindings_ = log_bindings; } - - // Updates the set of sockets that the server uses to talk to "internal" - // clients. These are clients that do the "port allocations". - void AddInternalSocket(rtc::AsyncPacketSocket* socket); - void RemoveInternalSocket(rtc::AsyncPacketSocket* socket); - - // Updates the set of sockets that the server uses to talk to "external" - // clients. These are the clients that do not do allocations. They do not - // know that these addresses represent a relay server. - void AddExternalSocket(rtc::AsyncPacketSocket* socket); - void RemoveExternalSocket(rtc::AsyncPacketSocket* socket); - - // Starts listening for connections on this sockets. When someone - // tries to connect, the connection will be accepted and a new - // internal socket will be added. - void AddInternalServerSocket(rtc::AsyncSocket* socket, - cricket::ProtocolType proto); - - // Removes this server socket from the list. - void RemoveInternalServerSocket(rtc::AsyncSocket* socket); - - // Methods for testing and debuging. - int GetConnectionCount() const; - rtc::SocketAddressPair GetConnection(int connection) const; - bool HasConnection(const rtc::SocketAddress& address) const; - - private: - rtc::Thread* thread_; - webrtc::Random random_; - bool log_bindings_; - std::vector<rtc::AsyncPacketSocket*> internal_sockets_; - std::vector<rtc::AsyncPacketSocket*> external_sockets_; - std::vector<rtc::AsyncPacketSocket*> removed_sockets_; - std::map<rtc::AsyncSocket*, cricket::ProtocolType> server_sockets_; - std::map<std::string, RelayServerBinding*> bindings_; - std::map<rtc::SocketAddressPair, RelayServerConnection*> connections_; - - // Called when a packet is received by the server on one of its sockets. - void OnInternalPacket(rtc::AsyncPacketSocket* socket, - const char* bytes, - size_t size, - const rtc::SocketAddress& remote_addr, - const int64_t& packet_time_us); - void OnExternalPacket(rtc::AsyncPacketSocket* socket, - const char* bytes, - size_t size, - const rtc::SocketAddress& remote_addr, - const int64_t& packet_time_us); - - void OnReadEvent(rtc::AsyncSocket* socket); - - // Processes the relevant STUN request types from the client. - bool HandleStun(const char* bytes, - size_t size, - const rtc::SocketAddress& remote_addr, - rtc::AsyncPacketSocket* socket, - std::string* username, - StunMessage* msg); - void HandleStunAllocate(const char* bytes, - size_t size, - const rtc::SocketAddressPair& ap, - rtc::AsyncPacketSocket* socket); - void HandleStun(RelayServerConnection* int_conn, - const char* bytes, - size_t size); - void HandleStunAllocate(RelayServerConnection* int_conn, - const StunMessage& msg); - void HandleStunSend(RelayServerConnection* int_conn, const StunMessage& msg); - - // Adds/Removes the a connection or binding. - void AddConnection(RelayServerConnection* conn); - void RemoveConnection(RelayServerConnection* conn); - void RemoveBinding(RelayServerBinding* binding); - - // Handle messages in our thread. - void OnMessage(rtc::Message* pmsg) override; - - // Called when the timer for checking lifetime times out. - void OnTimeout(RelayServerBinding* binding); - - // Accept connections on this server socket. - void AcceptConnection(rtc::AsyncSocket* server_socket); - - friend class RelayServerConnection; - friend class RelayServerBinding; -}; - -// Maintains information about a connection to the server. Each connection is -// part of one and only one binding. -class RelayServerConnection { - public: - RelayServerConnection(RelayServerBinding* binding, - const rtc::SocketAddressPair& addrs, - rtc::AsyncPacketSocket* socket); - ~RelayServerConnection(); - - RelayServerBinding* binding() { return binding_; } - rtc::AsyncPacketSocket* socket() { return socket_; } - - // Returns a pair where the source is the remote address and the destination - // is the local address. - const rtc::SocketAddressPair& addr_pair() { return addr_pair_; } - - // Sends a packet to the connected client. If an address is provided, then - // we make sure the internal client receives it, wrapping if necessary. - void Send(const char* data, size_t size); - void Send(const char* data, size_t size, const rtc::SocketAddress& ext_addr); - - // Sends a STUN message to the connected client with no wrapping. - void SendStun(const StunMessage& msg); - void SendStunError(const StunMessage& request, int code, const char* desc); - - // A locked connection is one for which we know the intended destination of - // any raw packet received. - bool locked() const { return locked_; } - void Lock(); - void Unlock(); - - // Records the address that raw packets should be forwarded to (for internal - // packets only; for external, we already know where they go). - const rtc::SocketAddress& default_destination() const { - return default_dest_; - } - void set_default_destination(const rtc::SocketAddress& addr) { - default_dest_ = addr; - } - - private: - RelayServerBinding* binding_; - rtc::SocketAddressPair addr_pair_; - rtc::AsyncPacketSocket* socket_; - bool locked_; - rtc::SocketAddress default_dest_; -}; - -// Records a set of internal and external connections that we relay between, -// or in other words, that are "bound" together. -class RelayServerBinding : public rtc::MessageHandler { - public: - RelayServerBinding(RelayServer* server, - const std::string& username, - const std::string& password, - int lifetime); - ~RelayServerBinding() override; - - RelayServer* server() { return server_; } - int lifetime() { return lifetime_; } - const std::string& username() { return username_; } - const std::string& password() { return password_; } - const std::string& magic_cookie() { return magic_cookie_; } - - // Adds/Removes a connection into the binding. - void AddInternalConnection(RelayServerConnection* conn); - void AddExternalConnection(RelayServerConnection* conn); - - // We keep track of the use of each binding. If we detect that it was not - // used for longer than the lifetime, then we send a signal. - void NoteUsed(); - sigslot::signal1<RelayServerBinding*> SignalTimeout; - - // Determines whether the given packet has the magic cookie present (in the - // right place). - bool HasMagicCookie(const char* bytes, size_t size) const; - - // Determines the connection to use to send packets to or from the given - // external address. - RelayServerConnection* GetInternalConnection( - const rtc::SocketAddress& ext_addr); - RelayServerConnection* GetExternalConnection( - const rtc::SocketAddress& ext_addr); - - // MessageHandler: - void OnMessage(rtc::Message* pmsg) override; - - private: - RelayServer* server_; - - std::string username_; - std::string password_; - std::string magic_cookie_; - - std::vector<RelayServerConnection*> internal_connections_; - std::vector<RelayServerConnection*> external_connections_; - - int lifetime_; - int64_t last_used_; - // TODO(?): bandwidth -}; - -} // namespace cricket - -#endif // P2P_BASE_RELAY_SERVER_H_ diff --git a/p2p/base/relay_server_unittest.cc b/p2p/base/relay_server_unittest.cc deleted file mode 100644 index 3debc5feb5..0000000000 --- a/p2p/base/relay_server_unittest.cc +++ /dev/null @@ -1,511 +0,0 @@ -/* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "p2p/base/relay_server.h" - -#include <string.h> - -#include <memory> -#include <string> -#include <utility> - -#include "absl/memory/memory.h" -#include "rtc_base/async_udp_socket.h" -#include "rtc_base/byte_buffer.h" -#include "rtc_base/helpers.h" -#include "rtc_base/socket_address.h" -#include "rtc_base/test_client.h" -#include "rtc_base/thread.h" -#include "rtc_base/virtual_socket_server.h" -#include "test/gtest.h" - -using rtc::SocketAddress; - -namespace cricket { -namespace { - -constexpr uint32_t LIFETIME = 4; // seconds -const SocketAddress server_int_addr("127.0.0.1", 5000); -const SocketAddress server_ext_addr("127.0.0.1", 5001); -const SocketAddress client1_addr("127.0.0.1", 6111); -const SocketAddress client2_addr("127.0.0.1", 7222); -const char* bad = - "this is a completely nonsensical message whose only " - "purpose is to make the parser go 'ack'. it doesn't " - "look anything like a normal stun message"; -const char* msg1 = "spamspamspamspamspamspamspambakedbeansspam"; -const char* msg2 = "Lobster Thermidor a Crevette with a mornay sauce..."; - -} // namespace - -class RelayServerTest : public ::testing::Test { - public: - RelayServerTest() - : ss_(new rtc::VirtualSocketServer()), - thread_(ss_.get()), - username_(rtc::CreateRandomString(12)), - password_(rtc::CreateRandomString(12)) {} - - protected: - virtual void SetUp() { - server_.reset(new RelayServer(rtc::Thread::Current())); - - server_->AddInternalSocket( - rtc::AsyncUDPSocket::Create(ss_.get(), server_int_addr)); - server_->AddExternalSocket( - rtc::AsyncUDPSocket::Create(ss_.get(), server_ext_addr)); - - client1_.reset(new rtc::TestClient(absl::WrapUnique( - rtc::AsyncUDPSocket::Create(ss_.get(), client1_addr)))); - client2_.reset(new rtc::TestClient(absl::WrapUnique( - rtc::AsyncUDPSocket::Create(ss_.get(), client2_addr)))); - } - - void Allocate() { - std::unique_ptr<StunMessage> req(CreateStunMessage(STUN_ALLOCATE_REQUEST)); - AddUsernameAttr(req.get(), username_); - AddLifetimeAttr(req.get(), LIFETIME); - Send1(req.get()); - delete Receive1(); - } - void Bind() { - std::unique_ptr<StunMessage> req(CreateStunMessage(STUN_BINDING_REQUEST)); - AddUsernameAttr(req.get(), username_); - Send2(req.get()); - delete Receive1(); - } - - void Send1(const StunMessage* msg) { - rtc::ByteBufferWriter buf; - msg->Write(&buf); - SendRaw1(buf.Data(), static_cast<int>(buf.Length())); - } - void Send2(const StunMessage* msg) { - rtc::ByteBufferWriter buf; - msg->Write(&buf); - SendRaw2(buf.Data(), static_cast<int>(buf.Length())); - } - void SendRaw1(const char* data, int len) { - return Send(client1_.get(), data, len, server_int_addr); - } - void SendRaw2(const char* data, int len) { - return Send(client2_.get(), data, len, server_ext_addr); - } - void Send(rtc::TestClient* client, - const char* data, - int len, - const SocketAddress& addr) { - client->SendTo(data, len, addr); - } - - bool Receive1Fails() { return client1_.get()->CheckNoPacket(); } - bool Receive2Fails() { return client2_.get()->CheckNoPacket(); } - - StunMessage* Receive1() { return Receive(client1_.get()); } - StunMessage* Receive2() { return Receive(client2_.get()); } - std::string ReceiveRaw1() { return ReceiveRaw(client1_.get()); } - std::string ReceiveRaw2() { return ReceiveRaw(client2_.get()); } - StunMessage* Receive(rtc::TestClient* client) { - StunMessage* msg = NULL; - std::unique_ptr<rtc::TestClient::Packet> packet = - client->NextPacket(rtc::TestClient::kTimeoutMs); - if (packet) { - rtc::ByteBufferWriter buf(packet->buf, packet->size); - rtc::ByteBufferReader read_buf(buf); - msg = new RelayMessage(); - msg->Read(&read_buf); - } - return msg; - } - std::string ReceiveRaw(rtc::TestClient* client) { - std::string raw; - std::unique_ptr<rtc::TestClient::Packet> packet = - client->NextPacket(rtc::TestClient::kTimeoutMs); - if (packet) { - raw = std::string(packet->buf, packet->size); - } - return raw; - } - - static StunMessage* CreateStunMessage(int type) { - StunMessage* msg = new RelayMessage(); - msg->SetType(type); - msg->SetTransactionID(rtc::CreateRandomString(kStunTransactionIdLength)); - return msg; - } - static void AddMagicCookieAttr(StunMessage* msg) { - auto attr = StunAttribute::CreateByteString(STUN_ATTR_MAGIC_COOKIE); - attr->CopyBytes(TURN_MAGIC_COOKIE_VALUE, sizeof(TURN_MAGIC_COOKIE_VALUE)); - msg->AddAttribute(std::move(attr)); - } - static void AddUsernameAttr(StunMessage* msg, const std::string& val) { - auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME); - attr->CopyBytes(val.c_str(), val.size()); - msg->AddAttribute(std::move(attr)); - } - static void AddLifetimeAttr(StunMessage* msg, int val) { - auto attr = StunAttribute::CreateUInt32(STUN_ATTR_LIFETIME); - attr->SetValue(val); - msg->AddAttribute(std::move(attr)); - } - static void AddDestinationAttr(StunMessage* msg, const SocketAddress& addr) { - auto attr = StunAttribute::CreateAddress(STUN_ATTR_DESTINATION_ADDRESS); - attr->SetIP(addr.ipaddr()); - attr->SetPort(addr.port()); - msg->AddAttribute(std::move(attr)); - } - - std::unique_ptr<rtc::VirtualSocketServer> ss_; - rtc::AutoSocketServerThread thread_; - std::unique_ptr<RelayServer> server_; - std::unique_ptr<rtc::TestClient> client1_; - std::unique_ptr<rtc::TestClient> client2_; - std::string username_; - std::string password_; -}; - -// Send a complete nonsense message and verify that it is eaten. -TEST_F(RelayServerTest, TestBadRequest) { - SendRaw1(bad, static_cast<int>(strlen(bad))); - ASSERT_TRUE(Receive1Fails()); -} - -// Send an allocate request without a username and verify it is rejected. -TEST_F(RelayServerTest, TestAllocateNoUsername) { - std::unique_ptr<StunMessage> req(CreateStunMessage(STUN_ALLOCATE_REQUEST)), - res; - - Send1(req.get()); - res.reset(Receive1()); - - ASSERT_TRUE(res); - EXPECT_EQ(STUN_ALLOCATE_ERROR_RESPONSE, res->type()); - EXPECT_EQ(req->transaction_id(), res->transaction_id()); - - const StunErrorCodeAttribute* err = res->GetErrorCode(); - ASSERT_TRUE(err != NULL); - EXPECT_EQ(4, err->eclass()); - EXPECT_EQ(32, err->number()); - EXPECT_EQ("Missing Username", err->reason()); -} - -// Send a binding request and verify that it is rejected. -TEST_F(RelayServerTest, TestBindingRequest) { - std::unique_ptr<StunMessage> req(CreateStunMessage(STUN_BINDING_REQUEST)), - res; - AddUsernameAttr(req.get(), username_); - - Send1(req.get()); - res.reset(Receive1()); - - ASSERT_TRUE(res); - EXPECT_EQ(STUN_BINDING_ERROR_RESPONSE, res->type()); - EXPECT_EQ(req->transaction_id(), res->transaction_id()); - - const StunErrorCodeAttribute* err = res->GetErrorCode(); - ASSERT_TRUE(err != NULL); - EXPECT_EQ(6, err->eclass()); - EXPECT_EQ(0, err->number()); - EXPECT_EQ("Operation Not Supported", err->reason()); -} - -// Send an allocate request and verify that it is accepted. -TEST_F(RelayServerTest, TestAllocate) { - std::unique_ptr<StunMessage> req(CreateStunMessage(STUN_ALLOCATE_REQUEST)), - res; - AddUsernameAttr(req.get(), username_); - AddLifetimeAttr(req.get(), LIFETIME); - - Send1(req.get()); - res.reset(Receive1()); - - ASSERT_TRUE(res); - EXPECT_EQ(STUN_ALLOCATE_RESPONSE, res->type()); - EXPECT_EQ(req->transaction_id(), res->transaction_id()); - - const StunAddressAttribute* mapped_addr = - res->GetAddress(STUN_ATTR_MAPPED_ADDRESS); - ASSERT_TRUE(mapped_addr != NULL); - EXPECT_EQ(1, mapped_addr->family()); - EXPECT_EQ(server_ext_addr.port(), mapped_addr->port()); - EXPECT_EQ(server_ext_addr.ipaddr(), mapped_addr->ipaddr()); - - const StunUInt32Attribute* res_lifetime_attr = - res->GetUInt32(STUN_ATTR_LIFETIME); - ASSERT_TRUE(res_lifetime_attr != NULL); - EXPECT_EQ(LIFETIME, res_lifetime_attr->value()); -} - -// Send a second allocate request and verify that it is also accepted, though -// the lifetime should be ignored. -TEST_F(RelayServerTest, TestReallocate) { - Allocate(); - - std::unique_ptr<StunMessage> req(CreateStunMessage(STUN_ALLOCATE_REQUEST)), - res; - AddMagicCookieAttr(req.get()); - AddUsernameAttr(req.get(), username_); - - Send1(req.get()); - res.reset(Receive1()); - - ASSERT_TRUE(res); - EXPECT_EQ(STUN_ALLOCATE_RESPONSE, res->type()); - EXPECT_EQ(req->transaction_id(), res->transaction_id()); - - const StunAddressAttribute* mapped_addr = - res->GetAddress(STUN_ATTR_MAPPED_ADDRESS); - ASSERT_TRUE(mapped_addr != NULL); - EXPECT_EQ(1, mapped_addr->family()); - EXPECT_EQ(server_ext_addr.port(), mapped_addr->port()); - EXPECT_EQ(server_ext_addr.ipaddr(), mapped_addr->ipaddr()); - - const StunUInt32Attribute* lifetime_attr = res->GetUInt32(STUN_ATTR_LIFETIME); - ASSERT_TRUE(lifetime_attr != NULL); - EXPECT_EQ(LIFETIME, lifetime_attr->value()); -} - -// Send a request from another client and see that it arrives at the first -// client in the binding. -TEST_F(RelayServerTest, TestRemoteBind) { - Allocate(); - - std::unique_ptr<StunMessage> req(CreateStunMessage(STUN_BINDING_REQUEST)), - res; - AddUsernameAttr(req.get(), username_); - - Send2(req.get()); - res.reset(Receive1()); - - ASSERT_TRUE(res); - EXPECT_EQ(STUN_DATA_INDICATION, res->type()); - - const StunByteStringAttribute* recv_data = res->GetByteString(STUN_ATTR_DATA); - ASSERT_TRUE(recv_data != NULL); - - rtc::ByteBufferReader buf(recv_data->bytes(), recv_data->length()); - std::unique_ptr<StunMessage> res2(new StunMessage()); - EXPECT_TRUE(res2->Read(&buf)); - EXPECT_EQ(STUN_BINDING_REQUEST, res2->type()); - EXPECT_EQ(req->transaction_id(), res2->transaction_id()); - - const StunAddressAttribute* src_addr = - res->GetAddress(STUN_ATTR_SOURCE_ADDRESS2); - ASSERT_TRUE(src_addr != NULL); - EXPECT_EQ(1, src_addr->family()); - EXPECT_EQ(client2_addr.ipaddr(), src_addr->ipaddr()); - EXPECT_EQ(client2_addr.port(), src_addr->port()); - - EXPECT_TRUE(Receive2Fails()); -} - -// Send a complete nonsense message to the established connection and verify -// that it is dropped by the server. -TEST_F(RelayServerTest, TestRemoteBadRequest) { - Allocate(); - Bind(); - - SendRaw1(bad, static_cast<int>(strlen(bad))); - EXPECT_TRUE(Receive1Fails()); - EXPECT_TRUE(Receive2Fails()); -} - -// Send a send request without a username and verify it is rejected. -TEST_F(RelayServerTest, TestSendRequestMissingUsername) { - Allocate(); - Bind(); - - std::unique_ptr<StunMessage> req(CreateStunMessage(STUN_SEND_REQUEST)), res; - AddMagicCookieAttr(req.get()); - - Send1(req.get()); - res.reset(Receive1()); - - ASSERT_TRUE(res); - EXPECT_EQ(STUN_SEND_ERROR_RESPONSE, res->type()); - EXPECT_EQ(req->transaction_id(), res->transaction_id()); - - const StunErrorCodeAttribute* err = res->GetErrorCode(); - ASSERT_TRUE(err != NULL); - EXPECT_EQ(4, err->eclass()); - EXPECT_EQ(32, err->number()); - EXPECT_EQ("Missing Username", err->reason()); -} - -// Send a send request with the wrong username and verify it is rejected. -TEST_F(RelayServerTest, TestSendRequestBadUsername) { - Allocate(); - Bind(); - - std::unique_ptr<StunMessage> req(CreateStunMessage(STUN_SEND_REQUEST)), res; - AddMagicCookieAttr(req.get()); - AddUsernameAttr(req.get(), "foobarbizbaz"); - - Send1(req.get()); - res.reset(Receive1()); - - ASSERT_TRUE(res); - EXPECT_EQ(STUN_SEND_ERROR_RESPONSE, res->type()); - EXPECT_EQ(req->transaction_id(), res->transaction_id()); - - const StunErrorCodeAttribute* err = res->GetErrorCode(); - ASSERT_TRUE(err != NULL); - EXPECT_EQ(4, err->eclass()); - EXPECT_EQ(30, err->number()); - EXPECT_EQ("Stale Credentials", err->reason()); -} - -// Send a send request without a destination address and verify that it is -// rejected. -TEST_F(RelayServerTest, TestSendRequestNoDestinationAddress) { - Allocate(); - Bind(); - - std::unique_ptr<StunMessage> req(CreateStunMessage(STUN_SEND_REQUEST)), res; - AddMagicCookieAttr(req.get()); - AddUsernameAttr(req.get(), username_); - - Send1(req.get()); - res.reset(Receive1()); - - ASSERT_TRUE(res); - EXPECT_EQ(STUN_SEND_ERROR_RESPONSE, res->type()); - EXPECT_EQ(req->transaction_id(), res->transaction_id()); - - const StunErrorCodeAttribute* err = res->GetErrorCode(); - ASSERT_TRUE(err != NULL); - EXPECT_EQ(4, err->eclass()); - EXPECT_EQ(0, err->number()); - EXPECT_EQ("Bad Request", err->reason()); -} - -// Send a send request without data and verify that it is rejected. -TEST_F(RelayServerTest, TestSendRequestNoData) { - Allocate(); - Bind(); - - std::unique_ptr<StunMessage> req(CreateStunMessage(STUN_SEND_REQUEST)), res; - AddMagicCookieAttr(req.get()); - AddUsernameAttr(req.get(), username_); - AddDestinationAttr(req.get(), client2_addr); - - Send1(req.get()); - res.reset(Receive1()); - - ASSERT_TRUE(res); - EXPECT_EQ(STUN_SEND_ERROR_RESPONSE, res->type()); - EXPECT_EQ(req->transaction_id(), res->transaction_id()); - - const StunErrorCodeAttribute* err = res->GetErrorCode(); - ASSERT_TRUE(err != NULL); - EXPECT_EQ(4, err->eclass()); - EXPECT_EQ(00, err->number()); - EXPECT_EQ("Bad Request", err->reason()); -} - -// Send a binding request after an allocate and verify that it is rejected. -TEST_F(RelayServerTest, TestSendRequestWrongType) { - Allocate(); - Bind(); - - std::unique_ptr<StunMessage> req(CreateStunMessage(STUN_BINDING_REQUEST)), - res; - AddMagicCookieAttr(req.get()); - AddUsernameAttr(req.get(), username_); - - Send1(req.get()); - res.reset(Receive1()); - - ASSERT_TRUE(res); - EXPECT_EQ(STUN_BINDING_ERROR_RESPONSE, res->type()); - EXPECT_EQ(req->transaction_id(), res->transaction_id()); - - const StunErrorCodeAttribute* err = res->GetErrorCode(); - ASSERT_TRUE(err != NULL); - EXPECT_EQ(6, err->eclass()); - EXPECT_EQ(0, err->number()); - EXPECT_EQ("Operation Not Supported", err->reason()); -} - -// Verify that we can send traffic back and forth between the clients after a -// successful allocate and bind. -TEST_F(RelayServerTest, TestSendRaw) { - Allocate(); - Bind(); - - for (int i = 0; i < 10; i++) { - std::unique_ptr<StunMessage> req(CreateStunMessage(STUN_SEND_REQUEST)), res; - AddMagicCookieAttr(req.get()); - AddUsernameAttr(req.get(), username_); - AddDestinationAttr(req.get(), client2_addr); - - auto send_data = StunAttribute::CreateByteString(STUN_ATTR_DATA); - send_data->CopyBytes(msg1); - req->AddAttribute(std::move(send_data)); - - Send1(req.get()); - EXPECT_EQ(msg1, ReceiveRaw2()); - SendRaw2(msg2, static_cast<int>(strlen(msg2))); - res.reset(Receive1()); - - ASSERT_TRUE(res); - EXPECT_EQ(STUN_DATA_INDICATION, res->type()); - - const StunAddressAttribute* src_addr = - res->GetAddress(STUN_ATTR_SOURCE_ADDRESS2); - ASSERT_TRUE(src_addr != NULL); - EXPECT_EQ(1, src_addr->family()); - EXPECT_EQ(client2_addr.ipaddr(), src_addr->ipaddr()); - EXPECT_EQ(client2_addr.port(), src_addr->port()); - - const StunByteStringAttribute* recv_data = - res->GetByteString(STUN_ATTR_DATA); - ASSERT_TRUE(recv_data != NULL); - EXPECT_EQ(strlen(msg2), recv_data->length()); - EXPECT_EQ(0, memcmp(msg2, recv_data->bytes(), recv_data->length())); - } -} - -// Verify that a binding expires properly, and rejects send requests. -// Flaky, see https://code.google.com/p/webrtc/issues/detail?id=4134 -TEST_F(RelayServerTest, DISABLED_TestExpiration) { - Allocate(); - Bind(); - - // Wait twice the lifetime to make sure the server has expired the binding. - rtc::Thread::Current()->ProcessMessages((LIFETIME * 2) * 1000); - - std::unique_ptr<StunMessage> req(CreateStunMessage(STUN_SEND_REQUEST)), res; - AddMagicCookieAttr(req.get()); - AddUsernameAttr(req.get(), username_); - AddDestinationAttr(req.get(), client2_addr); - - auto data_attr = StunAttribute::CreateByteString(STUN_ATTR_DATA); - data_attr->CopyBytes(msg1); - req->AddAttribute(std::move(data_attr)); - - Send1(req.get()); - res.reset(Receive1()); - - ASSERT_TRUE(res.get() != NULL); - EXPECT_EQ(STUN_SEND_ERROR_RESPONSE, res->type()); - - const StunErrorCodeAttribute* err = res->GetErrorCode(); - ASSERT_TRUE(err != NULL); - EXPECT_EQ(6, err->eclass()); - EXPECT_EQ(0, err->number()); - EXPECT_EQ("Operation Not Supported", err->reason()); - - // Also verify that traffic from the external client is ignored. - SendRaw2(msg2, static_cast<int>(strlen(msg2))); - EXPECT_TRUE(ReceiveRaw1().empty()); -} - -} // namespace cricket diff --git a/p2p/base/test_relay_server.h b/p2p/base/test_relay_server.h deleted file mode 100644 index be58251cd6..0000000000 --- a/p2p/base/test_relay_server.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2008 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef P2P_BASE_TEST_RELAY_SERVER_H_ -#define P2P_BASE_TEST_RELAY_SERVER_H_ - -#include <memory> - -#include "p2p/base/relay_server.h" -#include "rtc_base/async_tcp_socket.h" -#include "rtc_base/server_socket_adapters.h" -#include "rtc_base/third_party/sigslot/sigslot.h" -#include "rtc_base/thread.h" - -namespace cricket { - -// A test relay server. Useful for unit tests. -class TestRelayServer : public sigslot::has_slots<> { - public: - TestRelayServer(rtc::Thread* thread, - const rtc::SocketAddress& udp_int_addr, - const rtc::SocketAddress& udp_ext_addr, - const rtc::SocketAddress& tcp_int_addr, - const rtc::SocketAddress& tcp_ext_addr, - const rtc::SocketAddress& ssl_int_addr, - const rtc::SocketAddress& ssl_ext_addr) - : server_(thread) { - server_.AddInternalSocket( - rtc::AsyncUDPSocket::Create(thread->socketserver(), udp_int_addr)); - server_.AddExternalSocket( - rtc::AsyncUDPSocket::Create(thread->socketserver(), udp_ext_addr)); - - tcp_int_socket_.reset(CreateListenSocket(thread, tcp_int_addr)); - tcp_ext_socket_.reset(CreateListenSocket(thread, tcp_ext_addr)); - ssl_int_socket_.reset(CreateListenSocket(thread, ssl_int_addr)); - ssl_ext_socket_.reset(CreateListenSocket(thread, ssl_ext_addr)); - } - int GetConnectionCount() const { return server_.GetConnectionCount(); } - rtc::SocketAddressPair GetConnection(int connection) const { - return server_.GetConnection(connection); - } - bool HasConnection(const rtc::SocketAddress& address) const { - return server_.HasConnection(address); - } - - private: - rtc::AsyncSocket* CreateListenSocket(rtc::Thread* thread, - const rtc::SocketAddress& addr) { - rtc::AsyncSocket* socket = - thread->socketserver()->CreateAsyncSocket(addr.family(), SOCK_STREAM); - socket->Bind(addr); - socket->Listen(5); - socket->SignalReadEvent.connect(this, &TestRelayServer::OnAccept); - return socket; - } - void OnAccept(rtc::AsyncSocket* socket) { - bool external = - (socket == tcp_ext_socket_.get() || socket == ssl_ext_socket_.get()); - bool ssl = - (socket == ssl_int_socket_.get() || socket == ssl_ext_socket_.get()); - rtc::AsyncSocket* raw_socket = socket->Accept(NULL); - if (raw_socket) { - rtc::AsyncTCPSocket* packet_socket = new rtc::AsyncTCPSocket( - (!ssl) ? raw_socket : new rtc::AsyncSSLServerSocket(raw_socket), - false); - if (!external) { - packet_socket->SignalClose.connect(this, - &TestRelayServer::OnInternalClose); - server_.AddInternalSocket(packet_socket); - } else { - packet_socket->SignalClose.connect(this, - &TestRelayServer::OnExternalClose); - server_.AddExternalSocket(packet_socket); - } - } - } - void OnInternalClose(rtc::AsyncPacketSocket* socket, int error) { - server_.RemoveInternalSocket(socket); - } - void OnExternalClose(rtc::AsyncPacketSocket* socket, int error) { - server_.RemoveExternalSocket(socket); - } - - private: - cricket::RelayServer server_; - std::unique_ptr<rtc::AsyncSocket> tcp_int_socket_; - std::unique_ptr<rtc::AsyncSocket> tcp_ext_socket_; - std::unique_ptr<rtc::AsyncSocket> ssl_int_socket_; - std::unique_ptr<rtc::AsyncSocket> ssl_ext_socket_; -}; - -} // namespace cricket - -#endif // P2P_BASE_TEST_RELAY_SERVER_H_ diff --git a/p2p/client/basic_port_allocator.cc b/p2p/client/basic_port_allocator.cc index b2cc99a2b7..216e737ffb 100644 --- a/p2p/client/basic_port_allocator.cc +++ b/p2p/client/basic_port_allocator.cc @@ -20,7 +20,6 @@ #include "absl/algorithm/container.h" #include "p2p/base/basic_packet_socket_factory.h" #include "p2p/base/port.h" -#include "p2p/base/relay_port.h" #include "p2p/base/stun_port.h" #include "p2p/base/tcp_port.h" #include "p2p/base/turn_port.h" @@ -1522,42 +1521,7 @@ void AllocationSequence::CreateRelayPorts() { } for (RelayServerConfig& relay : config_->relays) { - if (relay.type == RELAY_GTURN) { - CreateGturnPort(relay); - } else if (relay.type == RELAY_TURN) { - CreateTurnPort(relay); - } else { - RTC_NOTREACHED(); - } - } -} - -void AllocationSequence::CreateGturnPort(const RelayServerConfig& config) { - // TODO(mallinath) - Rename RelayPort to GTurnPort. - std::unique_ptr<RelayPort> port = RelayPort::Create( - session_->network_thread(), session_->socket_factory(), network_, - session_->allocator()->min_port(), session_->allocator()->max_port(), - config_->username, config_->password); - if (port) { - RelayPort* port_ptr = port.release(); - // Since RelayPort is not created using shared socket, |port| will not be - // added to the dequeue. - // Note: We must add the allocated port before we add addresses because - // the latter will create candidates that need name and preference - // settings. However, we also can't prepare the address (normally - // done by AddAllocatedPort) until we have these addresses. So we - // wait to do that until below. - session_->AddAllocatedPort(port_ptr, this, false); - - // Add the addresses of this protocol. - PortList::const_iterator relay_port; - for (relay_port = config.ports.begin(); relay_port != config.ports.end(); - ++relay_port) { - port_ptr->AddServerAddress(*relay_port); - port_ptr->AddExternalAddress(*relay_port); - } - // Start fetching an address for this port. - port_ptr->PrepareAddress(); + CreateTurnPort(relay); } } @@ -1720,7 +1684,7 @@ ServerAddresses PortConfiguration::StunServers() { // Every UDP TURN server should also be used as a STUN server if // use_turn_server_as_stun_server is not disabled or the stun servers are // empty. - ServerAddresses turn_servers = GetRelayServerAddresses(RELAY_TURN, PROTO_UDP); + ServerAddresses turn_servers = GetRelayServerAddresses(PROTO_UDP); for (const rtc::SocketAddress& turn_server : turn_servers) { if (stun_servers.find(turn_server) == stun_servers.end()) { stun_servers.insert(turn_server); @@ -1744,21 +1708,19 @@ bool PortConfiguration::SupportsProtocol(const RelayServerConfig& relay, return false; } -bool PortConfiguration::SupportsProtocol(RelayType turn_type, - ProtocolType type) const { +bool PortConfiguration::SupportsProtocol(ProtocolType type) const { for (size_t i = 0; i < relays.size(); ++i) { - if (relays[i].type == turn_type && SupportsProtocol(relays[i], type)) + if (SupportsProtocol(relays[i], type)) return true; } return false; } ServerAddresses PortConfiguration::GetRelayServerAddresses( - RelayType turn_type, ProtocolType type) const { ServerAddresses servers; for (size_t i = 0; i < relays.size(); ++i) { - if (relays[i].type == turn_type && SupportsProtocol(relays[i], type)) { + if (SupportsProtocol(relays[i], type)) { servers.insert(relays[i].ports.front().address); } } diff --git a/p2p/client/basic_port_allocator.h b/p2p/client/basic_port_allocator.h index 274b89da48..ab47ce1030 100644 --- a/p2p/client/basic_port_allocator.h +++ b/p2p/client/basic_port_allocator.h @@ -316,11 +316,10 @@ struct RTC_EXPORT PortConfiguration : public rtc::MessageData { // Determines whether the given relay server supports the given protocol. bool SupportsProtocol(const RelayServerConfig& relay, ProtocolType type) const; - bool SupportsProtocol(RelayType turn_type, ProtocolType type) const; + bool SupportsProtocol(ProtocolType type) const; // Helper method returns the server addresses for the matching RelayType and // Protocol type. - ServerAddresses GetRelayServerAddresses(RelayType turn_type, - ProtocolType type) const; + ServerAddresses GetRelayServerAddresses(ProtocolType type) const; }; class UDPPort; @@ -388,7 +387,6 @@ class AllocationSequence : public rtc::MessageHandler, void CreateTCPPorts(); void CreateStunPorts(); void CreateRelayPorts(); - void CreateGturnPort(const RelayServerConfig& config); void OnReadPacket(rtc::AsyncPacketSocket* socket, const char* data, diff --git a/p2p/client/basic_port_allocator_unittest.cc b/p2p/client/basic_port_allocator_unittest.cc index 1822432686..797778c73c 100644 --- a/p2p/client/basic_port_allocator_unittest.cc +++ b/p2p/client/basic_port_allocator_unittest.cc @@ -19,7 +19,6 @@ #include "p2p/base/stun_port.h" #include "p2p/base/stun_request.h" #include "p2p/base/stun_server.h" -#include "p2p/base/test_relay_server.h" #include "p2p/base/test_stun_server.h" #include "p2p/base/test_turn_server.h" #include "rtc_base/fake_clock.h" @@ -218,7 +217,7 @@ class BasicPortAllocatorTestBase : public ::testing::Test, RelayServerConfig CreateTurnServers(const rtc::SocketAddress& udp_turn, const rtc::SocketAddress& tcp_turn) { - RelayServerConfig turn_server(RELAY_TURN); + RelayServerConfig turn_server; RelayCredentials credentials(kTurnUsername, kTurnPassword); turn_server.credentials = credentials; @@ -1778,7 +1777,7 @@ TEST_F(BasicPortAllocatorTestWithRealClock, AddInterface(kClientAddr); allocator_.reset(new BasicPortAllocator(&network_manager_)); allocator_->Initialize(); - RelayServerConfig turn_server(RELAY_TURN); + RelayServerConfig turn_server; RelayCredentials credentials(kTurnUsername, kTurnPassword); turn_server.credentials = credentials; turn_server.ports.push_back( |