summaryrefslogtreecommitdiffstats
path: root/chrome/common/ipc_channel_posix.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/common/ipc_channel_posix.cc')
-rw-r--r--chrome/common/ipc_channel_posix.cc89
1 files changed, 76 insertions, 13 deletions
diff --git a/chrome/common/ipc_channel_posix.cc b/chrome/common/ipc_channel_posix.cc
index 2cdbca4..dad5ff8 100644
--- a/chrome/common/ipc_channel_posix.cc
+++ b/chrome/common/ipc_channel_posix.cc
@@ -16,21 +16,29 @@
#include <sys/un.h>
#endif
-
+#include "base/command_line.h"
#include "base/logging.h"
#include "base/process_util.h"
#include "base/scoped_ptr.h"
#include "base/string_util.h"
#include "chrome/common/chrome_counters.h"
+#include "chrome/common/chrome_switches.h"
#include "chrome/common/ipc_message_utils.h"
namespace IPC {
//------------------------------------------------------------------------------
-// TODO(playmobil): Only use FIFOs for debugging, for real work, use a
-// socketpair.
namespace {
+// Used to map a channel name to the equivalent FD # in the client process.
+int ChannelNameToClientFD(const std::string& channel_id) {
+ // TODO(playmobil): Support a smarter mapping that allows for a process to
+ // be a client of multiple channels.
+ const int kClientChannelID = 50;
+ return kClientChannelID;
+}
+
+//------------------------------------------------------------------------------
// The -1 is to take the NULL terminator into account.
#if defined(OS_LINUX)
const size_t kMaxPipeNameLength = UNIX_PATH_MAX - 1;
@@ -156,8 +164,10 @@ Channel::ChannelImpl::ChannelImpl(const std::wstring& channel_id, Mode mode,
: mode_(mode),
is_blocked_on_write_(false),
message_send_bytes_written_(0),
+ uses_fifo_(CommandLine().HasSwitch(switches::kTestingChannelID)),
server_listen_pipe_(-1),
pipe_(-1),
+ client_pipe_(-1),
listener_(listener),
waiting_connect_(true),
processing_incoming_(false),
@@ -183,19 +193,42 @@ bool Channel::ChannelImpl::CreatePipe(const std::wstring& channel_id,
Mode mode) {
DCHECK(server_listen_pipe_ == -1 && pipe_ == -1);
- // TODO(playmobil): Should we just change pipe_name to be a normal string
- // everywhere?
- pipe_name_ = WideToUTF8(PipeName(channel_id));
+ if (uses_fifo_) {
+ // TODO(playmobil): Should we just change pipe_name to be a normal string
+ // everywhere?
+ pipe_name_ = WideToUTF8(PipeName(channel_id));
- if (mode == MODE_SERVER) {
- if (!CreateServerFifo(pipe_name_, &server_listen_pipe_)) {
- return false;
+ if (mode == MODE_SERVER) {
+ if (!CreateServerFifo(pipe_name_, &server_listen_pipe_)) {
+ return false;
+ }
+ } else {
+ if (!ClientConnectToFifo(pipe_name_, &pipe_)) {
+ return false;
+ }
+ waiting_connect_ = false;
}
} else {
- if (!ClientConnectToFifo(pipe_name_, &pipe_)) {
- return false;
+ // socketpair()
+ if (mode == MODE_SERVER) {
+ int pipe_fds[2];
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipe_fds) != 0) {
+ return false;
+ }
+ // Set both ends to be non-blocking.
+ if (fcntl(pipe_fds[0], F_SETFL, O_NONBLOCK) == -1 ||
+ fcntl(pipe_fds[1], F_SETFL, O_NONBLOCK) == -1) {
+ close(pipe_fds[0]);
+ close(pipe_fds[1]);
+ return false;
+ }
+ pipe_ = pipe_fds[0];
+ client_pipe_ = pipe_fds[1];
+ } else {
+ pipe_ = ChannelNameToClientFD(pipe_name_);
+ DCHECK(pipe_ > 0);
+ waiting_connect_ = false;
}
- waiting_connect_ = false;
}
// Create the Hello message to be sent when Connect is called
@@ -212,7 +245,7 @@ bool Channel::ChannelImpl::CreatePipe(const std::wstring& channel_id,
}
bool Channel::ChannelImpl::Connect() {
- if (mode_ == MODE_SERVER) {
+ if (mode_ == MODE_SERVER && uses_fifo_) {
if (server_listen_pipe_ == -1) {
return false;
}
@@ -396,10 +429,27 @@ bool Channel::ChannelImpl::Send(Message* message) {
return true;
}
+void Channel::ChannelImpl::GetClientFileDescriptorMapping(int *src_fd,
+ int *dest_fd) {
+ DCHECK(mode_ == MODE_SERVER);
+ *src_fd = client_pipe_;
+ *dest_fd = ChannelNameToClientFD(pipe_name_);
+}
+
+void Channel::ChannelImpl::OnClientConnected() {
+ DCHECK(mode_ == MODE_SERVER);
+ close(client_pipe_);
+ client_pipe_ = -1;
+}
+
// Called by libevent when we can read from th pipe without blocking.
void Channel::ChannelImpl::OnFileCanReadWithoutBlocking(int fd) {
bool send_server_hello_msg = false;
if (waiting_connect_ && mode_ == MODE_SERVER) {
+ // In the case of a socketpair() the server starts listening on its end
+ // of the pipe in Connect().
+ DCHECK(uses_fifo_);
+
if (!ServerAcceptFifoConnection(server_listen_pipe_, &pipe_)) {
Close();
}
@@ -465,6 +515,10 @@ void Channel::ChannelImpl::Close() {
close(pipe_);
pipe_ = -1;
}
+ if (client_pipe_ != -1) {
+ close(client_pipe_);
+ client_pipe_ = -1;
+ }
// Unlink the FIFO
unlink(pipe_name_.c_str());
@@ -503,4 +557,13 @@ bool Channel::Send(Message* message) {
return channel_impl_->Send(message);
}
+void Channel::GetClientFileDescriptorMapping(int *src_fd, int *dest_fd) {
+ return channel_impl_->GetClientFileDescriptorMapping(src_fd, dest_fd);
+}
+
+void Channel::OnClientConnected() {
+ return channel_impl_->OnClientConnected();
+}
+
+
} // namespace IPC