chromium/services/network/public/cpp/transferable_socket.cc

// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "services/network/public/cpp/transferable_socket.h"

#if BUILDFLAG(IS_WIN)
#include <winsock2.h>
#elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
#include "base/files/scoped_file.h"
#include "mojo/public/cpp/platform/platform_handle.h"
#else
#error "unsupported platform"
#endif

#include "base/dcheck_is_on.h"
#include "base/logging.h"
#include "base/notreached.h"
#include "base/process/process_handle.h"
#include "net/socket/tcp_socket.h"
#include "net/socket/udp_socket.h"

namespace network {

TransferableSocket::TransferableSocket() = default;

#if BUILDFLAG(IS_WIN)
TransferableSocket::TransferableSocket(net::SocketDescriptor socket,
                                       const base::Process& destination_process)
    : wsa_info_buffer_(sizeof(WSAPROTOCOL_INFOW), 0) {
  DCHECK(destination_process.IsValid());

  if (socket == net::kInvalidSocket) {
    // Send across an empty buffer if invalid socket.
    wsa_info_buffer_.clear();
    return;
  }

  // If the duplicate fails, the network service process has likely died
  // asynchronously, or the caller does not have the ability to duplicate a
  // socket to that process.
  if (::WSADuplicateSocketW(socket, destination_process.Pid(),
                            reinterpret_cast<LPWSAPROTOCOL_INFOW>(
                                wsa_info_buffer_.data())) != 0) {
    wsa_info_buffer_.clear();
  }
  // The source handle must always be closed otherwise it will leak. In the
  // event of a real failure (e.g. network process died), the network stack will
  // retry.
  ::closesocket(socket);
}
#elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
TransferableSocket::TransferableSocket(net::SocketDescriptor socket)
    :{}
#else
#error "Unsupported Platform"
#endif  // BUILDFLAG(IS_WIN)

TransferableSocket::~TransferableSocket() = default;
TransferableSocket& TransferableSocket::operator=(TransferableSocket&& other) =
    default;
TransferableSocket::TransferableSocket(TransferableSocket&& other) = default;

#if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
TransferableSocket::TransferableSocket(mojo::PlatformHandle socket)
    :{}
#elif !BUILDFLAG(IS_WIN)
#error "Unsupported Platform"
#endif

net::SocketDescriptor TransferableSocket::TakeSocket() {}

}  // namespace network