// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "net/socket/tcp_server_socket.h" #include #include #include "base/bind.h" #include "base/callback_helpers.h" #include "base/check.h" #include "base/notreached.h" #include "net/base/net_errors.h" #include "net/socket/socket_descriptor.h" #include "net/socket/tcp_client_socket.h" namespace net { TCPServerSocket::TCPServerSocket(NetLog* net_log, const NetLogSource& source) : TCPServerSocket( std::make_unique(nullptr /* socket_performance_watcher */, net_log, source)) {} TCPServerSocket::TCPServerSocket(std::unique_ptr socket) : socket_(std::move(socket)) {} int TCPServerSocket::AdoptSocket(SocketDescriptor socket) { return socket_->AdoptUnconnectedSocket(socket); } TCPServerSocket::~TCPServerSocket() = default; int TCPServerSocket::Listen(const IPEndPoint& address, int backlog) { int result = socket_->Open(address.GetFamily()); if (result != OK) return result; result = socket_->SetDefaultOptionsForServer(); if (result != OK) { socket_->Close(); return result; } result = socket_->Bind(address); if (result != OK) { socket_->Close(); return result; } result = socket_->Listen(backlog); if (result != OK) { socket_->Close(); return result; } return OK; } int TCPServerSocket::GetLocalAddress(IPEndPoint* address) const { return socket_->GetLocalAddress(address); } int TCPServerSocket::Accept(std::unique_ptr* socket, CompletionOnceCallback callback) { return Accept(socket, std::move(callback), nullptr); } int TCPServerSocket::Accept(std::unique_ptr* socket, CompletionOnceCallback callback, IPEndPoint* peer_address) { DCHECK(socket); DCHECK(!callback.is_null()); if (pending_accept_) { NOTREACHED(); return ERR_UNEXPECTED; } // It is safe to use base::Unretained(this). |socket_| is owned by this class, // and the callback won't be run after |socket_| is destroyed. CompletionOnceCallback accept_callback = base::BindOnce( &TCPServerSocket::OnAcceptCompleted, base::Unretained(this), socket, peer_address, std::move(callback)); int result = socket_->Accept(&accepted_socket_, &accepted_address_, std::move(accept_callback)); if (result != ERR_IO_PENDING) { // |accept_callback| won't be called so we need to run // ConvertAcceptedSocket() ourselves in order to do the conversion from // |accepted_socket_| to |socket|. result = ConvertAcceptedSocket(result, socket, peer_address); } else { pending_accept_ = true; } return result; } void TCPServerSocket::DetachFromThread() { socket_->DetachFromThread(); } int TCPServerSocket::ConvertAcceptedSocket( int result, std::unique_ptr* output_accepted_socket, IPEndPoint* output_accepted_address) { // Make sure the TCPSocket object is destroyed in any case. std::unique_ptr temp_accepted_socket(std::move(accepted_socket_)); if (result != OK) return result; if (output_accepted_address) *output_accepted_address = accepted_address_; *output_accepted_socket = std::make_unique( std::move(temp_accepted_socket), accepted_address_); return OK; } void TCPServerSocket::OnAcceptCompleted( std::unique_ptr* output_accepted_socket, IPEndPoint* output_accepted_address, CompletionOnceCallback forward_callback, int result) { result = ConvertAcceptedSocket(result, output_accepted_socket, output_accepted_address); pending_accept_ = false; std::move(forward_callback).Run(result); } } // namespace net