tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ipc_channel.h (8067B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
      4 // Use of this source code is governed by a BSD-style license that can be
      5 // found in the LICENSE file.
      6 
      7 #ifndef CHROME_COMMON_IPC_CHANNEL_H_
      8 #define CHROME_COMMON_IPC_CHANNEL_H_
      9 
     10 #include <cstdint>
     11 #include <queue>
     12 #include <variant>
     13 #include "base/basictypes.h"
     14 #include "base/process.h"
     15 #include "mozilla/EventTargetAndLockCapability.h"
     16 #include "mozilla/Mutex.h"
     17 #include "mozilla/UniquePtr.h"
     18 #include "mozilla/UniquePtrExtensions.h"
     19 #include "chrome/common/ipc_message.h"
     20 
     21 #include "nsISerialEventTarget.h"
     22 
     23 #ifdef XP_WIN
     24 #endif
     25 
     26 namespace IPC {
     27 
     28 class Message;
     29 class MessageReader;
     30 class MessageWriter;
     31 
     32 //------------------------------------------------------------------------------
     33 
     34 class Channel {
     35 public:
     36  NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_DELETE_ON_EVENT_TARGET(
     37      Channel, IOThread().GetEventTarget());
     38 
     39  // For channels which are created after initialization, handles to the pipe
     40  // endpoints may be passed around directly using IPC messages.
     41  using ChannelHandle =
     42      std::variant<std::monostate, mozilla::UniqueFileHandle
     43 #if defined(XP_DARWIN)
     44                   ,
     45                   mozilla::UniqueMachSendRight, mozilla::UniqueMachReceiveRight
     46 #endif
     47                   >;
     48 
     49  // Implemented by consumers of a Channel to receive messages.
     50  //
     51  // All listeners will only be called on the IO thread, and must be destroyed
     52  // on the IO thread.
     53  class Listener {
     54   public:
     55    virtual ~Listener() = default;
     56 
     57    // Called when a message is received.
     58    virtual void OnMessageReceived(mozilla::UniquePtr<Message> message) = 0;
     59 
     60    // Called when the channel is connected and we have received the internal
     61    // Hello message from the peer.
     62    virtual void OnChannelConnected(base::ProcessId peer_pid) {}
     63 
     64    // Called when an error is detected that causes the channel to close.
     65    // This method is not called when a channel is closed normally.
     66    virtual void OnChannelError() {}
     67  };
     68 
     69  enum Mode { MODE_BROKER_SERVER, MODE_BROKER_CLIENT, MODE_PEER };
     70 
     71  enum {
     72 
     73  // The maximum message size in bytes. Attempting to receive a
     74  // message of this size or bigger results in a channel error.
     75  // This is larger in fuzzing builds to allow the fuzzing of passing
     76  // large data structures into DOM methods without crashing.
     77 #ifndef FUZZING
     78    kMaximumMessageSize = 256 * 1024 * 1024,
     79 #else
     80    kMaximumMessageSize = 1792 * 1024 * 1024,  // 1.75GB
     81 #endif
     82 
     83    // Amount of data to read at once from the pipe.
     84    kReadBufferSize = 4 * 1024,
     85  };
     86 
     87  // Each channel implementation has a static ChannelKind vtable which can be
     88  // used to access "static" methods, not associated with a Channel instance.
     89  struct ChannelKind {
     90    // Create a new pair of pipe endpoints which can be used to establish a
     91    // native IPC::Channel connection.
     92    bool (*create_raw_pipe)(ChannelHandle* server, ChannelHandle* client);
     93 
     94    // The number of attachments in |message| which will need to be relayed via.
     95    // the broker channel, rather than being sent directly to a non-broker peer.
     96    uint32_t (*num_relayed_attachments)(const IPC::Message& message);
     97 
     98    // Check if |handle| is a valid handle for creating a channel of this kind.
     99    bool (*is_valid_handle)(const ChannelHandle& handle);
    100  };
    101 
    102  // Initialize a Channel.
    103  //
    104  // |pipe| identifies the pipe which will be used. It should have been created
    105  // using CreateRawPipe().
    106  // |mode| specifies whether this channel is operating in server mode or client
    107  // mode. One side of the connection should be the client, and the other should
    108  // be the server.
    109  // |other_pid| specifies the pid of the other side of this channel. This will
    110  // be used for logging, and for transferring HANDLEs from a privileged process
    111  // on Windows (if enabled).
    112  //
    113  // The Channel must be created and destroyed on the IO thread, and all
    114  // methods, unless otherwise noted, are only safe to call on the I/O thread.
    115  //
    116  static already_AddRefed<Channel> Create(ChannelHandle pipe, Mode mode,
    117                                          base::ProcessId other_pid);
    118 
    119  Channel(const Channel&) = delete;
    120  Channel& operator=(const Channel&) = delete;
    121 
    122  // Connect the pipe.  On the server side, this will initiate
    123  // waiting for connections.  On the client, it attempts to
    124  // connect to a pre-existing pipe.  Note, calling Connect()
    125  // will not block the calling thread and may complete
    126  // asynchronously.
    127  //
    128  // |listener| will receive a callback on the current thread for each newly
    129  // received message.
    130  virtual bool Connect(Listener* listener) MOZ_EXCLUDES(SendMutex()) = 0;
    131 
    132  // Close this Channel explicitly.  May be called multiple times.
    133  virtual void Close() MOZ_EXCLUDES(SendMutex()) = 0;
    134 
    135  // Send a message over the Channel to the listener on the other end.
    136  //
    137  // This method may be called from any thread, so long as the `Channel` is not
    138  // destroyed before it returns.
    139  //
    140  // If you Send() a message on a Close()'d channel, we delete the message
    141  // immediately.
    142  virtual bool Send(mozilla::UniquePtr<Message> message)
    143      MOZ_EXCLUDES(SendMutex()) = 0;
    144 
    145  // Explicitly set the pid expected for the other side of this channel. This
    146  // will be used for logging, and on Windows may be used for transferring
    147  // handles between processes.
    148  //
    149  // If it is set this way, the "hello" message will be checked to ensure that
    150  // the same pid is reported.
    151  virtual void SetOtherPid(base::ProcessId other_pid)
    152      MOZ_EXCLUDES(SendMutex()) = 0;
    153 
    154 #if defined(XP_DARWIN)
    155  // Configure the mach task_t for the peer task.
    156  virtual void SetOtherMachTask(task_t task) MOZ_EXCLUDES(SendMutex()) = 0;
    157 #endif
    158 
    159  // Get the static ChannelKind vtable for this Channel's implementation.
    160  virtual const ChannelKind* GetKind() const = 0;
    161 
    162 protected:
    163  Channel();
    164  virtual ~Channel();
    165 
    166  // Capability for members which may only be used on the IO thread. Generally
    167  // used for state related to receiving IPC messages.
    168  const mozilla::EventTargetCapability<nsISerialEventTarget>& IOThread() const
    169      MOZ_RETURN_CAPABILITY(chan_cap_.Target()) {
    170    return chan_cap_.Target();
    171  }
    172 
    173  // Capability for members which may only be used with the send mutex held.
    174  // Generally used for state related to sending IPC messages.
    175  mozilla::Mutex& SendMutex() MOZ_RETURN_CAPABILITY(chan_cap_.Lock()) {
    176    return chan_cap_.Lock();
    177  }
    178 
    179  // Compound capability of the IO thread and a Mutex. This can be used for
    180  // members which may be used immutably either on the IO thread or with the
    181  // send mutex held, but may only be modified if both on the IO thread, and
    182  // holding the send mutex.
    183  mozilla::EventTargetAndLockCapability<nsISerialEventTarget, mozilla::Mutex>
    184      chan_cap_;
    185 
    186  enum {
    187 #if defined(XP_DARWIN)
    188    // If the channel receives a message that contains file descriptors, then
    189    // it will reply back with this message, indicating that the message has
    190    // been received. The sending channel can then close any descriptors that
    191    // had been marked as auto_close. This works around a sendmsg() bug on BSD
    192    // where the kernel can eagerly close file descriptors that are in message
    193    // queues but not yet delivered.
    194    RECEIVED_FDS_MESSAGE_TYPE = kuint16max - 1,
    195 #endif
    196 
    197    // The Hello message is internal to the Channel class.  It is sent
    198    // by the peer when the channel is connected.  The message contains
    199    // just the process id (pid).  The message has a special routing_id
    200    // (MSG_ROUTING_NONE) and type (HELLO_MESSAGE_TYPE).
    201    HELLO_MESSAGE_TYPE = kuint16max  // Maximum value of message type
    202                                     // (uint16_t), to avoid conflicting with
    203                                     // normal message types, which are
    204                                     // enumeration constants starting from 0.
    205  };
    206 };
    207 
    208 }  // namespace IPC
    209 
    210 #endif  // CHROME_COMMON_IPC_CHANNEL_H_