Bug 564086, part j: Add IPC::Channel support for getting OS-level pipe info and creating from existing pipe descriptors. r=bent

This commit is contained in:
Chris Jones 2011-06-03 13:33:55 -05:00
parent 8499bc3fba
commit a17a5d62d4
5 changed files with 129 additions and 16 deletions

View File

@ -59,6 +59,20 @@ class Channel : public Message::Sender {
//
Channel(const std::wstring& channel_id, Mode mode, Listener* listener);
#if defined(CHROMIUM_MOZILLA_BUILD)
// XXX it would nice not to have yet more platform-specific code in
// here but it's just not worth the trouble.
# if defined(OS_POSIX)
// Connect to a pre-created channel |fd| as |mode|.
Channel(int fd, Mode mode, Listener* listener);
# elif defined(OS_WIN)
// Connect to a pre-created channel as |mode|. Clients connect to
// the pre-existing server pipe, and servers take over |server_pipe|.
Channel(const std::wstring& channel_id, void* server_pipe,
Mode mode, Listener* listener);
# endif
#endif
~Channel();
// Connect the pipe. On the server side, this will initiate
@ -99,6 +113,16 @@ class Channel : public Message::Sender {
// a named FIFO is used as the channel transport mechanism rather than a
// socketpair() in which case this method returns -1 for both parameters.
void GetClientFileDescriptorMapping(int *src_fd, int *dest_fd) const;
# if defined(CHROMIUM_MOZILLA_BUILD)
// Return the server side of the socketpair.
int GetServerFileDescriptor() const;
# endif
#elif defined(OS_WIN)
# if defined(CHROMIUM_MOZILLA_BUILD)
// Return the server pipe handle.
void* GetServerPipeHandle() const;
# endif
#endif // defined(OS_POSIX)
private:

View File

@ -257,18 +257,10 @@ bool SetCloseOnExec(int fd) {
Channel::ChannelImpl::ChannelImpl(const std::wstring& channel_id, Mode mode,
Listener* listener)
: mode_(mode),
is_blocked_on_write_(false),
message_send_bytes_written_(0),
uses_fifo_(CommandLine::ForCurrentProcess()->HasSwitch(
switches::kIPCUseFIFO)),
server_listen_pipe_(-1),
pipe_(-1),
client_pipe_(-1),
listener_(listener),
waiting_connect_(true),
processing_incoming_(false),
factory_(this) {
: factory_(this) {
Init(mode, listener);
uses_fifo_ = CommandLine::ForCurrentProcess()->HasSwitch(switches::kIPCUseFIFO);
if (!CreatePipe(channel_id, mode)) {
// The pipe may have been closed already.
LOG(WARNING) << "Unable to create pipe named \"" << channel_id <<
@ -277,6 +269,28 @@ Channel::ChannelImpl::ChannelImpl(const std::wstring& channel_id, Mode mode,
}
}
Channel::ChannelImpl::ChannelImpl(int fd, Mode mode, Listener* listener)
: factory_(this) {
Init(mode, listener);
pipe_ = fd;
waiting_connect_ = (MODE_SERVER == mode);
EnqueueHelloMessage();
}
void Channel::ChannelImpl::Init(Mode mode, Listener* listener) {
mode_ = mode;
is_blocked_on_write_ = false;
message_send_bytes_written_ = 0;
uses_fifo_ = false;
server_listen_pipe_ = -1;
pipe_ = -1;
client_pipe_ = -1;
listener_ = listener;
waiting_connect_ = true;
processing_incoming_ = false;
}
bool Channel::ChannelImpl::CreatePipe(const std::wstring& channel_id,
Mode mode) {
DCHECK(server_listen_pipe_ == -1 && pipe_ == -1);
@ -334,6 +348,10 @@ bool Channel::ChannelImpl::CreatePipe(const std::wstring& channel_id,
}
// Create the Hello message to be sent when Connect is called
return EnqueueHelloMessage();
}
bool Channel::ChannelImpl::EnqueueHelloMessage() {
scoped_ptr<Message> msg(new Message(MSG_ROUTING_NONE,
HELLO_MESSAGE_TYPE,
IPC::Message::PRIORITY_NORMAL));
@ -796,6 +814,12 @@ Channel::Channel(const std::wstring& channel_id, Mode mode,
: channel_impl_(new ChannelImpl(channel_id, mode, listener)) {
}
#if defined(CHROMIUM_MOZILLA_BUILD)
Channel::Channel(int fd, Mode mode, Listener* listener)
: channel_impl_(new ChannelImpl(fd, mode, listener)) {
}
#endif
Channel::~Channel() {
delete channel_impl_;
}
@ -826,4 +850,10 @@ void Channel::GetClientFileDescriptorMapping(int *src_fd, int *dest_fd) const {
return channel_impl_->GetClientFileDescriptorMapping(src_fd, dest_fd);
}
#ifdef CHROMIUM_MOZILLA_BUILD
int Channel::GetServerFileDescriptor() const {
return channel_impl_->GetServerFileDescriptor();
}
#endif
} // namespace IPC

View File

@ -24,6 +24,7 @@ class Channel::ChannelImpl : public MessageLoopForIO::Watcher {
public:
// Mirror methods of Channel, see ipc_channel.h for description.
ChannelImpl(const std::wstring& channel_id, Mode mode, Listener* listener);
ChannelImpl(int fd, Mode mode, Listener* listener);
~ChannelImpl() { Close(); }
bool Connect();
void Close();
@ -38,9 +39,17 @@ class Channel::ChannelImpl : public MessageLoopForIO::Watcher {
#endif
bool Send(Message* message);
void GetClientFileDescriptorMapping(int *src_fd, int *dest_fd) const;
#ifdef CHROMIUM_MOZILLA_BUILD
int GetServerFileDescriptor() const {
DCHECK(mode_ == MODE_SERVER);
return pipe_;
}
#endif
private:
void Init(Mode mode, Listener* listener);
bool CreatePipe(const std::wstring& channel_id, Mode mode);
bool EnqueueHelloMessage();
bool ProcessIncomingMessages();
bool ProcessOutgoingMessages();

View File

@ -35,11 +35,9 @@ Channel::ChannelImpl::ChannelImpl(const std::wstring& channel_id, Mode mode,
Listener* listener)
: ALLOW_THIS_IN_INITIALIZER_LIST(input_state_(this)),
ALLOW_THIS_IN_INITIALIZER_LIST(output_state_(this)),
pipe_(INVALID_HANDLE_VALUE),
listener_(listener),
waiting_connect_(mode == MODE_SERVER),
processing_incoming_(false),
ALLOW_THIS_IN_INITIALIZER_LIST(factory_(this)) {
Init(mode, listener);
if (!CreatePipe(channel_id, mode)) {
// The pipe may have been closed already.
LOG(WARNING) << "Unable to create pipe named \"" << channel_id <<
@ -47,6 +45,37 @@ Channel::ChannelImpl::ChannelImpl(const std::wstring& channel_id, Mode mode,
}
}
#if defined(CHROMIUM_MOZILLA_BUILD)
Channel::ChannelImpl::ChannelImpl(const std::wstring& channel_id,
HANDLE server_pipe,
Mode mode, Listener* listener)
: ALLOW_THIS_IN_INITIALIZER_LIST(input_state_(this)),
ALLOW_THIS_IN_INITIALIZER_LIST(output_state_(this)),
ALLOW_THIS_IN_INITIALIZER_LIST(factory_(this)) {
Init(mode, listener);
if (mode == MODE_SERVER) {
// Use the existing handle that was dup'd to us
pipe_ = server_pipe;
EnqueueHelloMessage();
} else {
// Take the normal init path to connect to the server pipe
CreatePipe(channel_id, mode);
}
}
void Channel::ChannelImpl::Init(Mode mode, Listener* listener) {
pipe_ = INVALID_HANDLE_VALUE;
listener_ = listener;
waiting_connect_ = (mode == MODE_SERVER);
processing_incoming_ = false;
}
HANDLE Channel::ChannelImpl::GetServerPipeHandle() const {
return pipe_;
}
#endif
void Channel::ChannelImpl::Close() {
if (thread_check_.get()) {
DCHECK(thread_check_->CalledOnValidThread());
@ -164,6 +193,10 @@ bool Channel::ChannelImpl::CreatePipe(const std::wstring& channel_id,
}
// Create the Hello message to be sent when Connect is called
return EnqueueHelloMessage();
}
bool Channel::ChannelImpl::EnqueueHelloMessage() {
scoped_ptr<Message> m(new Message(MSG_ROUTING_NONE,
HELLO_MESSAGE_TYPE,
IPC::Message::PRIORITY_NORMAL));
@ -426,6 +459,13 @@ Channel::Channel(const std::wstring& channel_id, Mode mode,
: channel_impl_(new ChannelImpl(channel_id, mode, listener)) {
}
#ifdef CHROMIUM_MOZILLA_BUILD
Channel::Channel(const std::wstring& channel_id, void* server_pipe,
Mode mode, Listener* listener)
: channel_impl_(new ChannelImpl(channel_id, server_pipe, mode, listener)) {
}
#endif
Channel::~Channel() {
delete channel_impl_;
}
@ -439,6 +479,10 @@ void Channel::Close() {
}
#ifdef CHROMIUM_MOZILLA_BUILD
void* Channel::GetServerPipeHandle() const {
return channel_impl_->GetServerPipeHandle();
}
Channel::Listener* Channel::set_listener(Listener* listener) {
return channel_impl_->set_listener(listener);
}

View File

@ -20,6 +20,8 @@ class Channel::ChannelImpl : public MessageLoopForIO::IOHandler {
public:
// Mirror methods of Channel, see ipc_channel.h for description.
ChannelImpl(const std::wstring& channel_id, Mode mode, Listener* listener);
ChannelImpl(const std::wstring& channel_id, HANDLE server_pipe,
Mode mode, Listener* listener);
~ChannelImpl() {
if (pipe_ != INVALID_HANDLE_VALUE) {
Close();
@ -28,6 +30,8 @@ class Channel::ChannelImpl : public MessageLoopForIO::IOHandler {
bool Connect();
void Close();
#ifdef CHROMIUM_MOZILLA_BUILD
HANDLE GetServerPipeHandle() const;
Listener* set_listener(Listener* listener) {
Listener* old = listener_;
listener_ = listener;
@ -38,8 +42,10 @@ class Channel::ChannelImpl : public MessageLoopForIO::IOHandler {
#endif
bool Send(Message* message);
private:
void Init(Mode mode, Listener* listener);
const std::wstring PipeName(const std::wstring& channel_id) const;
bool CreatePipe(const std::wstring& channel_id, Mode mode);
bool EnqueueHelloMessage();
bool ProcessConnection();
bool ProcessIncomingMessages(MessageLoopForIO::IOContext* context,