xref: /aosp_15_r20/external/webrtc/p2p/base/basic_packet_socket_factory.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
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 
11 #include "p2p/base/basic_packet_socket_factory.h"
12 
13 #include <stddef.h>
14 
15 #include <string>
16 
17 #include "absl/memory/memory.h"
18 #include "api/async_dns_resolver.h"
19 #include "api/wrapping_async_dns_resolver.h"
20 #include "p2p/base/async_stun_tcp_socket.h"
21 #include "rtc_base/async_tcp_socket.h"
22 #include "rtc_base/async_udp_socket.h"
23 #include "rtc_base/checks.h"
24 #include "rtc_base/logging.h"
25 #include "rtc_base/socket.h"
26 #include "rtc_base/socket_adapters.h"
27 #include "rtc_base/ssl_adapter.h"
28 
29 namespace rtc {
30 
BasicPacketSocketFactory(SocketFactory * socket_factory)31 BasicPacketSocketFactory::BasicPacketSocketFactory(
32     SocketFactory* socket_factory)
33     : socket_factory_(socket_factory) {}
34 
~BasicPacketSocketFactory()35 BasicPacketSocketFactory::~BasicPacketSocketFactory() {}
36 
CreateUdpSocket(const SocketAddress & address,uint16_t min_port,uint16_t max_port)37 AsyncPacketSocket* BasicPacketSocketFactory::CreateUdpSocket(
38     const SocketAddress& address,
39     uint16_t min_port,
40     uint16_t max_port) {
41   // UDP sockets are simple.
42   Socket* socket = socket_factory_->CreateSocket(address.family(), SOCK_DGRAM);
43   if (!socket) {
44     return NULL;
45   }
46   if (BindSocket(socket, address, min_port, max_port) < 0) {
47     RTC_LOG(LS_ERROR) << "UDP bind failed with error " << socket->GetError();
48     delete socket;
49     return NULL;
50   }
51   return new AsyncUDPSocket(socket);
52 }
53 
CreateServerTcpSocket(const SocketAddress & local_address,uint16_t min_port,uint16_t max_port,int opts)54 AsyncListenSocket* BasicPacketSocketFactory::CreateServerTcpSocket(
55     const SocketAddress& local_address,
56     uint16_t min_port,
57     uint16_t max_port,
58     int opts) {
59   // Fail if TLS is required.
60   if (opts & PacketSocketFactory::OPT_TLS) {
61     RTC_LOG(LS_ERROR) << "TLS support currently is not available.";
62     return NULL;
63   }
64 
65   if (opts & PacketSocketFactory::OPT_TLS_FAKE) {
66     RTC_LOG(LS_ERROR) << "Fake TLS not supported.";
67     return NULL;
68   }
69   Socket* socket =
70       socket_factory_->CreateSocket(local_address.family(), SOCK_STREAM);
71   if (!socket) {
72     return NULL;
73   }
74 
75   if (BindSocket(socket, local_address, min_port, max_port) < 0) {
76     RTC_LOG(LS_ERROR) << "TCP bind failed with error " << socket->GetError();
77     delete socket;
78     return NULL;
79   }
80 
81   RTC_CHECK(!(opts & PacketSocketFactory::OPT_STUN));
82 
83   return new AsyncTcpListenSocket(absl::WrapUnique(socket));
84 }
85 
CreateClientTcpSocket(const SocketAddress & local_address,const SocketAddress & remote_address,const ProxyInfo & proxy_info,const std::string & user_agent,const PacketSocketTcpOptions & tcp_options)86 AsyncPacketSocket* BasicPacketSocketFactory::CreateClientTcpSocket(
87     const SocketAddress& local_address,
88     const SocketAddress& remote_address,
89     const ProxyInfo& proxy_info,
90     const std::string& user_agent,
91     const PacketSocketTcpOptions& tcp_options) {
92   Socket* socket =
93       socket_factory_->CreateSocket(local_address.family(), SOCK_STREAM);
94   if (!socket) {
95     return NULL;
96   }
97 
98   if (BindSocket(socket, local_address, 0, 0) < 0) {
99     // Allow BindSocket to fail if we're binding to the ANY address, since this
100     // is mostly redundant in the first place. The socket will be bound when we
101     // call Connect() instead.
102     if (local_address.IsAnyIP()) {
103       RTC_LOG(LS_WARNING) << "TCP bind failed with error " << socket->GetError()
104                           << "; ignoring since socket is using 'any' address.";
105     } else {
106       RTC_LOG(LS_ERROR) << "TCP bind failed with error " << socket->GetError();
107       delete socket;
108       return NULL;
109     }
110   }
111 
112   // Set TCP_NODELAY (via OPT_NODELAY) for improved performance; this causes
113   // small media packets to be sent immediately rather than being buffered up,
114   // reducing latency.
115   //
116   // Must be done before calling Connect, otherwise it may fail.
117   if (socket->SetOption(Socket::OPT_NODELAY, 1) != 0) {
118     RTC_LOG(LS_ERROR) << "Setting TCP_NODELAY option failed with error "
119                       << socket->GetError();
120   }
121 
122   // If using a proxy, wrap the socket in a proxy socket.
123   if (proxy_info.type == PROXY_SOCKS5) {
124     socket = new AsyncSocksProxySocket(
125         socket, proxy_info.address, proxy_info.username, proxy_info.password);
126   } else if (proxy_info.type == PROXY_HTTPS) {
127     socket =
128         new AsyncHttpsProxySocket(socket, user_agent, proxy_info.address,
129                                   proxy_info.username, proxy_info.password);
130   }
131 
132   // Assert that at most one TLS option is used.
133   int tlsOpts = tcp_options.opts & (PacketSocketFactory::OPT_TLS |
134                                     PacketSocketFactory::OPT_TLS_FAKE |
135                                     PacketSocketFactory::OPT_TLS_INSECURE);
136   RTC_DCHECK((tlsOpts & (tlsOpts - 1)) == 0);
137 
138   if ((tlsOpts & PacketSocketFactory::OPT_TLS) ||
139       (tlsOpts & PacketSocketFactory::OPT_TLS_INSECURE)) {
140     // Using TLS, wrap the socket in an SSL adapter.
141     SSLAdapter* ssl_adapter = SSLAdapter::Create(socket);
142     if (!ssl_adapter) {
143       return NULL;
144     }
145 
146     if (tlsOpts & PacketSocketFactory::OPT_TLS_INSECURE) {
147       ssl_adapter->SetIgnoreBadCert(true);
148     }
149 
150     ssl_adapter->SetAlpnProtocols(tcp_options.tls_alpn_protocols);
151     ssl_adapter->SetEllipticCurves(tcp_options.tls_elliptic_curves);
152     ssl_adapter->SetCertVerifier(tcp_options.tls_cert_verifier);
153 
154     socket = ssl_adapter;
155 
156     if (ssl_adapter->StartSSL(remote_address.hostname().c_str()) != 0) {
157       delete ssl_adapter;
158       return NULL;
159     }
160 
161   } else if (tlsOpts & PacketSocketFactory::OPT_TLS_FAKE) {
162     // Using fake TLS, wrap the TCP socket in a pseudo-SSL socket.
163     socket = new AsyncSSLSocket(socket);
164   }
165 
166   if (socket->Connect(remote_address) < 0) {
167     RTC_LOG(LS_ERROR) << "TCP connect failed with error " << socket->GetError();
168     delete socket;
169     return NULL;
170   }
171 
172   // Finally, wrap that socket in a TCP or STUN TCP packet socket.
173   AsyncPacketSocket* tcp_socket;
174   if (tcp_options.opts & PacketSocketFactory::OPT_STUN) {
175     tcp_socket = new cricket::AsyncStunTCPSocket(socket);
176   } else {
177     tcp_socket = new AsyncTCPSocket(socket);
178   }
179 
180   return tcp_socket;
181 }
182 
CreateAsyncResolver()183 AsyncResolverInterface* BasicPacketSocketFactory::CreateAsyncResolver() {
184   return new AsyncResolver();
185 }
186 
187 std::unique_ptr<webrtc::AsyncDnsResolverInterface>
CreateAsyncDnsResolver()188 BasicPacketSocketFactory::CreateAsyncDnsResolver() {
189   return std::make_unique<webrtc::WrappingAsyncDnsResolver>(
190       new AsyncResolver());
191 }
192 
BindSocket(Socket * socket,const SocketAddress & local_address,uint16_t min_port,uint16_t max_port)193 int BasicPacketSocketFactory::BindSocket(Socket* socket,
194                                          const SocketAddress& local_address,
195                                          uint16_t min_port,
196                                          uint16_t max_port) {
197   int ret = -1;
198   if (min_port == 0 && max_port == 0) {
199     // If there's no port range, let the OS pick a port for us.
200     ret = socket->Bind(local_address);
201   } else {
202     // Otherwise, try to find a port in the provided range.
203     for (int port = min_port; ret < 0 && port <= max_port; ++port) {
204       ret = socket->Bind(SocketAddress(local_address.ipaddr(), port));
205     }
206   }
207   return ret;
208 }
209 
210 }  // namespace rtc
211