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. 19 DispatcherTransport DispatcherTryStartTransport( 20 Dispatcher* dispatcher) { 21 return Dispatcher::HandleTableAccess::TryStartTransport(dispatcher); 22 } 23 24 } // namespace test 25 26 // Dispatcher ------------------------------------------------------------------ 27 28 // static 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 227 void Dispatcher::RemoveWaiter(Waiter* waiter) { 228 base::AutoLock locker(lock_); 229 if (is_closed_) 230 return; 231 RemoveWaiterImplNoLock(waiter); 232 } 233 234 Dispatcher::Dispatcher() 235 : is_closed_(false) { 236 } 237 238 Dispatcher::~Dispatcher() { 239 // Make sure that |Close()| was called. 240 DCHECK(is_closed_); 241 } 242 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 387 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 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> 405 Dispatcher::CreateEquivalentDispatcherAndCloseNoLock() { 406 lock_.AssertAcquired(); 407 DCHECK(!is_closed_); 408 409 is_closed_ = true; 410 CancelAllWaitersNoLock(); 411 return CreateEquivalentDispatcherAndCloseImplNoLock(); 412 } 413 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 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 454 void DispatcherTransport::End() { 455 DCHECK(dispatcher_); 456 dispatcher_->lock_.Release(); 457 dispatcher_ = NULL; 458 } 459 460 } // namespace system 461 } // namespace mojo 462