• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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