blob: 38e14ef14b684f5fc7f76a1386b4a4aae91ff403 [file] [log] [blame]
brettw@chromium.org293988a2012-03-01 07:48:14 +09001// Copyright (c) 2012 The Chromium Authors. All rights reserved.
agl@chromium.org1c6dcf22009-07-23 08:57:21 +09002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef IPC_IPC_CHANNEL_POSIX_H_
6#define IPC_IPC_CHANNEL_POSIX_H_
7
8#include "ipc/ipc_channel.h"
9
10#include <sys/socket.h> // for CMSG macros
11
12#include <queue>
13#include <string>
14#include <vector>
15
16#include "base/message_loop.h"
jschuh@chromium.orga5cd0762012-04-05 11:38:34 +090017#include "base/process.h"
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090018#include "ipc/file_descriptor_set_posix.h"
brettw@chromium.org0e9d0a12012-03-08 21:30:28 +090019#include "ipc/ipc_channel_reader.h"
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090020
dmaclach@chromium.org2680d3a2010-12-09 06:22:24 +090021#if !defined(OS_MACOSX)
22// On Linux, the seccomp sandbox makes it very expensive to call
23// recvmsg() and sendmsg(). The restriction on calling read() and write(), which
24// are cheap, is that we can't pass file descriptors over them.
25//
26// As we cannot anticipate when the sender will provide us with file
27// descriptors, we have to make the decision about whether we call read() or
28// recvmsg() before we actually make the call. The easiest option is to
brettw@chromium.org0d7e0192011-05-14 04:22:14 +090029// create a dedicated socketpair() for exchanging file descriptors. Any file
30// descriptors are split out of a message, with the non-file-descriptor payload
31// going over the normal connection, and the file descriptors being sent
32// separately over the other channel. When read()ing from a channel, we'll
33// notice if the message was supposed to have come with file descriptors and
34// use recvmsg on the other socketpair to retrieve them and combine them
35// back with the rest of the message.
36//
dmaclach@chromium.org2680d3a2010-12-09 06:22:24 +090037// Mac can also run in IPC_USES_READWRITE mode if necessary, but at this time
38// doesn't take a performance hit from recvmsg and sendmsg, so it doesn't
39// make sense to waste resources on having the separate dedicated socketpair.
40// It is however useful for debugging between Linux and Mac to be able to turn
41// this switch 'on' on the Mac as well.
brettw@chromium.org0d7e0192011-05-14 04:22:14 +090042//
dmaclach@chromium.org2680d3a2010-12-09 06:22:24 +090043// The HELLO message from the client to the server is always sent using
44// sendmsg because it will contain the file descriptor that the server
45// needs to send file descriptors in later messages.
46#define IPC_USES_READWRITE 1
47#endif
48
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090049namespace IPC {
50
brettw@chromium.org0e9d0a12012-03-08 21:30:28 +090051class Channel::ChannelImpl : public internal::ChannelReader,
52 public MessageLoopForIO::Watcher {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090053 public:
54 // Mirror methods of Channel, see ipc_channel.h for description.
dmaclach@chromium.orgc1d3d422010-12-20 15:59:23 +090055 ChannelImpl(const IPC::ChannelHandle& channel_handle, Mode mode,
dmaclach@chromium.org058c4a72010-12-09 04:28:09 +090056 Listener* listener);
hans@chromium.org78b75932011-05-25 18:08:19 +090057 virtual ~ChannelImpl();
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090058 bool Connect();
59 void Close();
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090060 bool Send(Message* message);
phajdan.jr@chromium.orgaf9455b2011-09-20 02:08:12 +090061 int GetClientFileDescriptor();
62 int TakeClientFileDescriptor();
63 void CloseClientFileDescriptor();
dmaclach@chromium.orgc1d3d422010-12-20 15:59:23 +090064 bool AcceptsConnections() const;
65 bool HasAcceptedConnection() const;
wez@chromium.org7cce0912011-04-06 21:01:44 +090066 bool GetClientEuid(uid_t* client_euid) const;
dmaclach@chromium.orgc1d3d422010-12-20 15:59:23 +090067 void ResetToAcceptingConnectionState();
jschuh@chromium.orga5cd0762012-04-05 11:38:34 +090068 base::ProcessId peer_pid() const { return peer_pid_; }
kkania@chromium.orgf37b4e52011-08-09 15:46:06 +090069 static bool IsNamedServerInitialized(const std::string& channel_id);
jamescook@chromium.org2d471f02011-09-01 06:11:04 +090070#if defined(OS_LINUX)
71 static void SetGlobalPid(int pid);
72#endif // OS_LINUX
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090073
74 private:
dmaclach@chromium.orgf146c292011-02-04 05:35:09 +090075 bool CreatePipe(const IPC::ChannelHandle& channel_handle);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090076
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090077 bool ProcessOutgoingMessages();
78
dmaclach@chromium.orgc1d3d422010-12-20 15:59:23 +090079 bool AcceptConnection();
80 void ClosePipeOnError();
jamescook@chromium.org2d471f02011-09-01 06:11:04 +090081 int GetHelloMessageProcId();
dmaclach@chromium.orgc1d3d422010-12-20 15:59:23 +090082 void QueueHelloMessage();
dmaclach@chromium.orgc1d3d422010-12-20 15:59:23 +090083
brettw@chromium.org0e9d0a12012-03-08 21:30:28 +090084 // ChannelReader implementation.
85 virtual ReadState ReadData(char* buffer,
86 int buffer_len,
87 int* bytes_read) OVERRIDE;
88 virtual bool WillDispatchInputMessage(Message* msg) OVERRIDE;
89 virtual bool DidEmptyInputBuffers() OVERRIDE;
90 virtual void HandleHelloMessage(const Message& msg) OVERRIDE;
brettw@chromium.org293988a2012-03-01 07:48:14 +090091
92#if defined(IPC_USES_READWRITE)
93 // Reads the next message from the fd_pipe_ and appends them to the
94 // input_fds_ queue. Returns false if there was a message receiving error.
95 // True means there was a message and it was processed properly, or there was
96 // no messages.
97 bool ReadFileDescriptorsFromFDPipe();
98#endif
99
brettw@chromium.org293988a2012-03-01 07:48:14 +0900100 // Finds the set of file descriptors in the given message. On success,
101 // appends the descriptors to the input_fds_ member and returns true
102 //
103 // Returns false if the message was truncated. In this case, any handles that
104 // were sent will be closed.
105 bool ExtractFileDescriptorsFromMsghdr(msghdr* msg);
106
107 // Closes all handles in the input_fds_ list and clears the list. This is
108 // used to clean up handles in error conditions to avoid leaking the handles.
109 void ClearInputFDs();
110
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900111 // MessageLoopForIO::Watcher implementation.
avi@chromium.org362c8a82011-11-18 01:09:44 +0900112 virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE;
113 virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE;
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900114
115 Mode mode_;
116
jschuh@chromium.orga5cd0762012-04-05 11:38:34 +0900117 base::ProcessId peer_pid_;
118
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900119 // After accepting one client connection on our server socket we want to
120 // stop listening.
121 MessageLoopForIO::FileDescriptorWatcher server_listen_connection_watcher_;
122 MessageLoopForIO::FileDescriptorWatcher read_watcher_;
123 MessageLoopForIO::FileDescriptorWatcher write_watcher_;
124
125 // Indicates whether we're currently blocked waiting for a write to complete.
126 bool is_blocked_on_write_;
dmaclach@chromium.orgc1d3d422010-12-20 15:59:23 +0900127 bool waiting_connect_;
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900128
129 // If sending a message blocks then we use this variable
130 // to keep track of where we are.
131 size_t message_send_bytes_written_;
132
dmaclach@chromium.orgc1d3d422010-12-20 15:59:23 +0900133 // File descriptor we're listening on for new connections if we listen
134 // for connections.
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900135 int server_listen_pipe_;
136
137 // The pipe used for communication.
138 int pipe_;
139
140 // For a server, the client end of our socketpair() -- the other end of our
141 // pipe_ that is passed to the client.
142 int client_pipe_;
phajdan.jr@chromium.orgaf9455b2011-09-20 02:08:12 +0900143 base::Lock client_pipe_lock_; // Lock that protects |client_pipe_|.
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900144
dmaclach@chromium.org2680d3a2010-12-09 06:22:24 +0900145#if defined(IPC_USES_READWRITE)
pvalchev@google.comc45765a2010-05-20 03:17:53 +0900146 // Linux/BSD use a dedicated socketpair() for passing file descriptors.
agl@chromium.orga81f84a2009-09-05 06:34:05 +0900147 int fd_pipe_;
148 int remote_fd_pipe_;
149#endif
150
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900151 // The "name" of our pipe. On Windows this is the global identifier for
152 // the pipe. On POSIX it's used as a key in a local map of file descriptors.
153 std::string pipe_name_;
154
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900155 // Messages to be sent are queued here.
156 std::queue<Message*> output_queue_;
157
pkasting@chromium.org9687a8f2011-09-01 09:50:13 +0900158 // We assume a worst case: kReadBufferSize bytes of messages, where each
159 // message has no payload and a full complement of descriptors.
160 static const size_t kMaxReadFDs =
161 (Channel::kReadBufferSize / sizeof(IPC::Message::Header)) *
162 FileDescriptorSet::kMaxDescriptorsPerMessage;
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900163
brettw@chromium.org293988a2012-03-01 07:48:14 +0900164 // Buffer size for file descriptors used for recvmsg. On Mac the CMSG macros
165 // don't seem to be constant so we have to pick a "large enough" value.
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900166#if defined(OS_MACOSX)
brettw@chromium.org293988a2012-03-01 07:48:14 +0900167 static const size_t kMaxReadFDBuffer = 1024;
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900168#else
brettw@chromium.org293988a2012-03-01 07:48:14 +0900169 static const size_t kMaxReadFDBuffer = CMSG_SPACE(sizeof(int) * kMaxReadFDs);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900170#endif
171
brettw@chromium.org293988a2012-03-01 07:48:14 +0900172 // Temporary buffer used to receive the file descriptors from recvmsg.
173 // Code that writes into this should immediately read them out and save
174 // them to input_fds_, since this buffer will be re-used anytime we call
175 // recvmsg.
176 char input_cmsg_buf_[kMaxReadFDBuffer];
177
178 // File descriptors extracted from messages coming off of the channel. The
179 // handles may span messages and come off different channels from the message
180 // data (in the case of READWRITE), and are processed in FIFO here.
fischman@chromium.org8b60dfa2012-04-10 06:40:44 +0900181 // NOTE: The implementation assumes underlying storage here is contiguous, so
182 // don't change to something like std::deque<> without changing the
183 // implementation!
184 std::vector<int> input_fds_;
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900185
dmaclach@chromium.orgc1d3d422010-12-20 15:59:23 +0900186 // True if we are responsible for unlinking the unix domain socket file.
187 bool must_unlink_;
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900188
jamescook@chromium.org2d471f02011-09-01 06:11:04 +0900189#if defined(OS_LINUX)
190 // If non-zero, overrides the process ID sent in the hello message.
191 static int global_pid_;
192#endif // OS_LINUX
193
dmaclach@chromium.org2812db62011-03-03 07:27:14 +0900194 DISALLOW_IMPLICIT_CONSTRUCTORS(ChannelImpl);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900195};
196
dmaclach@chromium.orgc1d3d422010-12-20 15:59:23 +0900197// The maximum length of the name of a pipe for MODE_NAMED_SERVER or
198// MODE_NAMED_CLIENT if you want to pass in your own socket.
199// The standard size on linux is 108, mac is 104. To maintain consistency
200// across platforms we standardize on the smaller value.
201static const size_t kMaxPipeNameLength = 104;
202
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900203} // namespace IPC
204
205#endif // IPC_IPC_CHANNEL_POSIX_H_