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(Dispatcher* dispatcher) { 20 return Dispatcher::HandleTableAccess::TryStartTransport(dispatcher); 21 } 22 23 } // namespace test 24 25 // Dispatcher ------------------------------------------------------------------ 26 27 // static 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 214 HandleSignalsState Dispatcher::GetHandleSignalsState() const { 215 base::AutoLock locker(lock_); 216 if (is_closed_) 217 return HandleSignalsState(); 218 219 return GetHandleSignalsStateImplNoLock(); 220 } 221 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 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 247 Dispatcher::Dispatcher() : is_closed_(false) { 248 } 249 250 Dispatcher::~Dispatcher() { 251 // Make sure that |Close()| was called. 252 DCHECK(is_closed_); 253 } 254 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 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 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 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 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 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 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 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 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 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 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 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 364 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 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 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 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 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 416 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 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> 434 Dispatcher::CreateEquivalentDispatcherAndCloseNoLock() { 435 lock_.AssertAcquired(); 436 DCHECK(!is_closed_); 437 438 is_closed_ = true; 439 CancelAllWaitersNoLock(); 440 return CreateEquivalentDispatcherAndCloseImplNoLock(); 441 } 442 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 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 482 void DispatcherTransport::End() { 483 DCHECK(dispatcher_); 484 dispatcher_->lock_.Release(); 485 dispatcher_ = nullptr; 486 } 487 488 } // namespace system 489 } // namespace mojo 490