chromium/mojo/core/channel_posix.cc

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

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/351564777): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif

#include "mojo/core/channel_posix.h"

#include <errno.h>
#include <sys/socket.h>

#include <atomic>
#include <limits>
#include <memory>
#include <tuple>

#include "base/cpu_reduction_experiment.h"
#include "base/functional/bind.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/message_loop/message_pump_for_io.h"
#include "base/metrics/histogram_macros.h"
#include "base/synchronization/lock.h"
#include "base/task/current_thread.h"
#include "base/task/single_thread_task_runner.h"
#include "base/task/task_runner.h"
#include "base/time/time.h"
#include "base/types/fixed_array.h"
#include "build/build_config.h"
#include "mojo/public/cpp/platform/socket_utils_posix.h"

#if !BUILDFLAG(IS_NACL)
#include <limits.h>
#include <sys/uio.h>

#if (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID))
#include "mojo/core/channel_linux.h"
#endif

#endif  // !BUILDFLAG(IS_NACL)

#if BUILDFLAG(IS_ANDROID)
#include "mojo/core/channel_binder.h"
#endif

namespace mojo::core {

namespace {
#if !BUILDFLAG(IS_NACL)
std::atomic<bool> g_use_writev{};
#endif  // !BUILDFLAG(IS_NACL)

const size_t kMaxBatchReadCapacity =;
}  // namespace

// A view over a Channel::Message object. The write queue uses these since
// large messages may need to be sent in chunks.
class MessageView {};

ChannelPosix::ChannelPosix(
    Delegate* delegate,
    ConnectionParams connection_params,
    HandlePolicy handle_policy,
    scoped_refptr<base::SingleThreadTaskRunner> io_task_runner)
    :{}

ChannelPosix::~ChannelPosix() {}

void ChannelPosix::Start() {}

void ChannelPosix::ShutDownImpl() {}

void ChannelPosix::Write(MessagePtr message) {}

void ChannelPosix::LeakHandle() {}

bool ChannelPosix::GetReadPlatformHandles(const void* payload,
                                          size_t payload_size,
                                          size_t num_handles,
                                          const void* extra_header,
                                          size_t extra_header_size,
                                          std::vector<PlatformHandle>* handles,
                                          bool* deferred) {}

bool ChannelPosix::GetReadPlatformHandlesForIpcz(
    size_t num_handles,
    std::vector<PlatformHandle>& handles) {}

void ChannelPosix::StartOnIOThread() {}

void ChannelPosix::WaitForWriteOnIOThread() {}

void ChannelPosix::WaitForWriteOnIOThreadNoLock() {}

void ChannelPosix::ShutDownOnIOThread() {}

void ChannelPosix::WillDestroyCurrentMessageLoop() {}

void ChannelPosix::OnFileCanReadWithoutBlocking(int fd) {}

void ChannelPosix::OnFileCanWriteWithoutBlocking(int fd) {}

// Attempts to write a message directly to the channel. If the full message
// cannot be written, it's queued and a wait is initiated to write the message
// ASAP on the I/O thread.
bool ChannelPosix::WriteNoLock(MessageView message_view) {}

bool ChannelPosix::FlushOutgoingMessagesNoLock() {}

void ChannelPosix::RejectUpgradeOffer() {}

void ChannelPosix::AcceptUpgradeOffer() {}

void ChannelPosix::OnWriteError(Error error) {}

#if !BUILDFLAG(IS_NACL)
bool ChannelPosix::WriteOutgoingMessagesWithWritev() {}

// FlushOutgoingMessagesWritevNoLock is equivalent to
// FlushOutgoingMessagesNoLock except it looks for opportunities to make only
// a single write syscall by using writev(2) instead of write(2). In most
// situations this is very straight forward; however, when a handle needs to
// be transferred we cannot use writev(2) and instead will fall back to the
// standard write.
bool ChannelPosix::FlushOutgoingMessagesWritevNoLock() {}
#endif  // !BUILDFLAG(IS_NACL)

bool ChannelPosix::OnControlMessage(Message::MessageType message_type,
                                    const void* payload,
                                    size_t payload_size,
                                    std::vector<PlatformHandle> handles) {}

#if BUILDFLAG(IS_IOS)
// Closes handles referenced by |fds|. Returns false if |num_fds| is 0, or if
// |fds| does not match a sequence of handles in |fds_to_close_|.
bool ChannelPosix::CloseHandles(const int* fds, size_t num_fds) {
  base::AutoLock l(fds_to_close_lock_);
  if (!num_fds)
    return false;

  auto start = base::ranges::find(fds_to_close_, fds[0], &base::ScopedFD::get);
  if (start == fds_to_close_.end())
    return false;

  auto it = start;
  size_t i = 0;
  // The FDs in the message should match a sequence of handles in
  // |fds_to_close_|.
  // TODO(wez): Consider making |fds_to_close_| a circular_deque<>
  // for greater efficiency? Or assign a unique Id to each FD-containing
  // message, and map that to a vector of FDs to close, to avoid the
  // need for this traversal? Id could even be the first FD in the message.
  for (; i < num_fds && it != fds_to_close_.end(); i++, ++it) {
    if (it->get() != fds[i])
      return false;
  }
  if (i != num_fds)
    return false;

  // Close the FDs by erase()ing their ScopedFDs.
  fds_to_close_.erase(start, it);
  return true;
}
#endif  // BUILDFLAG(IS_IOS)

#if !BUILDFLAG(IS_NACL)
// static
void Channel::set_posix_use_writev(bool use_writev) {}
#endif  // !BUILDFLAG(IS_NACL)

// static
scoped_refptr<Channel> Channel::Create(
    Delegate* delegate,
    ConnectionParams connection_params,
    HandlePolicy handle_policy,
    scoped_refptr<base::SingleThreadTaskRunner> io_task_runner) {}

#if !BUILDFLAG(IS_NACL)
#if (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID))
// static
bool Channel::SupportsChannelUpgrade() {}

void Channel::OfferChannelUpgrade() {}
#endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) ||
        // BUILDFLAG(IS_ANDROID)
#endif  // !BUILDFLAG(IS_NACL)

}  // namespace mojo::core