Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(114)

Side by Side Diff: mojo/edk/system/channel.cc

Issue 799113004: Update mojo sdk to rev 59145288bae55b0fce4276b017df6a1117bcf00f (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: add mojo's ply to checklicenses whitelist Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « mojo/edk/system/channel.h ('k') | mojo/edk/system/channel_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "mojo/edk/system/channel.h" 5 #include "mojo/edk/system/channel.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/macros.h" 11 #include "base/macros.h"
12 #include "base/strings/stringprintf.h" 12 #include "base/strings/stringprintf.h"
13 #include "mojo/edk/embedder/platform_handle_vector.h" 13 #include "mojo/edk/embedder/platform_handle_vector.h"
14 #include "mojo/edk/system/transport_data.h" 14 #include "mojo/edk/system/transport_data.h"
15 15
16 namespace mojo { 16 namespace mojo {
17 namespace system { 17 namespace system {
18 18
19 namespace {
20
21 struct SerializedEndpoint {
22 // This is the endpoint ID on the receiving side, and should be a "remote ID".
23 // (The receiving side should already have had an endpoint attached and been
24 // run via the |Channel|s. This endpoint will have both IDs assigned, so this
25 // ID is only needed to associate that endpoint with a particular dispatcher.)
26 ChannelEndpointId receiver_endpoint_id;
27 };
28
29 } // namespace
30
19 Channel::Channel(embedder::PlatformSupport* platform_support) 31 Channel::Channel(embedder::PlatformSupport* platform_support)
20 : platform_support_(platform_support), 32 : platform_support_(platform_support),
21 is_running_(false), 33 is_running_(false),
22 is_shutting_down_(false), 34 is_shutting_down_(false),
23 channel_manager_(nullptr) { 35 channel_manager_(nullptr) {
24 } 36 }
25 37
26 bool Channel::Init(scoped_ptr<RawChannel> raw_channel) { 38 bool Channel::Init(scoped_ptr<RawChannel> raw_channel) {
27 DCHECK(creation_thread_checker_.CalledOnValidThread()); 39 DCHECK(creation_thread_checker_.CalledOnValidThread());
28 DCHECK(raw_channel); 40 DCHECK(raw_channel);
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
83 << " live endpoints and " << num_zombies 95 << " live endpoints and " << num_zombies
84 << " zombies"; 96 << " zombies";
85 } 97 }
86 98
87 void Channel::WillShutdownSoon() { 99 void Channel::WillShutdownSoon() {
88 base::AutoLock locker(lock_); 100 base::AutoLock locker(lock_);
89 is_shutting_down_ = true; 101 is_shutting_down_ = true;
90 channel_manager_ = nullptr; 102 channel_manager_ = nullptr;
91 } 103 }
92 104
93 // Note: |endpoint| being a |scoped_refptr| makes this function safe, since it 105 void Channel::SetBootstrapEndpoint(scoped_refptr<ChannelEndpoint> endpoint) {
94 // keeps the endpoint alive even after the lock is released. Otherwise, there's
95 // the temptation to simply pass the result of |new ChannelEndpoint(...)|
96 // directly to this function, which wouldn't be sufficient for safety.
97 ChannelEndpointId Channel::AttachAndRunEndpoint(
98 scoped_refptr<ChannelEndpoint> endpoint,
99 bool is_bootstrap) {
100 DCHECK(endpoint); 106 DCHECK(endpoint);
101 107
102 ChannelEndpointId local_id; 108 // Used for both local and remote IDs.
103 ChannelEndpointId remote_id; 109 ChannelEndpointId bootstrap_id = ChannelEndpointId::GetBootstrap();
110
104 { 111 {
105 base::AutoLock locker(lock_); 112 base::AutoLock locker(lock_);
106 113
107 DLOG_IF(WARNING, is_shutting_down_) 114 DLOG_IF(WARNING, is_shutting_down_)
108 << "AttachEndpoint() while shutting down"; 115 << "SetBootstrapEndpoint() while shutting down";
109 116
110 if (is_bootstrap) { 117 // Bootstrap endpoint should be the first.
111 local_id = ChannelEndpointId::GetBootstrap(); 118 DCHECK(local_id_to_endpoint_map_.empty());
112 DCHECK(local_id_to_endpoint_map_.find(local_id) ==
113 local_id_to_endpoint_map_.end());
114 119
115 remote_id = ChannelEndpointId::GetBootstrap(); 120 local_id_to_endpoint_map_[bootstrap_id] = endpoint;
116 } else {
117 do {
118 local_id = local_id_generator_.GetNext();
119 } while (local_id_to_endpoint_map_.find(local_id) !=
120 local_id_to_endpoint_map_.end());
121
122 // TODO(vtl): We also need to check for collisions of remote IDs here.
123 remote_id = remote_id_generator_.GetNext();
124 }
125
126 local_id_to_endpoint_map_[local_id] = endpoint;
127 } 121 }
128 122
129 if (!is_bootstrap) { 123 endpoint->AttachAndRun(this, bootstrap_id, bootstrap_id);
130 if (!SendControlMessage(
131 MessageInTransit::kSubtypeChannelAttachAndRunEndpoint, local_id,
132 remote_id)) {
133 HandleLocalError(base::StringPrintf(
134 "Failed to send message to run remote message pipe endpoint (local "
135 "ID %u, remote ID %u)",
136 static_cast<unsigned>(local_id.value()),
137 static_cast<unsigned>(remote_id.value())));
138 // TODO(vtl): Should we continue on to |AttachAndRun()|?
139 }
140 }
141
142 endpoint->AttachAndRun(this, local_id, remote_id);
143 return remote_id;
144 } 124 }
145 125
146 bool Channel::WriteMessage(scoped_ptr<MessageInTransit> message) { 126 bool Channel::WriteMessage(scoped_ptr<MessageInTransit> message) {
147 base::AutoLock locker(lock_); 127 base::AutoLock locker(lock_);
148 if (!is_running_) { 128 if (!is_running_) {
149 // TODO(vtl): I think this is probably not an error condition, but I should 129 // TODO(vtl): I think this is probably not an error condition, but I should
150 // think about it (and the shutdown sequence) more carefully. 130 // think about it (and the shutdown sequence) more carefully.
151 LOG(WARNING) << "WriteMessage() after shutdown"; 131 LOG(WARNING) << "WriteMessage() after shutdown";
152 return false; 132 return false;
153 } 133 }
(...skipping 30 matching lines...) Expand all
184 // nothing more to do. 164 // nothing more to do.
185 if (it == local_id_to_endpoint_map_.end() || it->second.get() != endpoint) 165 if (it == local_id_to_endpoint_map_.end() || it->second.get() != endpoint)
186 return; 166 return;
187 167
188 DCHECK(it->second); 168 DCHECK(it->second);
189 it->second = nullptr; 169 it->second = nullptr;
190 170
191 // Send a remove message outside the lock. 171 // Send a remove message outside the lock.
192 } 172 }
193 173
194 if (!SendControlMessage( 174 if (!SendControlMessage(MessageInTransit::kSubtypeChannelRemoveEndpoint,
195 MessageInTransit::kSubtypeChannelRemoveMessagePipeEndpoint, local_id, 175 local_id, remote_id)) {
196 remote_id)) {
197 HandleLocalError(base::StringPrintf( 176 HandleLocalError(base::StringPrintf(
198 "Failed to send message to remove remote message pipe endpoint (local " 177 "Failed to send message to remove remote endpoint (local ID %u, remote "
199 "ID %u, remote ID %u)", 178 "ID %u)",
200 static_cast<unsigned>(local_id.value()), 179 static_cast<unsigned>(local_id.value()),
201 static_cast<unsigned>(remote_id.value()))); 180 static_cast<unsigned>(remote_id.value())));
202 } 181 }
203 } 182 }
204 183
205 scoped_refptr<MessagePipe> Channel::PassIncomingMessagePipe( 184 size_t Channel::GetSerializedEndpointSize() const {
206 ChannelEndpointId local_id) { 185 return sizeof(SerializedEndpoint);
186 }
187
188 void Channel::SerializeEndpoint(scoped_refptr<ChannelEndpoint> endpoint,
189 void* destination) {
190 SerializedEndpoint* s = static_cast<SerializedEndpoint*>(destination);
191 s->receiver_endpoint_id = AttachAndRunEndpoint(endpoint);
192 DVLOG(2) << "Serializing endpoint (remote ID = " << s->receiver_endpoint_id
193 << ")";
194 }
195
196 scoped_refptr<IncomingEndpoint> Channel::DeserializeEndpoint(
197 const void* source) {
198 const SerializedEndpoint* s = static_cast<const SerializedEndpoint*>(source);
199 ChannelEndpointId local_id = s->receiver_endpoint_id;
207 // No need to check the validity of |local_id| -- if it's not valid, it simply 200 // No need to check the validity of |local_id| -- if it's not valid, it simply
208 // won't be in |incoming_message_pipes_|. 201 // won't be in |incoming_endpoints_|.
209 DVLOG_IF(2, !local_id.is_valid() || !local_id.is_remote()) 202 DVLOG_IF(2, !local_id.is_valid() || !local_id.is_remote())
210 << "Attempt to get invalid incoming message pipe for ID " << local_id; 203 << "Attempt to get incoming endpoint for invalid ID " << local_id;
211 204
212 base::AutoLock locker(lock_); 205 base::AutoLock locker(lock_);
213 206
214 auto it = incoming_message_pipes_.find(local_id); 207 auto it = incoming_endpoints_.find(local_id);
215 if (it == incoming_message_pipes_.end()) 208 if (it == incoming_endpoints_.end()) {
209 LOG(ERROR) << "Failed to deserialize endpoint (ID = " << local_id << ")";
216 return nullptr; 210 return nullptr;
211 }
217 212
218 scoped_refptr<MessagePipe> rv; 213 DVLOG(2) << "Deserializing endpoint (new local ID = " << local_id << ")";
214
215 scoped_refptr<IncomingEndpoint> rv;
219 rv.swap(it->second); 216 rv.swap(it->second);
220 incoming_message_pipes_.erase(it); 217 incoming_endpoints_.erase(it);
221 return rv; 218 return rv;
222 } 219 }
223 220
224 size_t Channel::GetSerializedPlatformHandleSize() const { 221 size_t Channel::GetSerializedPlatformHandleSize() const {
225 return raw_channel_->GetSerializedPlatformHandleSize(); 222 return raw_channel_->GetSerializedPlatformHandleSize();
226 } 223 }
227 224
228 Channel::~Channel() { 225 Channel::~Channel() {
229 // The channel should have been shut down first. 226 // The channel should have been shut down first.
230 DCHECK(!is_running_); 227 DCHECK(!is_running_);
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
349 // Currently, no channel messages take platform handles. 346 // Currently, no channel messages take platform handles.
350 if (platform_handles) { 347 if (platform_handles) {
351 HandleRemoteError( 348 HandleRemoteError(
352 "Received invalid channel message (has platform handles)"); 349 "Received invalid channel message (has platform handles)");
353 NOTREACHED(); 350 NOTREACHED();
354 return; 351 return;
355 } 352 }
356 353
357 switch (message_view.subtype()) { 354 switch (message_view.subtype()) {
358 case MessageInTransit::kSubtypeChannelAttachAndRunEndpoint: 355 case MessageInTransit::kSubtypeChannelAttachAndRunEndpoint:
359 DVLOG(2) << "Handling channel message to attach and run message pipe " 356 DVLOG(2) << "Handling channel message to attach and run endpoint (local "
360 "(local ID " << message_view.destination_id() 357 "ID " << message_view.destination_id() << ", remote ID "
361 << ", remote ID " << message_view.source_id() << ")"; 358 << message_view.source_id() << ")";
362 if (!OnAttachAndRunEndpoint(message_view.destination_id(), 359 if (!OnAttachAndRunEndpoint(message_view.destination_id(),
363 message_view.source_id())) { 360 message_view.source_id())) {
364 HandleRemoteError( 361 HandleRemoteError(
365 "Received invalid channel message to attach and run message pipe"); 362 "Received invalid channel message to attach and run endpoint");
366 } 363 }
367 break; 364 break;
368 case MessageInTransit::kSubtypeChannelRemoveMessagePipeEndpoint: 365 case MessageInTransit::kSubtypeChannelRemoveEndpoint:
369 DVLOG(2) << "Handling channel message to remove message pipe (local ID " 366 DVLOG(2) << "Handling channel message to remove endpoint (local ID "
370 << message_view.destination_id() << ", remote ID " 367 << message_view.destination_id() << ", remote ID "
371 << message_view.source_id() << ")"; 368 << message_view.source_id() << ")";
372 if (!OnRemoveMessagePipeEndpoint(message_view.destination_id(), 369 if (!OnRemoveEndpoint(message_view.destination_id(),
373 message_view.source_id())) { 370 message_view.source_id())) {
374 HandleRemoteError( 371 HandleRemoteError(
375 "Received invalid channel message to remove message pipe"); 372 "Received invalid channel message to remove endpoint");
376 } 373 }
377 break; 374 break;
378 case MessageInTransit::kSubtypeChannelRemoveMessagePipeEndpointAck: 375 case MessageInTransit::kSubtypeChannelRemoveEndpointAck:
379 DVLOG(2) << "Handling channel message to ack remove message pipe (local " 376 DVLOG(2) << "Handling channel message to ack remove endpoint (local ID "
380 "ID " << message_view.destination_id() << ", remote ID " 377 << message_view.destination_id() << ", remote ID "
381 << message_view.source_id() << ")"; 378 << message_view.source_id() << ")";
382 if (!OnRemoveMessagePipeEndpointAck(message_view.destination_id())) { 379 if (!OnRemoveEndpointAck(message_view.destination_id())) {
383 HandleRemoteError( 380 HandleRemoteError(
384 "Received invalid channel message to ack remove message pipe"); 381 "Received invalid channel message to ack remove endpoint");
385 } 382 }
386 break; 383 break;
387 default: 384 default:
388 HandleRemoteError("Received invalid channel message"); 385 HandleRemoteError("Received invalid channel message");
389 NOTREACHED(); 386 NOTREACHED();
390 break; 387 break;
391 } 388 }
392 } 389 }
393 390
394 bool Channel::OnAttachAndRunEndpoint(ChannelEndpointId local_id, 391 bool Channel::OnAttachAndRunEndpoint(ChannelEndpointId local_id,
395 ChannelEndpointId remote_id) { 392 ChannelEndpointId remote_id) {
396 // We should only get this for remotely-created local endpoints, so our local 393 // We should only get this for remotely-created local endpoints, so our local
397 // ID should be "remote". 394 // ID should be "remote".
398 if (!local_id.is_valid() || !local_id.is_remote()) { 395 if (!local_id.is_valid() || !local_id.is_remote()) {
399 DVLOG(2) << "Received attach and run endpoint with invalid local ID"; 396 DVLOG(2) << "Received attach and run endpoint with invalid local ID";
400 return false; 397 return false;
401 } 398 }
402 399
403 // Conversely, the remote end should be "local". 400 // Conversely, the remote end should be "local".
404 if (!remote_id.is_valid() || remote_id.is_remote()) { 401 if (!remote_id.is_valid() || remote_id.is_remote()) {
405 DVLOG(2) << "Received attach and run endpoint with invalid remote ID"; 402 DVLOG(2) << "Received attach and run endpoint with invalid remote ID";
406 return false; 403 return false;
407 } 404 }
408 405
409 // Create a message pipe and thus an endpoint (outside the lock). 406 // Create/initialize an |IncomingEndpoint| and thus an endpoint (outside the
410 scoped_refptr<ChannelEndpoint> endpoint; 407 // lock).
411 scoped_refptr<MessagePipe> message_pipe( 408 scoped_refptr<IncomingEndpoint> incoming_endpoint(new IncomingEndpoint());
412 MessagePipe::CreateLocalProxy(&endpoint)); 409 scoped_refptr<ChannelEndpoint> endpoint = incoming_endpoint->Init();
413 410
414 bool success = true; 411 bool success = true;
415 { 412 {
416 base::AutoLock locker(lock_); 413 base::AutoLock locker(lock_);
417 414
418 if (local_id_to_endpoint_map_.find(local_id) == 415 if (local_id_to_endpoint_map_.find(local_id) ==
419 local_id_to_endpoint_map_.end()) { 416 local_id_to_endpoint_map_.end()) {
420 DCHECK(incoming_message_pipes_.find(local_id) == 417 DCHECK(incoming_endpoints_.find(local_id) == incoming_endpoints_.end());
421 incoming_message_pipes_.end());
422 418
423 // TODO(vtl): Use emplace when we move to C++11 unordered_maps. (It'll 419 // TODO(vtl): Use emplace when we move to C++11 unordered_maps. (It'll
424 // avoid some refcount churn.) 420 // avoid some refcount churn.)
425 local_id_to_endpoint_map_[local_id] = endpoint; 421 local_id_to_endpoint_map_[local_id] = endpoint;
426 incoming_message_pipes_[local_id] = message_pipe; 422 incoming_endpoints_[local_id] = incoming_endpoint;
427 } else { 423 } else {
428 // We need to call |Close()| on the message pipe outside the lock. 424 // We need to call |Close()| outside the lock.
429 success = false; 425 success = false;
430 } 426 }
431 } 427 }
432 if (!success) { 428 if (!success) {
433 DVLOG(2) << "Received attach and run endpoint for existing local ID"; 429 DVLOG(2) << "Received attach and run endpoint for existing local ID";
434 message_pipe->Close(0); 430 incoming_endpoint->Close();
435 return false; 431 return false;
436 } 432 }
437 433
438 endpoint->AttachAndRun(this, local_id, remote_id); 434 endpoint->AttachAndRun(this, local_id, remote_id);
439 return true; 435 return true;
440 } 436 }
441 437
442 bool Channel::OnRemoveMessagePipeEndpoint(ChannelEndpointId local_id, 438 bool Channel::OnRemoveEndpoint(ChannelEndpointId local_id,
443 ChannelEndpointId remote_id) { 439 ChannelEndpointId remote_id) {
444 DCHECK(creation_thread_checker_.CalledOnValidThread()); 440 DCHECK(creation_thread_checker_.CalledOnValidThread());
445 441
446 scoped_refptr<ChannelEndpoint> endpoint; 442 scoped_refptr<ChannelEndpoint> endpoint;
447 { 443 {
448 base::AutoLock locker(lock_); 444 base::AutoLock locker(lock_);
449 445
450 IdToEndpointMap::iterator it = local_id_to_endpoint_map_.find(local_id); 446 IdToEndpointMap::iterator it = local_id_to_endpoint_map_.find(local_id);
451 if (it == local_id_to_endpoint_map_.end()) { 447 if (it == local_id_to_endpoint_map_.end()) {
452 DVLOG(2) << "Remove message pipe endpoint error: not found"; 448 DVLOG(2) << "Remove endpoint error: not found";
453 return false; 449 return false;
454 } 450 }
455 451
456 if (!it->second) { 452 if (!it->second) {
457 // Remove messages "crossed"; we have to wait for the ack. 453 // Remove messages "crossed"; we have to wait for the ack.
458 return true; 454 return true;
459 } 455 }
460 456
461 endpoint = it->second; 457 endpoint = it->second;
462 local_id_to_endpoint_map_.erase(it); 458 local_id_to_endpoint_map_.erase(it);
463 // Detach and send the remove ack message outside the lock. 459 // Detach and send the remove ack message outside the lock.
464 } 460 }
465 461
466 endpoint->DetachFromChannel(); 462 endpoint->DetachFromChannel();
467 463
468 if (!SendControlMessage( 464 if (!SendControlMessage(MessageInTransit::kSubtypeChannelRemoveEndpointAck,
469 MessageInTransit::kSubtypeChannelRemoveMessagePipeEndpointAck, 465 local_id, remote_id)) {
470 local_id, remote_id)) {
471 HandleLocalError(base::StringPrintf( 466 HandleLocalError(base::StringPrintf(
472 "Failed to send message to remove remote message pipe endpoint ack " 467 "Failed to send message to ack remove remote endpoint (local ID %u, "
473 "(local ID %u, remote ID %u)", 468 "remote ID %u)",
474 static_cast<unsigned>(local_id.value()), 469 static_cast<unsigned>(local_id.value()),
475 static_cast<unsigned>(remote_id.value()))); 470 static_cast<unsigned>(remote_id.value())));
476 } 471 }
477 472
478 return true; 473 return true;
479 } 474 }
480 475
481 bool Channel::OnRemoveMessagePipeEndpointAck(ChannelEndpointId local_id) { 476 bool Channel::OnRemoveEndpointAck(ChannelEndpointId local_id) {
482 DCHECK(creation_thread_checker_.CalledOnValidThread()); 477 DCHECK(creation_thread_checker_.CalledOnValidThread());
483 478
484 base::AutoLock locker(lock_); 479 base::AutoLock locker(lock_);
485 480
486 IdToEndpointMap::iterator it = local_id_to_endpoint_map_.find(local_id); 481 IdToEndpointMap::iterator it = local_id_to_endpoint_map_.find(local_id);
487 if (it == local_id_to_endpoint_map_.end()) { 482 if (it == local_id_to_endpoint_map_.end()) {
488 DVLOG(2) << "Remove message pipe endpoint ack error: not found"; 483 DVLOG(2) << "Remove endpoint ack error: not found";
489 return false; 484 return false;
490 } 485 }
491 486
492 if (it->second) { 487 if (it->second) {
493 DVLOG(2) << "Remove message pipe endpoint ack error: wrong state"; 488 DVLOG(2) << "Remove endpoint ack error: wrong state";
494 return false; 489 return false;
495 } 490 }
496 491
497 local_id_to_endpoint_map_.erase(it); 492 local_id_to_endpoint_map_.erase(it);
498 return true; 493 return true;
499 } 494 }
500 495
501 bool Channel::SendControlMessage(MessageInTransit::Subtype subtype,
502 ChannelEndpointId local_id,
503 ChannelEndpointId remote_id) {
504 DVLOG(2) << "Sending channel control message: subtype " << subtype
505 << ", local ID " << local_id << ", remote ID " << remote_id;
506 scoped_ptr<MessageInTransit> message(new MessageInTransit(
507 MessageInTransit::kTypeChannel, subtype, 0, nullptr));
508 message->set_source_id(local_id);
509 message->set_destination_id(remote_id);
510 return WriteMessage(message.Pass());
511 }
512
513 void Channel::HandleRemoteError(const base::StringPiece& error_message) { 496 void Channel::HandleRemoteError(const base::StringPiece& error_message) {
514 // TODO(vtl): Is this how we really want to handle this? Probably we want to 497 // TODO(vtl): Is this how we really want to handle this? Probably we want to
515 // terminate the connection, since it's spewing invalid stuff. 498 // terminate the connection, since it's spewing invalid stuff.
516 LOG(WARNING) << error_message; 499 LOG(WARNING) << error_message;
517 } 500 }
518 501
519 void Channel::HandleLocalError(const base::StringPiece& error_message) { 502 void Channel::HandleLocalError(const base::StringPiece& error_message) {
520 // TODO(vtl): Is this how we really want to handle this? 503 // TODO(vtl): Is this how we really want to handle this?
521 // Sometimes we'll want to propagate the error back to the message pipe 504 // Sometimes we'll want to propagate the error back to the message pipe
522 // (endpoint), and notify it that the remote is (effectively) closed. 505 // (endpoint), and notify it that the remote is (effectively) closed.
523 // Sometimes we'll want to kill the channel (and notify all the endpoints that 506 // Sometimes we'll want to kill the channel (and notify all the endpoints that
524 // their remotes are dead. 507 // their remotes are dead.
525 LOG(WARNING) << error_message; 508 LOG(WARNING) << error_message;
526 } 509 }
527 510
511 // Note: |endpoint| being a |scoped_refptr| makes this function safe, since it
512 // keeps the endpoint alive even after the lock is released. Otherwise, there's
513 // the temptation to simply pass the result of |new ChannelEndpoint(...)|
514 // directly to this function, which wouldn't be sufficient for safety.
515 ChannelEndpointId Channel::AttachAndRunEndpoint(
516 scoped_refptr<ChannelEndpoint> endpoint) {
517 DCHECK(endpoint);
518
519 ChannelEndpointId local_id;
520 ChannelEndpointId remote_id;
521 {
522 base::AutoLock locker(lock_);
523
524 DLOG_IF(WARNING, is_shutting_down_)
525 << "AttachAndRunEndpoint() while shutting down";
526
527 do {
528 local_id = local_id_generator_.GetNext();
529 } while (local_id_to_endpoint_map_.find(local_id) !=
530 local_id_to_endpoint_map_.end());
531
532 // TODO(vtl): We also need to check for collisions of remote IDs here.
533 remote_id = remote_id_generator_.GetNext();
534
535 local_id_to_endpoint_map_[local_id] = endpoint;
536 }
537
538 if (!SendControlMessage(MessageInTransit::kSubtypeChannelAttachAndRunEndpoint,
539 local_id, remote_id)) {
540 HandleLocalError(base::StringPrintf(
541 "Failed to send message to run remote endpoint (local ID %u, remote ID "
542 "%u)",
543 static_cast<unsigned>(local_id.value()),
544 static_cast<unsigned>(remote_id.value())));
545 // TODO(vtl): Should we continue on to |AttachAndRun()|?
546 }
547
548 endpoint->AttachAndRun(this, local_id, remote_id);
549 return remote_id;
550 }
551
552 bool Channel::SendControlMessage(MessageInTransit::Subtype subtype,
553 ChannelEndpointId local_id,
554 ChannelEndpointId remote_id) {
555 DVLOG(2) << "Sending channel control message: subtype " << subtype
556 << ", local ID " << local_id << ", remote ID " << remote_id;
557 scoped_ptr<MessageInTransit> message(new MessageInTransit(
558 MessageInTransit::kTypeChannel, subtype, 0, nullptr));
559 message->set_source_id(local_id);
560 message->set_destination_id(remote_id);
561 return WriteMessage(message.Pass());
562 }
563
528 } // namespace system 564 } // namespace system
529 } // namespace mojo 565 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/edk/system/channel.h ('k') | mojo/edk/system/channel_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698