summaryrefslogtreecommitdiff
path: root/chromium/ipc/ipc_channel.h
blob: ba5ef42ee7a0f75feaeb4335de0c28ebc2c8b0fb (plain)
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
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// 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/compiler_specific.h"
#include "base/files/scoped_file.h"
#include "base/memory/ref_counted.h"
#include "base/process/process.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "ipc/ipc_channel_handle.h"
#include "ipc/ipc_endpoint.h"
#include "ipc/ipc_message.h"
#include "mojo/public/cpp/bindings/associated_group.h"
#include "mojo/public/cpp/bindings/associated_interface_ptr.h"
#include "mojo/public/cpp/bindings/associated_interface_request.h"
#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"

#if defined(OS_POSIX)
#include <sys/types.h>
#endif

namespace IPC {

class Listener;

//------------------------------------------------------------------------------
// See
// http://www.chromium.org/developers/design-documents/inter-process-communication
// for overview of IPC in Chromium.

// Channels are implemented using named pipes on Windows, and
// socket pairs (or in some special cases unix domain sockets) on POSIX.
// On Windows we access pipes in various processes by name.
// On POSIX we pass file descriptors to child processes and assign names to them
// in a lookup table.
// In general on POSIX we do not use unix domain sockets due to security
// concerns and the fact that they can leave garbage around the file system
// (MacOS does not support abstract named unix domain sockets).
// You can use unix domain sockets if you like on POSIX by constructing the
// the channel with the mode set to one of the NAMED modes. NAMED modes are
// currently used by automation and service processes.

class IPC_EXPORT Channel : public Endpoint {
  // Security tests need access to the pipe handle.
  friend class ChannelTest;

 public:
  // Flags to test modes
  enum ModeFlags {
    MODE_NO_FLAG = 0x0,
    MODE_SERVER_FLAG = 0x1,
    MODE_CLIENT_FLAG = 0x2,
    MODE_NAMED_FLAG = 0x4,
  };

  // 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,
    MODE_NAMED_SERVER = MODE_SERVER_FLAG | MODE_NAMED_FLAG,
    MODE_NAMED_CLIENT = MODE_CLIENT_FLAG | MODE_NAMED_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 IPC_EXPORT AssociatedInterfaceSupport {
   public:
    using GenericAssociatedInterfaceFactory =
        base::Callback<void(mojo::ScopedInterfaceEndpointHandle)>;

    virtual ~AssociatedInterfaceSupport() {}

    // Accesses the AssociatedGroup used to associate new interface endpoints
    // with this Channel. Must be safe to call from any thread.
    virtual mojo::AssociatedGroup* GetAssociatedGroup() = 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 GetGenericRemoteAssociatedInterface(
        const std::string& name,
        mojo::ScopedInterfaceEndpointHandle handle) = 0;

    // Template helper to add an interface factory to this channel.
    template <typename Interface>
    using AssociatedInterfaceFactory =
        base::Callback<void(mojo::AssociatedInterfaceRequest<Interface>)>;
    template <typename Interface>
    void AddAssociatedInterface(
        const AssociatedInterfaceFactory<Interface>& factory) {
      AddGenericAssociatedInterface(
          Interface::Name_,
          base::Bind(&BindAssociatedInterfaceRequest<Interface>, factory));
    }

    // Template helper to request a remote associated interface.
    template <typename Interface>
    void GetRemoteAssociatedInterface(
        mojo::AssociatedInterfacePtr<Interface>* proxy) {
      mojo::AssociatedInterfaceRequest<Interface> request =
          mojo::GetProxy(proxy, GetAssociatedGroup());
      GetGenericRemoteAssociatedInterface(
          Interface::Name_, request.PassHandle());
    }

   private:
    template <typename Interface>
    static void BindAssociatedInterfaceRequest(
        const AssociatedInterfaceFactory<Interface>& factory,
        mojo::ScopedInterfaceEndpointHandle handle) {
      mojo::AssociatedInterfaceRequest<Interface> request;
      request.Bind(std::move(handle));
      factory.Run(std::move(request));
    }
  };

  // The maximum message size in bytes. Attempting to receive a message of this
  // size or bigger results in a channel error.
  static const 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 settingb 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 =
          base::ThreadTaskRunnerHandle::Get());

  // Channels on Windows are named by default and accessible from other
  // processes. On POSIX channels are anonymous by default and not accessible
  // from other processes. Named channels work via named unix domain sockets.
  // On Windows MODE_NAMED_SERVER is equivalent to MODE_SERVER and
  // MODE_NAMED_CLIENT is equivalent to MODE_CLIENT.
  static std::unique_ptr<Channel> CreateNamedServer(
      const IPC::ChannelHandle& channel_handle,
      Listener* listener);
  static std::unique_ptr<Channel> CreateNamedClient(
      const IPC::ChannelHandle& channel_handle,
      Listener* listener);
  static std::unique_ptr<Channel> CreateServer(
      const IPC::ChannelHandle& channel_handle,
      Listener* listener,
      const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner =
          base::ThreadTaskRunnerHandle::Get());

  ~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.
  virtual bool Connect() WARN_UNUSED_RESULT = 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;

  // Get its own process id. This value is told to the peer.
  virtual base::ProcessId GetSelfPID() const = 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;

  // NaCl in Non-SFI mode runs on Linux directly, and the following functions
  // compiled on Linux are also needed. Please see also comments in
  // components/nacl_nonsfi.gyp for more details.
#if defined(OS_POSIX) && !defined(OS_NACL_SFI)
  // On POSIX an IPC::Channel wraps a socketpair(), this method returns the
  // FD # for the client end of the socket.
  // This method may only be called on the server side of a channel.
  // This method can be called on any thread.
  virtual int GetClientFileDescriptor() const = 0;

  // Same as GetClientFileDescriptor, but transfers the ownership of the
  // file descriptor to the caller.
  // This method can be called on any thread.
  virtual base::ScopedFD TakeClientFileDescriptor() = 0;
#endif

  // Returns true if a named server channel is initialized on the given channel
  // ID. Even if true, the server may have already accepted a connection.
  static bool IsNamedServerInitialized(const std::string& channel_id);

#if !defined(OS_NACL_SFI)
  // Generates a channel ID that's non-predictable and unique.
  static std::string GenerateUniqueRandomChannelID();

  // Generates a channel ID that, if passed to the client as a shared secret,
  // will validate that the client's authenticity. On platforms that do not
  // require additional this is simply calls GenerateUniqueRandomChannelID().
  // For portability the prefix should not include the \ character.
  static std::string GenerateVerifiedChannelID(const std::string& prefix);
#endif

  // Generates a pair of channel handles that can be used as the client and
  // server ends of a ChannelMojo. |name_postfix| is appended to the end of the
  // handle name to help identify the handles.
  //
  // Note, when using ChannelMojo, |ChannelHandle::name| serves no functional
  // purpose other than to identify the channel in logging.
  static void GenerateMojoChannelHandlePair(
      const std::string& name_postfix,
      IPC::ChannelHandle* handle0,
      IPC::ChannelHandle* handle1);

#if defined(OS_LINUX)
  // 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

#if defined(OS_ANDROID)
  // Most tests are single process and work the same on all platforms. However
  // in some cases we want to test multi-process, and Android differs in that it
  // can't 'exec' after forking. This callback resets any data in the forked
  // process such that it acts similar to if it was exec'd, for tests.
  static void NotifyProcessForkedForTesting();
#endif

 protected:
  // An OutputElement is a wrapper around a Message or raw buffer while it is
  // waiting to be passed to the system's underlying IPC mechanism.
  class OutputElement {
   public:
    // Takes ownership of message.
    OutputElement(Message* message);
    // Takes ownership of the buffer. |buffer| is freed via free(), so it
    // must be malloced.
    OutputElement(void* buffer, size_t length);
    ~OutputElement();
    size_t size() const { return message_ ? message_->size() : length_; }
    const void* data() const { return message_ ? message_->data() : buffer_; }
    Message* get_message() const { return message_.get(); }

   private:
    std::unique_ptr<Message> message_;
    void* buffer_;
    size_t length_;
  };

  // Endpoint overrides.
  void OnSetAttachmentBrokerEndpoint() override;

  // Subclasses must call this method at the beginning of their implementation
  // of Connect().
  void WillConnect();

 private:
  bool did_start_connect_ = false;
};

#if defined(OS_POSIX)
// SocketPair() creates a pair of socket FDs suitable for using with
// IPC::Channel.
IPC_EXPORT bool SocketPair(int* fd1, int* fd2);
#endif

}  // namespace IPC

#endif  // IPC_IPC_CHANNEL_H_