OLD | NEW |
| (Empty) |
1 // Copyright (c) 2008 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 #include "chrome/common/ipc_channel_posix.h" | |
6 | |
7 #include <errno.h> | |
8 #include <fcntl.h> | |
9 #include <stddef.h> | |
10 #include <sys/types.h> | |
11 #include <sys/socket.h> | |
12 #include <sys/stat.h> | |
13 #include <sys/un.h> | |
14 | |
15 #include <string> | |
16 #include <map> | |
17 | |
18 #include "base/command_line.h" | |
19 #include "base/eintr_wrapper.h" | |
20 #include "base/global_descriptors_posix.h" | |
21 #include "base/lock.h" | |
22 #include "base/logging.h" | |
23 #include "base/process_util.h" | |
24 #include "base/scoped_ptr.h" | |
25 #include "base/string_util.h" | |
26 #include "base/singleton.h" | |
27 #include "base/stats_counters.h" | |
28 #include "chrome/common/chrome_counters.h" | |
29 #include "chrome/common/chrome_descriptors.h" | |
30 #include "chrome/common/chrome_switches.h" | |
31 #include "chrome/common/file_descriptor_set_posix.h" | |
32 #include "chrome/common/ipc_logging.h" | |
33 #include "chrome/common/ipc_message_utils.h" | |
34 | |
35 namespace IPC { | |
36 | |
37 // IPC channels on Windows use named pipes (CreateNamedPipe()) with | |
38 // channel ids as the pipe names. Channels on POSIX use anonymous | |
39 // Unix domain sockets created via socketpair() as pipes. These don't | |
40 // quite line up. | |
41 // | |
42 // When creating a child subprocess, the parent side of the fork | |
43 // arranges it such that the initial control channel ends up on the | |
44 // magic file descriptor kPrimaryIPCChannel in the child. Future | |
45 // connections (file descriptors) can then be passed via that | |
46 // connection via sendmsg(). | |
47 | |
48 //------------------------------------------------------------------------------ | |
49 namespace { | |
50 | |
51 // The PipeMap class works around this quirk related to unit tests: | |
52 // | |
53 // When running as a server, we install the client socket in a | |
54 // specific file descriptor number (@kPrimaryIPCChannel). However, we | |
55 // also have to support the case where we are running unittests in the | |
56 // same process. (We do not support forking without execing.) | |
57 // | |
58 // Case 1: normal running | |
59 // The IPC server object will install a mapping in PipeMap from the | |
60 // name which it was given to the client pipe. When forking the client, the | |
61 // GetClientFileDescriptorMapping will ensure that the socket is installed in | |
62 // the magic slot (@kPrimaryIPCChannel). The client will search for the | |
63 // mapping, but it won't find any since we are in a new process. Thus the | |
64 // magic fd number is returned. Once the client connects, the server will | |
65 // close its copy of the client socket and remove the mapping. | |
66 // | |
67 // Case 2: unittests - client and server in the same process | |
68 // The IPC server will install a mapping as before. The client will search | |
69 // for a mapping and find out. It duplicates the file descriptor and | |
70 // connects. Once the client connects, the server will close the original | |
71 // copy of the client socket and remove the mapping. Thus, when the client | |
72 // object closes, it will close the only remaining copy of the client socket | |
73 // in the fd table and the server will see EOF on its side. | |
74 // | |
75 // TODO(port): a client process cannot connect to multiple IPC channels with | |
76 // this scheme. | |
77 | |
78 class PipeMap { | |
79 public: | |
80 // Lookup a given channel id. Return -1 if not found. | |
81 int Lookup(const std::string& channel_id) { | |
82 AutoLock locked(lock_); | |
83 | |
84 ChannelToFDMap::const_iterator i = map_.find(channel_id); | |
85 if (i == map_.end()) | |
86 return -1; | |
87 return i->second; | |
88 } | |
89 | |
90 // Remove the mapping for the given channel id. No error is signaled if the | |
91 // channel_id doesn't exist | |
92 void RemoveAndClose(const std::string& channel_id) { | |
93 AutoLock locked(lock_); | |
94 | |
95 ChannelToFDMap::iterator i = map_.find(channel_id); | |
96 if (i != map_.end()) { | |
97 HANDLE_EINTR(close(i->second)); | |
98 map_.erase(i); | |
99 } | |
100 } | |
101 | |
102 // Insert a mapping from @channel_id to @fd. It's a fatal error to insert a | |
103 // mapping if one already exists for the given channel_id | |
104 void Insert(const std::string& channel_id, int fd) { | |
105 AutoLock locked(lock_); | |
106 DCHECK(fd != -1); | |
107 | |
108 ChannelToFDMap::const_iterator i = map_.find(channel_id); | |
109 CHECK(i == map_.end()) << "Creating second IPC server (fd " << fd << ") " | |
110 << "for '" << channel_id << "' while first " | |
111 << "(fd " << i->second << ") still exists"; | |
112 map_[channel_id] = fd; | |
113 } | |
114 | |
115 private: | |
116 Lock lock_; | |
117 typedef std::map<std::string, int> ChannelToFDMap; | |
118 ChannelToFDMap map_; | |
119 }; | |
120 | |
121 // Used to map a channel name to the equivalent FD # in the current process. | |
122 // Returns -1 if the channel is unknown. | |
123 int ChannelNameToFD(const std::string& channel_id) { | |
124 // See the large block comment above PipeMap for the reasoning here. | |
125 const int fd = Singleton<PipeMap>()->Lookup(channel_id); | |
126 | |
127 if (fd != -1) { | |
128 int dup_fd = dup(fd); | |
129 if (dup_fd < 0) | |
130 LOG(FATAL) << "dup(" << fd << "): " << strerror(errno); | |
131 return dup_fd; | |
132 } | |
133 | |
134 return fd; | |
135 } | |
136 | |
137 //------------------------------------------------------------------------------ | |
138 sockaddr_un sizecheck; | |
139 const size_t kMaxPipeNameLength = sizeof(sizecheck.sun_path); | |
140 | |
141 // Creates a Fifo with the specified name ready to listen on. | |
142 bool CreateServerFifo(const std::string& pipe_name, int* server_listen_fd) { | |
143 DCHECK(server_listen_fd); | |
144 DCHECK_GT(pipe_name.length(), 0u); | |
145 DCHECK_LT(pipe_name.length(), kMaxPipeNameLength); | |
146 | |
147 if (pipe_name.length() == 0 || pipe_name.length() >= kMaxPipeNameLength) { | |
148 return false; | |
149 } | |
150 | |
151 // Create socket. | |
152 int fd = socket(AF_UNIX, SOCK_STREAM, 0); | |
153 if (fd < 0) { | |
154 return false; | |
155 } | |
156 | |
157 // Make socket non-blocking | |
158 if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) { | |
159 HANDLE_EINTR(close(fd)); | |
160 return false; | |
161 } | |
162 | |
163 // Delete any old FS instances. | |
164 unlink(pipe_name.c_str()); | |
165 | |
166 // Create unix_addr structure | |
167 struct sockaddr_un unix_addr; | |
168 memset(&unix_addr, 0, sizeof(unix_addr)); | |
169 unix_addr.sun_family = AF_UNIX; | |
170 snprintf(unix_addr.sun_path, kMaxPipeNameLength, "%s", pipe_name.c_str()); | |
171 size_t unix_addr_len = offsetof(struct sockaddr_un, sun_path) + | |
172 strlen(unix_addr.sun_path) + 1; | |
173 | |
174 // Bind the socket. | |
175 if (bind(fd, reinterpret_cast<const sockaddr*>(&unix_addr), | |
176 unix_addr_len) != 0) { | |
177 HANDLE_EINTR(close(fd)); | |
178 return false; | |
179 } | |
180 | |
181 // Start listening on the socket. | |
182 const int listen_queue_length = 1; | |
183 if (listen(fd, listen_queue_length) != 0) { | |
184 HANDLE_EINTR(close(fd)); | |
185 return false; | |
186 } | |
187 | |
188 *server_listen_fd = fd; | |
189 return true; | |
190 } | |
191 | |
192 // Accept a connection on a fifo. | |
193 bool ServerAcceptFifoConnection(int server_listen_fd, int* server_socket) { | |
194 DCHECK(server_socket); | |
195 | |
196 int accept_fd = HANDLE_EINTR(accept(server_listen_fd, NULL, 0)); | |
197 if (accept_fd < 0) | |
198 return false; | |
199 if (fcntl(accept_fd, F_SETFL, O_NONBLOCK) == -1) { | |
200 HANDLE_EINTR(close(accept_fd)); | |
201 return false; | |
202 } | |
203 | |
204 *server_socket = accept_fd; | |
205 return true; | |
206 } | |
207 | |
208 bool ClientConnectToFifo(const std::string &pipe_name, int* client_socket) { | |
209 DCHECK(client_socket); | |
210 DCHECK_LT(pipe_name.length(), kMaxPipeNameLength); | |
211 | |
212 // Create socket. | |
213 int fd = socket(AF_UNIX, SOCK_STREAM, 0); | |
214 if (fd < 0) { | |
215 LOG(ERROR) << "fd is invalid"; | |
216 return false; | |
217 } | |
218 | |
219 // Make socket non-blocking | |
220 if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) { | |
221 LOG(ERROR) << "fcntl failed"; | |
222 HANDLE_EINTR(close(fd)); | |
223 return false; | |
224 } | |
225 | |
226 // Create server side of socket. | |
227 struct sockaddr_un server_unix_addr; | |
228 memset(&server_unix_addr, 0, sizeof(server_unix_addr)); | |
229 server_unix_addr.sun_family = AF_UNIX; | |
230 snprintf(server_unix_addr.sun_path, kMaxPipeNameLength, "%s", | |
231 pipe_name.c_str()); | |
232 size_t server_unix_addr_len = offsetof(struct sockaddr_un, sun_path) + | |
233 strlen(server_unix_addr.sun_path) + 1; | |
234 | |
235 if (HANDLE_EINTR(connect(fd, reinterpret_cast<sockaddr*>(&server_unix_addr), | |
236 server_unix_addr_len)) != 0) { | |
237 HANDLE_EINTR(close(fd)); | |
238 return false; | |
239 } | |
240 | |
241 *client_socket = fd; | |
242 return true; | |
243 } | |
244 | |
245 } // namespace | |
246 //------------------------------------------------------------------------------ | |
247 | |
248 Channel::ChannelImpl::ChannelImpl(const std::string& channel_id, Mode mode, | |
249 Listener* listener) | |
250 : mode_(mode), | |
251 is_blocked_on_write_(false), | |
252 message_send_bytes_written_(0), | |
253 uses_fifo_(CommandLine::ForCurrentProcess()->HasSwitch( | |
254 switches::kIPCUseFIFO)), | |
255 server_listen_pipe_(-1), | |
256 pipe_(-1), | |
257 client_pipe_(-1), | |
258 listener_(listener), | |
259 waiting_connect_(true), | |
260 processing_incoming_(false), | |
261 factory_(this) { | |
262 if (!CreatePipe(channel_id, mode)) { | |
263 // The pipe may have been closed already. | |
264 LOG(WARNING) << "Unable to create pipe named \"" << channel_id << | |
265 "\" in " << (mode == MODE_SERVER ? "server" : "client") << | |
266 " mode error(" << strerror(errno) << ")."; | |
267 } | |
268 } | |
269 | |
270 // static | |
271 void AddChannelSocket(const std::string& name, int socket) { | |
272 Singleton<PipeMap>()->Insert(name, socket); | |
273 } | |
274 | |
275 // static | |
276 void RemoveAndCloseChannelSocket(const std::string& name) { | |
277 Singleton<PipeMap>()->RemoveAndClose(name); | |
278 } | |
279 | |
280 // static | |
281 bool SocketPair(int* fd1, int* fd2) { | |
282 int pipe_fds[2]; | |
283 if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipe_fds) != 0) { | |
284 LOG(ERROR) << "socketpair(): " << strerror(errno); | |
285 return false; | |
286 } | |
287 | |
288 // Set both ends to be non-blocking. | |
289 if (fcntl(pipe_fds[0], F_SETFL, O_NONBLOCK) == -1 || | |
290 fcntl(pipe_fds[1], F_SETFL, O_NONBLOCK) == -1) { | |
291 LOG(ERROR) << "fcntl(O_NONBLOCK): " << strerror(errno); | |
292 HANDLE_EINTR(close(pipe_fds[0])); | |
293 HANDLE_EINTR(close(pipe_fds[1])); | |
294 return false; | |
295 } | |
296 | |
297 *fd1 = pipe_fds[0]; | |
298 *fd2 = pipe_fds[1]; | |
299 | |
300 return true; | |
301 } | |
302 | |
303 bool Channel::ChannelImpl::CreatePipe(const std::string& channel_id, | |
304 Mode mode) { | |
305 DCHECK(server_listen_pipe_ == -1 && pipe_ == -1); | |
306 | |
307 if (uses_fifo_) { | |
308 // This only happens in unit tests; see the comment above PipeMap. | |
309 // TODO(playmobil): We shouldn't need to create fifos on disk. | |
310 // TODO(playmobil): If we do, they should be in the user data directory. | |
311 // TODO(playmobil): Cleanup any stale fifos. | |
312 pipe_name_ = "/var/tmp/chrome_" + channel_id; | |
313 if (mode == MODE_SERVER) { | |
314 if (!CreateServerFifo(pipe_name_, &server_listen_pipe_)) { | |
315 return false; | |
316 } | |
317 } else { | |
318 if (!ClientConnectToFifo(pipe_name_, &pipe_)) { | |
319 return false; | |
320 } | |
321 waiting_connect_ = false; | |
322 } | |
323 } else { | |
324 // This is the normal (non-unit-test) case, where we're using sockets. | |
325 // Three possible cases: | |
326 // 1) It's for a channel we already have a pipe for; reuse it. | |
327 // 2) It's the initial IPC channel: | |
328 // 2a) Server side: create the pipe. | |
329 // 2b) Client side: Pull the pipe out of the GlobalDescriptors set. | |
330 pipe_name_ = channel_id; | |
331 pipe_ = ChannelNameToFD(pipe_name_); | |
332 if (pipe_ < 0) { | |
333 // Initial IPC channel. | |
334 if (mode == MODE_SERVER) { | |
335 if (!SocketPair(&pipe_, &client_pipe_)) | |
336 return false; | |
337 AddChannelSocket(pipe_name_, client_pipe_); | |
338 } else { | |
339 pipe_ = Singleton<base::GlobalDescriptors>()->Get(kPrimaryIPCChannel); | |
340 } | |
341 } else { | |
342 waiting_connect_ = false; | |
343 } | |
344 } | |
345 | |
346 // Create the Hello message to be sent when Connect is called | |
347 scoped_ptr<Message> msg(new Message(MSG_ROUTING_NONE, | |
348 HELLO_MESSAGE_TYPE, | |
349 IPC::Message::PRIORITY_NORMAL)); | |
350 if (!msg->WriteInt(base::GetCurrentProcId())) { | |
351 Close(); | |
352 return false; | |
353 } | |
354 | |
355 output_queue_.push(msg.release()); | |
356 return true; | |
357 } | |
358 | |
359 bool Channel::ChannelImpl::Connect() { | |
360 if (mode_ == MODE_SERVER && uses_fifo_) { | |
361 if (server_listen_pipe_ == -1) { | |
362 return false; | |
363 } | |
364 MessageLoopForIO::current()->WatchFileDescriptor( | |
365 server_listen_pipe_, | |
366 true, | |
367 MessageLoopForIO::WATCH_READ, | |
368 &server_listen_connection_watcher_, | |
369 this); | |
370 } else { | |
371 if (pipe_ == -1) { | |
372 return false; | |
373 } | |
374 MessageLoopForIO::current()->WatchFileDescriptor( | |
375 pipe_, | |
376 true, | |
377 MessageLoopForIO::WATCH_READ, | |
378 &read_watcher_, | |
379 this); | |
380 waiting_connect_ = false; | |
381 } | |
382 | |
383 if (!waiting_connect_) | |
384 return ProcessOutgoingMessages(); | |
385 return true; | |
386 } | |
387 | |
388 bool Channel::ChannelImpl::ProcessIncomingMessages() { | |
389 ssize_t bytes_read = 0; | |
390 | |
391 struct msghdr msg = {0}; | |
392 struct iovec iov = {input_buf_, Channel::kReadBufferSize}; | |
393 | |
394 msg.msg_iov = &iov; | |
395 msg.msg_iovlen = 1; | |
396 msg.msg_control = input_cmsg_buf_; | |
397 | |
398 for (;;) { | |
399 msg.msg_controllen = sizeof(input_cmsg_buf_); | |
400 | |
401 if (bytes_read == 0) { | |
402 if (pipe_ == -1) | |
403 return false; | |
404 | |
405 // Read from pipe. | |
406 // recvmsg() returns 0 if the connection has closed or EAGAIN if no data | |
407 // is waiting on the pipe. | |
408 bytes_read = HANDLE_EINTR(recvmsg(pipe_, &msg, MSG_DONTWAIT)); | |
409 | |
410 if (bytes_read < 0) { | |
411 if (errno == EAGAIN) { | |
412 return true; | |
413 #if defined(OS_MACOSX) | |
414 } else if (errno == EPERM) { | |
415 // On OSX, reading from a pipe with no listener returns EPERM | |
416 // treat this as a special case to prevent spurious error messages | |
417 // to the console. | |
418 return false; | |
419 #endif // defined(OS_MACOSX) | |
420 } else { | |
421 LOG(ERROR) << "pipe error (" << pipe_ << "): " << strerror(errno); | |
422 return false; | |
423 } | |
424 } else if (bytes_read == 0) { | |
425 // The pipe has closed... | |
426 Close(); | |
427 return false; | |
428 } | |
429 } | |
430 DCHECK(bytes_read); | |
431 | |
432 if (client_pipe_ != -1) { | |
433 Singleton<PipeMap>()->RemoveAndClose(pipe_name_); | |
434 client_pipe_ = -1; | |
435 } | |
436 | |
437 // a pointer to an array of |num_wire_fds| file descriptors from the read | |
438 const int* wire_fds = NULL; | |
439 unsigned num_wire_fds = 0; | |
440 | |
441 // walk the list of control messages and, if we find an array of file | |
442 // descriptors, save a pointer to the array | |
443 | |
444 // This next if statement is to work around an OSX issue where | |
445 // CMSG_FIRSTHDR will return non-NULL in the case that controllen == 0. | |
446 // Here's a test case: | |
447 // | |
448 // int main() { | |
449 // struct msghdr msg; | |
450 // msg.msg_control = &msg; | |
451 // msg.msg_controllen = 0; | |
452 // if (CMSG_FIRSTHDR(&msg)) | |
453 // printf("Bug found!\n"); | |
454 // } | |
455 if (msg.msg_controllen > 0) { | |
456 // On OSX, CMSG_FIRSTHDR doesn't handle the case where controllen is 0 | |
457 // and will return a pointer into nowhere. | |
458 for (struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); cmsg; | |
459 cmsg = CMSG_NXTHDR(&msg, cmsg)) { | |
460 if (cmsg->cmsg_level == SOL_SOCKET && | |
461 cmsg->cmsg_type == SCM_RIGHTS) { | |
462 const unsigned payload_len = cmsg->cmsg_len - CMSG_LEN(0); | |
463 DCHECK(payload_len % sizeof(int) == 0); | |
464 wire_fds = reinterpret_cast<int*>(CMSG_DATA(cmsg)); | |
465 num_wire_fds = payload_len / 4; | |
466 | |
467 if (msg.msg_flags & MSG_CTRUNC) { | |
468 LOG(ERROR) << "SCM_RIGHTS message was truncated" | |
469 << " cmsg_len:" << cmsg->cmsg_len | |
470 << " fd:" << pipe_; | |
471 for (unsigned i = 0; i < num_wire_fds; ++i) | |
472 HANDLE_EINTR(close(wire_fds[i])); | |
473 return false; | |
474 } | |
475 break; | |
476 } | |
477 } | |
478 } | |
479 | |
480 // Process messages from input buffer. | |
481 const char *p; | |
482 const char *end; | |
483 if (input_overflow_buf_.empty()) { | |
484 p = input_buf_; | |
485 end = p + bytes_read; | |
486 } else { | |
487 if (input_overflow_buf_.size() > | |
488 static_cast<size_t>(kMaximumMessageSize - bytes_read)) { | |
489 input_overflow_buf_.clear(); | |
490 LOG(ERROR) << "IPC message is too big"; | |
491 return false; | |
492 } | |
493 input_overflow_buf_.append(input_buf_, bytes_read); | |
494 p = input_overflow_buf_.data(); | |
495 end = p + input_overflow_buf_.size(); | |
496 } | |
497 | |
498 // A pointer to an array of |num_fds| file descriptors which includes any | |
499 // fds that have spilled over from a previous read. | |
500 const int* fds; | |
501 unsigned num_fds; | |
502 unsigned fds_i = 0; // the index of the first unused descriptor | |
503 | |
504 if (input_overflow_fds_.empty()) { | |
505 fds = wire_fds; | |
506 num_fds = num_wire_fds; | |
507 } else { | |
508 const size_t prev_size = input_overflow_fds_.size(); | |
509 input_overflow_fds_.resize(prev_size + num_wire_fds); | |
510 memcpy(&input_overflow_fds_[prev_size], wire_fds, | |
511 num_wire_fds * sizeof(int)); | |
512 fds = &input_overflow_fds_[0]; | |
513 num_fds = input_overflow_fds_.size(); | |
514 } | |
515 | |
516 while (p < end) { | |
517 const char* message_tail = Message::FindNext(p, end); | |
518 if (message_tail) { | |
519 int len = static_cast<int>(message_tail - p); | |
520 Message m(p, len); | |
521 if (m.header()->num_fds) { | |
522 // the message has file descriptors | |
523 const char* error = NULL; | |
524 if (m.header()->num_fds > num_fds - fds_i) { | |
525 // the message has been completely received, but we didn't get | |
526 // enough file descriptors. | |
527 error = "Message needs unreceived descriptors"; | |
528 } | |
529 | |
530 if (m.header()->num_fds > | |
531 FileDescriptorSet::MAX_DESCRIPTORS_PER_MESSAGE) { | |
532 // There are too many descriptors in this message | |
533 error = "Message requires an excessive number of descriptors"; | |
534 } | |
535 | |
536 if (error) { | |
537 LOG(WARNING) << error | |
538 << " channel:" << this | |
539 << " message-type:" << m.type() | |
540 << " header()->num_fds:" << m.header()->num_fds | |
541 << " num_fds:" << num_fds | |
542 << " fds_i:" << fds_i; | |
543 // close the existing file descriptors so that we don't leak them | |
544 for (unsigned i = fds_i; i < num_fds; ++i) | |
545 HANDLE_EINTR(close(fds[i])); | |
546 input_overflow_fds_.clear(); | |
547 // abort the connection | |
548 return false; | |
549 } | |
550 | |
551 m.file_descriptor_set()->SetDescriptors( | |
552 &fds[fds_i], m.header()->num_fds); | |
553 fds_i += m.header()->num_fds; | |
554 } | |
555 #ifdef IPC_MESSAGE_DEBUG_EXTRA | |
556 DLOG(INFO) << "received message on channel @" << this << | |
557 " with type " << m.type(); | |
558 #endif | |
559 if (m.routing_id() == MSG_ROUTING_NONE && | |
560 m.type() == HELLO_MESSAGE_TYPE) { | |
561 // The Hello message contains only the process id. | |
562 listener_->OnChannelConnected(MessageIterator(m).NextInt()); | |
563 } else { | |
564 listener_->OnMessageReceived(m); | |
565 } | |
566 p = message_tail; | |
567 } else { | |
568 // Last message is partial. | |
569 break; | |
570 } | |
571 } | |
572 input_overflow_buf_.assign(p, end - p); | |
573 input_overflow_fds_ = std::vector<int>(&fds[fds_i], &fds[num_fds]); | |
574 | |
575 // When the input data buffer is empty, the overflow fds should be too. If | |
576 // this is not the case, we probably have a rogue renderer which is trying | |
577 // to fill our descriptor table. | |
578 if (input_overflow_buf_.empty() && !input_overflow_fds_.empty()) { | |
579 // We close these descriptors in Close() | |
580 return false; | |
581 } | |
582 | |
583 bytes_read = 0; // Get more data. | |
584 } | |
585 | |
586 return true; | |
587 } | |
588 | |
589 bool Channel::ChannelImpl::ProcessOutgoingMessages() { | |
590 DCHECK(!waiting_connect_); // Why are we trying to send messages if there's | |
591 // no connection? | |
592 is_blocked_on_write_ = false; | |
593 | |
594 if (output_queue_.empty()) | |
595 return true; | |
596 | |
597 if (pipe_ == -1) | |
598 return false; | |
599 | |
600 // Write out all the messages we can till the write blocks or there are no | |
601 // more outgoing messages. | |
602 while (!output_queue_.empty()) { | |
603 Message* msg = output_queue_.front(); | |
604 | |
605 size_t amt_to_write = msg->size() - message_send_bytes_written_; | |
606 DCHECK(amt_to_write != 0); | |
607 const char *out_bytes = reinterpret_cast<const char*>(msg->data()) + | |
608 message_send_bytes_written_; | |
609 | |
610 struct msghdr msgh = {0}; | |
611 struct iovec iov = {const_cast<char*>(out_bytes), amt_to_write}; | |
612 msgh.msg_iov = &iov; | |
613 msgh.msg_iovlen = 1; | |
614 char buf[CMSG_SPACE( | |
615 sizeof(int[FileDescriptorSet::MAX_DESCRIPTORS_PER_MESSAGE]))]; | |
616 | |
617 if (message_send_bytes_written_ == 0 && | |
618 !msg->file_descriptor_set()->empty()) { | |
619 // This is the first chunk of a message which has descriptors to send | |
620 struct cmsghdr *cmsg; | |
621 const unsigned num_fds = msg->file_descriptor_set()->size(); | |
622 | |
623 DCHECK_LE(num_fds, FileDescriptorSet::MAX_DESCRIPTORS_PER_MESSAGE); | |
624 | |
625 msgh.msg_control = buf; | |
626 msgh.msg_controllen = CMSG_SPACE(sizeof(int) * num_fds); | |
627 cmsg = CMSG_FIRSTHDR(&msgh); | |
628 cmsg->cmsg_level = SOL_SOCKET; | |
629 cmsg->cmsg_type = SCM_RIGHTS; | |
630 cmsg->cmsg_len = CMSG_LEN(sizeof(int) * num_fds); | |
631 msg->file_descriptor_set()->GetDescriptors( | |
632 reinterpret_cast<int*>(CMSG_DATA(cmsg))); | |
633 msgh.msg_controllen = cmsg->cmsg_len; | |
634 | |
635 msg->header()->num_fds = num_fds; | |
636 } | |
637 | |
638 ssize_t bytes_written = HANDLE_EINTR(sendmsg(pipe_, &msgh, MSG_DONTWAIT)); | |
639 if (bytes_written > 0) | |
640 msg->file_descriptor_set()->CommitAll(); | |
641 | |
642 if (bytes_written < 0 && errno != EAGAIN) { | |
643 #if defined(OS_MACOSX) | |
644 // On OSX writing to a pipe with no listener returns EPERM. | |
645 if (errno == EPERM) { | |
646 Close(); | |
647 return false; | |
648 } | |
649 #endif // OS_MACOSX | |
650 LOG(ERROR) << "pipe error on " << pipe_ << ": " << strerror(errno); | |
651 return false; | |
652 } | |
653 | |
654 if (static_cast<size_t>(bytes_written) != amt_to_write) { | |
655 if (bytes_written > 0) { | |
656 // If write() fails with EAGAIN then bytes_written will be -1. | |
657 message_send_bytes_written_ += bytes_written; | |
658 } | |
659 | |
660 // Tell libevent to call us back once things are unblocked. | |
661 is_blocked_on_write_ = true; | |
662 MessageLoopForIO::current()->WatchFileDescriptor( | |
663 pipe_, | |
664 false, // One shot | |
665 MessageLoopForIO::WATCH_WRITE, | |
666 &write_watcher_, | |
667 this); | |
668 return true; | |
669 } else { | |
670 message_send_bytes_written_ = 0; | |
671 | |
672 // Message sent OK! | |
673 #ifdef IPC_MESSAGE_DEBUG_EXTRA | |
674 DLOG(INFO) << "sent message @" << msg << " on channel @" << this << | |
675 " with type " << msg->type(); | |
676 #endif | |
677 output_queue_.pop(); | |
678 delete msg; | |
679 } | |
680 } | |
681 return true; | |
682 } | |
683 | |
684 bool Channel::ChannelImpl::Send(Message* message) { | |
685 chrome::Counters::ipc_send_counter().Increment(); | |
686 #ifdef IPC_MESSAGE_DEBUG_EXTRA | |
687 DLOG(INFO) << "sending message @" << message << " on channel @" << this | |
688 << " with type " << message->type() | |
689 << " (" << output_queue_.size() << " in queue)"; | |
690 #endif | |
691 | |
692 #ifdef IPC_MESSAGE_LOG_ENABLED | |
693 Logging::current()->OnSendMessage(message, ""); | |
694 #endif | |
695 | |
696 output_queue_.push(message); | |
697 if (!waiting_connect_) { | |
698 if (!is_blocked_on_write_) { | |
699 if (!ProcessOutgoingMessages()) | |
700 return false; | |
701 } | |
702 } | |
703 | |
704 return true; | |
705 } | |
706 | |
707 int Channel::ChannelImpl::GetClientFileDescriptor() const { | |
708 return client_pipe_; | |
709 } | |
710 | |
711 // Called by libevent when we can read from th pipe without blocking. | |
712 void Channel::ChannelImpl::OnFileCanReadWithoutBlocking(int fd) { | |
713 bool send_server_hello_msg = false; | |
714 if (waiting_connect_ && mode_ == MODE_SERVER) { | |
715 // In the case of a socketpair() the server starts listening on its end | |
716 // of the pipe in Connect(). | |
717 DCHECK(uses_fifo_); | |
718 | |
719 if (!ServerAcceptFifoConnection(server_listen_pipe_, &pipe_)) { | |
720 Close(); | |
721 } | |
722 | |
723 // No need to watch the listening socket any longer since only one client | |
724 // can connect. So unregister with libevent. | |
725 server_listen_connection_watcher_.StopWatchingFileDescriptor(); | |
726 | |
727 // Start watching our end of the socket. | |
728 MessageLoopForIO::current()->WatchFileDescriptor( | |
729 pipe_, | |
730 true, | |
731 MessageLoopForIO::WATCH_READ, | |
732 &read_watcher_, | |
733 this); | |
734 | |
735 waiting_connect_ = false; | |
736 send_server_hello_msg = true; | |
737 } | |
738 | |
739 if (!waiting_connect_ && fd == pipe_) { | |
740 if (!ProcessIncomingMessages()) { | |
741 Close(); | |
742 listener_->OnChannelError(); | |
743 } | |
744 } | |
745 | |
746 // If we're a server and handshaking, then we want to make sure that we | |
747 // only send our handshake message after we've processed the client's. | |
748 // This gives us a chance to kill the client if the incoming handshake | |
749 // is invalid. | |
750 if (send_server_hello_msg) { | |
751 // This should be our first write so there's no chance we can block here... | |
752 DCHECK(is_blocked_on_write_ == false); | |
753 ProcessOutgoingMessages(); | |
754 } | |
755 } | |
756 | |
757 // Called by libevent when we can write to the pipe without blocking. | |
758 void Channel::ChannelImpl::OnFileCanWriteWithoutBlocking(int fd) { | |
759 if (!ProcessOutgoingMessages()) { | |
760 Close(); | |
761 listener_->OnChannelError(); | |
762 } | |
763 } | |
764 | |
765 void Channel::ChannelImpl::Close() { | |
766 // Close can be called multiple time, so we need to make sure we're | |
767 // idempotent. | |
768 | |
769 // Unregister libevent for the listening socket and close it. | |
770 server_listen_connection_watcher_.StopWatchingFileDescriptor(); | |
771 | |
772 if (server_listen_pipe_ != -1) { | |
773 HANDLE_EINTR(close(server_listen_pipe_)); | |
774 server_listen_pipe_ = -1; | |
775 } | |
776 | |
777 // Unregister libevent for the FIFO and close it. | |
778 read_watcher_.StopWatchingFileDescriptor(); | |
779 write_watcher_.StopWatchingFileDescriptor(); | |
780 if (pipe_ != -1) { | |
781 HANDLE_EINTR(close(pipe_)); | |
782 pipe_ = -1; | |
783 } | |
784 if (client_pipe_ != -1) { | |
785 Singleton<PipeMap>()->RemoveAndClose(pipe_name_); | |
786 client_pipe_ = -1; | |
787 } | |
788 | |
789 if (uses_fifo_) { | |
790 // Unlink the FIFO | |
791 unlink(pipe_name_.c_str()); | |
792 } | |
793 | |
794 while (!output_queue_.empty()) { | |
795 Message* m = output_queue_.front(); | |
796 output_queue_.pop(); | |
797 delete m; | |
798 } | |
799 | |
800 // Close any outstanding, received file descriptors | |
801 for (std::vector<int>::iterator | |
802 i = input_overflow_fds_.begin(); i != input_overflow_fds_.end(); ++i) { | |
803 HANDLE_EINTR(close(*i)); | |
804 } | |
805 input_overflow_fds_.clear(); | |
806 } | |
807 | |
808 //------------------------------------------------------------------------------ | |
809 // Channel's methods simply call through to ChannelImpl. | |
810 Channel::Channel(const std::string& channel_id, Mode mode, | |
811 Listener* listener) | |
812 : channel_impl_(new ChannelImpl(channel_id, mode, listener)) { | |
813 } | |
814 | |
815 Channel::~Channel() { | |
816 delete channel_impl_; | |
817 } | |
818 | |
819 bool Channel::Connect() { | |
820 return channel_impl_->Connect(); | |
821 } | |
822 | |
823 void Channel::Close() { | |
824 channel_impl_->Close(); | |
825 } | |
826 | |
827 void Channel::set_listener(Listener* listener) { | |
828 channel_impl_->set_listener(listener); | |
829 } | |
830 | |
831 bool Channel::Send(Message* message) { | |
832 return channel_impl_->Send(message); | |
833 } | |
834 | |
835 int Channel::GetClientFileDescriptor() const { | |
836 return channel_impl_->GetClientFileDescriptor(); | |
837 } | |
838 | |
839 } // namespace IPC | |
OLD | NEW |