1 // Copyright (c) 2012 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_tcp_server.h"
6 
7 #include <utility>
8 
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "mojo/public/cpp/bindings/remote.h"
12 #include "net/base/address_list.h"
13 #include "net/base/net_errors.h"
14 #include "net/log/net_log_source.h"
15 #include "net/socket/stream_socket.h"
16 #include "services/network/p2p/socket_manager.h"
17 #include "services/network/p2p/socket_tcp.h"
18 #include "services/network/public/cpp/p2p_param_traits.h"
19 
20 namespace {
21 const int kListenBacklog = 5;
22 }  // namespace
23 
24 namespace network {
25 
P2PSocketTcpServer(Delegate * delegate,mojo::PendingRemote<mojom::P2PSocketClient> client,mojo::PendingReceiver<mojom::P2PSocket> socket,P2PSocketType client_type)26 P2PSocketTcpServer::P2PSocketTcpServer(
27     Delegate* delegate,
28     mojo::PendingRemote<mojom::P2PSocketClient> client,
29     mojo::PendingReceiver<mojom::P2PSocket> socket,
30     P2PSocketType client_type)
31     : P2PSocket(delegate, std::move(client), std::move(socket), P2PSocket::TCP),
32       client_type_(client_type),
33       socket_(new net::TCPServerSocket(nullptr, net::NetLogSource())),
34       accept_callback_(base::BindRepeating(&P2PSocketTcpServer::OnAccepted,
35                                            base::Unretained(this))) {}
36 
37 P2PSocketTcpServer::~P2PSocketTcpServer() = default;
38 
39 // TODO(guidou): Add support for port range.
Init(const net::IPEndPoint & local_address,uint16_t min_port,uint16_t max_port,const P2PHostAndIPEndPoint & remote_address)40 void P2PSocketTcpServer::Init(const net::IPEndPoint& local_address,
41                               uint16_t min_port,
42                               uint16_t max_port,
43                               const P2PHostAndIPEndPoint& remote_address) {
44   int result = socket_->Listen(local_address, kListenBacklog);
45   if (result < 0) {
46     LOG(ERROR) << "Listen() failed: " << result;
47     OnError();
48     return;
49   }
50 
51   result = socket_->GetLocalAddress(&local_address_);
52   if (result < 0) {
53     LOG(ERROR) << "P2PSocketTcpServer::Init(): can't to get local address: "
54                << result;
55     OnError();
56     return;
57   }
58   VLOG(1) << "Local address: " << local_address_.ToString();
59 
60   // NOTE: Remote address can be empty as socket is just listening
61   // in this state.
62   client_->SocketCreated(local_address_, remote_address.ip_address);
63   DoAccept();
64 }
65 
DoAccept()66 void P2PSocketTcpServer::DoAccept() {
67   while (true) {
68     int result = socket_->Accept(&accept_socket_, accept_callback_);
69     if (result == net::ERR_IO_PENDING) {
70       break;
71     } else {
72       HandleAcceptResult(result);
73     }
74   }
75 }
76 
HandleAcceptResult(int result)77 void P2PSocketTcpServer::HandleAcceptResult(int result) {
78   if (result < 0) {
79     if (result != net::ERR_IO_PENDING)
80       OnError();
81     return;
82   }
83 
84   net::IPEndPoint remote_address;
85   if (accept_socket_->GetPeerAddress(&remote_address) != net::OK) {
86     LOG(ERROR) << "Failed to get address of an accepted socket.";
87     accept_socket_.reset();
88     return;
89   }
90 
91   mojo::PendingRemote<mojom::P2PSocket> socket_pending_remote;
92   auto socket_receiver = socket_pending_remote.InitWithNewPipeAndPassReceiver();
93 
94   mojo::PendingRemote<mojom::P2PSocketClient> client;
95   client_->IncomingTcpConnection(remote_address,
96                                  std::move(socket_pending_remote),
97                                  client.InitWithNewPipeAndPassReceiver());
98 
99   std::unique_ptr<P2PSocketTcpBase> p2p_socket;
100   if (client_type_ == P2P_SOCKET_TCP_CLIENT) {
101     p2p_socket = std::make_unique<P2PSocketTcp>(delegate_, std::move(client),
102                                                 std::move(socket_receiver),
103                                                 client_type_, nullptr);
104   } else {
105     p2p_socket = std::make_unique<P2PSocketStunTcp>(
106         delegate_, std::move(client), std::move(socket_receiver), client_type_,
107         nullptr);
108   }
109 
110   P2PSocketTcpBase* p2p_socket_ptr = p2p_socket.get();
111   delegate_->AddAcceptedConnection(std::move(p2p_socket));
112 
113   // InitAccepted() may call delegate_->DestroySocket(), so it must be
114   // called after AddAcceptedConnection().
115   p2p_socket_ptr->InitAccepted(remote_address, std::move(accept_socket_));
116 }
117 
OnAccepted(int result)118 void P2PSocketTcpServer::OnAccepted(int result) {
119   HandleAcceptResult(result);
120   if (result == net::OK)
121     DoAccept();
122 }
123 
Send(const std::vector<int8_t> & data,const P2PPacketInfo & packet_info,const net::MutableNetworkTrafficAnnotationTag & traffic_annotation)124 void P2PSocketTcpServer::Send(
125     const std::vector<int8_t>& data,
126     const P2PPacketInfo& packet_info,
127     const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
128   OnError();
129 }
130 
SetOption(P2PSocketOption option,int32_t value)131 void P2PSocketTcpServer::SetOption(P2PSocketOption option, int32_t value) {
132   // Currently we don't have use case tcp server sockets are used for p2p.
133 }
134 
135 }  // namespace network
136