blob: 1476939a3d209157099e7e02dfce15b2878e8635 [file] [log] [blame]
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001/*
2 * Copyright 2011 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Steve Anton10542f22019-01-11 09:11:00 -080011#include "p2p/base/basic_packet_socket_factory.h"
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000012
Yves Gerey3e707812018-11-28 16:47:49 +010013#include <stddef.h>
Jonas Olssona4d87372019-07-05 19:08:33 +020014
johan57e13de2016-10-25 10:15:06 -070015#include <string>
16
Steve Anton10542f22019-01-11 09:11:00 -080017#include "p2p/base/async_stun_tcp_socket.h"
18#include "rtc_base/async_tcp_socket.h"
19#include "rtc_base/async_udp_socket.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "rtc_base/checks.h"
21#include "rtc_base/logging.h"
Steve Anton10542f22019-01-11 09:11:00 -080022#include "rtc_base/net_helpers.h"
Yves Gerey3e707812018-11-28 16:47:49 +010023#include "rtc_base/socket.h"
Steve Anton10542f22019-01-11 09:11:00 -080024#include "rtc_base/socket_adapters.h"
25#include "rtc_base/socket_server.h"
26#include "rtc_base/ssl_adapter.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020027#include "rtc_base/thread.h"
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000028
29namespace rtc {
30
31BasicPacketSocketFactory::BasicPacketSocketFactory()
Yves Gerey665174f2018-06-19 15:03:05 +020032 : thread_(Thread::Current()), socket_factory_(NULL) {}
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000033
34BasicPacketSocketFactory::BasicPacketSocketFactory(Thread* thread)
Yves Gerey665174f2018-06-19 15:03:05 +020035 : thread_(thread), socket_factory_(NULL) {}
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000036
37BasicPacketSocketFactory::BasicPacketSocketFactory(
38 SocketFactory* socket_factory)
Yves Gerey665174f2018-06-19 15:03:05 +020039 : thread_(NULL), socket_factory_(socket_factory) {}
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000040
Yves Gerey665174f2018-06-19 15:03:05 +020041BasicPacketSocketFactory::~BasicPacketSocketFactory() {}
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000042
43AsyncPacketSocket* BasicPacketSocketFactory::CreateUdpSocket(
Peter Boström0c4e06b2015-10-07 12:23:21 +020044 const SocketAddress& address,
45 uint16_t min_port,
46 uint16_t max_port) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000047 // UDP sockets are simple.
johan57e13de2016-10-25 10:15:06 -070048 AsyncSocket* socket =
49 socket_factory()->CreateAsyncSocket(address.family(), SOCK_DGRAM);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000050 if (!socket) {
51 return NULL;
52 }
53 if (BindSocket(socket, address, min_port, max_port) < 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +010054 RTC_LOG(LS_ERROR) << "UDP bind failed with error " << socket->GetError();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000055 delete socket;
56 return NULL;
57 }
johan57e13de2016-10-25 10:15:06 -070058 return new AsyncUDPSocket(socket);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000059}
60
61AsyncPacketSocket* BasicPacketSocketFactory::CreateServerTcpSocket(
Peter Boström0c4e06b2015-10-07 12:23:21 +020062 const SocketAddress& local_address,
63 uint16_t min_port,
64 uint16_t max_port,
pkasting@chromium.org332331f2014-11-06 20:19:22 +000065 int opts) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000066 // Fail if TLS is required.
67 if (opts & PacketSocketFactory::OPT_TLS) {
Mirko Bonadei675513b2017-11-09 11:09:25 +010068 RTC_LOG(LS_ERROR) << "TLS support currently is not available.";
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000069 return NULL;
70 }
71
johan57e13de2016-10-25 10:15:06 -070072 AsyncSocket* socket =
73 socket_factory()->CreateAsyncSocket(local_address.family(), SOCK_STREAM);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000074 if (!socket) {
75 return NULL;
76 }
77
78 if (BindSocket(socket, local_address, min_port, max_port) < 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +010079 RTC_LOG(LS_ERROR) << "TCP bind failed with error " << socket->GetError();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000080 delete socket;
81 return NULL;
82 }
83
hnsl04833622017-01-09 08:35:45 -080084 // If using fake TLS, wrap the TCP socket in a pseudo-SSL socket.
85 if (opts & PacketSocketFactory::OPT_TLS_FAKE) {
nisseede5da42017-01-12 05:15:36 -080086 RTC_DCHECK(!(opts & PacketSocketFactory::OPT_TLS));
johan57e13de2016-10-25 10:15:06 -070087 socket = new AsyncSSLSocket(socket);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000088 }
89
90 // Set TCP_NODELAY (via OPT_NODELAY) for improved performance.
91 // See http://go/gtalktcpnodelayexperiment
johan57e13de2016-10-25 10:15:06 -070092 socket->SetOption(Socket::OPT_NODELAY, 1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000093
94 if (opts & PacketSocketFactory::OPT_STUN)
95 return new cricket::AsyncStunTCPSocket(socket, true);
96
johan57e13de2016-10-25 10:15:06 -070097 return new AsyncTCPSocket(socket, true);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000098}
99
100AsyncPacketSocket* BasicPacketSocketFactory::CreateClientTcpSocket(
Diogo Real1dca9d52017-08-29 12:18:32 -0700101 const SocketAddress& local_address,
102 const SocketAddress& remote_address,
103 const ProxyInfo& proxy_info,
104 const std::string& user_agent,
105 const PacketSocketTcpOptions& tcp_options) {
johan57e13de2016-10-25 10:15:06 -0700106 AsyncSocket* socket =
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000107 socket_factory()->CreateAsyncSocket(local_address.family(), SOCK_STREAM);
108 if (!socket) {
109 return NULL;
110 }
111
112 if (BindSocket(socket, local_address, 0, 0) < 0) {
deadbeef1ee21252017-06-13 15:49:45 -0700113 // Allow BindSocket to fail if we're binding to the ANY address, since this
114 // is mostly redundant in the first place. The socket will be bound when we
115 // call Connect() instead.
116 if (local_address.IsAnyIP()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100117 RTC_LOG(LS_WARNING) << "TCP bind failed with error " << socket->GetError()
118 << "; ignoring since socket is using 'any' address.";
deadbeef1ee21252017-06-13 15:49:45 -0700119 } else {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100120 RTC_LOG(LS_ERROR) << "TCP bind failed with error " << socket->GetError();
deadbeef1ee21252017-06-13 15:49:45 -0700121 delete socket;
122 return NULL;
123 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000124 }
125
deadbeeff137e972017-03-23 15:45:49 -0700126 // If using a proxy, wrap the socket in a proxy socket.
127 if (proxy_info.type == PROXY_SOCKS5) {
128 socket = new AsyncSocksProxySocket(
129 socket, proxy_info.address, proxy_info.username, proxy_info.password);
130 } else if (proxy_info.type == PROXY_HTTPS) {
131 socket =
132 new AsyncHttpsProxySocket(socket, user_agent, proxy_info.address,
133 proxy_info.username, proxy_info.password);
134 }
135
hnsl04833622017-01-09 08:35:45 -0800136 // Assert that at most one TLS option is used.
Diogo Real1dca9d52017-08-29 12:18:32 -0700137 int tlsOpts = tcp_options.opts & (PacketSocketFactory::OPT_TLS |
138 PacketSocketFactory::OPT_TLS_FAKE |
139 PacketSocketFactory::OPT_TLS_INSECURE);
nisseede5da42017-01-12 05:15:36 -0800140 RTC_DCHECK((tlsOpts & (tlsOpts - 1)) == 0);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000141
hnsl04833622017-01-09 08:35:45 -0800142 if ((tlsOpts & PacketSocketFactory::OPT_TLS) ||
143 (tlsOpts & PacketSocketFactory::OPT_TLS_INSECURE)) {
144 // Using TLS, wrap the socket in an SSL adapter.
johan57e13de2016-10-25 10:15:06 -0700145 SSLAdapter* ssl_adapter = SSLAdapter::Create(socket);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000146 if (!ssl_adapter) {
147 return NULL;
148 }
149
Sergey Silkin9c147dd2018-09-12 10:45:38 +0000150 if (tlsOpts & PacketSocketFactory::OPT_TLS_INSECURE) {
151 ssl_adapter->SetIgnoreBadCert(true);
152 }
153
154 ssl_adapter->SetAlpnProtocols(tcp_options.tls_alpn_protocols);
155 ssl_adapter->SetEllipticCurves(tcp_options.tls_elliptic_curves);
Benjamin Wrightd6f86e82018-05-08 13:12:25 -0700156 ssl_adapter->SetCertVerifier(tcp_options.tls_cert_verifier);
Diogo Real1dca9d52017-08-29 12:18:32 -0700157
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000158 socket = ssl_adapter;
159
160 if (ssl_adapter->StartSSL(remote_address.hostname().c_str(), false) != 0) {
161 delete ssl_adapter;
162 return NULL;
163 }
164
hnsl04833622017-01-09 08:35:45 -0800165 } else if (tlsOpts & PacketSocketFactory::OPT_TLS_FAKE) {
166 // Using fake TLS, wrap the TCP socket in a pseudo-SSL socket.
johan57e13de2016-10-25 10:15:06 -0700167 socket = new AsyncSSLSocket(socket);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000168 }
169
170 if (socket->Connect(remote_address) < 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100171 RTC_LOG(LS_ERROR) << "TCP connect failed with error " << socket->GetError();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000172 delete socket;
173 return NULL;
174 }
175
176 // Finally, wrap that socket in a TCP or STUN TCP packet socket.
177 AsyncPacketSocket* tcp_socket;
Diogo Real1dca9d52017-08-29 12:18:32 -0700178 if (tcp_options.opts & PacketSocketFactory::OPT_STUN) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000179 tcp_socket = new cricket::AsyncStunTCPSocket(socket, false);
180 } else {
johan57e13de2016-10-25 10:15:06 -0700181 tcp_socket = new AsyncTCPSocket(socket, false);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000182 }
183
184 // Set TCP_NODELAY (via OPT_NODELAY) for improved performance.
185 // See http://go/gtalktcpnodelayexperiment
johan57e13de2016-10-25 10:15:06 -0700186 tcp_socket->SetOption(Socket::OPT_NODELAY, 1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000187
188 return tcp_socket;
189}
190
191AsyncResolverInterface* BasicPacketSocketFactory::CreateAsyncResolver() {
johan57e13de2016-10-25 10:15:06 -0700192 return new AsyncResolver();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000193}
194
Peter Boström0c4e06b2015-10-07 12:23:21 +0200195int BasicPacketSocketFactory::BindSocket(AsyncSocket* socket,
196 const SocketAddress& local_address,
197 uint16_t min_port,
198 uint16_t max_port) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000199 int ret = -1;
200 if (min_port == 0 && max_port == 0) {
201 // If there's no port range, let the OS pick a port for us.
202 ret = socket->Bind(local_address);
203 } else {
204 // Otherwise, try to find a port in the provided range.
205 for (int port = min_port; ret < 0 && port <= max_port; ++port) {
johan57e13de2016-10-25 10:15:06 -0700206 ret = socket->Bind(SocketAddress(local_address.ipaddr(), port));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000207 }
208 }
209 return ret;
210}
211
212SocketFactory* BasicPacketSocketFactory::socket_factory() {
213 if (thread_) {
nisseede5da42017-01-12 05:15:36 -0800214 RTC_DCHECK(thread_ == Thread::Current());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000215 return thread_->socketserver();
216 } else {
217 return socket_factory_;
218 }
219}
220
221} // namespace rtc