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_DISPATCHER_H_ 6 #define MOJO_EDK_SYSTEM_DISPATCHER_H_ 7 8 #include <stddef.h> 9 #include <stdint.h> 10 11 #include <memory> 12 #include <ostream> 13 #include <vector> 14 15 #include "base/macros.h" 16 #include "base/memory/ref_counted.h" 17 #include "base/synchronization/lock.h" 18 #include "mojo/edk/embedder/platform_handle.h" 19 #include "mojo/edk/embedder/platform_shared_buffer.h" 20 #include "mojo/edk/system/handle_signals_state.h" 21 #include "mojo/edk/system/ports/name.h" 22 #include "mojo/edk/system/system_impl_export.h" 23 #include "mojo/edk/system/watcher.h" 24 #include "mojo/public/c/system/buffer.h" 25 #include "mojo/public/c/system/data_pipe.h" 26 #include "mojo/public/c/system/message_pipe.h" 27 #include "mojo/public/c/system/types.h" 28 29 namespace mojo { 30 namespace edk { 31 32 class Awakable; 33 class Dispatcher; 34 class MessageForTransit; 35 36 using DispatcherVector = std::vector<scoped_refptr<Dispatcher>>; 37 38 // A |Dispatcher| implements Mojo EDK calls that are associated with a 39 // particular MojoHandle, with the exception of MojoWait and MojoWaitMany ( 40 // which are implemented directly in Core.). 41 class MOJO_SYSTEM_IMPL_EXPORT Dispatcher 42 : public base::RefCountedThreadSafe<Dispatcher> { 43 public: 44 struct DispatcherInTransit { 45 DispatcherInTransit(); 46 DispatcherInTransit(const DispatcherInTransit& other); 47 ~DispatcherInTransit(); 48 49 scoped_refptr<Dispatcher> dispatcher; 50 MojoHandle local_handle; 51 }; 52 53 enum class Type { 54 UNKNOWN = 0, 55 MESSAGE_PIPE, 56 DATA_PIPE_PRODUCER, 57 DATA_PIPE_CONSUMER, 58 SHARED_BUFFER, 59 WAIT_SET, 60 61 // "Private" types (not exposed via the public interface): 62 PLATFORM_HANDLE = -1, 63 }; 64 65 // All Dispatchers must minimally implement these methods. 66 67 virtual Type GetType() const = 0; 68 virtual MojoResult Close() = 0; 69 70 ///////////// Watch API //////////////////// 71 72 virtual MojoResult Watch(MojoHandleSignals signals, 73 const Watcher::WatchCallback& callback, 74 uintptr_t context); 75 76 virtual MojoResult CancelWatch(uintptr_t context); 77 78 ///////////// Message pipe API ///////////// 79 80 virtual MojoResult WriteMessage(std::unique_ptr<MessageForTransit> message, 81 MojoWriteMessageFlags flags); 82 83 virtual MojoResult ReadMessage(std::unique_ptr<MessageForTransit>* message, 84 uint32_t* num_bytes, 85 MojoHandle* handles, 86 uint32_t* num_handles, 87 MojoReadMessageFlags flags, 88 bool read_any_size); 89 90 ///////////// Shared buffer API ///////////// 91 92 // |options| may be null. |new_dispatcher| must not be null, but 93 // |*new_dispatcher| should be null (and will contain the dispatcher for the 94 // new handle on success). 95 virtual MojoResult DuplicateBufferHandle( 96 const MojoDuplicateBufferHandleOptions* options, 97 scoped_refptr<Dispatcher>* new_dispatcher); 98 99 virtual MojoResult MapBuffer( 100 uint64_t offset, 101 uint64_t num_bytes, 102 MojoMapBufferFlags flags, 103 std::unique_ptr<PlatformSharedBufferMapping>* mapping); 104 105 ///////////// Data pipe consumer API ///////////// 106 107 virtual MojoResult ReadData(void* elements, 108 uint32_t* num_bytes, 109 MojoReadDataFlags flags); 110 111 virtual MojoResult BeginReadData(const void** buffer, 112 uint32_t* buffer_num_bytes, 113 MojoReadDataFlags flags); 114 115 virtual MojoResult EndReadData(uint32_t num_bytes_read); 116 117 ///////////// Data pipe producer API ///////////// 118 119 virtual MojoResult WriteData(const void* elements, 120 uint32_t* num_bytes, 121 MojoWriteDataFlags flags); 122 123 virtual MojoResult BeginWriteData(void** buffer, 124 uint32_t* buffer_num_bytes, 125 MojoWriteDataFlags flags); 126 127 virtual MojoResult EndWriteData(uint32_t num_bytes_written); 128 129 ///////////// Wait set API ///////////// 130 131 // Adds a dispatcher to wait on. When the dispatcher satisfies |signals|, it 132 // will be returned in the next call to |GetReadyDispatchers()|. If 133 // |dispatcher| has been added, it must be removed before adding again, 134 // otherwise |MOJO_RESULT_ALREADY_EXISTS| will be returned. 135 virtual MojoResult AddWaitingDispatcher( 136 const scoped_refptr<Dispatcher>& dispatcher, 137 MojoHandleSignals signals, 138 uintptr_t context); 139 140 // Removes a dispatcher to wait on. If |dispatcher| has not been added, 141 // |MOJO_RESULT_NOT_FOUND| will be returned. 142 virtual MojoResult RemoveWaitingDispatcher( 143 const scoped_refptr<Dispatcher>& dispatcher); 144 145 // Returns a set of ready dispatchers. |*count| is the maximum number of 146 // dispatchers to return, and will contain the number of dispatchers returned 147 // in |dispatchers| on completion. 148 virtual MojoResult GetReadyDispatchers(uint32_t* count, 149 DispatcherVector* dispatchers, 150 MojoResult* results, 151 uintptr_t* contexts); 152 153 ///////////// General-purpose API for all handle types ///////// 154 155 // Gets the current handle signals state. (The default implementation simply 156 // returns a default-constructed |HandleSignalsState|, i.e., no signals 157 // satisfied or satisfiable.) Note: The state is subject to change from other 158 // threads. 159 virtual HandleSignalsState GetHandleSignalsState() const; 160 161 // Adds an awakable to this dispatcher, which will be woken up when this 162 // object changes state to satisfy |signals| with context |context|. It will 163 // also be woken up when it becomes impossible for the object to ever satisfy 164 // |signals| with a suitable error status. 165 // 166 // If |signals_state| is non-null, on *failure* |*signals_state| will be set 167 // to the current handle signals state (on success, it is left untouched). 168 // 169 // Returns: 170 // - |MOJO_RESULT_OK| if the awakable was added; 171 // - |MOJO_RESULT_ALREADY_EXISTS| if |signals| is already satisfied; 172 // - |MOJO_RESULT_INVALID_ARGUMENT| if the dispatcher has been closed; and 173 // - |MOJO_RESULT_FAILED_PRECONDITION| if it is not (or no longer) possible 174 // that |signals| will ever be satisfied. 175 virtual MojoResult AddAwakable(Awakable* awakable, 176 MojoHandleSignals signals, 177 uintptr_t context, 178 HandleSignalsState* signals_state); 179 180 // Removes an awakable from this dispatcher. (It is valid to call this 181 // multiple times for the same |awakable| on the same object, so long as 182 // |AddAwakable()| was called at most once.) If |signals_state| is non-null, 183 // |*signals_state| will be set to the current handle signals state. 184 virtual void RemoveAwakable(Awakable* awakable, 185 HandleSignalsState* signals_state); 186 187 // Informs the caller of the total serialized size (in bytes) and the total 188 // number of platform handles and ports needed to transfer this dispatcher 189 // across a message pipe. 190 // 191 // Must eventually be followed by a call to EndSerializeAndClose(). Note that 192 // StartSerialize() and EndSerialize() are always called in sequence, and 193 // only between calls to BeginTransit() and either (but not both) 194 // CompleteTransitAndClose() or CancelTransit(). 195 // 196 // For this reason it is IMPERATIVE that the implementation ensure a 197 // consistent serializable state between BeginTransit() and 198 // CompleteTransitAndClose()/CancelTransit(). 199 virtual void StartSerialize(uint32_t* num_bytes, 200 uint32_t* num_ports, 201 uint32_t* num_platform_handles); 202 203 // Serializes this dispatcher into |destination|, |ports|, and |handles|. 204 // Returns true iff successful, false otherwise. In either case the dispatcher 205 // will close. 206 // 207 // NOTE: Transit MAY still fail after this call returns. Implementations 208 // should not assume PlatformHandle ownership has transferred until 209 // CompleteTransitAndClose() is called. In other words, if CancelTransit() is 210 // called, the implementation should retain its PlatformHandles in working 211 // condition. 212 virtual bool EndSerialize(void* destination, 213 ports::PortName* ports, 214 PlatformHandle* handles); 215 216 // Does whatever is necessary to begin transit of the dispatcher. This 217 // should return |true| if transit is OK, or false if the underlying resource 218 // is deemed busy by the implementation. 219 virtual bool BeginTransit(); 220 221 // Does whatever is necessary to complete transit of the dispatcher, including 222 // closure. This is only called upon successfully transmitting an outgoing 223 // message containing this serialized dispatcher. 224 virtual void CompleteTransitAndClose(); 225 226 // Does whatever is necessary to cancel transit of the dispatcher. The 227 // dispatcher should remain in a working state and resume normal operation. 228 virtual void CancelTransit(); 229 230 // Deserializes a specific dispatcher type from an incoming message. 231 static scoped_refptr<Dispatcher> Deserialize( 232 Type type, 233 const void* bytes, 234 size_t num_bytes, 235 const ports::PortName* ports, 236 size_t num_ports, 237 PlatformHandle* platform_handles, 238 size_t num_platform_handles); 239 240 protected: 241 friend class base::RefCountedThreadSafe<Dispatcher>; 242 243 Dispatcher(); 244 virtual ~Dispatcher(); 245 246 DISALLOW_COPY_AND_ASSIGN(Dispatcher); 247 }; 248 249 // So logging macros and |DCHECK_EQ()|, etc. work. 250 MOJO_SYSTEM_IMPL_EXPORT inline std::ostream& operator<<(std::ostream& out, 251 Dispatcher::Type type) { 252 return out << static_cast<int>(type); 253 } 254 255 } // namespace edk 256 } // namespace mojo 257 258 #endif // MOJO_EDK_SYSTEM_DISPATCHER_H_ 259