1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240
|
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef IPC_IPC_CHANNEL_H_
#define IPC_IPC_CHANNEL_H_
#include <stddef.h>
#include <stdint.h>
#include <memory>
#include <string>
#include "base/component_export.h"
#include "base/files/scoped_file.h"
#include "base/functional/bind.h"
#include "base/memory/ref_counted.h"
#include "base/process/process.h"
#include "base/task/single_thread_task_runner.h"
#include "build/build_config.h"
#include "ipc/ipc.mojom-forward.h"
#include "ipc/ipc_channel_handle.h"
#include "ipc/ipc_message.h"
#include "ipc/ipc_sender.h"
#include "mojo/public/cpp/bindings/generic_pending_associated_receiver.h"
#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
#include "mojo/public/cpp/bindings/shared_remote.h"
#if BUILDFLAG(IS_POSIX)
#include <sys/types.h>
#endif
namespace IPC {
class Listener;
class UrgentMessageObserver;
//------------------------------------------------------------------------------
// See
// http://www.chromium.org/developers/design-documents/inter-process-communication
// for overview of IPC in Chromium.
// Channels are implemented using mojo message pipes (via IPC::ChannelMojo) on
// all platforms other than NaCl.
class COMPONENT_EXPORT(IPC) Channel : public Sender {
// Security tests need access to the pipe handle.
friend class ChannelTest;
public:
// Flags to test modes
using ModeFlags = int;
static constexpr ModeFlags MODE_NO_FLAG = 0x0;
static constexpr ModeFlags MODE_SERVER_FLAG = 0x1;
static constexpr ModeFlags MODE_CLIENT_FLAG = 0x2;
// Some Standard Modes
// TODO(morrita): These are under deprecation work. You should use Create*()
// functions instead.
enum Mode {
MODE_NONE = MODE_NO_FLAG,
MODE_SERVER = MODE_SERVER_FLAG,
MODE_CLIENT = MODE_CLIENT_FLAG,
};
// Messages internal to the IPC implementation are defined here.
// Uses Maximum value of message type (uint16_t), to avoid conflicting
// with normal message types, which are enumeration constants starting from 0.
enum {
// The Hello message is sent by the peer when the channel is connected.
// The message contains just the process id (pid).
// The message has a special routing_id (MSG_ROUTING_NONE)
// and type (HELLO_MESSAGE_TYPE).
HELLO_MESSAGE_TYPE = UINT16_MAX,
// The CLOSE_FD_MESSAGE_TYPE is used in the IPC class to
// work around a bug in sendmsg() on Mac. When an FD is sent
// over the socket, a CLOSE_FD_MESSAGE is sent with hops = 2.
// The client will return the message with hops = 1, *after* it
// has received the message that contains the FD. When we
// receive it again on the sender side, we close the FD.
CLOSE_FD_MESSAGE_TYPE = HELLO_MESSAGE_TYPE - 1
};
// Helper interface a Channel may implement to expose support for associated
// Mojo interfaces.
class COMPONENT_EXPORT(IPC) AssociatedInterfaceSupport {
public:
using GenericAssociatedInterfaceFactory =
base::RepeatingCallback<void(mojo::ScopedInterfaceEndpointHandle)>;
virtual ~AssociatedInterfaceSupport() {}
// Returns a ThreadSafeForwarded for this channel which can be used to
// safely send mojom::Channel requests from arbitrary threads.
virtual std::unique_ptr<mojo::ThreadSafeForwarder<mojom::Channel>>
CreateThreadSafeChannel() = 0;
// Adds an interface factory to this channel for interface |name|. Must be
// safe to call from any thread.
virtual void AddGenericAssociatedInterface(
const std::string& name,
const GenericAssociatedInterfaceFactory& factory) = 0;
// Requests an associated interface from the remote endpoint.
virtual void GetRemoteAssociatedInterface(
mojo::GenericPendingAssociatedReceiver receiver) = 0;
};
// The maximum message size in bytes. Attempting to receive a message of this
// size or bigger results in a channel error.
static constexpr size_t kMaximumMessageSize = 128 * 1024 * 1024;
// Amount of data to read at once from the pipe.
static const size_t kReadBufferSize = 4 * 1024;
// Maximum persistent read buffer size. Read buffer can grow larger to
// accommodate large messages, but it's recommended to shrink back to this
// value because it fits 99.9% of all messages (see issue 529940 for data).
static const size_t kMaximumReadBufferSize = 64 * 1024;
// Initialize a Channel.
//
// |channel_handle| identifies the communication Channel. For POSIX, if
// the file descriptor in the channel handle is != -1, the channel takes
// ownership of the file descriptor and will close it appropriately, otherwise
// it will create a new descriptor internally.
// |listener| receives a callback on the current thread for each newly
// received message.
//
// There are four type of modes how channels operate:
//
// - Server and named server: In these modes, the Channel is
// responsible for setting up the IPC object.
// - An "open" named server: It accepts connections from ANY client.
// The caller must then implement their own access-control based on the
// client process' user Id.
// - Client and named client: In these mode, the Channel merely
// connects to the already established IPC object.
//
// Each mode has its own Create*() API to create the Channel object.
static std::unique_ptr<Channel> Create(
const IPC::ChannelHandle& channel_handle,
Mode mode,
Listener* listener);
static std::unique_ptr<Channel> CreateClient(
const IPC::ChannelHandle& channel_handle,
Listener* listener,
const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner);
static std::unique_ptr<Channel> CreateServer(
const IPC::ChannelHandle& channel_handle,
Listener* listener,
const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner);
~Channel() override;
// Connect the pipe. On the server side, this will initiate
// waiting for connections. On the client, it attempts to
// connect to a pre-existing pipe. Note, calling Connect()
// will not block the calling thread and may complete
// asynchronously.
//
// The subclass implementation must call WillConnect() at the beginning of its
// implementation.
[[nodiscard]] virtual bool Connect() = 0;
// Pause the channel. Subsequent sends will be queued internally until
// Unpause() is called and the channel is flushed either by Unpause() or a
// subsequent call to Flush().
virtual void Pause();
// Unpause the channel. This allows subsequent Send() calls to transmit
// messages immediately, without queueing. If |flush| is true, any messages
// queued while paused will be flushed immediately upon unpausing. Otherwise
// you must call Flush() explicitly.
//
// Not all implementations support Unpause(). See ConnectPaused() above for
// details.
virtual void Unpause(bool flush);
// Manually flush the pipe. This is only useful exactly once, and only after
// a call to Unpause(false), in order to explicitly flush out any
// messages which were queued prior to unpausing.
//
// Not all implementations support Flush(). See ConnectPaused() above for
// details.
virtual void Flush();
// Close this Channel explicitly. May be called multiple times.
// On POSIX calling close on an IPC channel that listens for connections will
// cause it to close any accepted connections, and it will stop listening for
// new connections. If you just want to close the currently accepted
// connection and listen for new ones, use ResetToAcceptingConnectionState.
virtual void Close() = 0;
// Gets a helper for associating Mojo interfaces with this Channel.
//
// NOTE: Not all implementations support this.
virtual AssociatedInterfaceSupport* GetAssociatedInterfaceSupport();
// Overridden from ipc::Sender.
// Send a message over the Channel to the listener on the other end.
//
// |message| must be allocated using operator new. This object will be
// deleted once the contents of the Message have been sent.
bool Send(Message* message) override = 0;
// Sets the UrgentMessageObserver for this channel. `observer` must outlive
// the channel.
//
// Only channel associated mojo interfaces support urgent messages.
virtual void SetUrgentMessageObserver(UrgentMessageObserver* observer);
#if !BUILDFLAG(IS_NACL)
// Generates a channel ID that's non-predictable and unique.
static std::string GenerateUniqueRandomChannelID();
#endif
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
// Sandboxed processes live in a PID namespace, so when sending the IPC hello
// message from client to server we need to send the PID from the global
// PID namespace.
static void SetGlobalPid(int pid);
static int GetGlobalPid();
#endif
protected:
// Subclasses must call this method at the beginning of their implementation
// of Connect().
void WillConnect();
private:
bool did_start_connect_ = false;
};
} // namespace IPC
#endif // IPC_IPC_CHANNEL_H_
|