• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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