summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/p2p/base/basic_packet_socket_factory.cc
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/libwebrtc/p2p/base/basic_packet_socket_factory.cc')
-rw-r--r--third_party/libwebrtc/p2p/base/basic_packet_socket_factory.cc210
1 files changed, 210 insertions, 0 deletions
diff --git a/third_party/libwebrtc/p2p/base/basic_packet_socket_factory.cc b/third_party/libwebrtc/p2p/base/basic_packet_socket_factory.cc
new file mode 100644
index 0000000000..7d87e12859
--- /dev/null
+++ b/third_party/libwebrtc/p2p/base/basic_packet_socket_factory.cc
@@ -0,0 +1,210 @@
+/*
+ * Copyright 2011 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/basic_packet_socket_factory.h"
+
+#include <stddef.h>
+
+#include <string>
+
+#include "absl/memory/memory.h"
+#include "api/async_dns_resolver.h"
+#include "api/wrapping_async_dns_resolver.h"
+#include "p2p/base/async_stun_tcp_socket.h"
+#include "rtc_base/async_dns_resolver.h"
+#include "rtc_base/async_tcp_socket.h"
+#include "rtc_base/async_udp_socket.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/logging.h"
+#include "rtc_base/socket.h"
+#include "rtc_base/socket_adapters.h"
+#include "rtc_base/ssl_adapter.h"
+
+namespace rtc {
+
+BasicPacketSocketFactory::BasicPacketSocketFactory(
+ SocketFactory* socket_factory)
+ : socket_factory_(socket_factory) {}
+
+BasicPacketSocketFactory::~BasicPacketSocketFactory() {}
+
+AsyncPacketSocket* BasicPacketSocketFactory::CreateUdpSocket(
+ const SocketAddress& address,
+ uint16_t min_port,
+ uint16_t max_port) {
+ // UDP sockets are simple.
+ Socket* socket = socket_factory_->CreateSocket(address.family(), SOCK_DGRAM);
+ if (!socket) {
+ return NULL;
+ }
+ if (BindSocket(socket, address, min_port, max_port) < 0) {
+ RTC_LOG(LS_ERROR) << "UDP bind failed with error " << socket->GetError();
+ delete socket;
+ return NULL;
+ }
+ return new AsyncUDPSocket(socket);
+}
+
+AsyncListenSocket* BasicPacketSocketFactory::CreateServerTcpSocket(
+ const SocketAddress& local_address,
+ uint16_t min_port,
+ uint16_t max_port,
+ int opts) {
+ // Fail if TLS is required.
+ if (opts & PacketSocketFactory::OPT_TLS) {
+ RTC_LOG(LS_ERROR) << "TLS support currently is not available.";
+ return NULL;
+ }
+
+ if (opts & PacketSocketFactory::OPT_TLS_FAKE) {
+ RTC_LOG(LS_ERROR) << "Fake TLS not supported.";
+ return NULL;
+ }
+ Socket* socket =
+ socket_factory_->CreateSocket(local_address.family(), SOCK_STREAM);
+ if (!socket) {
+ return NULL;
+ }
+
+ if (BindSocket(socket, local_address, min_port, max_port) < 0) {
+ RTC_LOG(LS_ERROR) << "TCP bind failed with error " << socket->GetError();
+ delete socket;
+ return NULL;
+ }
+
+ RTC_CHECK(!(opts & PacketSocketFactory::OPT_STUN));
+
+ return new AsyncTcpListenSocket(absl::WrapUnique(socket));
+}
+
+AsyncPacketSocket* BasicPacketSocketFactory::CreateClientTcpSocket(
+ const SocketAddress& local_address,
+ const SocketAddress& remote_address,
+ const ProxyInfo& proxy_info,
+ const std::string& user_agent,
+ const PacketSocketTcpOptions& tcp_options) {
+ Socket* socket =
+ socket_factory_->CreateSocket(local_address.family(), SOCK_STREAM);
+ if (!socket) {
+ return NULL;
+ }
+
+ if (BindSocket(socket, local_address, 0, 0) < 0) {
+ // Allow BindSocket to fail if we're binding to the ANY address, since this
+ // is mostly redundant in the first place. The socket will be bound when we
+ // call Connect() instead.
+ if (local_address.IsAnyIP()) {
+ RTC_LOG(LS_WARNING) << "TCP bind failed with error " << socket->GetError()
+ << "; ignoring since socket is using 'any' address.";
+ } else {
+ RTC_LOG(LS_ERROR) << "TCP bind failed with error " << socket->GetError();
+ delete socket;
+ return NULL;
+ }
+ }
+
+ // Set TCP_NODELAY (via OPT_NODELAY) for improved performance; this causes
+ // small media packets to be sent immediately rather than being buffered up,
+ // reducing latency.
+ //
+ // Must be done before calling Connect, otherwise it may fail.
+ if (socket->SetOption(Socket::OPT_NODELAY, 1) != 0) {
+ RTC_LOG(LS_ERROR) << "Setting TCP_NODELAY option failed with error "
+ << socket->GetError();
+ }
+
+ // If using a proxy, wrap the socket in a proxy socket.
+ if (proxy_info.type == PROXY_SOCKS5) {
+ socket = new AsyncSocksProxySocket(
+ socket, proxy_info.address, proxy_info.username, proxy_info.password);
+ } else if (proxy_info.type == PROXY_HTTPS) {
+ socket =
+ new AsyncHttpsProxySocket(socket, user_agent, proxy_info.address,
+ proxy_info.username, proxy_info.password);
+ }
+
+ // Assert that at most one TLS option is used.
+ int tlsOpts = tcp_options.opts & (PacketSocketFactory::OPT_TLS |
+ PacketSocketFactory::OPT_TLS_FAKE |
+ PacketSocketFactory::OPT_TLS_INSECURE);
+ RTC_DCHECK((tlsOpts & (tlsOpts - 1)) == 0);
+
+ if ((tlsOpts & PacketSocketFactory::OPT_TLS) ||
+ (tlsOpts & PacketSocketFactory::OPT_TLS_INSECURE)) {
+ // Using TLS, wrap the socket in an SSL adapter.
+ SSLAdapter* ssl_adapter = SSLAdapter::Create(socket);
+ if (!ssl_adapter) {
+ return NULL;
+ }
+
+ if (tlsOpts & PacketSocketFactory::OPT_TLS_INSECURE) {
+ ssl_adapter->SetIgnoreBadCert(true);
+ }
+
+ ssl_adapter->SetAlpnProtocols(tcp_options.tls_alpn_protocols);
+ ssl_adapter->SetEllipticCurves(tcp_options.tls_elliptic_curves);
+ ssl_adapter->SetCertVerifier(tcp_options.tls_cert_verifier);
+
+ socket = ssl_adapter;
+
+ if (ssl_adapter->StartSSL(remote_address.hostname().c_str()) != 0) {
+ delete ssl_adapter;
+ return NULL;
+ }
+
+ } else if (tlsOpts & PacketSocketFactory::OPT_TLS_FAKE) {
+ // Using fake TLS, wrap the TCP socket in a pseudo-SSL socket.
+ socket = new AsyncSSLSocket(socket);
+ }
+
+ if (socket->Connect(remote_address) < 0) {
+ RTC_LOG(LS_ERROR) << "TCP connect failed with error " << socket->GetError();
+ delete socket;
+ return NULL;
+ }
+
+ // Finally, wrap that socket in a TCP or STUN TCP packet socket.
+ AsyncPacketSocket* tcp_socket;
+ if (tcp_options.opts & PacketSocketFactory::OPT_STUN) {
+ tcp_socket = new cricket::AsyncStunTCPSocket(socket);
+ } else {
+ tcp_socket = new AsyncTCPSocket(socket);
+ }
+
+ return tcp_socket;
+}
+
+AsyncResolverInterface* BasicPacketSocketFactory::CreateAsyncResolver() {
+ return new AsyncResolver();
+}
+
+std::unique_ptr<webrtc::AsyncDnsResolverInterface>
+BasicPacketSocketFactory::CreateAsyncDnsResolver() {
+ return std::make_unique<webrtc::AsyncDnsResolver>();
+}
+
+int BasicPacketSocketFactory::BindSocket(Socket* socket,
+ const SocketAddress& local_address,
+ uint16_t min_port,
+ uint16_t max_port) {
+ int ret = -1;
+ if (min_port == 0 && max_port == 0) {
+ // If there's no port range, let the OS pick a port for us.
+ ret = socket->Bind(local_address);
+ } else {
+ // Otherwise, try to find a port in the provided range.
+ for (int port = min_port; ret < 0 && port <= max_port; ++port) {
+ ret = socket->Bind(SocketAddress(local_address.ipaddr(), port));
+ }
+ }
+ return ret;
+}
+
+} // namespace rtc