This is a recommit of
https://webrtc.googlesource.com/src.git/+/26246cac660a95f439b7d1c593edec2929806d3f
that was reverted due to compile error on windows.
Changes since last is an addition of a cast to uint16_t in stun.cc:1018.
---
Add RelayPortFactoryInterface that allows for custom relay (e.g turn) ports
This patch adds a RelayPortFactoryInterface that allows
for custom relay ports. The factor is added as optional argument
to BasicPortAlloctor. If none is provided a default implementation
that mimics existing behavior is created.
The patch also adds 2 stun functions, namely to copy a
StunAttribute and to remove StunAttribute's from a StunMessage.
Bug: webrtc:8640
Change-Id: If23638317130060286f576c94401de55c60a1821
Reviewed-on: https://webrtc-review.googlesource.com/34181
Reviewed-by: Guido Urdaneta <guidou@webrtc.org>
Reviewed-by: Peter Thatcher <pthatcher@webrtc.org>
Commit-Queue: Jonas Oreland <jonaso@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#21345}
diff --git a/p2p/BUILD.gn b/p2p/BUILD.gn
index 8e61730..cd54b7d 100644
--- a/p2p/BUILD.gn
+++ b/p2p/BUILD.gn
@@ -81,8 +81,11 @@
"base/udptransport.h",
"client/basicportallocator.cc",
"client/basicportallocator.h",
+ "client/relayportfactoryinterface.h",
"client/socketmonitor.cc",
"client/socketmonitor.h",
+ "client/turnportfactory.cc",
+ "client/turnportfactory.h",
]
defines = []
diff --git a/p2p/base/port.cc b/p2p/base/port.cc
index 66685ec..af96582 100644
--- a/p2p/base/port.cc
+++ b/p2p/base/port.cc
@@ -621,6 +621,10 @@
return false;
}
+bool Port::CanHandleIncomingPacketsFrom(const rtc::SocketAddress&) const {
+ return false;
+}
+
void Port::SendBindingResponse(StunMessage* request,
const rtc::SocketAddress& addr) {
RTC_DCHECK(request->type() == STUN_BINDING_REQUEST);
diff --git a/p2p/base/port.h b/p2p/base/port.h
index 2957fd8..e56afc4 100644
--- a/p2p/base/port.h
+++ b/p2p/base/port.h
@@ -254,6 +254,11 @@
const rtc::SocketAddress& remote_addr,
const rtc::PacketTime& packet_time);
+ // Shall the port handle packet from this |remote_addr|.
+ // This method is overridden by TurnPort.
+ virtual bool CanHandleIncomingPacketsFrom(
+ const rtc::SocketAddress& remote_addr) const;
+
// Sends a response message (normal or error) to the given request. One of
// these methods should be called as a response to SignalUnknownAddress.
// NOTE: You MUST call CreateConnection BEFORE SendBindingResponse.
diff --git a/p2p/base/stun.cc b/p2p/base/stun.cc
index cad33af..6e8f098 100644
--- a/p2p/base/stun.cc
+++ b/p2p/base/stun.cc
@@ -92,6 +92,26 @@
attrs_.push_back(std::move(attr));
}
+std::unique_ptr<StunAttribute> StunMessage::RemoveAttribute(int type) {
+ std::unique_ptr<StunAttribute> attribute;
+ for (auto it = attrs_.rbegin(); it != attrs_.rend(); ++it) {
+ if ((* it)->type() == type) {
+ attribute = std::move(* it);
+ attrs_.erase(std::next(it).base());
+ break;
+ }
+ }
+ if (attribute) {
+ attribute->SetOwner(nullptr);
+ size_t attr_length = attribute->length();
+ if (attr_length % 4 != 0) {
+ attr_length += (4 - (attr_length % 4));
+ }
+ length_ -= static_cast<uint16_t>(attr_length + 4);
+ }
+ return attribute;
+}
+
const StunAddressAttribute* StunMessage::GetAddress(int type) const {
switch (type) {
case STUN_ATTR_MAPPED_ADDRESS: {
@@ -984,6 +1004,35 @@
return true;
}
+std::unique_ptr<StunAttribute> CopyStunAttribute(
+ const StunAttribute& attribute,
+ rtc::ByteBufferWriter* tmp_buffer_ptr) {
+ ByteBufferWriter tmpBuffer;
+ if (tmp_buffer_ptr == nullptr) {
+ tmp_buffer_ptr = &tmpBuffer;
+ }
+
+ std::unique_ptr<StunAttribute> copy(
+ StunAttribute::Create(attribute.value_type(),
+ attribute.type(),
+ static_cast<uint16_t>(attribute.length()),
+ nullptr));
+
+ if (!copy) {
+ return nullptr;
+ }
+ tmp_buffer_ptr->Clear();
+ if (!attribute.Write(tmp_buffer_ptr)) {
+ return nullptr;
+ }
+ rtc::ByteBufferReader reader(*tmp_buffer_ptr);
+ if (!copy->Read(&reader)) {
+ return nullptr;
+ }
+
+ return copy;
+}
+
StunAttributeValueType RelayMessage::GetAttributeValueType(int type) const {
switch (type) {
case STUN_ATTR_LIFETIME:
diff --git a/p2p/base/stun.h b/p2p/base/stun.h
index b576d37..a1cce87 100644
--- a/p2p/base/stun.h
+++ b/p2p/base/stun.h
@@ -165,6 +165,9 @@
// Takes ownership of the specified attribute and adds it to the message.
void AddAttribute(std::unique_ptr<StunAttribute> attr);
+ // Remove the last occurrence of an attribute.
+ std::unique_ptr<StunAttribute> RemoveAttribute(int type);
+
// Validates that a raw STUN message has a correct MESSAGE-INTEGRITY value.
// This can't currently be done on a StunMessage, since it is affected by
// padding data (which we discard when reading a StunMessage).
@@ -477,6 +480,18 @@
bool ComputeStunCredentialHash(const std::string& username,
const std::string& realm, const std::string& password, std::string* hash);
+// Make a copy af |attribute| and return a new StunAttribute.
+// This is useful if you don't care about what kind of attribute you
+// are handling.
+//
+// The implementation copies by calling Write() followed by Read().
+//
+// If |tmp_buffer| is supplied this buffer will be used, otherwise
+// a buffer will created in the method.
+std::unique_ptr<StunAttribute> CopyStunAttribute(
+ const StunAttribute& attribute,
+ rtc::ByteBufferWriter* tmp_buffer_ptr = 0);
+
// TODO(?): Move the TURN/ICE stuff below out to separate files.
extern const char TURN_MAGIC_COOKIE_VALUE[4];
diff --git a/p2p/base/stun_unittest.cc b/p2p/base/stun_unittest.cc
index 9d418c4..5c805dc 100644
--- a/p2p/base/stun_unittest.cc
+++ b/p2p/base/stun_unittest.cc
@@ -1480,4 +1480,94 @@
EXPECT_EQ(0, memcmp(outstring2.c_str(), input, len2));
}
+// Test that we can remove attribute from a message.
+TEST_F(StunTest, RemoveAttribute) {
+ StunMessage msg;
+
+ // Removing something that does exist should return nullptr.
+ EXPECT_EQ(msg.RemoveAttribute(STUN_ATTR_USERNAME), nullptr);
+
+ {
+ auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
+ attr->CopyBytes("kes", sizeof("kes"));
+ msg.AddAttribute(std::move(attr));
+ }
+
+ size_t len = msg.length();
+ {
+ auto attr = msg.RemoveAttribute(STUN_ATTR_USERNAME);
+ ASSERT_NE(attr, nullptr);
+ EXPECT_EQ(attr->type(), STUN_ATTR_USERNAME);
+ EXPECT_STREQ("kes",
+ static_cast<StunByteStringAttribute*>(attr.get())->bytes());
+ EXPECT_LT(msg.length(), len);
+ }
+
+ // Now add same attribute type twice.
+ {
+ auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
+ attr->CopyBytes("kes", sizeof("kes"));
+ msg.AddAttribute(std::move(attr));
+ }
+
+ {
+ auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
+ attr->CopyBytes("kenta", sizeof("kenta"));
+ msg.AddAttribute(std::move(attr));
+ }
+
+ // Remove should remove the last added occurrence.
+ {
+ auto attr = msg.RemoveAttribute(STUN_ATTR_USERNAME);
+ ASSERT_NE(attr, nullptr);
+ EXPECT_EQ(attr->type(), STUN_ATTR_USERNAME);
+ EXPECT_STREQ("kenta",
+ static_cast<StunByteStringAttribute*>(attr.get())->bytes());
+ }
+
+ // Remove should remove the last added occurrence.
+ {
+ auto attr = msg.RemoveAttribute(STUN_ATTR_USERNAME);
+ ASSERT_NE(attr, nullptr);
+ EXPECT_EQ(attr->type(), STUN_ATTR_USERNAME);
+ EXPECT_STREQ("kes",
+ static_cast<StunByteStringAttribute*>(attr.get())->bytes());
+ }
+
+ // Removing something that does exist should return nullptr.
+ EXPECT_EQ(msg.RemoveAttribute(STUN_ATTR_USERNAME), nullptr);
+}
+
+// Test CopyStunAttribute
+TEST_F(StunTest, CopyAttribute) {
+ rtc::ByteBufferWriter buf;
+ rtc::ByteBufferWriter* buffer_ptrs[] = { &buf, nullptr };
+ // Test both with and without supplied ByteBufferWriter.
+ for (auto buffer_ptr : buffer_ptrs) {
+ { // Test StunByteStringAttribute.
+ auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
+ attr->CopyBytes("kes", sizeof("kes"));
+
+ auto copy = CopyStunAttribute(*attr.get(), buffer_ptr);
+ ASSERT_EQ(copy->value_type(), STUN_VALUE_BYTE_STRING);
+ EXPECT_STREQ("kes",
+ static_cast<StunByteStringAttribute*>(copy.get())->bytes());
+ }
+
+ { // Test StunAddressAttribute.
+ rtc::IPAddress test_ip(kIPv6TestAddress2);
+ auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
+ rtc::SocketAddress test_addr(test_ip, kTestMessagePort2);
+ addr->SetAddress(test_addr);
+ CheckStunAddressAttribute(addr.get(),
+ STUN_ADDRESS_IPV6, kTestMessagePort2, test_ip);
+
+ auto copy = CopyStunAttribute(*addr.get(), buffer_ptr);
+ ASSERT_EQ(copy->value_type(), STUN_VALUE_ADDRESS);
+ CheckStunAddressAttribute(static_cast<StunAddressAttribute*>(copy.get()),
+ STUN_ADDRESS_IPV6, kTestMessagePort2, test_ip);
+ }
+ }
+}
+
} // namespace cricket
diff --git a/p2p/base/turnport.cc b/p2p/base/turnport.cc
index e676824..285d41b 100644
--- a/p2p/base/turnport.cc
+++ b/p2p/base/turnport.cc
@@ -523,7 +523,11 @@
remote_candidate.address().family()) {
// Create an entry, if needed, so we can get our permissions set up
// correctly.
- CreateOrRefreshEntry(remote_candidate.address());
+ if (CreateOrRefreshEntry(remote_candidate.address(),
+ next_channel_number_)) {
+ // An entry was created.
+ next_channel_number_++;
+ }
ProxyConnection* conn =
new ProxyConnection(this, index, remote_candidate);
AddOrReplaceConnection(conn);
@@ -596,6 +600,11 @@
return static_cast<int>(size);
}
+bool TurnPort::CanHandleIncomingPacketsFrom(
+ const rtc::SocketAddress& addr) const {
+ return server_address_.address == addr;
+}
+
bool TurnPort::HandleIncomingPacket(rtc::AsyncPacketSocket* socket,
const char* data, size_t size,
const rtc::SocketAddress& remote_addr,
@@ -1070,11 +1079,13 @@
return it != entries_.end();
}
-void TurnPort::CreateOrRefreshEntry(const rtc::SocketAddress& addr) {
+bool TurnPort::CreateOrRefreshEntry(const rtc::SocketAddress& addr,
+ int channel_number) {
TurnEntry* entry = FindEntry(addr);
if (entry == nullptr) {
- entry = new TurnEntry(this, next_channel_number_++, addr);
+ entry = new TurnEntry(this, channel_number, addr);
entries_.push_back(entry);
+ return true;
} else {
if (entry->destruction_timestamp()) {
// Destruction should have only been scheduled (indicated by
@@ -1092,6 +1103,7 @@
RTC_DCHECK(GetConnection(addr));
}
}
+ return false;
}
void TurnPort::DestroyEntry(TurnEntry* entry) {
diff --git a/p2p/base/turnport.h b/p2p/base/turnport.h
index 8246b43..4ee5f89 100644
--- a/p2p/base/turnport.h
+++ b/p2p/base/turnport.h
@@ -124,6 +124,8 @@
size_t size,
const rtc::SocketAddress& remote_addr,
const rtc::PacketTime& packet_time) override;
+ bool CanHandleIncomingPacketsFrom(
+ const rtc::SocketAddress& addr) const override;
virtual void OnReadPacket(rtc::AsyncPacketSocket* socket,
const char* data, size_t size,
const rtc::SocketAddress& remote_addr,
@@ -175,6 +177,8 @@
// Shuts down the turn port, usually because of some fatal errors.
void Close();
+ void HandleConnectionDestroyed(Connection* conn) override;
+
protected:
TurnPort(rtc::Thread* thread,
rtc::PacketSocketFactory* factory,
@@ -203,6 +207,11 @@
const std::vector<std::string>& tls_elliptic_curves,
webrtc::TurnCustomizer* customizer);
+ // NOTE: This method needs to be accessible for StacPort
+ // return true if entry was created (i.e channel_number consumed).
+ bool CreateOrRefreshEntry(const rtc::SocketAddress& addr,
+ int channel_number);
+
private:
enum {
MSG_ALLOCATE_ERROR = MSG_FIRST_AVAILABLE,
@@ -216,7 +225,6 @@
typedef std::set<rtc::SocketAddress> AttemptedServerSet;
void OnMessage(rtc::Message* pmsg) override;
- void HandleConnectionDestroyed(Connection* conn) override;
bool CreateTurnClientSocket();
@@ -264,7 +272,6 @@
TurnEntry* FindEntry(const rtc::SocketAddress& address) const;
TurnEntry* FindEntry(int channel_id) const;
bool EntryExists(TurnEntry* e);
- void CreateOrRefreshEntry(const rtc::SocketAddress& address);
void DestroyEntry(TurnEntry* entry);
// Destroys the entry only if |timestamp| matches the destruction timestamp
// in |entry|.
diff --git a/p2p/client/basicportallocator.cc b/p2p/client/basicportallocator.cc
index b3b9e73..5f27a7d 100644
--- a/p2p/client/basicportallocator.cc
+++ b/p2p/client/basicportallocator.cc
@@ -100,8 +100,11 @@
BasicPortAllocator::BasicPortAllocator(
rtc::NetworkManager* network_manager,
rtc::PacketSocketFactory* socket_factory,
- webrtc::TurnCustomizer* customizer)
+ webrtc::TurnCustomizer* customizer,
+ RelayPortFactoryInterface* relay_port_factory)
: network_manager_(network_manager), socket_factory_(socket_factory) {
+ InitRelayPortFactory(relay_port_factory);
+ RTC_DCHECK(relay_port_factory_ != nullptr);
RTC_DCHECK(network_manager_ != nullptr);
RTC_DCHECK(socket_factory_ != nullptr);
SetConfiguration(ServerAddresses(), std::vector<RelayServerConfig>(),
@@ -109,16 +112,22 @@
Construct();
}
-BasicPortAllocator::BasicPortAllocator(rtc::NetworkManager* network_manager)
+BasicPortAllocator::BasicPortAllocator(
+ rtc::NetworkManager* network_manager)
: network_manager_(network_manager), socket_factory_(nullptr) {
+ InitRelayPortFactory(nullptr);
+ RTC_DCHECK(relay_port_factory_ != nullptr);
RTC_DCHECK(network_manager_ != nullptr);
Construct();
}
-BasicPortAllocator::BasicPortAllocator(rtc::NetworkManager* network_manager,
- rtc::PacketSocketFactory* socket_factory,
- const ServerAddresses& stun_servers)
+BasicPortAllocator::BasicPortAllocator(
+ rtc::NetworkManager* network_manager,
+ rtc::PacketSocketFactory* socket_factory,
+ const ServerAddresses& stun_servers)
: network_manager_(network_manager), socket_factory_(socket_factory) {
+ InitRelayPortFactory(nullptr);
+ RTC_DCHECK(relay_port_factory_ != nullptr);
RTC_DCHECK(socket_factory_ != NULL);
SetConfiguration(stun_servers, std::vector<RelayServerConfig>(), 0, false,
nullptr);
@@ -132,6 +141,9 @@
const rtc::SocketAddress& relay_address_tcp,
const rtc::SocketAddress& relay_address_ssl)
: network_manager_(network_manager), socket_factory_(NULL) {
+ InitRelayPortFactory(nullptr);
+ RTC_DCHECK(relay_port_factory_ != nullptr);
+ RTC_DCHECK(network_manager_ != nullptr);
std::vector<RelayServerConfig> turn_servers;
RelayServerConfig config(RELAY_GTURN);
if (!relay_address_udp.IsNil()) {
@@ -204,6 +216,16 @@
prune_turn_ports(), turn_customizer());
}
+void BasicPortAllocator::InitRelayPortFactory(
+ RelayPortFactoryInterface* relay_port_factory) {
+ if (relay_port_factory != nullptr) {
+ relay_port_factory_ = relay_port_factory;
+ } else {
+ default_relay_port_factory_.reset(new TurnPortFactory());
+ relay_port_factory_ = default_relay_port_factory_.get();
+ }
+}
+
// BasicPortAllocatorSession
BasicPortAllocatorSession::BasicPortAllocatorSession(
BasicPortAllocator* allocator,
@@ -1107,7 +1129,7 @@
void AllocationSequence::Clear() {
udp_port_ = NULL;
- turn_ports_.clear();
+ relay_ports_.clear();
}
void AllocationSequence::OnNetworkFailed() {
@@ -1387,8 +1409,6 @@
PortList::const_iterator relay_port;
for (relay_port = config.ports.begin();
relay_port != config.ports.end(); ++relay_port) {
- TurnPort* port = NULL;
-
// Skip UDP connections to relay servers if it's disallowed.
if (IsFlagSet(PORTALLOCATOR_DISABLE_UDP_RELAY) &&
relay_port->proto == PROTO_UDP) {
@@ -1407,35 +1427,53 @@
continue;
}
+ CreateRelayPortArgs args;
+ args.network_thread = session_->network_thread();
+ args.socket_factory = session_->socket_factory();
+ args.network = network_;
+ args.username = session_->username();
+ args.password = session_->password();
+ args.server_address = &(*relay_port);
+ args.config = &config;
+ args.origin = session_->allocator()->origin();
+ args.turn_customizer = session_->allocator()->turn_customizer();
+
+ std::unique_ptr<cricket::Port> port;
// Shared socket mode must be enabled only for UDP based ports. Hence
// don't pass shared socket for ports which will create TCP sockets.
// TODO(mallinath) - Enable shared socket mode for TURN ports. Disabled
// due to webrtc bug https://code.google.com/p/webrtc/issues/detail?id=3537
if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET) &&
relay_port->proto == PROTO_UDP && udp_socket_) {
- port = TurnPort::Create(session_->network_thread(),
- session_->socket_factory(),
- network_, udp_socket_.get(),
- session_->username(), session_->password(),
- *relay_port, config.credentials, config.priority,
- session_->allocator()->origin(),
- session_->allocator()->turn_customizer());
- turn_ports_.push_back(port);
+ port = session_->allocator()->relay_port_factory()->Create(
+ args, udp_socket_.get());
+
+ if (!port) {
+ RTC_LOG(LS_WARNING)
+ << "Failed to create relay port with "
+ << args.server_address->address.ToString();
+ continue;
+ }
+
+ relay_ports_.push_back(port.get());
// Listen to the port destroyed signal, to allow AllocationSequence to
// remove entrt from it's map.
port->SignalDestroyed.connect(this, &AllocationSequence::OnPortDestroyed);
} else {
- port = TurnPort::Create(
- session_->network_thread(), session_->socket_factory(), network_,
- session_->allocator()->min_port(), session_->allocator()->max_port(),
- session_->username(), session_->password(), *relay_port,
- config.credentials, config.priority, session_->allocator()->origin(),
- config.tls_alpn_protocols, config.tls_elliptic_curves,
- session_->allocator()->turn_customizer());
+ port = session_->allocator()->relay_port_factory()->Create(
+ args,
+ session_->allocator()->min_port(),
+ session_->allocator()->max_port());
+
+ if (!port) {
+ RTC_LOG(LS_WARNING)
+ << "Failed to create relay port with "
+ << args.server_address->address.ToString();
+ continue;
+ }
}
RTC_DCHECK(port != NULL);
- port->SetTlsCertPolicy(config.tls_cert_policy);
- session_->AddAllocatedPort(port, this, true);
+ session_->AddAllocatedPort(port.release(), this, true);
}
}
@@ -1453,8 +1491,8 @@
// a STUN binding response, so we pass the message to TurnPort regardless of
// the message type. The TurnPort will just ignore the message since it will
// not find any request by transaction ID.
- for (TurnPort* port : turn_ports_) {
- if (port->server_address().address == remote_addr) {
+ for (auto* port : relay_ports_) {
+ if (port->CanHandleIncomingPacketsFrom(remote_addr)) {
if (port->HandleIncomingPacket(socket, data, size, remote_addr,
packet_time)) {
return;
@@ -1483,9 +1521,9 @@
return;
}
- auto it = std::find(turn_ports_.begin(), turn_ports_.end(), port);
- if (it != turn_ports_.end()) {
- turn_ports_.erase(it);
+ auto it = std::find(relay_ports_.begin(), relay_ports_.end(), port);
+ if (it != relay_ports_.end()) {
+ relay_ports_.erase(it);
} else {
RTC_LOG(LS_ERROR) << "Unexpected OnPortDestroyed for nonexistent port.";
RTC_NOTREACHED();
diff --git a/p2p/client/basicportallocator.h b/p2p/client/basicportallocator.h
index f5cc1d1..23faff1 100644
--- a/p2p/client/basicportallocator.h
+++ b/p2p/client/basicportallocator.h
@@ -17,6 +17,8 @@
#include "api/turncustomizer.h"
#include "p2p/base/portallocator.h"
+#include "p2p/client/turnportfactory.h"
+#include "p2p/client/relayportfactoryinterface.h"
#include "rtc_base/checks.h"
#include "rtc_base/messagequeue.h"
#include "rtc_base/network.h"
@@ -26,18 +28,21 @@
class BasicPortAllocator : public PortAllocator {
public:
+ // note: The (optional) relay_port_factory is owned by caller
+ // and must have a life time that exceeds that of BasicPortAllocator.
BasicPortAllocator(rtc::NetworkManager* network_manager,
rtc::PacketSocketFactory* socket_factory,
- webrtc::TurnCustomizer* customizer = nullptr);
+ webrtc::TurnCustomizer* customizer = nullptr,
+ RelayPortFactoryInterface* relay_port_factory = nullptr);
explicit BasicPortAllocator(rtc::NetworkManager* network_manager);
BasicPortAllocator(rtc::NetworkManager* network_manager,
rtc::PacketSocketFactory* socket_factory,
const ServerAddresses& stun_servers);
BasicPortAllocator(rtc::NetworkManager* network_manager,
const ServerAddresses& stun_servers,
- const rtc::SocketAddress& relay_server_udp,
- const rtc::SocketAddress& relay_server_tcp,
- const rtc::SocketAddress& relay_server_ssl);
+ const rtc::SocketAddress& relay_address_udp,
+ const rtc::SocketAddress& relay_address_tcp,
+ const rtc::SocketAddress& relay_address_ssl);
~BasicPortAllocator() override;
// Set to kDefaultNetworkIgnoreMask by default.
@@ -59,16 +64,29 @@
// Convenience method that adds a TURN server to the configuration.
void AddTurnServer(const RelayServerConfig& turn_server);
+ RelayPortFactoryInterface* relay_port_factory() {
+ return relay_port_factory_;
+ }
+
private:
void Construct();
void OnIceRegathering(PortAllocatorSession* session,
IceRegatheringReason reason);
+ // This function makes sure that relay_port_factory_ is set properly.
+ void InitRelayPortFactory(RelayPortFactoryInterface* relay_port_factory);
+
rtc::NetworkManager* network_manager_;
rtc::PacketSocketFactory* socket_factory_;
bool allow_tcp_listen_;
int network_ignore_mask_ = rtc::kDefaultNetworkIgnoreMask;
+
+ // This is the factory being used.
+ RelayPortFactoryInterface* relay_port_factory_;
+
+ // This instance is created if caller does pass a factory.
+ std::unique_ptr<RelayPortFactoryInterface> default_relay_port_factory_;
};
struct PortConfiguration;
@@ -369,7 +387,7 @@
std::unique_ptr<rtc::AsyncPacketSocket> udp_socket_;
// There will be only one udp port per AllocationSequence.
UDPPort* udp_port_;
- std::vector<TurnPort*> turn_ports_;
+ std::vector<Port*> relay_ports_;
int phase_;
};
diff --git a/p2p/client/relayportfactoryinterface.h b/p2p/client/relayportfactoryinterface.h
new file mode 100644
index 0000000..5890bcd
--- /dev/null
+++ b/p2p/client/relayportfactoryinterface.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2017 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_CLIENT_RELAYPORTFACTORYINTERFACE_H_
+#define P2P_CLIENT_RELAYPORTFACTORYINTERFACE_H_
+
+#include <memory>
+#include <string>
+
+#include "p2p/base/portinterface.h"
+#include "rtc_base/refcount.h"
+
+namespace rtc {
+class AsyncPacketSocket;
+class Network;
+class PacketSocketFactory;
+class Thread;
+} // namespace rtc
+
+namespace webrtc {
+class TurnCustomizer;
+} // namespace webrtc
+
+namespace cricket {
+class Port;
+struct ProtocolAddress;
+struct RelayServerConfig;
+
+// A struct containing arguments to RelayPortFactory::Create()
+struct CreateRelayPortArgs {
+ CreateRelayPortArgs();
+ rtc::Thread* network_thread;
+ rtc::PacketSocketFactory* socket_factory;
+ rtc::Network* network;
+ const ProtocolAddress* server_address;
+ const RelayServerConfig* config;
+ std::string username;
+ std::string password;
+ std::string origin;
+ webrtc::TurnCustomizer* turn_customizer;
+};
+
+inline CreateRelayPortArgs::CreateRelayPortArgs() {}
+
+// A factory for creating RelayPort's.
+class RelayPortFactoryInterface {
+ public:
+ virtual ~RelayPortFactoryInterface() {}
+
+ // This variant is used for UDP connection to the relay server
+ // using a already existing shared socket.
+ virtual std::unique_ptr<Port> Create(
+ const CreateRelayPortArgs& args,
+ rtc::AsyncPacketSocket* udp_socket) = 0;
+
+ // This variant is used for the other cases.
+ virtual std::unique_ptr<Port> Create(
+ const CreateRelayPortArgs& args,
+ int min_port,
+ int max_port) = 0;
+};
+
+} // namespace cricket
+
+#endif // P2P_CLIENT_RELAYPORTFACTORYINTERFACE_H_
diff --git a/p2p/client/turnportfactory.cc b/p2p/client/turnportfactory.cc
new file mode 100644
index 0000000..9f24f5f
--- /dev/null
+++ b/p2p/client/turnportfactory.cc
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2017 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/client/turnportfactory.h"
+
+#include <memory>
+
+#include "p2p/base/turnport.h"
+
+namespace cricket {
+
+TurnPortFactory::~TurnPortFactory() {
+}
+
+std::unique_ptr<Port> TurnPortFactory::Create(
+ const CreateRelayPortArgs& args,
+ rtc::AsyncPacketSocket* udp_socket) {
+
+ TurnPort* port = TurnPort::Create(
+ args.network_thread,
+ args.socket_factory,
+ args.network,
+ udp_socket,
+ args.username,
+ args.password,
+ *args.server_address,
+ args.config->credentials,
+ args.config->priority,
+ args.origin,
+ args.turn_customizer);
+ port->SetTlsCertPolicy(args.config->tls_cert_policy);
+ return std::unique_ptr<Port>(port);
+}
+
+std::unique_ptr<Port> TurnPortFactory::Create(
+ const CreateRelayPortArgs& args,
+ int min_port,
+ int max_port) {
+
+ TurnPort* port = TurnPort::Create(
+ args.network_thread,
+ args.socket_factory,
+ args.network,
+ min_port,
+ max_port,
+ args.username,
+ args.password,
+ *args.server_address,
+ args.config->credentials,
+ args.config->priority,
+ args.origin,
+ args.config->tls_alpn_protocols,
+ args.config->tls_elliptic_curves,
+ args.turn_customizer);
+ port->SetTlsCertPolicy(args.config->tls_cert_policy);
+ return std::unique_ptr<Port>(port);
+}
+
+} // namespace cricket
diff --git a/p2p/client/turnportfactory.h b/p2p/client/turnportfactory.h
new file mode 100644
index 0000000..d5c510b
--- /dev/null
+++ b/p2p/client/turnportfactory.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2017 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_CLIENT_TURNPORTFACTORY_H_
+#define P2P_CLIENT_TURNPORTFACTORY_H_
+
+#include <memory>
+
+#include "p2p/client/relayportfactoryinterface.h"
+
+namespace cricket {
+
+// This is a RelayPortFactory that produces TurnPorts.
+class TurnPortFactory : public RelayPortFactoryInterface {
+ public:
+ ~TurnPortFactory() override;
+
+ std::unique_ptr<Port> Create(
+ const CreateRelayPortArgs& args,
+ rtc::AsyncPacketSocket* udp_socket) override;
+
+ std::unique_ptr<Port> Create(
+ const CreateRelayPortArgs& args,
+ int min_port,
+ int max_port) override;
+};
+
+} // namespace cricket
+
+#endif // P2P_CLIENT_TURNPORTFACTORY_H_