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