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