diff options
author | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-22 23:57:21 +0000 |
---|---|---|
committer | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-22 23:57:21 +0000 |
commit | 946d1b2c806795351598aeb9faaed797284a8ee3 (patch) | |
tree | d8d2695f73a56ec33ab068f9070fe93cb7c0e4a3 /ipc/ipc_channel_posix.h | |
parent | 00fceac62015db950f3dde84f5aeeacb82f1b2c6 (diff) | |
download | chromium_src-946d1b2c806795351598aeb9faaed797284a8ee3.zip chromium_src-946d1b2c806795351598aeb9faaed797284a8ee3.tar.gz chromium_src-946d1b2c806795351598aeb9faaed797284a8ee3.tar.bz2 |
Split the IPC code into ipc/
This splits the ipc code from the common project. The 'common' project pulls in
all of webkit, the v8 bindings, skia, googleurl, and a number of other projects
which makes it very difficult to deal with especially for external projects
wanting just to use some of Chromium's infrastructure. This puts the ipc code
into its top-level ipc/ directory with a dependency only on base. The common
project depends on the new ipc/ipc.gyp:ipc target so that all projects currently
pulling common in to get the IPC code still have it available. This mostly
follows agl's pre-gyp attempt to do this which was r13062.
Known issues:
- Currently a number of projects depend on chrome/chrome.gyp:common in order to
use the IPC infrastructure. Rather than fixing all of these dependencies I have
made common depend on ipc/ipc.gyp:ipc and added "ipc" to the include_rules
section of DEPS so that checkdeps.py doesn't complain. Over time projects that
need IPC should depend on the IPC project themselves and dependencies on common
removed, although I don't think many projects that need IPC will be able to get
away without common currently.
- ipc/ipc_message_macros.h still has #include "chrome/common/..." inside of a
ipc/ should not refer to files in chrome/... now. I'm not sure how to resolve
this since it's really an IDE bug
- the named pipe name (windows+linux) and the logging event name (all) + env
variable (posix) refer explicitly to 'Chrome' which somewhat hurts the illusion
of ipc/ being an independent library. I think this should be examined in a
subsequent, much smaller patch.
- I've eliminated the IPC.SendMsgCount counter since it was implemented in a way
to create a dependency from ipc/ to chrome/common/chrome_counters. This is the
same approach that r13062 took.
http://codereview.chromium.org/155905
(Patch from James Robinson)
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@21342 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ipc/ipc_channel_posix.h')
-rw-r--r-- | ipc/ipc_channel_posix.h | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/ipc/ipc_channel_posix.h b/ipc/ipc_channel_posix.h new file mode 100644 index 0000000..aa69d4f --- /dev/null +++ b/ipc/ipc_channel_posix.h @@ -0,0 +1,135 @@ +// Copyright (c) 2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IPC_IPC_CHANNEL_POSIX_H_ +#define IPC_IPC_CHANNEL_POSIX_H_ + +#include "ipc/ipc_channel.h" + +#include <sys/socket.h> // for CMSG macros + +#include <queue> +#include <string> +#include <vector> + +#include "base/message_loop.h" +#include "ipc/file_descriptor_set_posix.h" + +namespace IPC { + +// Store that channel name |name| is available via socket |socket|. +// Used when the channel has been precreated by another process on +// our behalf and they've just shipped us the socket. +void AddChannelSocket(const std::string& name, int socket); + +// Remove the channel name mapping, and close the corresponding socket. +void RemoveAndCloseChannelSocket(const std::string& name); + +// Construct a socket pair appropriate for IPC: UNIX domain, nonblocking. +// Returns false on error. +bool SocketPair(int* fd1, int* fd2); + +// An implementation of ChannelImpl for POSIX systems that works via +// socketpairs. See the .cc file for an overview of the implementation. +class Channel::ChannelImpl : public MessageLoopForIO::Watcher { + public: + // Mirror methods of Channel, see ipc_channel.h for description. + ChannelImpl(const std::string& channel_id, Mode mode, Listener* listener); + ~ChannelImpl() { Close(); } + bool Connect(); + void Close(); + void set_listener(Listener* listener) { listener_ = listener; } + bool Send(Message* message); + int GetClientFileDescriptor() const; + + private: + bool CreatePipe(const std::string& channel_id, Mode mode); + + bool ProcessIncomingMessages(); + bool ProcessOutgoingMessages(); + + // MessageLoopForIO::Watcher implementation. + virtual void OnFileCanReadWithoutBlocking(int fd); + virtual void OnFileCanWriteWithoutBlocking(int fd); + + Mode mode_; + + // After accepting one client connection on our server socket we want to + // stop listening. + MessageLoopForIO::FileDescriptorWatcher server_listen_connection_watcher_; + MessageLoopForIO::FileDescriptorWatcher read_watcher_; + MessageLoopForIO::FileDescriptorWatcher write_watcher_; + + // Indicates whether we're currently blocked waiting for a write to complete. + bool is_blocked_on_write_; + + // If sending a message blocks then we use this variable + // to keep track of where we are. + size_t message_send_bytes_written_; + + // If the kTestingChannelID flag is specified, we use a FIFO instead of + // a socketpair(). + bool uses_fifo_; + + // File descriptor we're listening on for new connections in the FIFO case; + // unused otherwise. + int server_listen_pipe_; + + // The pipe used for communication. + int pipe_; + + // For a server, the client end of our socketpair() -- the other end of our + // pipe_ that is passed to the client. + int client_pipe_; + + // The "name" of our pipe. On Windows this is the global identifier for + // the pipe. On POSIX it's used as a key in a local map of file descriptors. + std::string pipe_name_; + + Listener* listener_; + + // Messages to be sent are queued here. + std::queue<Message*> output_queue_; + + // We read from the pipe into this buffer + char input_buf_[Channel::kReadBufferSize]; + + enum { + // We assume a worst case: kReadBufferSize bytes of messages, where each + // message has no payload and a full complement of descriptors. + MAX_READ_FDS = (Channel::kReadBufferSize / sizeof(IPC::Message::Header)) * + FileDescriptorSet::MAX_DESCRIPTORS_PER_MESSAGE, + }; + + // This is a control message buffer large enough to hold kMaxReadFDs +#if defined(OS_MACOSX) + // TODO(agl): OSX appears to have non-constant CMSG macros! + char input_cmsg_buf_[1024]; +#else + char input_cmsg_buf_[CMSG_SPACE(sizeof(int) * MAX_READ_FDS)]; +#endif + + // Large messages that span multiple pipe buffers, get built-up using + // this buffer. + std::string input_overflow_buf_; + std::vector<int> input_overflow_fds_; + + // In server-mode, we have to wait for the client to connect before we + // can begin reading. We make use of the input_state_ when performing + // the connect operation in overlapped mode. + bool waiting_connect_; + + // This flag is set when processing incoming messages. It is used to + // avoid recursing through ProcessIncomingMessages, which could cause + // problems. TODO(darin): make this unnecessary + bool processing_incoming_; + + ScopedRunnableMethodFactory<ChannelImpl> factory_; + + DISALLOW_COPY_AND_ASSIGN(ChannelImpl); +}; + +} // namespace IPC + +#endif // IPC_IPC_CHANNEL_POSIX_H_ |