OLD | NEW |
| (Empty) |
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 | |
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 <stddef.h> | |
11 #include <sys/socket.h> // for CMSG macros | |
12 | |
13 #include <queue> | |
14 #include <set> | |
15 #include <string> | |
16 #include <vector> | |
17 | |
18 #include "base/files/scoped_file.h" | |
19 #include "base/macros.h" | |
20 #include "base/message_loop/message_loop.h" | |
21 #include "base/process/process.h" | |
22 #include "build/build_config.h" | |
23 #include "ipc/ipc_channel_reader.h" | |
24 #include "ipc/ipc_message_attachment_set.h" | |
25 | |
26 namespace IPC { | |
27 | |
28 class IPC_EXPORT ChannelPosix : public Channel, | |
29 public internal::ChannelReader, | |
30 public base::MessageLoopForIO::Watcher { | |
31 public: | |
32 // |broker| must outlive the newly created object. | |
33 ChannelPosix(const IPC::ChannelHandle& channel_handle, | |
34 Mode mode, | |
35 Listener* listener); | |
36 ~ChannelPosix() override; | |
37 | |
38 // Channel implementation | |
39 bool Connect() override; | |
40 void Close() override; | |
41 bool Send(Message* message) override; | |
42 AttachmentBroker* GetAttachmentBroker() override; | |
43 base::ProcessId GetPeerPID() const override; | |
44 base::ProcessId GetSelfPID() const override; | |
45 int GetClientFileDescriptor() const override; | |
46 base::ScopedFD TakeClientFileDescriptor() override; | |
47 | |
48 // Returns true if the channel supports listening for connections. | |
49 bool AcceptsConnections() const; | |
50 | |
51 // Returns true if the channel supports listening for connections and is | |
52 // currently connected. | |
53 bool HasAcceptedConnection() const; | |
54 | |
55 // Closes any currently connected socket, and returns to a listening state | |
56 // for more connections. | |
57 void ResetToAcceptingConnectionState(); | |
58 | |
59 // Returns true if the peer process' effective user id can be determined, in | |
60 // which case the supplied peer_euid is updated with it. | |
61 bool GetPeerEuid(uid_t* peer_euid) const; | |
62 | |
63 void CloseClientFileDescriptor(); | |
64 | |
65 static bool IsNamedServerInitialized(const std::string& channel_id); | |
66 #if defined(OS_LINUX) | |
67 static void SetGlobalPid(int pid); | |
68 static int GetGlobalPid(); | |
69 #endif // OS_LINUX | |
70 | |
71 private: | |
72 bool CreatePipe(const IPC::ChannelHandle& channel_handle); | |
73 | |
74 // Returns false on recoverable error. | |
75 // There are two reasons why this method might leave messages in the | |
76 // output_queue_. | |
77 // 1. |waiting_connect_| is |true|. | |
78 // 2. |is_blocked_on_write_| is |true|. | |
79 // If any of these conditionals change, this method should be called, as | |
80 // previously blocked messages may no longer be blocked. | |
81 bool ProcessOutgoingMessages(); | |
82 | |
83 bool OnConnect(); | |
84 void ClosePipeOnError(); | |
85 int GetHelloMessageProcId() const; | |
86 void QueueHelloMessage(); | |
87 void CloseFileDescriptors(Message* msg); | |
88 void QueueCloseFDMessage(int fd, int hops); | |
89 | |
90 // ChannelReader implementation. | |
91 ReadState ReadData(char* buffer, int buffer_len, int* bytes_read) override; | |
92 bool ShouldDispatchInputMessage(Message* msg) override; | |
93 bool GetNonBrokeredAttachments(Message* msg) override; | |
94 bool DidEmptyInputBuffers() override; | |
95 void HandleInternalMessage(const Message& msg) override; | |
96 base::ProcessId GetSenderPID() override; | |
97 bool IsAttachmentBrokerEndpoint() override; | |
98 | |
99 // Finds the set of file descriptors in the given message. On success, | |
100 // appends the descriptors to the input_fds_ member and returns true | |
101 // | |
102 // Returns false if the message was truncated. In this case, any handles that | |
103 // were sent will be closed. | |
104 bool ExtractFileDescriptorsFromMsghdr(msghdr* msg); | |
105 | |
106 // Closes all handles in the input_fds_ list and clears the list. This is | |
107 // used to clean up handles in error conditions to avoid leaking the handles. | |
108 void ClearInputFDs(); | |
109 | |
110 // MessageLoopForIO::Watcher implementation. | |
111 void OnFileCanReadWithoutBlocking(int fd) override; | |
112 void OnFileCanWriteWithoutBlocking(int fd) override; | |
113 | |
114 // Returns |false| on channel error. | |
115 // If |message| has brokerable attachments, those attachments are passed to | |
116 // the AttachmentBroker (which in turn invokes Send()), so this method must | |
117 // be re-entrant. | |
118 // Adds |message| to |output_queue_| and calls ProcessOutgoingMessages(). | |
119 bool ProcessMessageForDelivery(Message* message); | |
120 | |
121 // Moves all messages from |prelim_queue_| to |output_queue_| by calling | |
122 // ProcessMessageForDelivery(). | |
123 // Returns |false| on channel error. | |
124 bool FlushPrelimQueue(); | |
125 | |
126 Mode mode_; | |
127 | |
128 base::ProcessId peer_pid_; | |
129 | |
130 // After accepting one client connection on our server socket we want to | |
131 // stop listening. | |
132 base::MessageLoopForIO::FileDescriptorWatcher | |
133 server_listen_connection_watcher_; | |
134 base::MessageLoopForIO::FileDescriptorWatcher read_watcher_; | |
135 base::MessageLoopForIO::FileDescriptorWatcher write_watcher_; | |
136 | |
137 // Indicates whether we're currently blocked waiting for a write to complete. | |
138 bool is_blocked_on_write_; | |
139 bool waiting_connect_; | |
140 | |
141 // If sending a message blocks then we use this variable | |
142 // to keep track of where we are. | |
143 size_t message_send_bytes_written_; | |
144 | |
145 // File descriptor we're listening on for new connections if we listen | |
146 // for connections. | |
147 base::ScopedFD server_listen_pipe_; | |
148 | |
149 // The pipe used for communication. | |
150 base::ScopedFD pipe_; | |
151 | |
152 // For a server, the client end of our socketpair() -- the other end of our | |
153 // pipe_ that is passed to the client. | |
154 base::ScopedFD client_pipe_; | |
155 mutable base::Lock client_pipe_lock_; // Lock that protects |client_pipe_|. | |
156 | |
157 // The "name" of our pipe. On Windows this is the global identifier for | |
158 // the pipe. On POSIX it's used as a key in a local map of file descriptors. | |
159 std::string pipe_name_; | |
160 | |
161 // Messages not yet ready to be sent are queued here. Messages removed from | |
162 // this queue are placed in the output_queue_. The double queue is | |
163 // unfortunate, but is necessary because messages with brokerable attachments | |
164 // can generate multiple messages to be sent (possibly from other channels). | |
165 // Some of these generated messages cannot be sent until |peer_pid_| has been | |
166 // configured. | |
167 // As soon as |peer_pid| has been configured, there is no longer any need for | |
168 // |prelim_queue_|. All messages are flushed, and no new messages are added. | |
169 std::queue<Message*> prelim_queue_; | |
170 | |
171 // Messages to be sent are queued here. | |
172 std::queue<OutputElement*> output_queue_; | |
173 | |
174 // We assume a worst case: kReadBufferSize bytes of messages, where each | |
175 // message has no payload and a full complement of descriptors. | |
176 static const size_t kMaxReadFDs = | |
177 (Channel::kReadBufferSize / sizeof(IPC::Message::Header)) * | |
178 MessageAttachmentSet::kMaxDescriptorsPerMessage; | |
179 | |
180 // Buffer size for file descriptors used for recvmsg. On Mac the CMSG macros | |
181 // are not constant so we have to pick a "large enough" padding for headers. | |
182 #if defined(OS_MACOSX) | |
183 static const size_t kMaxReadFDBuffer = 1024 + sizeof(int) * kMaxReadFDs; | |
184 #else | |
185 static const size_t kMaxReadFDBuffer = CMSG_SPACE(sizeof(int) * kMaxReadFDs); | |
186 #endif | |
187 static_assert(kMaxReadFDBuffer <= 8192, | |
188 "kMaxReadFDBuffer too big for a stack buffer"); | |
189 | |
190 // File descriptors extracted from messages coming off of the channel. The | |
191 // handles may span messages and come off different channels from the message | |
192 // data (in the case of READWRITE), and are processed in FIFO here. | |
193 // NOTE: The implementation assumes underlying storage here is contiguous, so | |
194 // don't change to something like std::deque<> without changing the | |
195 // implementation! | |
196 std::vector<int> input_fds_; | |
197 | |
198 | |
199 void ResetSafely(base::ScopedFD* fd); | |
200 bool in_dtor_; | |
201 | |
202 #if defined(OS_MACOSX) | |
203 // On OSX, sent FDs must not be closed until we get an ack. | |
204 // Keep track of sent FDs here to make sure the remote is not | |
205 // trying to bamboozle us. | |
206 std::set<int> fds_to_close_; | |
207 #endif | |
208 | |
209 // True if we are responsible for unlinking the unix domain socket file. | |
210 bool must_unlink_; | |
211 | |
212 #if defined(OS_LINUX) | |
213 // If non-zero, overrides the process ID sent in the hello message. | |
214 static int global_pid_; | |
215 #endif // OS_LINUX | |
216 | |
217 DISALLOW_IMPLICIT_CONSTRUCTORS(ChannelPosix); | |
218 }; | |
219 | |
220 } // namespace IPC | |
221 | |
222 #endif // IPC_IPC_CHANNEL_POSIX_H_ | |
OLD | NEW |