chromium/chrome/services/sharing/nearby/platform/wifi_lan_socket.cc

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

#include "chrome/services/sharing/nearby/platform/wifi_lan_socket.h"

#include "base/logging.h"
#include "base/task/thread_pool.h"
#include "chrome/services/sharing/nearby/platform/bidirectional_stream.h"

namespace nearby {
namespace chrome {

WifiLanSocket::ConnectedSocketParameters::ConnectedSocketParameters(
    mojo::PendingRemote<network::mojom::TCPConnectedSocket>
        tcp_connected_socket,
    mojo::ScopedDataPipeConsumerHandle receive_stream,
    mojo::ScopedDataPipeProducerHandle send_stream)
    : tcp_connected_socket(std::move(tcp_connected_socket)),
      receive_stream(std::move(receive_stream)),
      send_stream(std::move(send_stream)) {}

WifiLanSocket::ConnectedSocketParameters::~ConnectedSocketParameters() =
    default;

WifiLanSocket::ConnectedSocketParameters::ConnectedSocketParameters(
    ConnectedSocketParameters&&) = default;

WifiLanSocket::ConnectedSocketParameters&
WifiLanSocket::ConnectedSocketParameters::operator=(
    ConnectedSocketParameters&&) = default;

WifiLanSocket::WifiLanSocket(
    ConnectedSocketParameters connected_socket_parameters)
    : task_runner_(
          base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()})),
      tcp_connected_socket_(
          std::move(connected_socket_parameters.tcp_connected_socket),
          task_runner_),
      bidirectional_stream_(
          connections::mojom::Medium::kWifiLan,
          task_runner_,
          std::move(connected_socket_parameters.receive_stream),
          std::move(connected_socket_parameters.send_stream)) {
  tcp_connected_socket_.set_disconnect_handler(
      base::BindOnce(&WifiLanSocket::OnTcpConnectedSocketDisconnected,
                     base::Unretained(this)),
      task_runner_);
}

WifiLanSocket::~WifiLanSocket() {
  Close();
}

InputStream& WifiLanSocket::GetInputStream() {
  DCHECK(bidirectional_stream_.GetInputStream());
  return *bidirectional_stream_.GetInputStream();
}

OutputStream& WifiLanSocket::GetOutputStream() {
  DCHECK(bidirectional_stream_.GetOutputStream());
  return *bidirectional_stream_.GetOutputStream();
}

// Note: Both CloseTcpSocketIfNecessary() and BidirectionalStream::Close() are
// thread safe.
Exception WifiLanSocket::Close() {
  CloseTcpSocketIfNecessary();

  return bidirectional_stream_.Close();
}

bool WifiLanSocket::IsClosed() const {
  return !tcp_connected_socket_.is_bound();
}

void WifiLanSocket::OnTcpConnectedSocketDisconnected() {
  LOG(WARNING) << "WifiLanSocket::" << __func__
               << ": TCP connected socket unexpectedly disconnected. Closing "
               << "WifiLanSocket.";
  Close();
}

void WifiLanSocket::CloseTcpSocketIfNecessary() {
  base::AutoLock lock(lock_);

  if (!tcp_connected_socket_)
    return;

  VLOG(1) << "WifiLanSocket::" << __func__ << ": Closing TCP connected socket.";
  tcp_connected_socket_.reset();
}

}  // namespace chrome
}  // namespace nearby