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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
|
// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef CHROME_COMMON_IPC_CHANNEL_H__
#define CHROME_COMMON_IPC_CHANNEL_H__
#include <queue>
#include "base/message_loop.h"
#include "chrome/common/ipc_message.h"
namespace IPC {
//------------------------------------------------------------------------------
class Channel : public MessageLoop::Watcher,
public Message::Sender {
// Security tests need access to the pipe handle.
friend class ChannelTest;
public:
// Implemented by consumers of a Channel to receive messages.
class Listener {
public:
// Called when a message is received.
virtual void OnMessageReceived(const Message& message) = 0;
// Called when the channel is connected and we have received the internal
// Hello message from the peer.
virtual void OnChannelConnected(int32 peer_pid) {}
// Called when an error is detected that causes the channel to close.
// This method is not called when a channel is closed normally.
virtual void OnChannelError() {}
};
enum Mode {
MODE_SERVER,
MODE_CLIENT
};
// The maximum message size in bytes. Attempting to receive a
// message of this size or bigger results in a channel error.
enum {
kMaximumMessageSize = 256 * 1024 * 1024
};
// Initialize a Channel.
//
// @param channel_id
// Identifies the communication Channel.
// @param mode
// Specifies whether this Channel is to operate in server mode or client
// mode. In server mode, the Channel is responsible for setting up the
// IPC object, whereas in client mode, the Channel merely connects
// to the already established IPC object.
// @param listener
// Receives a callback on the current thread for each newly received
// message.
//
Channel(const std::wstring& channel_id, Mode mode, Listener* listener);
~Channel() { Close(); }
// Connect the pipe. On the server side, this will initiate
// waiting for connections. On the client, it attempts to
// connect to a pre-existing pipe. Note, calling Connect()
// will not block the calling thread and may complete
// asynchronously.
bool Connect();
// Close this Channel explicitly. May be called multiple times.
void Close();
// Modify the Channel's listener.
void set_listener(Listener* listener) { listener_ = listener; }
// Send a message over the Channel to the listener on the other end.
//
// @param message
// The Message to send, which must be allocated using operator new. This
// object will be deleted once the contents of the Message have been sent.
//
// FIXME bug 551500: the channel does not notice failures, so if the
// renderer crashes, it will silently succeed, leaking the parameter.
// At least the leak will be fixed by...
//
virtual bool Send(Message* message);
// Process any pending incoming and outgoing messages. Wait for at most
// max_wait_msec for pending messages if there are none. Returns true if
// there were no pending messages or if pending messages were successfully
// processed. Returns false if there are pending messages that cannot be
// processed for some reason (e.g., because ProcessIncomingMessages would be
// re-entered).
// TODO(darin): Need a better way of dealing with the recursion problem.
bool ProcessPendingMessages(DWORD max_wait_msec);
private:
const std::wstring PipeName(const std::wstring& channel_id) const;
bool CreatePipe(const std::wstring& channel_id, Mode mode);
bool ProcessConnection();
bool ProcessIncomingMessages();
bool ProcessOutgoingMessages();
// MessageLoop::Watcher implementation
virtual void OnObjectSignaled(HANDLE object);
private:
enum {
BUF_SIZE = 4096
};
struct State {
State();
~State();
OVERLAPPED overlapped;
bool is_pending;
};
State input_state_;
State output_state_;
HANDLE pipe_;
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_[BUF_SIZE];
// Large messages that span multiple pipe buffers, get built-up using
// this buffer.
std::string input_overflow_buf_;
// 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_;
// The Hello message is internal to the Channel class. It is sent
// by the peer when the channel is connected. The message contains
// just the process id (pid). The message has a special routing_id
// (MSG_ROUTING_NONE) and type (HELLO_MESSAGE_TYPE).
enum {
HELLO_MESSAGE_TYPE = MAXWORD // Maximum value of message type (WORD),
// to avoid conflicting with normal
// message types, which are enumeration
// constants starting from 0.
};
};
}
#endif // CHROME_COMMON_IPC_CHANNEL_H__
|