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_