Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(20)

Side by Side Diff: ipc/ipc_channel_posix.cc

Issue 310293002: Make IPC::Channel polymorphic (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Another attempt to fix build breakage Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ipc/ipc_channel_posix.h ('k') | ipc/ipc_channel_posix_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 #include "ipc/ipc_channel_posix.h" 5 #include "ipc/ipc_channel_posix.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <fcntl.h> 8 #include <fcntl.h>
9 #include <stddef.h> 9 #include <stddef.h>
10 #include <sys/socket.h> 10 #include <sys/socket.h>
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
167 // When we fork for simple tests on Android, we can't 'exec', so we need to 167 // When we fork for simple tests on Android, we can't 'exec', so we need to
168 // reset these entries manually to get the expected testing behavior. 168 // reset these entries manually to get the expected testing behavior.
169 void Channel::NotifyProcessForkedForTesting() { 169 void Channel::NotifyProcessForkedForTesting() {
170 PipeMap::GetInstance()->map_.clear(); 170 PipeMap::GetInstance()->map_.clear();
171 } 171 }
172 #endif 172 #endif
173 173
174 //------------------------------------------------------------------------------ 174 //------------------------------------------------------------------------------
175 175
176 #if defined(OS_LINUX) 176 #if defined(OS_LINUX)
177 int Channel::ChannelImpl::global_pid_ = 0; 177 int ChannelPosix::global_pid_ = 0;
178 #endif // OS_LINUX 178 #endif // OS_LINUX
179 179
180 Channel::ChannelImpl::ChannelImpl(const IPC::ChannelHandle& channel_handle, 180 ChannelPosix::ChannelPosix(const IPC::ChannelHandle& channel_handle,
181 Mode mode, Listener* listener) 181 Mode mode, Listener* listener)
182 : ChannelReader(listener), 182 : ChannelReader(listener),
183 mode_(mode), 183 mode_(mode),
184 peer_pid_(base::kNullProcessId), 184 peer_pid_(base::kNullProcessId),
185 is_blocked_on_write_(false), 185 is_blocked_on_write_(false),
186 waiting_connect_(true), 186 waiting_connect_(true),
187 message_send_bytes_written_(0), 187 message_send_bytes_written_(0),
188 server_listen_pipe_(-1), 188 server_listen_pipe_(-1),
189 pipe_(-1), 189 pipe_(-1),
190 client_pipe_(-1), 190 client_pipe_(-1),
191 #if defined(IPC_USES_READWRITE) 191 #if defined(IPC_USES_READWRITE)
192 fd_pipe_(-1), 192 fd_pipe_(-1),
193 remote_fd_pipe_(-1), 193 remote_fd_pipe_(-1),
194 #endif // IPC_USES_READWRITE 194 #endif // IPC_USES_READWRITE
195 pipe_name_(channel_handle.name), 195 pipe_name_(channel_handle.name),
196 must_unlink_(false) { 196 must_unlink_(false) {
197 memset(input_cmsg_buf_, 0, sizeof(input_cmsg_buf_)); 197 memset(input_cmsg_buf_, 0, sizeof(input_cmsg_buf_));
198 if (!CreatePipe(channel_handle)) { 198 if (!CreatePipe(channel_handle)) {
199 // The pipe may have been closed already. 199 // The pipe may have been closed already.
200 const char *modestr = (mode_ & MODE_SERVER_FLAG) ? "server" : "client"; 200 const char *modestr = (mode_ & MODE_SERVER_FLAG) ? "server" : "client";
201 LOG(WARNING) << "Unable to create pipe named \"" << channel_handle.name 201 LOG(WARNING) << "Unable to create pipe named \"" << channel_handle.name
202 << "\" in " << modestr << " mode"; 202 << "\" in " << modestr << " mode";
203 } 203 }
204 } 204 }
205 205
206 Channel::ChannelImpl::~ChannelImpl() { 206 ChannelPosix::~ChannelPosix() {
207 Close(); 207 Close();
208 } 208 }
209 209
210 bool SocketPair(int* fd1, int* fd2) { 210 bool SocketPair(int* fd1, int* fd2) {
211 int pipe_fds[2]; 211 int pipe_fds[2];
212 if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipe_fds) != 0) { 212 if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipe_fds) != 0) {
213 PLOG(ERROR) << "socketpair()"; 213 PLOG(ERROR) << "socketpair()";
214 return false; 214 return false;
215 } 215 }
216 216
217 // Set both ends to be non-blocking. 217 // Set both ends to be non-blocking.
218 if (fcntl(pipe_fds[0], F_SETFL, O_NONBLOCK) == -1 || 218 if (fcntl(pipe_fds[0], F_SETFL, O_NONBLOCK) == -1 ||
219 fcntl(pipe_fds[1], F_SETFL, O_NONBLOCK) == -1) { 219 fcntl(pipe_fds[1], F_SETFL, O_NONBLOCK) == -1) {
220 PLOG(ERROR) << "fcntl(O_NONBLOCK)"; 220 PLOG(ERROR) << "fcntl(O_NONBLOCK)";
221 if (IGNORE_EINTR(close(pipe_fds[0])) < 0) 221 if (IGNORE_EINTR(close(pipe_fds[0])) < 0)
222 PLOG(ERROR) << "close"; 222 PLOG(ERROR) << "close";
223 if (IGNORE_EINTR(close(pipe_fds[1])) < 0) 223 if (IGNORE_EINTR(close(pipe_fds[1])) < 0)
224 PLOG(ERROR) << "close"; 224 PLOG(ERROR) << "close";
225 return false; 225 return false;
226 } 226 }
227 227
228 *fd1 = pipe_fds[0]; 228 *fd1 = pipe_fds[0];
229 *fd2 = pipe_fds[1]; 229 *fd2 = pipe_fds[1];
230 230
231 return true; 231 return true;
232 } 232 }
233 233
234 bool Channel::ChannelImpl::CreatePipe( 234 bool ChannelPosix::CreatePipe(
235 const IPC::ChannelHandle& channel_handle) { 235 const IPC::ChannelHandle& channel_handle) {
236 DCHECK(server_listen_pipe_ == -1 && pipe_ == -1); 236 DCHECK(server_listen_pipe_ == -1 && pipe_ == -1);
237 237
238 // Four possible cases: 238 // Four possible cases:
239 // 1) It's a channel wrapping a pipe that is given to us. 239 // 1) It's a channel wrapping a pipe that is given to us.
240 // 2) It's for a named channel, so we create it. 240 // 2) It's for a named channel, so we create it.
241 // 3) It's for a client that we implement ourself. This is used 241 // 3) It's for a client that we implement ourself. This is used
242 // in single-process unittesting. 242 // in single-process unittesting.
243 // 4) It's the initial IPC channel: 243 // 4) It's the initial IPC channel:
244 // 4a) Client side: Pull the pipe out of the GlobalDescriptors set. 244 // 4a) Client side: Pull the pipe out of the GlobalDescriptors set.
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
330 330
331 if ((mode_ & MODE_SERVER_FLAG) && (mode_ & MODE_NAMED_FLAG)) { 331 if ((mode_ & MODE_SERVER_FLAG) && (mode_ & MODE_NAMED_FLAG)) {
332 server_listen_pipe_ = local_pipe; 332 server_listen_pipe_ = local_pipe;
333 local_pipe = -1; 333 local_pipe = -1;
334 } 334 }
335 335
336 pipe_ = local_pipe; 336 pipe_ = local_pipe;
337 return true; 337 return true;
338 } 338 }
339 339
340 bool Channel::ChannelImpl::Connect() { 340 bool ChannelPosix::Connect() {
341 if (server_listen_pipe_ == -1 && pipe_ == -1) { 341 if (server_listen_pipe_ == -1 && pipe_ == -1) {
342 DLOG(WARNING) << "Channel creation failed: " << pipe_name_; 342 DLOG(WARNING) << "Channel creation failed: " << pipe_name_;
343 return false; 343 return false;
344 } 344 }
345 345
346 bool did_connect = true; 346 bool did_connect = true;
347 if (server_listen_pipe_ != -1) { 347 if (server_listen_pipe_ != -1) {
348 // Watch the pipe for connections, and turn any connections into 348 // Watch the pipe for connections, and turn any connections into
349 // active sockets. 349 // active sockets.
350 base::MessageLoopForIO::current()->WatchFileDescriptor( 350 base::MessageLoopForIO::current()->WatchFileDescriptor(
351 server_listen_pipe_, 351 server_listen_pipe_,
352 true, 352 true,
353 base::MessageLoopForIO::WATCH_READ, 353 base::MessageLoopForIO::WATCH_READ,
354 &server_listen_connection_watcher_, 354 &server_listen_connection_watcher_,
355 this); 355 this);
356 } else { 356 } else {
357 did_connect = AcceptConnection(); 357 did_connect = AcceptConnection();
358 } 358 }
359 return did_connect; 359 return did_connect;
360 } 360 }
361 361
362 void Channel::ChannelImpl::CloseFileDescriptors(Message* msg) { 362 void ChannelPosix::CloseFileDescriptors(Message* msg) {
363 #if defined(OS_MACOSX) 363 #if defined(OS_MACOSX)
364 // There is a bug on OSX which makes it dangerous to close 364 // There is a bug on OSX which makes it dangerous to close
365 // a file descriptor while it is in transit. So instead we 365 // a file descriptor while it is in transit. So instead we
366 // store the file descriptor in a set and send a message to 366 // store the file descriptor in a set and send a message to
367 // the recipient, which is queued AFTER the message that 367 // the recipient, which is queued AFTER the message that
368 // sent the FD. The recipient will reply to the message, 368 // sent the FD. The recipient will reply to the message,
369 // letting us know that it is now safe to close the file 369 // letting us know that it is now safe to close the file
370 // descriptor. For more information, see: 370 // descriptor. For more information, see:
371 // http://crbug.com/298276 371 // http://crbug.com/298276
372 std::vector<int> to_close; 372 std::vector<int> to_close;
373 msg->file_descriptor_set()->ReleaseFDsToClose(&to_close); 373 msg->file_descriptor_set()->ReleaseFDsToClose(&to_close);
374 for (size_t i = 0; i < to_close.size(); i++) { 374 for (size_t i = 0; i < to_close.size(); i++) {
375 fds_to_close_.insert(to_close[i]); 375 fds_to_close_.insert(to_close[i]);
376 QueueCloseFDMessage(to_close[i], 2); 376 QueueCloseFDMessage(to_close[i], 2);
377 } 377 }
378 #else 378 #else
379 msg->file_descriptor_set()->CommitAll(); 379 msg->file_descriptor_set()->CommitAll();
380 #endif 380 #endif
381 } 381 }
382 382
383 bool Channel::ChannelImpl::ProcessOutgoingMessages() { 383 bool ChannelPosix::ProcessOutgoingMessages() {
384 DCHECK(!waiting_connect_); // Why are we trying to send messages if there's 384 DCHECK(!waiting_connect_); // Why are we trying to send messages if there's
385 // no connection? 385 // no connection?
386 if (output_queue_.empty()) 386 if (output_queue_.empty())
387 return true; 387 return true;
388 388
389 if (pipe_ == -1) 389 if (pipe_ == -1)
390 return false; 390 return false;
391 391
392 // Write out all the messages we can till the write blocks or there are no 392 // Write out all the messages we can till the write blocks or there are no
393 // more outgoing messages. 393 // more outgoing messages.
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
519 // Message sent OK! 519 // Message sent OK!
520 DVLOG(2) << "sent message @" << msg << " on channel @" << this 520 DVLOG(2) << "sent message @" << msg << " on channel @" << this
521 << " with type " << msg->type() << " on fd " << pipe_; 521 << " with type " << msg->type() << " on fd " << pipe_;
522 delete output_queue_.front(); 522 delete output_queue_.front();
523 output_queue_.pop(); 523 output_queue_.pop();
524 } 524 }
525 } 525 }
526 return true; 526 return true;
527 } 527 }
528 528
529 bool Channel::ChannelImpl::Send(Message* message) { 529 bool ChannelPosix::Send(Message* message) {
530 DVLOG(2) << "sending message @" << message << " on channel @" << this 530 DVLOG(2) << "sending message @" << message << " on channel @" << this
531 << " with type " << message->type() 531 << " with type " << message->type()
532 << " (" << output_queue_.size() << " in queue)"; 532 << " (" << output_queue_.size() << " in queue)";
533 533
534 #ifdef IPC_MESSAGE_LOG_ENABLED 534 #ifdef IPC_MESSAGE_LOG_ENABLED
535 Logging::GetInstance()->OnSendMessage(message, ""); 535 Logging::GetInstance()->OnSendMessage(message, "");
536 #endif // IPC_MESSAGE_LOG_ENABLED 536 #endif // IPC_MESSAGE_LOG_ENABLED
537 537
538 message->TraceMessageBegin(); 538 message->TraceMessageBegin();
539 output_queue_.push(message); 539 output_queue_.push(message);
540 if (!is_blocked_on_write_ && !waiting_connect_) { 540 if (!is_blocked_on_write_ && !waiting_connect_) {
541 return ProcessOutgoingMessages(); 541 return ProcessOutgoingMessages();
542 } 542 }
543 543
544 return true; 544 return true;
545 } 545 }
546 546
547 int Channel::ChannelImpl::GetClientFileDescriptor() { 547 int ChannelPosix::GetClientFileDescriptor() const {
548 base::AutoLock lock(client_pipe_lock_); 548 base::AutoLock lock(client_pipe_lock_);
549 return client_pipe_; 549 return client_pipe_;
550 } 550 }
551 551
552 int Channel::ChannelImpl::TakeClientFileDescriptor() { 552 int ChannelPosix::TakeClientFileDescriptor() {
553 base::AutoLock lock(client_pipe_lock_); 553 base::AutoLock lock(client_pipe_lock_);
554 int fd = client_pipe_; 554 int fd = client_pipe_;
555 if (client_pipe_ != -1) { 555 if (client_pipe_ != -1) {
556 PipeMap::GetInstance()->Remove(pipe_name_); 556 PipeMap::GetInstance()->Remove(pipe_name_);
557 client_pipe_ = -1; 557 client_pipe_ = -1;
558 } 558 }
559 return fd; 559 return fd;
560 } 560 }
561 561
562 void Channel::ChannelImpl::CloseClientFileDescriptor() { 562 void ChannelPosix::CloseClientFileDescriptor() {
563 base::AutoLock lock(client_pipe_lock_); 563 base::AutoLock lock(client_pipe_lock_);
564 if (client_pipe_ != -1) { 564 if (client_pipe_ != -1) {
565 PipeMap::GetInstance()->Remove(pipe_name_); 565 PipeMap::GetInstance()->Remove(pipe_name_);
566 if (IGNORE_EINTR(close(client_pipe_)) < 0) 566 if (IGNORE_EINTR(close(client_pipe_)) < 0)
567 PLOG(ERROR) << "close " << pipe_name_; 567 PLOG(ERROR) << "close " << pipe_name_;
568 client_pipe_ = -1; 568 client_pipe_ = -1;
569 } 569 }
570 } 570 }
571 571
572 bool Channel::ChannelImpl::AcceptsConnections() const { 572 bool ChannelPosix::AcceptsConnections() const {
573 return server_listen_pipe_ != -1; 573 return server_listen_pipe_ != -1;
574 } 574 }
575 575
576 bool Channel::ChannelImpl::HasAcceptedConnection() const { 576 bool ChannelPosix::HasAcceptedConnection() const {
577 return AcceptsConnections() && pipe_ != -1; 577 return AcceptsConnections() && pipe_ != -1;
578 } 578 }
579 579
580 bool Channel::ChannelImpl::GetPeerEuid(uid_t* peer_euid) const { 580 bool ChannelPosix::GetPeerEuid(uid_t* peer_euid) const {
581 DCHECK(!(mode_ & MODE_SERVER) || HasAcceptedConnection()); 581 DCHECK(!(mode_ & MODE_SERVER) || HasAcceptedConnection());
582 return IPC::GetPeerEuid(pipe_, peer_euid); 582 return IPC::GetPeerEuid(pipe_, peer_euid);
583 } 583 }
584 584
585 void Channel::ChannelImpl::ResetToAcceptingConnectionState() { 585 void ChannelPosix::ResetToAcceptingConnectionState() {
586 // Unregister libevent for the unix domain socket and close it. 586 // Unregister libevent for the unix domain socket and close it.
587 read_watcher_.StopWatchingFileDescriptor(); 587 read_watcher_.StopWatchingFileDescriptor();
588 write_watcher_.StopWatchingFileDescriptor(); 588 write_watcher_.StopWatchingFileDescriptor();
589 if (pipe_ != -1) { 589 if (pipe_ != -1) {
590 if (IGNORE_EINTR(close(pipe_)) < 0) 590 if (IGNORE_EINTR(close(pipe_)) < 0)
591 PLOG(ERROR) << "close pipe_ " << pipe_name_; 591 PLOG(ERROR) << "close pipe_ " << pipe_name_;
592 pipe_ = -1; 592 pipe_ = -1;
593 } 593 }
594 #if defined(IPC_USES_READWRITE) 594 #if defined(IPC_USES_READWRITE)
595 if (fd_pipe_ != -1) { 595 if (fd_pipe_ != -1) {
(...skipping 23 matching lines...) Expand all
619 i != fds_to_close_.end(); 619 i != fds_to_close_.end();
620 ++i) { 620 ++i) {
621 if (IGNORE_EINTR(close(*i)) < 0) 621 if (IGNORE_EINTR(close(*i)) < 0)
622 PLOG(ERROR) << "close"; 622 PLOG(ERROR) << "close";
623 } 623 }
624 fds_to_close_.clear(); 624 fds_to_close_.clear();
625 #endif 625 #endif
626 } 626 }
627 627
628 // static 628 // static
629 bool Channel::ChannelImpl::IsNamedServerInitialized( 629 bool ChannelPosix::IsNamedServerInitialized(
630 const std::string& channel_id) { 630 const std::string& channel_id) {
631 return base::PathExists(base::FilePath(channel_id)); 631 return base::PathExists(base::FilePath(channel_id));
632 } 632 }
633 633
634 #if defined(OS_LINUX) 634 #if defined(OS_LINUX)
635 // static 635 // static
636 void Channel::ChannelImpl::SetGlobalPid(int pid) { 636 void ChannelPosix::SetGlobalPid(int pid) {
637 global_pid_ = pid; 637 global_pid_ = pid;
638 } 638 }
639 #endif // OS_LINUX 639 #endif // OS_LINUX
640 640
641 // Called by libevent when we can read from the pipe without blocking. 641 // Called by libevent when we can read from the pipe without blocking.
642 void Channel::ChannelImpl::OnFileCanReadWithoutBlocking(int fd) { 642 void ChannelPosix::OnFileCanReadWithoutBlocking(int fd) {
643 if (fd == server_listen_pipe_) { 643 if (fd == server_listen_pipe_) {
644 int new_pipe = 0; 644 int new_pipe = 0;
645 if (!ServerAcceptConnection(server_listen_pipe_, &new_pipe) || 645 if (!ServerAcceptConnection(server_listen_pipe_, &new_pipe) ||
646 new_pipe < 0) { 646 new_pipe < 0) {
647 Close(); 647 Close();
648 listener()->OnChannelListenError(); 648 listener()->OnChannelListenError();
649 } 649 }
650 650
651 if (pipe_ != -1) { 651 if (pipe_ != -1) {
652 // We already have a connection. We only handle one at a time. 652 // We already have a connection. We only handle one at a time.
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
698 // This gives us a chance to kill the client if the incoming handshake 698 // This gives us a chance to kill the client if the incoming handshake
699 // is invalid. This also flushes any closefd messages. 699 // is invalid. This also flushes any closefd messages.
700 if (!is_blocked_on_write_) { 700 if (!is_blocked_on_write_) {
701 if (!ProcessOutgoingMessages()) { 701 if (!ProcessOutgoingMessages()) {
702 ClosePipeOnError(); 702 ClosePipeOnError();
703 } 703 }
704 } 704 }
705 } 705 }
706 706
707 // Called by libevent when we can write to the pipe without blocking. 707 // Called by libevent when we can write to the pipe without blocking.
708 void Channel::ChannelImpl::OnFileCanWriteWithoutBlocking(int fd) { 708 void ChannelPosix::OnFileCanWriteWithoutBlocking(int fd) {
709 DCHECK_EQ(pipe_, fd); 709 DCHECK_EQ(pipe_, fd);
710 is_blocked_on_write_ = false; 710 is_blocked_on_write_ = false;
711 if (!ProcessOutgoingMessages()) { 711 if (!ProcessOutgoingMessages()) {
712 ClosePipeOnError(); 712 ClosePipeOnError();
713 } 713 }
714 } 714 }
715 715
716 bool Channel::ChannelImpl::AcceptConnection() { 716 bool ChannelPosix::AcceptConnection() {
717 base::MessageLoopForIO::current()->WatchFileDescriptor( 717 base::MessageLoopForIO::current()->WatchFileDescriptor(
718 pipe_, true, base::MessageLoopForIO::WATCH_READ, &read_watcher_, this); 718 pipe_, true, base::MessageLoopForIO::WATCH_READ, &read_watcher_, this);
719 QueueHelloMessage(); 719 QueueHelloMessage();
720 720
721 if (mode_ & MODE_CLIENT_FLAG) { 721 if (mode_ & MODE_CLIENT_FLAG) {
722 // If we are a client we want to send a hello message out immediately. 722 // If we are a client we want to send a hello message out immediately.
723 // In server mode we will send a hello message when we receive one from a 723 // In server mode we will send a hello message when we receive one from a
724 // client. 724 // client.
725 waiting_connect_ = false; 725 waiting_connect_ = false;
726 return ProcessOutgoingMessages(); 726 return ProcessOutgoingMessages();
727 } else if (mode_ & MODE_SERVER_FLAG) { 727 } else if (mode_ & MODE_SERVER_FLAG) {
728 waiting_connect_ = true; 728 waiting_connect_ = true;
729 return true; 729 return true;
730 } else { 730 } else {
731 NOTREACHED(); 731 NOTREACHED();
732 return false; 732 return false;
733 } 733 }
734 } 734 }
735 735
736 void Channel::ChannelImpl::ClosePipeOnError() { 736 void ChannelPosix::ClosePipeOnError() {
737 if (HasAcceptedConnection()) { 737 if (HasAcceptedConnection()) {
738 ResetToAcceptingConnectionState(); 738 ResetToAcceptingConnectionState();
739 listener()->OnChannelError(); 739 listener()->OnChannelError();
740 } else { 740 } else {
741 Close(); 741 Close();
742 if (AcceptsConnections()) { 742 if (AcceptsConnections()) {
743 listener()->OnChannelListenError(); 743 listener()->OnChannelListenError();
744 } else { 744 } else {
745 listener()->OnChannelError(); 745 listener()->OnChannelError();
746 } 746 }
747 } 747 }
748 } 748 }
749 749
750 int Channel::ChannelImpl::GetHelloMessageProcId() { 750 int ChannelPosix::GetHelloMessageProcId() {
751 int pid = base::GetCurrentProcId(); 751 int pid = base::GetCurrentProcId();
752 #if defined(OS_LINUX) 752 #if defined(OS_LINUX)
753 // Our process may be in a sandbox with a separate PID namespace. 753 // Our process may be in a sandbox with a separate PID namespace.
754 if (global_pid_) { 754 if (global_pid_) {
755 pid = global_pid_; 755 pid = global_pid_;
756 } 756 }
757 #endif 757 #endif
758 return pid; 758 return pid;
759 } 759 }
760 760
761 void Channel::ChannelImpl::QueueHelloMessage() { 761 void ChannelPosix::QueueHelloMessage() {
762 // Create the Hello message 762 // Create the Hello message
763 scoped_ptr<Message> msg(new Message(MSG_ROUTING_NONE, 763 scoped_ptr<Message> msg(new Message(MSG_ROUTING_NONE,
764 HELLO_MESSAGE_TYPE, 764 HELLO_MESSAGE_TYPE,
765 IPC::Message::PRIORITY_NORMAL)); 765 IPC::Message::PRIORITY_NORMAL));
766 if (!msg->WriteInt(GetHelloMessageProcId())) { 766 if (!msg->WriteInt(GetHelloMessageProcId())) {
767 NOTREACHED() << "Unable to pickle hello message proc id"; 767 NOTREACHED() << "Unable to pickle hello message proc id";
768 } 768 }
769 #if defined(IPC_USES_READWRITE) 769 #if defined(IPC_USES_READWRITE)
770 scoped_ptr<Message> hello; 770 scoped_ptr<Message> hello;
771 if (remote_fd_pipe_ != -1) { 771 if (remote_fd_pipe_ != -1) {
772 if (!msg->WriteFileDescriptor(base::FileDescriptor(remote_fd_pipe_, 772 if (!msg->WriteFileDescriptor(base::FileDescriptor(remote_fd_pipe_,
773 false))) { 773 false))) {
774 NOTREACHED() << "Unable to pickle hello message file descriptors"; 774 NOTREACHED() << "Unable to pickle hello message file descriptors";
775 } 775 }
776 DCHECK_EQ(msg->file_descriptor_set()->size(), 1U); 776 DCHECK_EQ(msg->file_descriptor_set()->size(), 1U);
777 } 777 }
778 #endif // IPC_USES_READWRITE 778 #endif // IPC_USES_READWRITE
779 output_queue_.push(msg.release()); 779 output_queue_.push(msg.release());
780 } 780 }
781 781
782 Channel::ChannelImpl::ReadState Channel::ChannelImpl::ReadData( 782 ChannelPosix::ReadState ChannelPosix::ReadData(
783 char* buffer, 783 char* buffer,
784 int buffer_len, 784 int buffer_len,
785 int* bytes_read) { 785 int* bytes_read) {
786 if (pipe_ == -1) 786 if (pipe_ == -1)
787 return READ_FAILED; 787 return READ_FAILED;
788 788
789 struct msghdr msg = {0}; 789 struct msghdr msg = {0};
790 790
791 struct iovec iov = {buffer, static_cast<size_t>(buffer_len)}; 791 struct iovec iov = {buffer, static_cast<size_t>(buffer_len)};
792 msg.msg_iov = &iov; 792 msg.msg_iov = &iov;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
830 830
831 CloseClientFileDescriptor(); 831 CloseClientFileDescriptor();
832 832
833 // Read any file descriptors from the message. 833 // Read any file descriptors from the message.
834 if (!ExtractFileDescriptorsFromMsghdr(&msg)) 834 if (!ExtractFileDescriptorsFromMsghdr(&msg))
835 return READ_FAILED; 835 return READ_FAILED;
836 return READ_SUCCEEDED; 836 return READ_SUCCEEDED;
837 } 837 }
838 838
839 #if defined(IPC_USES_READWRITE) 839 #if defined(IPC_USES_READWRITE)
840 bool Channel::ChannelImpl::ReadFileDescriptorsFromFDPipe() { 840 bool ChannelPosix::ReadFileDescriptorsFromFDPipe() {
841 char dummy; 841 char dummy;
842 struct iovec fd_pipe_iov = { &dummy, 1 }; 842 struct iovec fd_pipe_iov = { &dummy, 1 };
843 843
844 struct msghdr msg = { 0 }; 844 struct msghdr msg = { 0 };
845 msg.msg_iov = &fd_pipe_iov; 845 msg.msg_iov = &fd_pipe_iov;
846 msg.msg_iovlen = 1; 846 msg.msg_iovlen = 1;
847 msg.msg_control = input_cmsg_buf_; 847 msg.msg_control = input_cmsg_buf_;
848 msg.msg_controllen = sizeof(input_cmsg_buf_); 848 msg.msg_controllen = sizeof(input_cmsg_buf_);
849 ssize_t bytes_received = HANDLE_EINTR(recvmsg(fd_pipe_, &msg, MSG_DONTWAIT)); 849 ssize_t bytes_received = HANDLE_EINTR(recvmsg(fd_pipe_, &msg, MSG_DONTWAIT));
850 850
851 if (bytes_received != 1) 851 if (bytes_received != 1)
852 return true; // No message waiting. 852 return true; // No message waiting.
853 853
854 if (!ExtractFileDescriptorsFromMsghdr(&msg)) 854 if (!ExtractFileDescriptorsFromMsghdr(&msg))
855 return false; 855 return false;
856 return true; 856 return true;
857 } 857 }
858 #endif 858 #endif
859 859
860 // On Posix, we need to fix up the file descriptors before the input message 860 // On Posix, we need to fix up the file descriptors before the input message
861 // is dispatched. 861 // is dispatched.
862 // 862 //
863 // This will read from the input_fds_ (READWRITE mode only) and read more 863 // This will read from the input_fds_ (READWRITE mode only) and read more
864 // handles from the FD pipe if necessary. 864 // handles from the FD pipe if necessary.
865 bool Channel::ChannelImpl::WillDispatchInputMessage(Message* msg) { 865 bool ChannelPosix::WillDispatchInputMessage(Message* msg) {
866 uint16 header_fds = msg->header()->num_fds; 866 uint16 header_fds = msg->header()->num_fds;
867 if (!header_fds) 867 if (!header_fds)
868 return true; // Nothing to do. 868 return true; // Nothing to do.
869 869
870 // The message has file descriptors. 870 // The message has file descriptors.
871 const char* error = NULL; 871 const char* error = NULL;
872 if (header_fds > input_fds_.size()) { 872 if (header_fds > input_fds_.size()) {
873 // The message has been completely received, but we didn't get 873 // The message has been completely received, but we didn't get
874 // enough file descriptors. 874 // enough file descriptors.
875 #if defined(IPC_USES_READWRITE) 875 #if defined(IPC_USES_READWRITE)
(...skipping 19 matching lines...) Expand all
895 895
896 // The shenaniganery below with &foo.front() requires input_fds_ to have 896 // The shenaniganery below with &foo.front() requires input_fds_ to have
897 // contiguous underlying storage (such as a simple array or a std::vector). 897 // contiguous underlying storage (such as a simple array or a std::vector).
898 // This is why the header warns not to make input_fds_ a deque<>. 898 // This is why the header warns not to make input_fds_ a deque<>.
899 msg->file_descriptor_set()->SetDescriptors(&input_fds_.front(), 899 msg->file_descriptor_set()->SetDescriptors(&input_fds_.front(),
900 header_fds); 900 header_fds);
901 input_fds_.erase(input_fds_.begin(), input_fds_.begin() + header_fds); 901 input_fds_.erase(input_fds_.begin(), input_fds_.begin() + header_fds);
902 return true; 902 return true;
903 } 903 }
904 904
905 bool Channel::ChannelImpl::DidEmptyInputBuffers() { 905 bool ChannelPosix::DidEmptyInputBuffers() {
906 // When the input data buffer is empty, the fds should be too. If this is 906 // When the input data buffer is empty, the fds should be too. If this is
907 // not the case, we probably have a rogue renderer which is trying to fill 907 // not the case, we probably have a rogue renderer which is trying to fill
908 // our descriptor table. 908 // our descriptor table.
909 return input_fds_.empty(); 909 return input_fds_.empty();
910 } 910 }
911 911
912 bool Channel::ChannelImpl::ExtractFileDescriptorsFromMsghdr(msghdr* msg) { 912 bool ChannelPosix::ExtractFileDescriptorsFromMsghdr(msghdr* msg) {
913 // Check that there are any control messages. On OSX, CMSG_FIRSTHDR will 913 // Check that there are any control messages. On OSX, CMSG_FIRSTHDR will
914 // return an invalid non-NULL pointer in the case that controllen == 0. 914 // return an invalid non-NULL pointer in the case that controllen == 0.
915 if (msg->msg_controllen == 0) 915 if (msg->msg_controllen == 0)
916 return true; 916 return true;
917 917
918 for (cmsghdr* cmsg = CMSG_FIRSTHDR(msg); 918 for (cmsghdr* cmsg = CMSG_FIRSTHDR(msg);
919 cmsg; 919 cmsg;
920 cmsg = CMSG_NXTHDR(msg, cmsg)) { 920 cmsg = CMSG_NXTHDR(msg, cmsg)) {
921 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { 921 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
922 unsigned payload_len = cmsg->cmsg_len - CMSG_LEN(0); 922 unsigned payload_len = cmsg->cmsg_len - CMSG_LEN(0);
(...skipping 11 matching lines...) Expand all
934 } 934 }
935 935
936 return true; 936 return true;
937 } 937 }
938 } 938 }
939 939
940 // No file descriptors found, but that's OK. 940 // No file descriptors found, but that's OK.
941 return true; 941 return true;
942 } 942 }
943 943
944 void Channel::ChannelImpl::ClearInputFDs() { 944 void ChannelPosix::ClearInputFDs() {
945 for (size_t i = 0; i < input_fds_.size(); ++i) { 945 for (size_t i = 0; i < input_fds_.size(); ++i) {
946 if (IGNORE_EINTR(close(input_fds_[i])) < 0) 946 if (IGNORE_EINTR(close(input_fds_[i])) < 0)
947 PLOG(ERROR) << "close "; 947 PLOG(ERROR) << "close ";
948 } 948 }
949 input_fds_.clear(); 949 input_fds_.clear();
950 } 950 }
951 951
952 void Channel::ChannelImpl::QueueCloseFDMessage(int fd, int hops) { 952 void ChannelPosix::QueueCloseFDMessage(int fd, int hops) {
953 switch (hops) { 953 switch (hops) {
954 case 1: 954 case 1:
955 case 2: { 955 case 2: {
956 // Create the message 956 // Create the message
957 scoped_ptr<Message> msg(new Message(MSG_ROUTING_NONE, 957 scoped_ptr<Message> msg(new Message(MSG_ROUTING_NONE,
958 CLOSE_FD_MESSAGE_TYPE, 958 CLOSE_FD_MESSAGE_TYPE,
959 IPC::Message::PRIORITY_NORMAL)); 959 IPC::Message::PRIORITY_NORMAL));
960 if (!msg->WriteInt(hops - 1) || !msg->WriteInt(fd)) { 960 if (!msg->WriteInt(hops - 1) || !msg->WriteInt(fd)) {
961 NOTREACHED() << "Unable to pickle close fd."; 961 NOTREACHED() << "Unable to pickle close fd.";
962 } 962 }
963 // Send(msg.release()); 963 // Send(msg.release());
964 output_queue_.push(msg.release()); 964 output_queue_.push(msg.release());
965 break; 965 break;
966 } 966 }
967 967
968 default: 968 default:
969 NOTREACHED(); 969 NOTREACHED();
970 break; 970 break;
971 } 971 }
972 } 972 }
973 973
974 void Channel::ChannelImpl::HandleInternalMessage(const Message& msg) { 974 void ChannelPosix::HandleInternalMessage(const Message& msg) {
975 // The Hello message contains only the process id. 975 // The Hello message contains only the process id.
976 PickleIterator iter(msg); 976 PickleIterator iter(msg);
977 977
978 switch (msg.type()) { 978 switch (msg.type()) {
979 default: 979 default:
980 NOTREACHED(); 980 NOTREACHED();
981 break; 981 break;
982 982
983 case Channel::HELLO_MESSAGE_TYPE: 983 case Channel::HELLO_MESSAGE_TYPE:
984 int pid; 984 int pid;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1018 NOTREACHED(); 1018 NOTREACHED();
1019 } 1019 }
1020 } else { 1020 } else {
1021 QueueCloseFDMessage(fd, hops); 1021 QueueCloseFDMessage(fd, hops);
1022 } 1022 }
1023 break; 1023 break;
1024 #endif 1024 #endif
1025 } 1025 }
1026 } 1026 }
1027 1027
1028 void Channel::ChannelImpl::Close() { 1028 void ChannelPosix::Close() {
1029 // Close can be called multiple time, so we need to make sure we're 1029 // Close can be called multiple time, so we need to make sure we're
1030 // idempotent. 1030 // idempotent.
1031 1031
1032 ResetToAcceptingConnectionState(); 1032 ResetToAcceptingConnectionState();
1033 1033
1034 if (must_unlink_) { 1034 if (must_unlink_) {
1035 unlink(pipe_name_.c_str()); 1035 unlink(pipe_name_.c_str());
1036 must_unlink_ = false; 1036 must_unlink_ = false;
1037 } 1037 }
1038 if (server_listen_pipe_ != -1) { 1038 if (server_listen_pipe_ != -1) {
1039 if (IGNORE_EINTR(close(server_listen_pipe_)) < 0) 1039 if (IGNORE_EINTR(close(server_listen_pipe_)) < 0)
1040 DPLOG(ERROR) << "close " << server_listen_pipe_; 1040 DPLOG(ERROR) << "close " << server_listen_pipe_;
1041 server_listen_pipe_ = -1; 1041 server_listen_pipe_ = -1;
1042 // Unregister libevent for the listening socket and close it. 1042 // Unregister libevent for the listening socket and close it.
1043 server_listen_connection_watcher_.StopWatchingFileDescriptor(); 1043 server_listen_connection_watcher_.StopWatchingFileDescriptor();
1044 } 1044 }
1045 1045
1046 CloseClientFileDescriptor(); 1046 CloseClientFileDescriptor();
1047 } 1047 }
1048 1048
1049 //------------------------------------------------------------------------------ 1049 base::ProcessId ChannelPosix::GetPeerPID() const {
1050 // Channel's methods simply call through to ChannelImpl. 1050 return peer_pid_;
1051 Channel::Channel(const IPC::ChannelHandle& channel_handle, Mode mode,
1052 Listener* listener)
1053 : channel_impl_(new ChannelImpl(channel_handle, mode, listener)) {
1054 } 1051 }
1055 1052
1056 Channel::~Channel() { 1053 //------------------------------------------------------------------------------
1057 delete channel_impl_; 1054 // Channel's methods
1058 }
1059 1055
1060 bool Channel::Connect() { 1056 // static
1061 return channel_impl_->Connect(); 1057 scoped_ptr<Channel> Channel::Create(
1062 } 1058 const IPC::ChannelHandle &channel_handle, Mode mode, Listener* listener) {
1063 1059 return scoped_ptr<Channel>(
1064 void Channel::Close() { 1060 new ChannelPosix(channel_handle, mode, listener));
1065 if (channel_impl_)
1066 channel_impl_->Close();
1067 }
1068
1069 base::ProcessId Channel::peer_pid() const {
1070 return channel_impl_->peer_pid();
1071 }
1072
1073 bool Channel::Send(Message* message) {
1074 return channel_impl_->Send(message);
1075 }
1076
1077 int Channel::GetClientFileDescriptor() const {
1078 return channel_impl_->GetClientFileDescriptor();
1079 }
1080
1081 int Channel::TakeClientFileDescriptor() {
1082 return channel_impl_->TakeClientFileDescriptor();
1083 }
1084
1085 bool Channel::AcceptsConnections() const {
1086 return channel_impl_->AcceptsConnections();
1087 }
1088
1089 bool Channel::HasAcceptedConnection() const {
1090 return channel_impl_->HasAcceptedConnection();
1091 }
1092
1093 bool Channel::GetPeerEuid(uid_t* peer_euid) const {
1094 return channel_impl_->GetPeerEuid(peer_euid);
1095 }
1096
1097 void Channel::ResetToAcceptingConnectionState() {
1098 channel_impl_->ResetToAcceptingConnectionState();
1099 } 1061 }
1100 1062
1101 // static 1063 // static
1102 bool Channel::IsNamedServerInitialized(const std::string& channel_id) {
1103 return ChannelImpl::IsNamedServerInitialized(channel_id);
1104 }
1105
1106 // static
1107 std::string Channel::GenerateVerifiedChannelID(const std::string& prefix) { 1064 std::string Channel::GenerateVerifiedChannelID(const std::string& prefix) {
1108 // A random name is sufficient validation on posix systems, so we don't need 1065 // A random name is sufficient validation on posix systems, so we don't need
1109 // an additional shared secret. 1066 // an additional shared secret.
1110 1067
1111 std::string id = prefix; 1068 std::string id = prefix;
1112 if (!id.empty()) 1069 if (!id.empty())
1113 id.append("."); 1070 id.append(".");
1114 1071
1115 return id.append(GenerateUniqueRandomChannelID()); 1072 return id.append(GenerateUniqueRandomChannelID());
1116 } 1073 }
1117 1074
1118 1075
1076 bool Channel::IsNamedServerInitialized(
1077 const std::string& channel_id) {
1078 return ChannelPosix::IsNamedServerInitialized(channel_id);
1079 }
1080
1119 #if defined(OS_LINUX) 1081 #if defined(OS_LINUX)
1120 // static 1082 // static
1121 void Channel::SetGlobalPid(int pid) { 1083 void Channel::SetGlobalPid(int pid) {
1122 ChannelImpl::SetGlobalPid(pid); 1084 ChannelPosix::SetGlobalPid(pid);
1123 } 1085 }
1124 #endif // OS_LINUX 1086 #endif // OS_LINUX
1125 1087
1126 } // namespace IPC 1088 } // namespace IPC
OLDNEW
« no previous file with comments | « ipc/ipc_channel_posix.h ('k') | ipc/ipc_channel_posix_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698