1 // Copyright 2013 The Chromium Authors
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 "net/socket/tcp_server_socket.h"
6
7 #include <memory>
8 #include <utility>
9
10 #include "base/check.h"
11 #include "base/functional/bind.h"
12 #include "base/functional/callback_helpers.h"
13 #include "base/notreached.h"
14 #include "net/base/net_errors.h"
15 #include "net/socket/socket_descriptor.h"
16 #include "net/socket/tcp_client_socket.h"
17
18 namespace net {
19
TCPServerSocket(NetLog * net_log,const NetLogSource & source)20 TCPServerSocket::TCPServerSocket(NetLog* net_log, const NetLogSource& source)
21 : TCPServerSocket(
22 std::make_unique<TCPSocket>(nullptr /* socket_performance_watcher */,
23 net_log,
24 source)) {}
25
TCPServerSocket(std::unique_ptr<TCPSocket> socket)26 TCPServerSocket::TCPServerSocket(std::unique_ptr<TCPSocket> socket)
27 : socket_(std::move(socket)) {}
28
AdoptSocket(SocketDescriptor socket)29 int TCPServerSocket::AdoptSocket(SocketDescriptor socket) {
30 adopted_opened_socket_ = true;
31 return socket_->AdoptUnconnectedSocket(socket);
32 }
33
34 TCPServerSocket::~TCPServerSocket() = default;
35
Listen(const IPEndPoint & address,int backlog,std::optional<bool> ipv6_only)36 int TCPServerSocket::Listen(const IPEndPoint& address,
37 int backlog,
38 std::optional<bool> ipv6_only) {
39 int result = OK;
40 if (!adopted_opened_socket_) {
41 result = socket_->Open(address.GetFamily());
42 if (result != OK) {
43 return result;
44 }
45 }
46
47 if (ipv6_only.has_value()) {
48 CHECK_EQ(address.address(), net::IPAddress::IPv6AllZeros());
49 result = socket_->SetIPv6Only(*ipv6_only);
50 if (result != OK) {
51 socket_->Close();
52 return result;
53 }
54 }
55
56 result = socket_->SetDefaultOptionsForServer();
57 if (result != OK) {
58 socket_->Close();
59 return result;
60 }
61
62 result = socket_->Bind(address);
63 if (result != OK) {
64 socket_->Close();
65 return result;
66 }
67
68 result = socket_->Listen(backlog);
69 if (result != OK) {
70 socket_->Close();
71 return result;
72 }
73
74 return OK;
75 }
76
GetLocalAddress(IPEndPoint * address) const77 int TCPServerSocket::GetLocalAddress(IPEndPoint* address) const {
78 return socket_->GetLocalAddress(address);
79 }
80
Accept(std::unique_ptr<StreamSocket> * socket,CompletionOnceCallback callback)81 int TCPServerSocket::Accept(std::unique_ptr<StreamSocket>* socket,
82 CompletionOnceCallback callback) {
83 return Accept(socket, std::move(callback), nullptr);
84 }
85
Accept(std::unique_ptr<StreamSocket> * socket,CompletionOnceCallback callback,IPEndPoint * peer_address)86 int TCPServerSocket::Accept(std::unique_ptr<StreamSocket>* socket,
87 CompletionOnceCallback callback,
88 IPEndPoint* peer_address) {
89 DCHECK(socket);
90 DCHECK(!callback.is_null());
91
92 if (pending_accept_) {
93 NOTREACHED();
94 return ERR_UNEXPECTED;
95 }
96
97 // It is safe to use base::Unretained(this). |socket_| is owned by this class,
98 // and the callback won't be run after |socket_| is destroyed.
99 CompletionOnceCallback accept_callback = base::BindOnce(
100 &TCPServerSocket::OnAcceptCompleted, base::Unretained(this), socket,
101 peer_address, std::move(callback));
102 int result = socket_->Accept(&accepted_socket_, &accepted_address_,
103 std::move(accept_callback));
104 if (result != ERR_IO_PENDING) {
105 // |accept_callback| won't be called so we need to run
106 // ConvertAcceptedSocket() ourselves in order to do the conversion from
107 // |accepted_socket_| to |socket|.
108 result = ConvertAcceptedSocket(result, socket, peer_address);
109 } else {
110 pending_accept_ = true;
111 }
112
113 return result;
114 }
115
DetachFromThread()116 void TCPServerSocket::DetachFromThread() {
117 socket_->DetachFromThread();
118 }
119
ConvertAcceptedSocket(int result,std::unique_ptr<StreamSocket> * output_accepted_socket,IPEndPoint * output_accepted_address)120 int TCPServerSocket::ConvertAcceptedSocket(
121 int result,
122 std::unique_ptr<StreamSocket>* output_accepted_socket,
123 IPEndPoint* output_accepted_address) {
124 // Make sure the TCPSocket object is destroyed in any case.
125 std::unique_ptr<TCPSocket> temp_accepted_socket(std::move(accepted_socket_));
126 if (result != OK)
127 return result;
128
129 if (output_accepted_address)
130 *output_accepted_address = accepted_address_;
131
132 *output_accepted_socket = std::make_unique<TCPClientSocket>(
133 std::move(temp_accepted_socket), accepted_address_);
134
135 return OK;
136 }
137
OnAcceptCompleted(std::unique_ptr<StreamSocket> * output_accepted_socket,IPEndPoint * output_accepted_address,CompletionOnceCallback forward_callback,int result)138 void TCPServerSocket::OnAcceptCompleted(
139 std::unique_ptr<StreamSocket>* output_accepted_socket,
140 IPEndPoint* output_accepted_address,
141 CompletionOnceCallback forward_callback,
142 int result) {
143 result = ConvertAcceptedSocket(result, output_accepted_socket,
144 output_accepted_address);
145 pending_accept_ = false;
146 std::move(forward_callback).Run(result);
147 }
148
149 } // namespace net
150