OLD | NEW |
| (Empty) |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #ifndef MOJO_EDK_SYSTEM_CHANNEL_H_ | |
6 #define MOJO_EDK_SYSTEM_CHANNEL_H_ | |
7 | |
8 #include <stdint.h> | |
9 | |
10 #include "base/containers/hash_tables.h" | |
11 #include "base/macros.h" | |
12 #include "base/memory/ref_counted.h" | |
13 #include "base/memory/scoped_ptr.h" | |
14 #include "base/strings/string_piece.h" | |
15 #include "base/synchronization/lock.h" | |
16 #include "base/threading/thread_checker.h" | |
17 #include "mojo/edk/embedder/scoped_platform_handle.h" | |
18 #include "mojo/edk/system/channel_endpoint.h" | |
19 #include "mojo/edk/system/channel_endpoint_id.h" | |
20 #include "mojo/edk/system/incoming_endpoint.h" | |
21 #include "mojo/edk/system/message_in_transit.h" | |
22 #include "mojo/edk/system/raw_channel.h" | |
23 #include "mojo/edk/system/system_impl_export.h" | |
24 #include "mojo/public/c/system/types.h" | |
25 | |
26 namespace mojo { | |
27 | |
28 namespace embedder { | |
29 class PlatformSupport; | |
30 } | |
31 | |
32 namespace system { | |
33 | |
34 class ChannelEndpointClient; | |
35 class ChannelManager; | |
36 class MessageInTransitQueue; | |
37 | |
38 // This class is mostly thread-safe. It must be created on an I/O thread. | |
39 // |Init()| must be called on that same thread before it becomes thread-safe (in | |
40 // particular, before references are given to any other thread) and |Shutdown()| | |
41 // must be called on that same thread before destruction. Its public methods are | |
42 // otherwise thread-safe. (Many private methods are restricted to the creation | |
43 // thread.) It may be destroyed on any thread, in the sense that the last | |
44 // reference to it may be released on any thread, with the proviso that | |
45 // |Shutdown()| must have been called first (so the pattern is that a "main" | |
46 // reference is kept on its creation thread and is released after |Shutdown()| | |
47 // is called, but other threads may have temporarily "dangling" references). | |
48 // | |
49 // Note the lock order (in order of allowable acquisition): | |
50 // |ChannelEndpointClient| (e.g., |MessagePipe|), |ChannelEndpoint|, |Channel|. | |
51 // Thus |Channel| may not call into |ChannelEndpoint| with |Channel|'s lock | |
52 // held. | |
53 class MOJO_SYSTEM_IMPL_EXPORT Channel | |
54 : public base::RefCountedThreadSafe<Channel>, | |
55 public RawChannel::Delegate { | |
56 public: | |
57 // |platform_support| (typically owned by |Core|) must remain alive until | |
58 // after |Shutdown()| is called. | |
59 explicit Channel(embedder::PlatformSupport* platform_support); | |
60 | |
61 // This must be called on the creation thread before any other methods are | |
62 // called, and before references to this object are given to any other | |
63 // threads. |raw_channel| should be uninitialized. | |
64 void Init(scoped_ptr<RawChannel> raw_channel); | |
65 | |
66 // Sets the channel manager associated with this channel. This should be set | |
67 // at most once and only called before |WillShutdownSoon()| (and | |
68 // |Shutdown()|). | |
69 void SetChannelManager(ChannelManager* channel_manager); | |
70 | |
71 // This must be called on the creation thread before destruction (which can | |
72 // happen on any thread). | |
73 void Shutdown(); | |
74 | |
75 // Signals that |Shutdown()| will be called soon (this may be called from any | |
76 // thread, unlike |Shutdown()|). Warnings will be issued if, e.g., messages | |
77 // are written after this is called; other warnings may be suppressed. (This | |
78 // may be called multiple times, or not at all.) | |
79 // | |
80 // If set, the channel manager associated with this channel will be reset. | |
81 void WillShutdownSoon(); | |
82 | |
83 // Called to set (i.e., attach and run) the bootstrap (first) endpoint on the | |
84 // channel. Both the local and remote IDs are the bootstrap ID (given by | |
85 // |ChannelEndpointId::GetBootstrap()|). | |
86 // | |
87 // (Bootstrapping is symmetric: Both sides call this, which will establish the | |
88 // first connection across a channel.) | |
89 void SetBootstrapEndpoint(scoped_refptr<ChannelEndpoint> endpoint); | |
90 | |
91 // This forwards |message| verbatim to |raw_channel_|. | |
92 bool WriteMessage(scoped_ptr<MessageInTransit> message); | |
93 | |
94 // See |RawChannel::IsWriteBufferEmpty()|. | |
95 // TODO(vtl): Maybe we shouldn't expose this, and instead have a | |
96 // |FlushWriteBufferAndShutdown()| or something like that. | |
97 bool IsWriteBufferEmpty(); | |
98 | |
99 // Removes the given endpoint from this channel (|local_id| and |remote_id| | |
100 // are specified as an optimization; the latter should be an invalid | |
101 // |ChannelEndpointId| if the endpoint is not yet running). Note: If this is | |
102 // called, the |Channel| will *not* call | |
103 // |ChannelEndpoint::DetachFromChannel()|. | |
104 void DetachEndpoint(ChannelEndpoint* endpoint, | |
105 ChannelEndpointId local_id, | |
106 ChannelEndpointId remote_id); | |
107 | |
108 // Returns the size of a serialized endpoint (see |SerializeEndpoint...()| and | |
109 // |DeserializeEndpoint()| below). This value will remain constant for a given | |
110 // instance of |Channel|. | |
111 size_t GetSerializedEndpointSize() const; | |
112 | |
113 // Endpoint serialization methods: From the |Channel|'s point of view, there | |
114 // are three cases (discussed further below) and thus three methods. | |
115 // | |
116 // All three methods have a |destination| argument, which should be a buffer | |
117 // to which auxiliary information will be written and which should be | |
118 // transmitted to the peer |Channel| by some other means, but using this | |
119 // |Channel|. It should be a buffer of (at least) the size returned by | |
120 // |GetSerializedEndpointSize()| (exactly that much data will be written). | |
121 // | |
122 // All three also have a |message_queue| argument, which if non-null is the | |
123 // queue of messages already received by the endpoint to be serialized. | |
124 // | |
125 // Note that "serialize" really means "send" -- the |endpoint| will be sent | |
126 // "immediately". The contents of the |destination| buffer can then be used to | |
127 // claim the rematerialized endpoint from the peer |Channel|. (|destination| | |
128 // must be sent using this |Channel|, since otherwise it may be received | |
129 // before it is valid to the peer |Channel|.) | |
130 // | |
131 // Case 1: The endpoint's peer is already closed. | |
132 // | |
133 // Case 2: The endpoint's peer is local (i.e., it has a | |
134 // |ChannelEndpointClient| but no peer |ChannelEndpoint|). | |
135 // | |
136 // Case 3: The endpoint's peer is remote (i.e., it has a peer | |
137 // |ChannelEndpoint|). (This has two subcases: the peer endpoint may be on | |
138 // this |Channel| or another |Channel|.) | |
139 void SerializeEndpointWithClosedPeer(void* destination, | |
140 MessageInTransitQueue* message_queue); | |
141 // This one returns the |ChannelEndpoint| for the serialized endpoint (which | |
142 // can be used by, e.g., a |ProxyMessagePipeEndpoint|. | |
143 scoped_refptr<ChannelEndpoint> SerializeEndpointWithLocalPeer( | |
144 void* destination, | |
145 MessageInTransitQueue* message_queue, | |
146 ChannelEndpointClient* endpoint_client, | |
147 unsigned endpoint_client_port); | |
148 void SerializeEndpointWithRemotePeer( | |
149 void* destination, | |
150 MessageInTransitQueue* message_queue, | |
151 scoped_refptr<ChannelEndpoint> peer_endpoint); | |
152 | |
153 // Deserializes an endpoint that was sent from the peer |Channel| (using | |
154 // |SerializeEndpoint...()|. |source| should be (a copy of) the data that | |
155 // |SerializeEndpoint...()| wrote, and must be (at least) | |
156 // |GetSerializedEndpointSize()| bytes. This returns the deserialized | |
157 // |IncomingEndpoint| (which can be converted into a |MessagePipe|) or null on | |
158 // error. | |
159 scoped_refptr<IncomingEndpoint> DeserializeEndpoint(const void* source); | |
160 | |
161 // See |RawChannel::GetSerializedPlatformHandleSize()|. | |
162 size_t GetSerializedPlatformHandleSize() const; | |
163 | |
164 embedder::PlatformSupport* platform_support() const { | |
165 return platform_support_; | |
166 } | |
167 | |
168 private: | |
169 friend class base::RefCountedThreadSafe<Channel>; | |
170 ~Channel() override; | |
171 | |
172 // |RawChannel::Delegate| implementation (only called on the creation thread): | |
173 void OnReadMessage( | |
174 const MessageInTransit::View& message_view, | |
175 embedder::ScopedPlatformHandleVectorPtr platform_handles) override; | |
176 void OnError(Error error) override; | |
177 | |
178 // Helpers for |OnReadMessage| (only called on the creation thread): | |
179 void OnReadMessageForEndpoint( | |
180 const MessageInTransit::View& message_view, | |
181 embedder::ScopedPlatformHandleVectorPtr platform_handles); | |
182 void OnReadMessageForChannel( | |
183 const MessageInTransit::View& message_view, | |
184 embedder::ScopedPlatformHandleVectorPtr platform_handles); | |
185 | |
186 // Handles "attach and run endpoint" messages. | |
187 bool OnAttachAndRunEndpoint(ChannelEndpointId local_id, | |
188 ChannelEndpointId remote_id); | |
189 // Handles "remove endpoint" messages. | |
190 bool OnRemoveEndpoint(ChannelEndpointId local_id, | |
191 ChannelEndpointId remote_id); | |
192 // Handles "remove endpoint ack" messages. | |
193 bool OnRemoveEndpointAck(ChannelEndpointId local_id); | |
194 | |
195 // Handles errors (e.g., invalid messages) from the remote side. Callable from | |
196 // any thread. | |
197 void HandleRemoteError(const base::StringPiece& error_message); | |
198 // Handles internal errors/failures from the local side. Callable from any | |
199 // thread. | |
200 void HandleLocalError(const base::StringPiece& error_message); | |
201 | |
202 // Helper for |SerializeEndpoint...()|: Attaches the given (non-bootstrap) | |
203 // endpoint to this channel and runs it. This assigns the endpoint both local | |
204 // and remote IDs. This will also send a |kSubtypeChannelAttachAndRunEndpoint| | |
205 // message to the remote side to tell it to create an endpoint as well. This | |
206 // returns the *remote* ID (one for which |is_remote()| returns true). | |
207 // | |
208 // TODO(vtl): Maybe limit the number of attached message pipes. | |
209 ChannelEndpointId AttachAndRunEndpoint( | |
210 scoped_refptr<ChannelEndpoint> endpoint); | |
211 | |
212 // Helper to send channel control messages. Returns true on success. Should be | |
213 // called *without* |lock_| held. Callable from any thread. | |
214 bool SendControlMessage(MessageInTransit::Subtype subtype, | |
215 ChannelEndpointId source_id, | |
216 ChannelEndpointId destination_id); | |
217 | |
218 base::ThreadChecker creation_thread_checker_; | |
219 | |
220 embedder::PlatformSupport* const platform_support_; | |
221 | |
222 // Note: |ChannelEndpointClient|s (in particular, |MessagePipe|s) MUST NOT be | |
223 // used under |lock_|. E.g., |lock_| can only be acquired after | |
224 // |MessagePipe::lock_|, never before. Thus to call into a | |
225 // |ChannelEndpointClient|, a reference should be acquired from | |
226 // |local_id_to_endpoint_map_| under |lock_| and then the lock released. | |
227 base::Lock lock_; // Protects the members below. | |
228 | |
229 scoped_ptr<RawChannel> raw_channel_; | |
230 bool is_running_; | |
231 // Set when |WillShutdownSoon()| is called. | |
232 bool is_shutting_down_; | |
233 | |
234 // Has a reference to us. | |
235 ChannelManager* channel_manager_; | |
236 | |
237 typedef base::hash_map<ChannelEndpointId, scoped_refptr<ChannelEndpoint>> | |
238 IdToEndpointMap; | |
239 // Map from local IDs to endpoints. If the endpoint is null, this means that | |
240 // we're just waiting for the remove ack before removing the entry. | |
241 IdToEndpointMap local_id_to_endpoint_map_; | |
242 // Note: The IDs generated by this should be checked for existence before use. | |
243 LocalChannelEndpointIdGenerator local_id_generator_; | |
244 | |
245 typedef base::hash_map<ChannelEndpointId, scoped_refptr<IncomingEndpoint>> | |
246 IdToIncomingEndpointMap; | |
247 // Map from local IDs to incoming endpoints (i.e., those received inside other | |
248 // messages, but not yet claimed via |DeserializeEndpoint()|). | |
249 IdToIncomingEndpointMap incoming_endpoints_; | |
250 // TODO(vtl): We need to keep track of remote IDs (so that we don't collide | |
251 // if/when we wrap). | |
252 RemoteChannelEndpointIdGenerator remote_id_generator_; | |
253 | |
254 DISALLOW_COPY_AND_ASSIGN(Channel); | |
255 }; | |
256 | |
257 } // namespace system | |
258 } // namespace mojo | |
259 | |
260 #endif // MOJO_EDK_SYSTEM_CHANNEL_H_ | |
OLD | NEW |