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