| 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 |