1 // Copyright 2014 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/public/cpp/bindings/lib/router.h" 6 7 namespace mojo { 8 namespace internal { 9 10 // ---------------------------------------------------------------------------- 11 12 class ResponderThunk : public MessageReceiver { 13 public: 14 explicit ResponderThunk(const SharedData<Router*>& router) 15 : router_(router) { 16 } 17 virtual ~ResponderThunk() { 18 } 19 20 // MessageReceiver implementation: 21 virtual bool Accept(Message* message) MOJO_OVERRIDE { 22 assert(message->has_flag(kMessageIsResponse)); 23 24 bool result = false; 25 26 Router* router = router_.value(); 27 if (router) 28 result = router->Accept(message); 29 30 return result; 31 } 32 33 private: 34 SharedData<Router*> router_; 35 }; 36 37 // ---------------------------------------------------------------------------- 38 39 Router::HandleIncomingMessageThunk::HandleIncomingMessageThunk(Router* router) 40 : router_(router) { 41 } 42 43 Router::HandleIncomingMessageThunk::~HandleIncomingMessageThunk() { 44 } 45 46 bool Router::HandleIncomingMessageThunk::Accept(Message* message) { 47 return router_->HandleIncomingMessage(message); 48 } 49 50 // ---------------------------------------------------------------------------- 51 52 Router::Router(ScopedMessagePipeHandle message_pipe, 53 FilterChain filters, 54 const MojoAsyncWaiter* waiter) 55 : thunk_(this), 56 filters_(filters.Pass()), 57 connector_(message_pipe.Pass(), waiter), 58 weak_self_(this), 59 incoming_receiver_(NULL), 60 next_request_id_(0), 61 testing_mode_(false) { 62 filters_.SetSink(&thunk_); 63 connector_.set_incoming_receiver(filters_.GetHead()); 64 } 65 66 Router::~Router() { 67 weak_self_.set_value(NULL); 68 69 for (ResponderMap::const_iterator i = responders_.begin(); 70 i != responders_.end(); ++i) { 71 delete i->second; 72 } 73 } 74 75 bool Router::Accept(Message* message) { 76 assert(!message->has_flag(kMessageExpectsResponse)); 77 return connector_.Accept(message); 78 } 79 80 bool Router::AcceptWithResponder(Message* message, 81 MessageReceiver* responder) { 82 assert(message->has_flag(kMessageExpectsResponse)); 83 84 // Reserve 0 in case we want it to convey special meaning in the future. 85 uint64_t request_id = next_request_id_++; 86 if (request_id == 0) 87 request_id = next_request_id_++; 88 89 message->set_request_id(request_id); 90 if (!connector_.Accept(message)) 91 return false; 92 93 // We assume ownership of |responder|. 94 responders_[request_id] = responder; 95 return true; 96 } 97 98 void Router::EnableTestingMode() { 99 testing_mode_ = true; 100 connector_.set_enforce_errors_from_incoming_receiver(false); 101 } 102 103 bool Router::HandleIncomingMessage(Message* message) { 104 if (message->has_flag(kMessageExpectsResponse)) { 105 if (incoming_receiver_) { 106 MessageReceiver* responder = new ResponderThunk(weak_self_); 107 bool ok = incoming_receiver_->AcceptWithResponder(message, responder); 108 if (!ok) 109 delete responder; 110 return ok; 111 } 112 113 // If we receive a request expecting a response when the client is not 114 // listening, then we have no choice but to tear down the pipe. 115 connector_.CloseMessagePipe(); 116 } else if (message->has_flag(kMessageIsResponse)) { 117 uint64_t request_id = message->request_id(); 118 ResponderMap::iterator it = responders_.find(request_id); 119 if (it == responders_.end()) { 120 assert(testing_mode_); 121 return false; 122 } 123 MessageReceiver* responder = it->second; 124 responders_.erase(it); 125 bool ok = responder->Accept(message); 126 delete responder; 127 return ok; 128 } else { 129 if (incoming_receiver_) 130 return incoming_receiver_->Accept(message); 131 // OK to drop message on the floor. 132 } 133 134 return false; 135 } 136 137 // ---------------------------------------------------------------------------- 138 139 } // namespace internal 140 } // namespace mojo 141