| 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 |