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_PUBLIC_CPP_BINDINGS_CONNECTOR_H_ 6 #define MOJO_PUBLIC_CPP_BINDINGS_CONNECTOR_H_ 7 8 #include <atomic> 9 #include <memory> 10 #include <utility> 11 12 #include "base/callback.h" 13 #include "base/compiler_specific.h" 14 #include "base/memory/ref_counted.h" 15 #include "base/memory/weak_ptr.h" 16 #include "base/optional.h" 17 #include "base/sequence_checker.h" 18 #include "base/sequenced_task_runner.h" 19 #include "mojo/public/cpp/bindings/bindings_export.h" 20 #include "mojo/public/cpp/bindings/message.h" 21 #include "mojo/public/cpp/bindings/sync_handle_watcher.h" 22 #include "mojo/public/cpp/system/core.h" 23 #include "mojo/public/cpp/system/handle_signal_tracker.h" 24 #include "mojo/public/cpp/system/simple_watcher.h" 25 26 namespace base { 27 class Lock; 28 } 29 30 namespace mojo { 31 32 // The Connector class is responsible for performing read/write operations on a 33 // MessagePipe. It writes messages it receives through the MessageReceiver 34 // interface that it subclasses, and it forwards messages it reads through the 35 // MessageReceiver interface assigned as its incoming receiver. 36 // 37 // NOTE: 38 // - MessagePipe I/O is non-blocking. 39 // - Sending messages can be configured to be thread safe (please see comments 40 // of the constructor). Other than that, the object should only be accessed 41 // on the creating sequence. 42 class MOJO_CPP_BINDINGS_EXPORT Connector : public MessageReceiver { 43 public: 44 enum ConnectorConfig { 45 // Connector::Accept() is only called from a single sequence. 46 SINGLE_THREADED_SEND, 47 // Connector::Accept() is allowed to be called from multiple sequences. 48 MULTI_THREADED_SEND 49 }; 50 51 // Determines how this Connector should behave with respect to serialization 52 // of outgoing messages. 53 enum class OutgoingSerializationMode { 54 // Lazy serialization. The Connector prefers to transmit serialized messages 55 // only when it knows its peer endpoint is remote. This ensures outgoing 56 // requests are unserialized by default (when possible, i.e. when generated 57 // bindings support it) and serialized only if and when necessary. 58 kLazy, 59 60 // Eager serialization. The Connector always prefers serialized messages, 61 // ensuring that interface calls will be serialized immediately before 62 // sending on the Connector. 63 kEager, 64 }; 65 66 // Determines how this Connector should behave with respect to serialization 67 // of incoming messages. 68 enum class IncomingSerializationMode { 69 // Accepts and dispatches either serialized or unserialized messages. This 70 // is the only mode that should be used in production. 71 kDispatchAsIs, 72 73 // Accepts either serialized or unserialized messages, but always forces 74 // serialization (if applicable) before dispatch. Should be used only in 75 // test environments to coerce the lazy serialization of a message after 76 // transmission. 77 kSerializeBeforeDispatchForTesting, 78 }; 79 80 // The Connector takes ownership of |message_pipe|. 81 Connector(ScopedMessagePipeHandle message_pipe, 82 ConnectorConfig config, 83 scoped_refptr<base::SequencedTaskRunner> runner); 84 ~Connector() override; 85 86 // Sets outgoing serialization mode. 87 void SetOutgoingSerializationMode(OutgoingSerializationMode mode); 88 void SetIncomingSerializationMode(IncomingSerializationMode mode); 89 90 // Sets the receiver to handle messages read from the message pipe. The 91 // Connector will read messages from the pipe regardless of whether or not an 92 // incoming receiver has been set. set_incoming_receiver(MessageReceiver * receiver)93 void set_incoming_receiver(MessageReceiver* receiver) { 94 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); 95 incoming_receiver_ = receiver; 96 } 97 98 // Errors from incoming receivers will force the connector into an error 99 // state, where no more messages will be processed. This method is used 100 // during testing to prevent that from happening. set_enforce_errors_from_incoming_receiver(bool enforce)101 void set_enforce_errors_from_incoming_receiver(bool enforce) { 102 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); 103 enforce_errors_from_incoming_receiver_ = enforce; 104 } 105 106 // Sets the error handler to receive notifications when an error is 107 // encountered while reading from the pipe or waiting to read from the pipe. set_connection_error_handler(base::OnceClosure error_handler)108 void set_connection_error_handler(base::OnceClosure error_handler) { 109 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); 110 connection_error_handler_ = std::move(error_handler); 111 } 112 113 // Returns true if an error was encountered while reading from the pipe or 114 // waiting to read from the pipe. encountered_error()115 bool encountered_error() const { 116 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); 117 return error_; 118 } 119 120 // Closes the pipe. The connector is put into a quiescent state. 121 // 122 // Please note that this method shouldn't be called unless it results from an 123 // explicit request of the user of bindings (e.g., the user sets an 124 // InterfacePtr to null or closes a Binding). 125 void CloseMessagePipe(); 126 127 // Releases the pipe. Connector is put into a quiescent state. 128 ScopedMessagePipeHandle PassMessagePipe(); 129 130 // Enters the error state. The upper layer may do this for unrecoverable 131 // issues such as invalid messages are received. If a connection error handler 132 // has been set, it will be called asynchronously. 133 // 134 // It is a no-op if the connector is already in the error state or there isn't 135 // a bound message pipe. Otherwise, it closes the message pipe, which notifies 136 // the other end and also prevents potential danger (say, the caller raises 137 // an error because it believes the other end is malicious). In order to 138 // appear to the user that the connector still binds to a message pipe, it 139 // creates a new message pipe, closes one end and binds to the other. 140 void RaiseError(); 141 142 // Is the connector bound to a MessagePipe handle? is_valid()143 bool is_valid() const { 144 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); 145 return message_pipe_.is_valid(); 146 } 147 148 // Waits for the next message on the pipe, blocking until one arrives, 149 // |deadline| elapses, or an error happens. Returns |true| if a message has 150 // been delivered, |false| otherwise. 151 bool WaitForIncomingMessage(MojoDeadline deadline); 152 153 // See Binding for details of pause/resume. 154 void PauseIncomingMethodCallProcessing(); 155 void ResumeIncomingMethodCallProcessing(); 156 157 // MessageReceiver implementation: 158 bool PrefersSerializedMessages() override; 159 bool Accept(Message* message) override; 160 handle()161 MessagePipeHandle handle() const { 162 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); 163 return message_pipe_.get(); 164 } 165 166 // Allows |message_pipe_| to be watched while others perform sync handle 167 // watching on the same sequence. Please see comments of 168 // SyncHandleWatcher::AllowWokenUpBySyncWatchOnSameThread(). 169 void AllowWokenUpBySyncWatchOnSameThread(); 170 171 // Watches |message_pipe_| (as well as other handles registered to be watched 172 // together) synchronously. 173 // This method: 174 // - returns true when |should_stop| is set to true; 175 // - return false when any error occurs, including |message_pipe_| being 176 // closed. 177 bool SyncWatch(const bool* should_stop); 178 179 // Whether currently the control flow is inside the sync handle watcher 180 // callback. 181 // It always returns false after CloseMessagePipe()/PassMessagePipe(). during_sync_handle_watcher_callback()182 bool during_sync_handle_watcher_callback() const { 183 return sync_handle_watcher_callback_count_ > 0; 184 } 185 task_runner()186 base::SequencedTaskRunner* task_runner() const { return task_runner_.get(); } 187 188 // Sets the tag used by the heap profiler. 189 // |tag| must be a const string literal. 190 void SetWatcherHeapProfilerTag(const char* tag); 191 192 // Allows testing environments to override the default serialization behavior 193 // of newly constructed Connector instances. Must be called before any 194 // Connector instances are constructed. 195 static void OverrideDefaultSerializationBehaviorForTesting( 196 OutgoingSerializationMode outgoing_mode, 197 IncomingSerializationMode incoming_mode); 198 199 private: 200 class ActiveDispatchTracker; 201 class RunLoopNestingObserver; 202 203 // Callback of mojo::SimpleWatcher. 204 void OnWatcherHandleReady(MojoResult result); 205 // Callback of SyncHandleWatcher. 206 void OnSyncHandleWatcherHandleReady(MojoResult result); 207 void OnHandleReadyInternal(MojoResult result); 208 209 void WaitToReadMore(); 210 211 // Returns false if it is impossible to receive more messages in the future. 212 // |this| may have been destroyed in that case. 213 WARN_UNUSED_RESULT bool ReadSingleMessage(MojoResult* read_result); 214 215 // |this| can be destroyed during message dispatch. 216 void ReadAllAvailableMessages(); 217 218 // If |force_pipe_reset| is true, this method replaces the existing 219 // |message_pipe_| with a dummy message pipe handle (whose peer is closed). 220 // If |force_async_handler| is true, |connection_error_handler_| is called 221 // asynchronously. 222 void HandleError(bool force_pipe_reset, bool force_async_handler); 223 224 // Cancels any calls made to |waiter_|. 225 void CancelWait(); 226 227 void EnsureSyncWatcherExists(); 228 229 base::OnceClosure connection_error_handler_; 230 231 ScopedMessagePipeHandle message_pipe_; 232 MessageReceiver* incoming_receiver_ = nullptr; 233 234 scoped_refptr<base::SequencedTaskRunner> task_runner_; 235 std::unique_ptr<SimpleWatcher> handle_watcher_; 236 base::Optional<HandleSignalTracker> peer_remoteness_tracker_; 237 238 std::atomic<bool> error_; 239 bool drop_writes_ = false; 240 bool enforce_errors_from_incoming_receiver_ = true; 241 242 bool paused_ = false; 243 244 OutgoingSerializationMode outgoing_serialization_mode_; 245 IncomingSerializationMode incoming_serialization_mode_; 246 247 // If sending messages is allowed from multiple sequences, |lock_| is used to 248 // protect modifications to |message_pipe_| and |drop_writes_|. 249 base::Optional<base::Lock> lock_; 250 251 std::unique_ptr<SyncHandleWatcher> sync_watcher_; 252 bool allow_woken_up_by_others_ = false; 253 // If non-zero, currently the control flow is inside the sync handle watcher 254 // callback. 255 size_t sync_handle_watcher_callback_count_ = 0; 256 257 SEQUENCE_CHECKER(sequence_checker_); 258 259 base::Lock connected_lock_; 260 bool connected_ = true; 261 262 // The tag used to track heap allocations that originated from a Watcher 263 // notification. 264 const char* heap_profiler_tag_ = "unknown interface"; 265 266 // A cached pointer to the RunLoopNestingObserver for the thread on which this 267 // Connector was created. 268 RunLoopNestingObserver* const nesting_observer_; 269 270 // |true| iff the Connector is currently dispatching a message. Used to detect 271 // nested dispatch operations. 272 bool is_dispatching_ = false; 273 274 #if defined(ENABLE_IPC_FUZZER) 275 std::unique_ptr<MessageReceiver> message_dumper_; 276 #endif 277 278 // Create a single weak ptr and use it everywhere, to avoid the malloc/free 279 // cost of creating a new weak ptr whenever it is needed. 280 // NOTE: This weak pointer is invalidated when the message pipe is closed or 281 // transferred (i.e., when |connected_| is set to false). 282 base::WeakPtr<Connector> weak_self_; 283 base::WeakPtrFactory<Connector> weak_factory_; 284 285 DISALLOW_COPY_AND_ASSIGN(Connector); 286 }; 287 288 } // namespace mojo 289 290 #endif // MOJO_PUBLIC_CPP_BINDINGS_CONNECTOR_H_ 291