-
Notifications
You must be signed in to change notification settings - Fork 2k
/
ipc_channel_posix.h
133 lines (104 loc) · 4.2 KB
/
ipc_channel_posix.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// 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 CHROME_COMMON_IPC_CHANNEL_POSIX_H_
#define CHROME_COMMON_IPC_CHANNEL_POSIX_H_
#include "chrome/common/ipc_channel.h"
#include <sys/socket.h> // for CMSG macros
#include <queue>
#include <string>
#include <vector>
#include "base/message_loop.h"
#include "chrome/common/file_descriptor_set_posix.h"
namespace IPC {
// 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::wstring& channel_id, Mode mode, Listener* listener);
ChannelImpl(int fd, Mode mode, Listener* listener);
~ChannelImpl() { Close(); }
bool Connect();
void Close();
#ifdef CHROMIUM_MOZILLA_BUILD
Listener* set_listener(Listener* listener) {
Listener* old = listener_;
listener_ = listener;
return old;
}
#else
void set_listener(Listener* listener) { listener_ = listener; }
#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();
// 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_;
int server_listen_pipe_;
int pipe_;
int client_pipe_; // The client end of our socketpair().
// 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 // CHROME_COMMON_IPC_CHANNEL_POSIX_H_