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 #include "mojo/system/dispatcher.h"
6
7 #include "base/logging.h"
8 #include "mojo/system/constants.h"
9 #include "mojo/system/message_pipe_dispatcher.h"
10 #include "mojo/system/platform_handle_dispatcher.h"
11 #include "mojo/system/shared_buffer_dispatcher.h"
12
13 namespace mojo {
14 namespace system {
15
16 namespace test {
17
18 // TODO(vtl): Maybe this should be defined in a test-only file instead.
DispatcherTryStartTransport(Dispatcher * dispatcher)19 DispatcherTransport DispatcherTryStartTransport(Dispatcher* dispatcher) {
20 return Dispatcher::HandleTableAccess::TryStartTransport(dispatcher);
21 }
22
23 } // namespace test
24
25 // Dispatcher ------------------------------------------------------------------
26
27 // static
TryStartTransport(Dispatcher * dispatcher)28 DispatcherTransport Dispatcher::HandleTableAccess::TryStartTransport(
29 Dispatcher* dispatcher) {
30 DCHECK(dispatcher);
31
32 if (!dispatcher->lock_.Try())
33 return DispatcherTransport();
34
35 // We shouldn't race with things that close dispatchers, since closing can
36 // only take place either under |handle_table_lock_| or when the handle is
37 // marked as busy.
38 DCHECK(!dispatcher->is_closed_);
39
40 return DispatcherTransport(dispatcher);
41 }
42
43 // static
StartSerialize(Dispatcher * dispatcher,Channel * channel,size_t * max_size,size_t * max_platform_handles)44 void Dispatcher::TransportDataAccess::StartSerialize(
45 Dispatcher* dispatcher,
46 Channel* channel,
47 size_t* max_size,
48 size_t* max_platform_handles) {
49 DCHECK(dispatcher);
50 dispatcher->StartSerialize(channel, max_size, max_platform_handles);
51 }
52
53 // static
EndSerializeAndClose(Dispatcher * dispatcher,Channel * channel,void * destination,size_t * actual_size,embedder::PlatformHandleVector * platform_handles)54 bool Dispatcher::TransportDataAccess::EndSerializeAndClose(
55 Dispatcher* dispatcher,
56 Channel* channel,
57 void* destination,
58 size_t* actual_size,
59 embedder::PlatformHandleVector* platform_handles) {
60 DCHECK(dispatcher);
61 return dispatcher->EndSerializeAndClose(
62 channel, destination, actual_size, platform_handles);
63 }
64
65 // static
Deserialize(Channel * channel,int32_t type,const void * source,size_t size,embedder::PlatformHandleVector * platform_handles)66 scoped_refptr<Dispatcher> Dispatcher::TransportDataAccess::Deserialize(
67 Channel* channel,
68 int32_t type,
69 const void* source,
70 size_t size,
71 embedder::PlatformHandleVector* platform_handles) {
72 switch (static_cast<int32_t>(type)) {
73 case kTypeUnknown:
74 DVLOG(2) << "Deserializing invalid handle";
75 return scoped_refptr<Dispatcher>();
76 case kTypeMessagePipe:
77 return scoped_refptr<Dispatcher>(
78 MessagePipeDispatcher::Deserialize(channel, source, size));
79 case kTypeDataPipeProducer:
80 case kTypeDataPipeConsumer:
81 // TODO(vtl): Implement.
82 LOG(WARNING) << "Deserialization of dispatcher type " << type
83 << " not supported";
84 return scoped_refptr<Dispatcher>();
85 case kTypeSharedBuffer:
86 return scoped_refptr<Dispatcher>(SharedBufferDispatcher::Deserialize(
87 channel, source, size, platform_handles));
88 case kTypePlatformHandle:
89 return scoped_refptr<Dispatcher>(PlatformHandleDispatcher::Deserialize(
90 channel, source, size, platform_handles));
91 }
92 LOG(WARNING) << "Unknown dispatcher type " << type;
93 return scoped_refptr<Dispatcher>();
94 }
95
Close()96 MojoResult Dispatcher::Close() {
97 base::AutoLock locker(lock_);
98 if (is_closed_)
99 return MOJO_RESULT_INVALID_ARGUMENT;
100
101 CloseNoLock();
102 return MOJO_RESULT_OK;
103 }
104
WriteMessage(UserPointer<const void> bytes,uint32_t num_bytes,std::vector<DispatcherTransport> * transports,MojoWriteMessageFlags flags)105 MojoResult Dispatcher::WriteMessage(
106 UserPointer<const void> bytes,
107 uint32_t num_bytes,
108 std::vector<DispatcherTransport>* transports,
109 MojoWriteMessageFlags flags) {
110 DCHECK(!transports || (transports->size() > 0 &&
111 transports->size() < kMaxMessageNumHandles));
112
113 base::AutoLock locker(lock_);
114 if (is_closed_)
115 return MOJO_RESULT_INVALID_ARGUMENT;
116
117 return WriteMessageImplNoLock(bytes, num_bytes, transports, flags);
118 }
119
ReadMessage(UserPointer<void> bytes,UserPointer<uint32_t> num_bytes,DispatcherVector * dispatchers,uint32_t * num_dispatchers,MojoReadMessageFlags flags)120 MojoResult Dispatcher::ReadMessage(UserPointer<void> bytes,
121 UserPointer<uint32_t> num_bytes,
122 DispatcherVector* dispatchers,
123 uint32_t* num_dispatchers,
124 MojoReadMessageFlags flags) {
125 DCHECK(!num_dispatchers || *num_dispatchers == 0 ||
126 (dispatchers && dispatchers->empty()));
127
128 base::AutoLock locker(lock_);
129 if (is_closed_)
130 return MOJO_RESULT_INVALID_ARGUMENT;
131
132 return ReadMessageImplNoLock(
133 bytes, num_bytes, dispatchers, num_dispatchers, flags);
134 }
135
WriteData(UserPointer<const void> elements,UserPointer<uint32_t> num_bytes,MojoWriteDataFlags flags)136 MojoResult Dispatcher::WriteData(UserPointer<const void> elements,
137 UserPointer<uint32_t> num_bytes,
138 MojoWriteDataFlags flags) {
139 base::AutoLock locker(lock_);
140 if (is_closed_)
141 return MOJO_RESULT_INVALID_ARGUMENT;
142
143 return WriteDataImplNoLock(elements, num_bytes, flags);
144 }
145
BeginWriteData(UserPointer<void * > buffer,UserPointer<uint32_t> buffer_num_bytes,MojoWriteDataFlags flags)146 MojoResult Dispatcher::BeginWriteData(UserPointer<void*> buffer,
147 UserPointer<uint32_t> buffer_num_bytes,
148 MojoWriteDataFlags flags) {
149 base::AutoLock locker(lock_);
150 if (is_closed_)
151 return MOJO_RESULT_INVALID_ARGUMENT;
152
153 return BeginWriteDataImplNoLock(buffer, buffer_num_bytes, flags);
154 }
155
EndWriteData(uint32_t num_bytes_written)156 MojoResult Dispatcher::EndWriteData(uint32_t num_bytes_written) {
157 base::AutoLock locker(lock_);
158 if (is_closed_)
159 return MOJO_RESULT_INVALID_ARGUMENT;
160
161 return EndWriteDataImplNoLock(num_bytes_written);
162 }
163
ReadData(UserPointer<void> elements,UserPointer<uint32_t> num_bytes,MojoReadDataFlags flags)164 MojoResult Dispatcher::ReadData(UserPointer<void> elements,
165 UserPointer<uint32_t> num_bytes,
166 MojoReadDataFlags flags) {
167 base::AutoLock locker(lock_);
168 if (is_closed_)
169 return MOJO_RESULT_INVALID_ARGUMENT;
170
171 return ReadDataImplNoLock(elements, num_bytes, flags);
172 }
173
BeginReadData(UserPointer<const void * > buffer,UserPointer<uint32_t> buffer_num_bytes,MojoReadDataFlags flags)174 MojoResult Dispatcher::BeginReadData(UserPointer<const void*> buffer,
175 UserPointer<uint32_t> buffer_num_bytes,
176 MojoReadDataFlags flags) {
177 base::AutoLock locker(lock_);
178 if (is_closed_)
179 return MOJO_RESULT_INVALID_ARGUMENT;
180
181 return BeginReadDataImplNoLock(buffer, buffer_num_bytes, flags);
182 }
183
EndReadData(uint32_t num_bytes_read)184 MojoResult Dispatcher::EndReadData(uint32_t num_bytes_read) {
185 base::AutoLock locker(lock_);
186 if (is_closed_)
187 return MOJO_RESULT_INVALID_ARGUMENT;
188
189 return EndReadDataImplNoLock(num_bytes_read);
190 }
191
DuplicateBufferHandle(UserPointer<const MojoDuplicateBufferHandleOptions> options,scoped_refptr<Dispatcher> * new_dispatcher)192 MojoResult Dispatcher::DuplicateBufferHandle(
193 UserPointer<const MojoDuplicateBufferHandleOptions> options,
194 scoped_refptr<Dispatcher>* new_dispatcher) {
195 base::AutoLock locker(lock_);
196 if (is_closed_)
197 return MOJO_RESULT_INVALID_ARGUMENT;
198
199 return DuplicateBufferHandleImplNoLock(options, new_dispatcher);
200 }
201
MapBuffer(uint64_t offset,uint64_t num_bytes,MojoMapBufferFlags flags,scoped_ptr<embedder::PlatformSharedBufferMapping> * mapping)202 MojoResult Dispatcher::MapBuffer(
203 uint64_t offset,
204 uint64_t num_bytes,
205 MojoMapBufferFlags flags,
206 scoped_ptr<embedder::PlatformSharedBufferMapping>* mapping) {
207 base::AutoLock locker(lock_);
208 if (is_closed_)
209 return MOJO_RESULT_INVALID_ARGUMENT;
210
211 return MapBufferImplNoLock(offset, num_bytes, flags, mapping);
212 }
213
GetHandleSignalsState() const214 HandleSignalsState Dispatcher::GetHandleSignalsState() const {
215 base::AutoLock locker(lock_);
216 if (is_closed_)
217 return HandleSignalsState();
218
219 return GetHandleSignalsStateImplNoLock();
220 }
221
AddWaiter(Waiter * waiter,MojoHandleSignals signals,uint32_t context,HandleSignalsState * signals_state)222 MojoResult Dispatcher::AddWaiter(Waiter* waiter,
223 MojoHandleSignals signals,
224 uint32_t context,
225 HandleSignalsState* signals_state) {
226 base::AutoLock locker(lock_);
227 if (is_closed_) {
228 if (signals_state)
229 *signals_state = HandleSignalsState();
230 return MOJO_RESULT_INVALID_ARGUMENT;
231 }
232
233 return AddWaiterImplNoLock(waiter, signals, context, signals_state);
234 }
235
RemoveWaiter(Waiter * waiter,HandleSignalsState * handle_signals_state)236 void Dispatcher::RemoveWaiter(Waiter* waiter,
237 HandleSignalsState* handle_signals_state) {
238 base::AutoLock locker(lock_);
239 if (is_closed_) {
240 if (handle_signals_state)
241 *handle_signals_state = HandleSignalsState();
242 return;
243 }
244 RemoveWaiterImplNoLock(waiter, handle_signals_state);
245 }
246
Dispatcher()247 Dispatcher::Dispatcher() : is_closed_(false) {
248 }
249
~Dispatcher()250 Dispatcher::~Dispatcher() {
251 // Make sure that |Close()| was called.
252 DCHECK(is_closed_);
253 }
254
CancelAllWaitersNoLock()255 void Dispatcher::CancelAllWaitersNoLock() {
256 lock_.AssertAcquired();
257 DCHECK(is_closed_);
258 // By default, waiting isn't supported. Only dispatchers that can be waited on
259 // will do something nontrivial.
260 }
261
CloseImplNoLock()262 void Dispatcher::CloseImplNoLock() {
263 lock_.AssertAcquired();
264 DCHECK(is_closed_);
265 // This may not need to do anything. Dispatchers should override this to do
266 // any actual close-time cleanup necessary.
267 }
268
WriteMessageImplNoLock(UserPointer<const void>,uint32_t,std::vector<DispatcherTransport> *,MojoWriteMessageFlags)269 MojoResult Dispatcher::WriteMessageImplNoLock(
270 UserPointer<const void> /*bytes*/,
271 uint32_t /*num_bytes*/,
272 std::vector<DispatcherTransport>* /*transports*/,
273 MojoWriteMessageFlags /*flags*/) {
274 lock_.AssertAcquired();
275 DCHECK(!is_closed_);
276 // By default, not supported. Only needed for message pipe dispatchers.
277 return MOJO_RESULT_INVALID_ARGUMENT;
278 }
279
ReadMessageImplNoLock(UserPointer<void>,UserPointer<uint32_t>,DispatcherVector *,uint32_t *,MojoReadMessageFlags)280 MojoResult Dispatcher::ReadMessageImplNoLock(
281 UserPointer<void> /*bytes*/,
282 UserPointer<uint32_t> /*num_bytes*/,
283 DispatcherVector* /*dispatchers*/,
284 uint32_t* /*num_dispatchers*/,
285 MojoReadMessageFlags /*flags*/) {
286 lock_.AssertAcquired();
287 DCHECK(!is_closed_);
288 // By default, not supported. Only needed for message pipe dispatchers.
289 return MOJO_RESULT_INVALID_ARGUMENT;
290 }
291
WriteDataImplNoLock(UserPointer<const void>,UserPointer<uint32_t>,MojoWriteDataFlags)292 MojoResult Dispatcher::WriteDataImplNoLock(UserPointer<const void> /*elements*/,
293 UserPointer<uint32_t> /*num_bytes*/,
294 MojoWriteDataFlags /*flags*/) {
295 lock_.AssertAcquired();
296 DCHECK(!is_closed_);
297 // By default, not supported. Only needed for data pipe dispatchers.
298 return MOJO_RESULT_INVALID_ARGUMENT;
299 }
300
BeginWriteDataImplNoLock(UserPointer<void * >,UserPointer<uint32_t>,MojoWriteDataFlags)301 MojoResult Dispatcher::BeginWriteDataImplNoLock(
302 UserPointer<void*> /*buffer*/,
303 UserPointer<uint32_t> /*buffer_num_bytes*/,
304 MojoWriteDataFlags /*flags*/) {
305 lock_.AssertAcquired();
306 DCHECK(!is_closed_);
307 // By default, not supported. Only needed for data pipe dispatchers.
308 return MOJO_RESULT_INVALID_ARGUMENT;
309 }
310
EndWriteDataImplNoLock(uint32_t)311 MojoResult Dispatcher::EndWriteDataImplNoLock(uint32_t /*num_bytes_written*/) {
312 lock_.AssertAcquired();
313 DCHECK(!is_closed_);
314 // By default, not supported. Only needed for data pipe dispatchers.
315 return MOJO_RESULT_INVALID_ARGUMENT;
316 }
317
ReadDataImplNoLock(UserPointer<void>,UserPointer<uint32_t>,MojoReadDataFlags)318 MojoResult Dispatcher::ReadDataImplNoLock(UserPointer<void> /*elements*/,
319 UserPointer<uint32_t> /*num_bytes*/,
320 MojoReadDataFlags /*flags*/) {
321 lock_.AssertAcquired();
322 DCHECK(!is_closed_);
323 // By default, not supported. Only needed for data pipe dispatchers.
324 return MOJO_RESULT_INVALID_ARGUMENT;
325 }
326
BeginReadDataImplNoLock(UserPointer<const void * >,UserPointer<uint32_t>,MojoReadDataFlags)327 MojoResult Dispatcher::BeginReadDataImplNoLock(
328 UserPointer<const void*> /*buffer*/,
329 UserPointer<uint32_t> /*buffer_num_bytes*/,
330 MojoReadDataFlags /*flags*/) {
331 lock_.AssertAcquired();
332 DCHECK(!is_closed_);
333 // By default, not supported. Only needed for data pipe dispatchers.
334 return MOJO_RESULT_INVALID_ARGUMENT;
335 }
336
EndReadDataImplNoLock(uint32_t)337 MojoResult Dispatcher::EndReadDataImplNoLock(uint32_t /*num_bytes_read*/) {
338 lock_.AssertAcquired();
339 DCHECK(!is_closed_);
340 // By default, not supported. Only needed for data pipe dispatchers.
341 return MOJO_RESULT_INVALID_ARGUMENT;
342 }
343
DuplicateBufferHandleImplNoLock(UserPointer<const MojoDuplicateBufferHandleOptions>,scoped_refptr<Dispatcher> *)344 MojoResult Dispatcher::DuplicateBufferHandleImplNoLock(
345 UserPointer<const MojoDuplicateBufferHandleOptions> /*options*/,
346 scoped_refptr<Dispatcher>* /*new_dispatcher*/) {
347 lock_.AssertAcquired();
348 DCHECK(!is_closed_);
349 // By default, not supported. Only needed for buffer dispatchers.
350 return MOJO_RESULT_INVALID_ARGUMENT;
351 }
352
MapBufferImplNoLock(uint64_t,uint64_t,MojoMapBufferFlags,scoped_ptr<embedder::PlatformSharedBufferMapping> *)353 MojoResult Dispatcher::MapBufferImplNoLock(
354 uint64_t /*offset*/,
355 uint64_t /*num_bytes*/,
356 MojoMapBufferFlags /*flags*/,
357 scoped_ptr<embedder::PlatformSharedBufferMapping>* /*mapping*/) {
358 lock_.AssertAcquired();
359 DCHECK(!is_closed_);
360 // By default, not supported. Only needed for buffer dispatchers.
361 return MOJO_RESULT_INVALID_ARGUMENT;
362 }
363
GetHandleSignalsStateImplNoLock() const364 HandleSignalsState Dispatcher::GetHandleSignalsStateImplNoLock() const {
365 lock_.AssertAcquired();
366 DCHECK(!is_closed_);
367 // By default, waiting isn't supported. Only dispatchers that can be waited on
368 // will do something nontrivial.
369 return HandleSignalsState();
370 }
371
AddWaiterImplNoLock(Waiter *,MojoHandleSignals,uint32_t,HandleSignalsState * signals_state)372 MojoResult Dispatcher::AddWaiterImplNoLock(Waiter* /*waiter*/,
373 MojoHandleSignals /*signals*/,
374 uint32_t /*context*/,
375 HandleSignalsState* signals_state) {
376 lock_.AssertAcquired();
377 DCHECK(!is_closed_);
378 // By default, waiting isn't supported. Only dispatchers that can be waited on
379 // will do something nontrivial.
380 if (signals_state)
381 *signals_state = HandleSignalsState();
382 return MOJO_RESULT_FAILED_PRECONDITION;
383 }
384
RemoveWaiterImplNoLock(Waiter *,HandleSignalsState * signals_state)385 void Dispatcher::RemoveWaiterImplNoLock(Waiter* /*waiter*/,
386 HandleSignalsState* signals_state) {
387 lock_.AssertAcquired();
388 DCHECK(!is_closed_);
389 // By default, waiting isn't supported. Only dispatchers that can be waited on
390 // will do something nontrivial.
391 if (signals_state)
392 *signals_state = HandleSignalsState();
393 }
394
StartSerializeImplNoLock(Channel *,size_t * max_size,size_t * max_platform_handles)395 void Dispatcher::StartSerializeImplNoLock(Channel* /*channel*/,
396 size_t* max_size,
397 size_t* max_platform_handles) {
398 DCHECK(HasOneRef()); // Only one ref => no need to take the lock.
399 DCHECK(!is_closed_);
400 *max_size = 0;
401 *max_platform_handles = 0;
402 }
403
EndSerializeAndCloseImplNoLock(Channel *,void *,size_t *,embedder::PlatformHandleVector *)404 bool Dispatcher::EndSerializeAndCloseImplNoLock(
405 Channel* /*channel*/,
406 void* /*destination*/,
407 size_t* /*actual_size*/,
408 embedder::PlatformHandleVector* /*platform_handles*/) {
409 DCHECK(HasOneRef()); // Only one ref => no need to take the lock.
410 DCHECK(is_closed_);
411 // By default, serializing isn't supported, so just close.
412 CloseImplNoLock();
413 return false;
414 }
415
IsBusyNoLock() const416 bool Dispatcher::IsBusyNoLock() const {
417 lock_.AssertAcquired();
418 DCHECK(!is_closed_);
419 // Most dispatchers support only "atomic" operations, so they are never busy
420 // (in this sense).
421 return false;
422 }
423
CloseNoLock()424 void Dispatcher::CloseNoLock() {
425 lock_.AssertAcquired();
426 DCHECK(!is_closed_);
427
428 is_closed_ = true;
429 CancelAllWaitersNoLock();
430 CloseImplNoLock();
431 }
432
433 scoped_refptr<Dispatcher>
CreateEquivalentDispatcherAndCloseNoLock()434 Dispatcher::CreateEquivalentDispatcherAndCloseNoLock() {
435 lock_.AssertAcquired();
436 DCHECK(!is_closed_);
437
438 is_closed_ = true;
439 CancelAllWaitersNoLock();
440 return CreateEquivalentDispatcherAndCloseImplNoLock();
441 }
442
StartSerialize(Channel * channel,size_t * max_size,size_t * max_platform_handles)443 void Dispatcher::StartSerialize(Channel* channel,
444 size_t* max_size,
445 size_t* max_platform_handles) {
446 DCHECK(channel);
447 DCHECK(max_size);
448 DCHECK(max_platform_handles);
449 DCHECK(HasOneRef()); // Only one ref => no need to take the lock.
450 DCHECK(!is_closed_);
451 StartSerializeImplNoLock(channel, max_size, max_platform_handles);
452 }
453
EndSerializeAndClose(Channel * channel,void * destination,size_t * actual_size,embedder::PlatformHandleVector * platform_handles)454 bool Dispatcher::EndSerializeAndClose(
455 Channel* channel,
456 void* destination,
457 size_t* actual_size,
458 embedder::PlatformHandleVector* platform_handles) {
459 DCHECK(channel);
460 DCHECK(actual_size);
461 DCHECK(HasOneRef()); // Only one ref => no need to take the lock.
462 DCHECK(!is_closed_);
463
464 // Like other |...Close()| methods, we mark ourselves as closed before calling
465 // the impl. But there's no need to cancel waiters: we shouldn't have any (and
466 // shouldn't be in |Core|'s handle table.
467 is_closed_ = true;
468
469 #if !defined(NDEBUG)
470 // See the comment above |EndSerializeAndCloseImplNoLock()|. In brief: Locking
471 // isn't actually needed, but we need to satisfy assertions (which we don't
472 // want to remove or weaken).
473 base::AutoLock locker(lock_);
474 #endif
475
476 return EndSerializeAndCloseImplNoLock(
477 channel, destination, actual_size, platform_handles);
478 }
479
480 // DispatcherTransport ---------------------------------------------------------
481
End()482 void DispatcherTransport::End() {
483 DCHECK(dispatcher_);
484 dispatcher_->lock_.Release();
485 dispatcher_ = nullptr;
486 }
487
488 } // namespace system
489 } // namespace mojo
490