xref: /aosp_15_r20/external/cronet/net/socket/tcp_server_socket.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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