• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
ResponderThunk(const SharedData<Router * > & router)14   explicit ResponderThunk(const SharedData<Router*>& router)
15       : router_(router) {
16   }
~ResponderThunk()17   virtual ~ResponderThunk() {
18   }
19 
20   // MessageReceiver implementation:
Accept(Message * message)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 
HandleIncomingMessageThunk(Router * router)39 Router::HandleIncomingMessageThunk::HandleIncomingMessageThunk(Router* router)
40     : router_(router) {
41 }
42 
~HandleIncomingMessageThunk()43 Router::HandleIncomingMessageThunk::~HandleIncomingMessageThunk() {
44 }
45 
Accept(Message * message)46 bool Router::HandleIncomingMessageThunk::Accept(Message* message) {
47   return router_->HandleIncomingMessage(message);
48 }
49 
50 // ----------------------------------------------------------------------------
51 
Router(ScopedMessagePipeHandle message_pipe,FilterChain filters,const MojoAsyncWaiter * waiter)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 
~Router()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 
Accept(Message * message)75 bool Router::Accept(Message* message) {
76   assert(!message->has_flag(kMessageExpectsResponse));
77   return connector_.Accept(message);
78 }
79 
AcceptWithResponder(Message * message,MessageReceiver * responder)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 
EnableTestingMode()98 void Router::EnableTestingMode() {
99   testing_mode_ = true;
100   connector_.set_enforce_errors_from_incoming_receiver(false);
101 }
102 
HandleIncomingMessage(Message * message)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