1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "services/network/p2p/socket_manager.h"
6
7 #include <stddef.h>
8
9 #include <utility>
10
11 #include "base/bind.h"
12 #include "base/task/post_task.h"
13 #include "base/task/thread_pool.h"
14 #include "base/threading/thread_task_runner_handle.h"
15 #include "net/base/address_list.h"
16 #include "net/base/net_errors.h"
17 #include "net/base/network_interfaces.h"
18 #include "net/base/sys_addrinfo.h"
19 #include "net/dns/host_resolver.h"
20 #include "net/log/net_log_source.h"
21 #include "net/log/net_log_with_source.h"
22 #include "net/socket/client_socket_factory.h"
23 #include "net/socket/datagram_client_socket.h"
24 #include "net/traffic_annotation/network_traffic_annotation.h"
25 #include "net/url_request/url_request_context.h"
26 #include "net/url_request/url_request_context_getter.h"
27 #include "services/network/p2p/socket.h"
28 #include "services/network/proxy_resolving_client_socket_factory.h"
29 #include "services/network/public/cpp/p2p_param_traits.h"
30 #include "third_party/webrtc/media/base/rtp_utils.h"
31 #include "third_party/webrtc/media/base/turn_utils.h"
32
33 namespace network {
34
35 namespace {
36
37 // Used by GetDefaultLocalAddress as the target to connect to for getting the
38 // default local address. They are public DNS servers on the internet.
39 const uint8_t kPublicIPv4Host[] = {8, 8, 8, 8};
40 const uint8_t kPublicIPv6Host[] = {
41 0x20, 0x01, 0x48, 0x60, 0x48, 0x60, 0, 0, 0, 0, 0, 0, 0, 0, 0x88, 0x88};
42 const int kPublicPort = 53; // DNS port.
43
44 // Experimentation shows that creating too many sockets creates odd problems
45 // because of resource exhaustion in the Unix sockets domain.
46 // Trouble has been seen on Linux at 3479 sockets in test, so leave a margin.
47 const int kMaxSimultaneousSockets = 3000;
48
49 const size_t kMinRtcpHeaderLength = 8;
50 const size_t kDtlsRecordHeaderLength = 13;
51
IsDtlsPacket(base::span<const uint8_t> data)52 bool IsDtlsPacket(base::span<const uint8_t> data) {
53 return data.size() >= kDtlsRecordHeaderLength &&
54 (data[0] > 19 && data[0] < 64);
55 }
56
IsRtcpPacket(base::span<const uint8_t> data)57 bool IsRtcpPacket(base::span<const uint8_t> data) {
58 if (data.size() < kMinRtcpHeaderLength)
59 return false;
60
61 int type = data[1] & 0x7F;
62 return type >= 64 && type < 96;
63 }
64
65 // Names ending in ".local." are link-local and used with Multicast DNS as
66 // described in RFC6762 (https://tools.ietf.org/html/rfc6762#section-3).
67 constexpr char kLocalTld[] = ".local.";
68
HasLocalTld(const std::string & host_name)69 bool HasLocalTld(const std::string& host_name) {
70 return EndsWith(host_name, kLocalTld, base::CompareCase::INSENSITIVE_ASCII);
71 }
72
73 } // namespace
74
75 class P2PSocketManager::DnsRequest {
76 public:
77 using DoneCallback = base::OnceCallback<void(const net::IPAddressList&)>;
78
DnsRequest(net::HostResolver * host_resolver,bool enable_mdns)79 DnsRequest(net::HostResolver* host_resolver, bool enable_mdns)
80 : resolver_(host_resolver), enable_mdns_(enable_mdns) {}
81
Resolve(const std::string & host_name,DoneCallback done_callback)82 void Resolve(const std::string& host_name, DoneCallback done_callback) {
83 DCHECK(!done_callback.is_null());
84
85 host_name_ = host_name;
86 done_callback_ = std::move(done_callback);
87
88 // Return an error if it's an empty string.
89 if (host_name_.empty()) {
90 net::IPAddressList address_list;
91 std::move(done_callback_).Run(address_list);
92 return;
93 }
94
95 // Add period at the end to make sure that we only resolve
96 // fully-qualified names.
97 if (host_name_.back() != '.')
98 host_name_ += '.';
99
100 net::HostPortPair host(host_name_, 0);
101
102 net::HostResolver::ResolveHostParameters parameters;
103 if (enable_mdns_ && HasLocalTld(host_name_)) {
104 #if BUILDFLAG(ENABLE_MDNS)
105 // HostResolver/MDnsClient expects a key without a trailing dot.
106 host.set_host(host_name_.substr(0, host_name_.size() - 1));
107 parameters.source = net::HostResolverSource::MULTICAST_DNS;
108 #endif // ENABLE_MDNS
109 }
110 request_ =
111 resolver_->CreateRequest(host, net::NetLogWithSource(), parameters);
112
113 int result = request_->Start(base::BindOnce(
114 &P2PSocketManager::DnsRequest::OnDone, base::Unretained(this)));
115 if (result != net::ERR_IO_PENDING)
116 OnDone(result);
117 }
118
119 private:
OnDone(int result)120 void OnDone(int result) {
121 net::IPAddressList list;
122 const base::Optional<net::AddressList>& addresses =
123 request_->GetAddressResults();
124 if (result != net::OK || !addresses) {
125 LOG(ERROR) << "Failed to resolve address for " << host_name_
126 << ", errorcode: " << result;
127 std::move(done_callback_).Run(list);
128 return;
129 }
130
131 for (const auto& endpoint : *addresses) {
132 list.push_back(endpoint.address());
133 }
134 std::move(done_callback_).Run(list);
135 }
136
137 std::string host_name_;
138 net::HostResolver* resolver_;
139 std::unique_ptr<net::HostResolver::ResolveHostRequest> request_;
140
141 DoneCallback done_callback_;
142
143 const bool enable_mdns_;
144 };
145
P2PSocketManager(mojo::PendingRemote<mojom::P2PTrustedSocketManagerClient> trusted_socket_manager_client,mojo::PendingReceiver<mojom::P2PTrustedSocketManager> trusted_socket_manager_receiver,mojo::PendingReceiver<mojom::P2PSocketManager> socket_manager_receiver,DeleteCallback delete_callback,net::URLRequestContext * url_request_context)146 P2PSocketManager::P2PSocketManager(
147 mojo::PendingRemote<mojom::P2PTrustedSocketManagerClient>
148 trusted_socket_manager_client,
149 mojo::PendingReceiver<mojom::P2PTrustedSocketManager>
150 trusted_socket_manager_receiver,
151 mojo::PendingReceiver<mojom::P2PSocketManager> socket_manager_receiver,
152 DeleteCallback delete_callback,
153 net::URLRequestContext* url_request_context)
154 : delete_callback_(std::move(delete_callback)),
155 url_request_context_(url_request_context),
156 network_list_task_runner_(base::ThreadPool::CreateSequencedTaskRunner(
157 {base::MayBlock(), base::TaskPriority::USER_VISIBLE})),
158 trusted_socket_manager_client_(std::move(trusted_socket_manager_client)),
159 trusted_socket_manager_receiver_(
160 this,
161 std::move(trusted_socket_manager_receiver)),
162 socket_manager_receiver_(this, std::move(socket_manager_receiver)) {
163 trusted_socket_manager_receiver_.set_disconnect_handler(base::BindOnce(
164 &P2PSocketManager::OnConnectionError, base::Unretained(this)));
165 socket_manager_receiver_.set_disconnect_handler(base::BindOnce(
166 &P2PSocketManager::OnConnectionError, base::Unretained(this)));
167 }
168
~P2PSocketManager()169 P2PSocketManager::~P2PSocketManager() {
170 // Reset the P2PSocketManager receiver before dropping pending dns requests.
171 socket_manager_receiver_.reset();
172
173 sockets_.clear();
174 dns_requests_.clear();
175
176 if (network_notification_client_)
177 net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
178
179 proxy_resolving_socket_factory_.reset();
180 }
181
OnNetworkChanged(net::NetworkChangeNotifier::ConnectionType type)182 void P2PSocketManager::OnNetworkChanged(
183 net::NetworkChangeNotifier::ConnectionType type) {
184 // NetworkChangeNotifier always emits CONNECTION_NONE notification whenever
185 // network configuration changes. All other notifications can be ignored.
186 if (type != net::NetworkChangeNotifier::CONNECTION_NONE)
187 return;
188
189 // Notify the renderer about changes to list of network interfaces.
190 network_list_task_runner_->PostTask(
191 FROM_HERE, base::BindOnce(&P2PSocketManager::DoGetNetworkList,
192 weak_factory_.GetWeakPtr(),
193 base::ThreadTaskRunnerHandle::Get()));
194 }
195
AddAcceptedConnection(std::unique_ptr<P2PSocket> accepted_connection)196 void P2PSocketManager::AddAcceptedConnection(
197 std::unique_ptr<P2PSocket> accepted_connection) {
198 sockets_[accepted_connection.get()] = std::move(accepted_connection);
199 }
200
DestroySocket(P2PSocket * socket)201 void P2PSocketManager::DestroySocket(P2PSocket* socket) {
202 auto iter = sockets_.find(socket);
203 DCHECK(iter != sockets_.end());
204 sockets_.erase(iter);
205 }
206
DumpPacket(base::span<const uint8_t> packet,bool incoming)207 void P2PSocketManager::DumpPacket(base::span<const uint8_t> packet,
208 bool incoming) {
209 if ((incoming && !dump_incoming_rtp_packet_) ||
210 (!incoming && !dump_outgoing_rtp_packet_)) {
211 return;
212 }
213
214 if (IsDtlsPacket(packet) || IsRtcpPacket(packet))
215 return;
216
217 size_t rtp_packet_pos = 0;
218 size_t rtp_packet_size = packet.size();
219 if (!cricket::UnwrapTurnPacket(packet.data(), packet.size(), &rtp_packet_pos,
220 &rtp_packet_size)) {
221 return;
222 }
223
224 auto rtp_packet = packet.subspan(rtp_packet_pos, rtp_packet_size);
225
226 size_t header_size = 0;
227 bool valid = cricket::ValidateRtpHeader(rtp_packet.data(), rtp_packet.size(),
228 &header_size);
229 if (!valid) {
230 NOTREACHED();
231 return;
232 }
233
234 std::vector<uint8_t> header_buffer(rtp_packet.data(),
235 rtp_packet.data() + header_size);
236 trusted_socket_manager_client_->DumpPacket(header_buffer, rtp_packet.size(),
237 incoming);
238 }
239
DoGetNetworkList(const base::WeakPtr<P2PSocketManager> & socket_manager,scoped_refptr<base::SingleThreadTaskRunner> main_task_runner)240 void P2PSocketManager::DoGetNetworkList(
241 const base::WeakPtr<P2PSocketManager>& socket_manager,
242 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner) {
243 net::NetworkInterfaceList list;
244 if (!net::GetNetworkList(&list, net::EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES)) {
245 LOG(ERROR) << "GetNetworkList failed.";
246 return;
247 }
248 net::IPAddress default_ipv4_local_address = GetDefaultLocalAddress(AF_INET);
249 net::IPAddress default_ipv6_local_address = GetDefaultLocalAddress(AF_INET6);
250 main_task_runner->PostTask(
251 FROM_HERE,
252 base::BindOnce(&P2PSocketManager::SendNetworkList, socket_manager, list,
253 default_ipv4_local_address, default_ipv6_local_address));
254 }
255
SendNetworkList(const net::NetworkInterfaceList & list,const net::IPAddress & default_ipv4_local_address,const net::IPAddress & default_ipv6_local_address)256 void P2PSocketManager::SendNetworkList(
257 const net::NetworkInterfaceList& list,
258 const net::IPAddress& default_ipv4_local_address,
259 const net::IPAddress& default_ipv6_local_address) {
260 network_notification_client_->NetworkListChanged(
261 list, default_ipv4_local_address, default_ipv6_local_address);
262 }
263
StartNetworkNotifications(mojo::PendingRemote<mojom::P2PNetworkNotificationClient> client)264 void P2PSocketManager::StartNetworkNotifications(
265 mojo::PendingRemote<mojom::P2PNetworkNotificationClient> client) {
266 DCHECK(!network_notification_client_);
267 network_notification_client_.Bind(std::move(client));
268 network_notification_client_.set_disconnect_handler(base::BindOnce(
269 &P2PSocketManager::NetworkNotificationClientConnectionError,
270 base::Unretained(this)));
271
272 net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
273
274 network_list_task_runner_->PostTask(
275 FROM_HERE, base::BindOnce(&P2PSocketManager::DoGetNetworkList,
276 weak_factory_.GetWeakPtr(),
277 base::ThreadTaskRunnerHandle::Get()));
278 }
279
GetHostAddress(const std::string & host_name,bool enable_mdns,mojom::P2PSocketManager::GetHostAddressCallback callback)280 void P2PSocketManager::GetHostAddress(
281 const std::string& host_name,
282 bool enable_mdns,
283 mojom::P2PSocketManager::GetHostAddressCallback callback) {
284 auto request = std::make_unique<DnsRequest>(
285 url_request_context_->host_resolver(), enable_mdns);
286 DnsRequest* request_ptr = request.get();
287 dns_requests_.insert(std::move(request));
288 request_ptr->Resolve(
289 host_name,
290 base::BindOnce(&P2PSocketManager::OnAddressResolved,
291 base::Unretained(this), request_ptr, std::move(callback)));
292 }
293
CreateSocket(P2PSocketType type,const net::IPEndPoint & local_address,const P2PPortRange & port_range,const P2PHostAndIPEndPoint & remote_address,mojo::PendingRemote<mojom::P2PSocketClient> client,mojo::PendingReceiver<mojom::P2PSocket> receiver)294 void P2PSocketManager::CreateSocket(
295 P2PSocketType type,
296 const net::IPEndPoint& local_address,
297 const P2PPortRange& port_range,
298 const P2PHostAndIPEndPoint& remote_address,
299 mojo::PendingRemote<mojom::P2PSocketClient> client,
300 mojo::PendingReceiver<mojom::P2PSocket> receiver) {
301 if (port_range.min_port > port_range.max_port ||
302 (port_range.min_port == 0 && port_range.max_port != 0)) {
303 trusted_socket_manager_client_->InvalidSocketPortRangeRequested();
304 return;
305 }
306
307 if (!proxy_resolving_socket_factory_) {
308 proxy_resolving_socket_factory_ =
309 std::make_unique<ProxyResolvingClientSocketFactory>(
310 url_request_context_);
311 }
312 if (sockets_.size() > kMaxSimultaneousSockets) {
313 LOG(ERROR) << "Too many sockets created";
314 return;
315 }
316 std::unique_ptr<P2PSocket> socket =
317 P2PSocket::Create(this, std::move(client), std::move(receiver), type,
318 url_request_context_->net_log(),
319 proxy_resolving_socket_factory_.get(), &throttler_);
320
321 if (!socket)
322 return;
323
324 P2PSocket* socket_ptr = socket.get();
325 sockets_[socket_ptr] = std::move(socket);
326
327 // Init() may call SocketManager::DestroySocket(), so it must be called after
328 // adding the socket to |sockets_|.
329 socket_ptr->Init(local_address, port_range.min_port, port_range.max_port,
330 remote_address);
331 }
332
StartRtpDump(bool incoming,bool outgoing)333 void P2PSocketManager::StartRtpDump(bool incoming, bool outgoing) {
334 dump_incoming_rtp_packet_ |= incoming;
335 dump_outgoing_rtp_packet_ |= outgoing;
336 }
337
StopRtpDump(bool incoming,bool outgoing)338 void P2PSocketManager::StopRtpDump(bool incoming, bool outgoing) {
339 dump_incoming_rtp_packet_ &= !incoming;
340 dump_outgoing_rtp_packet_ &= !outgoing;
341 }
342
NetworkNotificationClientConnectionError()343 void P2PSocketManager::NetworkNotificationClientConnectionError() {
344 net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
345 }
346
GetDefaultLocalAddress(int family)347 net::IPAddress P2PSocketManager::GetDefaultLocalAddress(int family) {
348 DCHECK(family == AF_INET || family == AF_INET6);
349
350 // Creation and connection of a UDP socket might be janky.
351 // DCHECK(network_list_task_runner_->RunsTasksInCurrentSequence());
352
353 auto socket =
354 net::ClientSocketFactory::GetDefaultFactory()->CreateDatagramClientSocket(
355 net::DatagramSocket::DEFAULT_BIND, nullptr, net::NetLogSource());
356
357 net::IPAddress ip_address;
358 if (family == AF_INET) {
359 ip_address = net::IPAddress(kPublicIPv4Host);
360 } else {
361 ip_address = net::IPAddress(kPublicIPv6Host);
362 }
363
364 if (socket->Connect(net::IPEndPoint(ip_address, kPublicPort)) != net::OK) {
365 return net::IPAddress();
366 }
367
368 net::IPEndPoint local_address;
369 if (socket->GetLocalAddress(&local_address) != net::OK)
370 return net::IPAddress();
371
372 return local_address.address();
373 }
374
OnAddressResolved(DnsRequest * request,mojom::P2PSocketManager::GetHostAddressCallback callback,const net::IPAddressList & addresses)375 void P2PSocketManager::OnAddressResolved(
376 DnsRequest* request,
377 mojom::P2PSocketManager::GetHostAddressCallback callback,
378 const net::IPAddressList& addresses) {
379 std::move(callback).Run(addresses);
380
381 dns_requests_.erase(dns_requests_.find(request));
382 }
383
OnConnectionError()384 void P2PSocketManager::OnConnectionError() {
385 std::move(delete_callback_).Run(this);
386 }
387
388 } // namespace network
389