OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef IPC_IPC_CHANNEL_POSIX_H_ | 5 #ifndef IPC_IPC_CHANNEL_POSIX_H_ |
6 #define IPC_IPC_CHANNEL_POSIX_H_ | 6 #define IPC_IPC_CHANNEL_POSIX_H_ |
7 #pragma once | 7 #pragma once |
8 | 8 |
9 #include "ipc/ipc_channel.h" | 9 #include "ipc/ipc_channel.h" |
10 | 10 |
11 #include <sys/socket.h> // for CMSG macros | 11 #include <sys/socket.h> // for CMSG macros |
12 | 12 |
13 #include <queue> | 13 #include <queue> |
14 #include <string> | 14 #include <string> |
15 #include <vector> | 15 #include <vector> |
16 | 16 |
17 #include "base/message_loop.h" | 17 #include "base/message_loop.h" |
18 #include "ipc/file_descriptor_set_posix.h" | 18 #include "ipc/file_descriptor_set_posix.h" |
| 19 #include "ipc/ipc_channel_reader.h" |
19 | 20 |
20 #if !defined(OS_MACOSX) | 21 #if !defined(OS_MACOSX) |
21 // On Linux, the seccomp sandbox makes it very expensive to call | 22 // On Linux, the seccomp sandbox makes it very expensive to call |
22 // recvmsg() and sendmsg(). The restriction on calling read() and write(), which | 23 // recvmsg() and sendmsg(). The restriction on calling read() and write(), which |
23 // are cheap, is that we can't pass file descriptors over them. | 24 // are cheap, is that we can't pass file descriptors over them. |
24 // | 25 // |
25 // As we cannot anticipate when the sender will provide us with file | 26 // As we cannot anticipate when the sender will provide us with file |
26 // descriptors, we have to make the decision about whether we call read() or | 27 // descriptors, we have to make the decision about whether we call read() or |
27 // recvmsg() before we actually make the call. The easiest option is to | 28 // recvmsg() before we actually make the call. The easiest option is to |
28 // create a dedicated socketpair() for exchanging file descriptors. Any file | 29 // create a dedicated socketpair() for exchanging file descriptors. Any file |
(...skipping 11 matching lines...) Expand all Loading... |
40 // this switch 'on' on the Mac as well. | 41 // this switch 'on' on the Mac as well. |
41 // | 42 // |
42 // The HELLO message from the client to the server is always sent using | 43 // The HELLO message from the client to the server is always sent using |
43 // sendmsg because it will contain the file descriptor that the server | 44 // sendmsg because it will contain the file descriptor that the server |
44 // needs to send file descriptors in later messages. | 45 // needs to send file descriptors in later messages. |
45 #define IPC_USES_READWRITE 1 | 46 #define IPC_USES_READWRITE 1 |
46 #endif | 47 #endif |
47 | 48 |
48 namespace IPC { | 49 namespace IPC { |
49 | 50 |
50 class Channel::ChannelImpl : public MessageLoopForIO::Watcher { | 51 class Channel::ChannelImpl : public internal::ChannelReader, |
| 52 public MessageLoopForIO::Watcher { |
51 public: | 53 public: |
52 // Mirror methods of Channel, see ipc_channel.h for description. | 54 // Mirror methods of Channel, see ipc_channel.h for description. |
53 ChannelImpl(const IPC::ChannelHandle& channel_handle, Mode mode, | 55 ChannelImpl(const IPC::ChannelHandle& channel_handle, Mode mode, |
54 Listener* listener); | 56 Listener* listener); |
55 virtual ~ChannelImpl(); | 57 virtual ~ChannelImpl(); |
56 bool Connect(); | 58 bool Connect(); |
57 void Close(); | 59 void Close(); |
58 void set_listener(Listener* listener) { listener_ = listener; } | |
59 bool Send(Message* message); | 60 bool Send(Message* message); |
60 int GetClientFileDescriptor(); | 61 int GetClientFileDescriptor(); |
61 int TakeClientFileDescriptor(); | 62 int TakeClientFileDescriptor(); |
62 void CloseClientFileDescriptor(); | 63 void CloseClientFileDescriptor(); |
63 bool AcceptsConnections() const; | 64 bool AcceptsConnections() const; |
64 bool HasAcceptedConnection() const; | 65 bool HasAcceptedConnection() const; |
65 bool GetClientEuid(uid_t* client_euid) const; | 66 bool GetClientEuid(uid_t* client_euid) const; |
66 void ResetToAcceptingConnectionState(); | 67 void ResetToAcceptingConnectionState(); |
67 static bool IsNamedServerInitialized(const std::string& channel_id); | 68 static bool IsNamedServerInitialized(const std::string& channel_id); |
68 #if defined(OS_LINUX) | 69 #if defined(OS_LINUX) |
69 static void SetGlobalPid(int pid); | 70 static void SetGlobalPid(int pid); |
70 #endif // OS_LINUX | 71 #endif // OS_LINUX |
71 | 72 |
72 private: | 73 private: |
73 enum ReadState { READ_SUCCEEDED, READ_FAILED, READ_PENDING }; | |
74 | |
75 bool CreatePipe(const IPC::ChannelHandle& channel_handle); | 74 bool CreatePipe(const IPC::ChannelHandle& channel_handle); |
76 | 75 |
77 bool ProcessIncomingMessages(); | |
78 bool ProcessOutgoingMessages(); | 76 bool ProcessOutgoingMessages(); |
79 | 77 |
80 bool AcceptConnection(); | 78 bool AcceptConnection(); |
81 void ClosePipeOnError(); | 79 void ClosePipeOnError(); |
82 int GetHelloMessageProcId(); | 80 int GetHelloMessageProcId(); |
83 void QueueHelloMessage(); | 81 void QueueHelloMessage(); |
84 bool IsHelloMessage(const Message* m) const; | |
85 | 82 |
86 // Populates the given buffer with data from the pipe. | 83 // ChannelReader implementation. |
87 // | 84 virtual ReadState ReadData(char* buffer, |
88 // Returns the state of the read. On READ_SUCCESS, the number of bytes | 85 int buffer_len, |
89 // read will be placed into |*bytes_read| (which can be less than the | 86 int* bytes_read) OVERRIDE; |
90 // buffer size). On READ_FAILED, the channel will be closed. | 87 virtual bool WillDispatchInputMessage(Message* msg) OVERRIDE; |
91 // | 88 virtual bool DidEmptyInputBuffers() OVERRIDE; |
92 // If the return value is READ_PENDING, it means that there was no data | 89 virtual void HandleHelloMessage(const Message& msg) OVERRIDE; |
93 // ready for reading. The implementation is then responsible for either | |
94 // calling AsyncReadComplete with the number of bytes read into the | |
95 // buffer, or ProcessIncomingMessages to try the read again (depending | |
96 // on whether the platform's async I/O is "try again" or "write | |
97 // asynchronously into your buffer"). | |
98 ReadState ReadData(char* buffer, int buffer_len, int* bytes_read); | |
99 | |
100 // Takes the given data received from the IPC channel and dispatches any | |
101 // fully completed messages. | |
102 // | |
103 // Returns true on success. False means channel error. | |
104 bool DispatchInputData(const char* input_data, int input_data_len); | |
105 | 90 |
106 #if defined(IPC_USES_READWRITE) | 91 #if defined(IPC_USES_READWRITE) |
107 // Reads the next message from the fd_pipe_ and appends them to the | 92 // Reads the next message from the fd_pipe_ and appends them to the |
108 // input_fds_ queue. Returns false if there was a message receiving error. | 93 // input_fds_ queue. Returns false if there was a message receiving error. |
109 // True means there was a message and it was processed properly, or there was | 94 // True means there was a message and it was processed properly, or there was |
110 // no messages. | 95 // no messages. |
111 bool ReadFileDescriptorsFromFDPipe(); | 96 bool ReadFileDescriptorsFromFDPipe(); |
112 #endif | 97 #endif |
113 | 98 |
114 // Loads the required file desciptors into the given message. Returns true | |
115 // on success. False means a fatal channel error. | |
116 // | |
117 // This will read from the input_fds_ and read more handles from the FD | |
118 // pipe if necessary. | |
119 bool WillDispatchInputMessage(Message* msg); | |
120 | |
121 // Performs post-dispatch checks. Called when all input buffers are empty, | |
122 // though there could be more data ready to be read from the OS. | |
123 bool DidEmptyInputBuffers(); | |
124 | |
125 // Finds the set of file descriptors in the given message. On success, | 99 // Finds the set of file descriptors in the given message. On success, |
126 // appends the descriptors to the input_fds_ member and returns true | 100 // appends the descriptors to the input_fds_ member and returns true |
127 // | 101 // |
128 // Returns false if the message was truncated. In this case, any handles that | 102 // Returns false if the message was truncated. In this case, any handles that |
129 // were sent will be closed. | 103 // were sent will be closed. |
130 bool ExtractFileDescriptorsFromMsghdr(msghdr* msg); | 104 bool ExtractFileDescriptorsFromMsghdr(msghdr* msg); |
131 | 105 |
132 // Closes all handles in the input_fds_ list and clears the list. This is | 106 // Closes all handles in the input_fds_ list and clears the list. This is |
133 // used to clean up handles in error conditions to avoid leaking the handles. | 107 // used to clean up handles in error conditions to avoid leaking the handles. |
134 void ClearInputFDs(); | 108 void ClearInputFDs(); |
135 | 109 |
136 // Handles the first message sent over the pipe which contains setup info. | |
137 void HandleHelloMessage(const Message& msg); | |
138 | |
139 // MessageLoopForIO::Watcher implementation. | 110 // MessageLoopForIO::Watcher implementation. |
140 virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE; | 111 virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE; |
141 virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE; | 112 virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE; |
142 | 113 |
143 Mode mode_; | 114 Mode mode_; |
144 | 115 |
145 // After accepting one client connection on our server socket we want to | 116 // After accepting one client connection on our server socket we want to |
146 // stop listening. | 117 // stop listening. |
147 MessageLoopForIO::FileDescriptorWatcher server_listen_connection_watcher_; | 118 MessageLoopForIO::FileDescriptorWatcher server_listen_connection_watcher_; |
148 MessageLoopForIO::FileDescriptorWatcher read_watcher_; | 119 MessageLoopForIO::FileDescriptorWatcher read_watcher_; |
(...skipping 22 matching lines...) Expand all Loading... |
171 #if defined(IPC_USES_READWRITE) | 142 #if defined(IPC_USES_READWRITE) |
172 // Linux/BSD use a dedicated socketpair() for passing file descriptors. | 143 // Linux/BSD use a dedicated socketpair() for passing file descriptors. |
173 int fd_pipe_; | 144 int fd_pipe_; |
174 int remote_fd_pipe_; | 145 int remote_fd_pipe_; |
175 #endif | 146 #endif |
176 | 147 |
177 // The "name" of our pipe. On Windows this is the global identifier for | 148 // The "name" of our pipe. On Windows this is the global identifier for |
178 // the pipe. On POSIX it's used as a key in a local map of file descriptors. | 149 // the pipe. On POSIX it's used as a key in a local map of file descriptors. |
179 std::string pipe_name_; | 150 std::string pipe_name_; |
180 | 151 |
181 Listener* listener_; | |
182 | |
183 // Messages to be sent are queued here. | 152 // Messages to be sent are queued here. |
184 std::queue<Message*> output_queue_; | 153 std::queue<Message*> output_queue_; |
185 | 154 |
186 // We read from the pipe into this buffer. Managed by DispatchInputData, do | |
187 // not access directly outside that function. | |
188 char input_buf_[Channel::kReadBufferSize]; | |
189 | |
190 // Large messages that span multiple pipe buffers, get built-up using | |
191 // this buffer. | |
192 std::string input_overflow_buf_; | |
193 | |
194 // We assume a worst case: kReadBufferSize bytes of messages, where each | 155 // We assume a worst case: kReadBufferSize bytes of messages, where each |
195 // message has no payload and a full complement of descriptors. | 156 // message has no payload and a full complement of descriptors. |
196 static const size_t kMaxReadFDs = | 157 static const size_t kMaxReadFDs = |
197 (Channel::kReadBufferSize / sizeof(IPC::Message::Header)) * | 158 (Channel::kReadBufferSize / sizeof(IPC::Message::Header)) * |
198 FileDescriptorSet::kMaxDescriptorsPerMessage; | 159 FileDescriptorSet::kMaxDescriptorsPerMessage; |
199 | 160 |
200 // Buffer size for file descriptors used for recvmsg. On Mac the CMSG macros | 161 // Buffer size for file descriptors used for recvmsg. On Mac the CMSG macros |
201 // don't seem to be constant so we have to pick a "large enough" value. | 162 // don't seem to be constant so we have to pick a "large enough" value. |
202 #if defined(OS_MACOSX) | 163 #if defined(OS_MACOSX) |
203 static const size_t kMaxReadFDBuffer = 1024; | 164 static const size_t kMaxReadFDBuffer = 1024; |
(...skipping 25 matching lines...) Expand all Loading... |
229 | 190 |
230 // The maximum length of the name of a pipe for MODE_NAMED_SERVER or | 191 // The maximum length of the name of a pipe for MODE_NAMED_SERVER or |
231 // MODE_NAMED_CLIENT if you want to pass in your own socket. | 192 // MODE_NAMED_CLIENT if you want to pass in your own socket. |
232 // The standard size on linux is 108, mac is 104. To maintain consistency | 193 // The standard size on linux is 108, mac is 104. To maintain consistency |
233 // across platforms we standardize on the smaller value. | 194 // across platforms we standardize on the smaller value. |
234 static const size_t kMaxPipeNameLength = 104; | 195 static const size_t kMaxPipeNameLength = 104; |
235 | 196 |
236 } // namespace IPC | 197 } // namespace IPC |
237 | 198 |
238 #endif // IPC_IPC_CHANNEL_POSIX_H_ | 199 #endif // IPC_IPC_CHANNEL_POSIX_H_ |
OLD | NEW |