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 TCPSocket::Create(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 }
95
96 // It is safe to use base::Unretained(this). |socket_| is owned by this class,
97 // and the callback won't be run after |socket_| is destroyed.
98 CompletionOnceCallback accept_callback = base::BindOnce(
99 &TCPServerSocket::OnAcceptCompleted, base::Unretained(this), socket,
100 peer_address, std::move(callback));
101 int result = socket_->Accept(&accepted_socket_, &accepted_address_,
102 std::move(accept_callback));
103 if (result != ERR_IO_PENDING) {
104 // |accept_callback| won't be called so we need to run
105 // ConvertAcceptedSocket() ourselves in order to do the conversion from
106 // |accepted_socket_| to |socket|.
107 result = ConvertAcceptedSocket(result, socket, peer_address);
108 } else {
109 pending_accept_ = true;
110 }
111
112 return result;
113 }
114
DetachFromThread()115 void TCPServerSocket::DetachFromThread() {
116 socket_->DetachFromThread();
117 }
118
ConvertAcceptedSocket(int result,std::unique_ptr<StreamSocket> * output_accepted_socket,IPEndPoint * output_accepted_address)119 int TCPServerSocket::ConvertAcceptedSocket(
120 int result,
121 std::unique_ptr<StreamSocket>* output_accepted_socket,
122 IPEndPoint* output_accepted_address) {
123 // Make sure the TCPSocket object is destroyed in any case.
124 std::unique_ptr<TCPSocket> temp_accepted_socket(std::move(accepted_socket_));
125 if (result != OK)
126 return result;
127
128 if (output_accepted_address)
129 *output_accepted_address = accepted_address_;
130
131 *output_accepted_socket = std::make_unique<TCPClientSocket>(
132 std::move(temp_accepted_socket), accepted_address_);
133
134 return OK;
135 }
136
OnAcceptCompleted(std::unique_ptr<StreamSocket> * output_accepted_socket,IPEndPoint * output_accepted_address,CompletionOnceCallback forward_callback,int result)137 void TCPServerSocket::OnAcceptCompleted(
138 std::unique_ptr<StreamSocket>* output_accepted_socket,
139 IPEndPoint* output_accepted_address,
140 CompletionOnceCallback forward_callback,
141 int result) {
142 result = ConvertAcceptedSocket(result, output_accepted_socket,
143 output_accepted_address);
144 pending_accept_ = false;
145 std::move(forward_callback).Run(result);
146 }
147
148 } // namespace net
149