[go: nahoru, domu]

blob: bf71e0243a3286a6f209270d44607be7cee79844 [file] [log] [blame]
initial.commit09911bf2008-07-26 23:55:291// Copyright 2008, Google Inc.
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
8// * Redistributions of source code must retain the above copyright
9// notice, this list of conditions and the following disclaimer.
10// * Redistributions in binary form must reproduce the above
11// copyright notice, this list of conditions and the following disclaimer
12// in the documentation and/or other materials provided with the
13// distribution.
14// * Neither the name of Google Inc. nor the names of its
15// contributors may be used to endorse or promote products derived from
16// this software without specific prior written permission.
17//
18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30#ifndef CHROME_COMMON_IPC_CHANNEL_H__
31#define CHROME_COMMON_IPC_CHANNEL_H__
32
33#include <queue>
34
35#include "base/message_loop.h"
36#include "chrome/common/ipc_message.h"
37
38namespace IPC {
39
40//------------------------------------------------------------------------------
41
42class Channel : public MessageLoop::Watcher,
43 public Message::Sender {
44 // Security tests need access to the pipe handle.
45 friend class ChannelTest;
46
47 public:
48 // Implemented by consumers of a Channel to receive messages.
49 class Listener {
50 public:
51 // Called when a message is received.
52 virtual void OnMessageReceived(const Message& message) = 0;
53
54 // Called when the channel is connected and we have received the internal
55 // Hello message from the peer.
56 virtual void OnChannelConnected(int32 peer_pid) {}
57
58 // Called when an error is detected that causes the channel to close.
59 // This method is not called when a channel is closed normally.
60 virtual void OnChannelError() {}
61 };
62
63 enum Mode {
64 MODE_SERVER,
65 MODE_CLIENT
66 };
67
68 // The maximum message size in bytes. Attempting to receive a
69 // message of this size or bigger results in a channel error.
70 enum {
71 kMaximumMessageSize = 256 * 1024 * 1024
72 };
73
74 // Initialize a Channel.
75 //
76 // @param channel_id
77 // Identifies the communication Channel.
78 // @param mode
79 // Specifies whether this Channel is to operate in server mode or client
80 // mode. In server mode, the Channel is responsible for setting up the
81 // IPC object, whereas in client mode, the Channel merely connects
82 // to the already established IPC object.
83 // @param listener
84 // Receives a callback on the current thread for each newly received
85 // message.
86 //
87 Channel(const std::wstring& channel_id, Mode mode, Listener* listener);
88
89 ~Channel() { Close(); }
90
91 // Connect the pipe. On the server side, this will initiate
92 // waiting for connections. On the client, it attempts to
93 // connect to a pre-existing pipe. Note, calling Connect()
94 // will not block the calling thread and may complete
95 // asynchronously.
96 bool Connect();
97
98 // Close this Channel explicitly. May be called multiple times.
99 void Close();
100
101 // Modify the Channel's listener.
102 void set_listener(Listener* listener) { listener_ = listener; }
103
104 // Send a message over the Channel to the listener on the other end.
105 //
106 // @param message
107 // The Message to send, which must be allocated using operator new. This
108 // object will be deleted once the contents of the Message have been sent.
109 //
110 // FIXME bug 551500: the channel does not notice failures, so if the
111 // renderer crashes, it will silently succeed, leaking the parameter.
112 // At least the leak will be fixed by...
113 //
114 virtual bool Send(Message* message);
115
116 // Process any pending incoming and outgoing messages. Wait for at most
117 // max_wait_msec for pending messages if there are none. Returns true if
118 // there were no pending messages or if pending messages were successfully
119 // processed. Returns false if there are pending messages that cannot be
120 // processed for some reason (e.g., because ProcessIncomingMessages would be
121 // re-entered).
122 // TODO(darin): Need a better way of dealing with the recursion problem.
123 bool ProcessPendingMessages(DWORD max_wait_msec);
124
125 private:
126 const std::wstring PipeName(const std::wstring& channel_id) const;
127 bool CreatePipe(const std::wstring& channel_id, Mode mode);
128 bool ProcessConnection();
129 bool ProcessIncomingMessages();
130 bool ProcessOutgoingMessages();
131
132 // MessageLoop::Watcher implementation
133 virtual void OnObjectSignaled(HANDLE object);
134
135 private:
136 enum {
137 BUF_SIZE = 4096
138 };
139
140 struct State {
141 State();
142 ~State();
143 OVERLAPPED overlapped;
144 bool is_pending;
145 };
146
147 State input_state_;
148 State output_state_;
149
150 HANDLE pipe_;
151 Listener* listener_;
152
153 // Messages to be sent are queued here.
154 std::queue<Message*> output_queue_;
155
156 // We read from the pipe into this buffer
157 char input_buf_[BUF_SIZE];
158
159 // Large messages that span multiple pipe buffers, get built-up using
160 // this buffer.
161 std::string input_overflow_buf_;
162
163 // In server-mode, we have to wait for the client to connect before we
164 // can begin reading. We make use of the input_state_ when performing
165 // the connect operation in overlapped mode.
166 bool waiting_connect_;
167
168 // This flag is set when processing incoming messages. It is used to
169 // avoid recursing through ProcessIncomingMessages, which could cause
170 // problems. TODO(darin): make this unnecessary
171 bool processing_incoming_;
172
173 // The Hello message is internal to the Channel class. It is sent
174 // by the peer when the channel is connected. The message contains
175 // just the process id (pid). The message has a special routing_id
176 // (MSG_ROUTING_NONE) and type (HELLO_MESSAGE_TYPE).
177 enum {
178 HELLO_MESSAGE_TYPE = MAXWORD // Maximum value of message type (WORD),
179 // to avoid conflicting with normal
180 // message types, which are enumeration
181 // constants starting from 0.
182 };
183};
184
185}
186
187#endif // CHROME_COMMON_IPC_CHANNEL_H__