OLD | NEW |
| (Empty) |
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 #include "mojo/public/cpp/environment/logging.h" | |
8 | |
9 namespace mojo { | |
10 namespace internal { | |
11 | |
12 // ---------------------------------------------------------------------------- | |
13 | |
14 class ResponderThunk : public MessageReceiver { | |
15 public: | |
16 explicit ResponderThunk(const SharedData<Router*>& router) | |
17 : router_(router) {} | |
18 ~ResponderThunk() override {} | |
19 | |
20 // MessageReceiver implementation: | |
21 bool Accept(Message* message) override { | |
22 MOJO_DCHECK(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_(nullptr), | |
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(nullptr); | |
68 | |
69 for (ResponderMap::const_iterator i = responders_.begin(); | |
70 i != responders_.end(); | |
71 ++i) { | |
72 delete i->second; | |
73 } | |
74 } | |
75 | |
76 bool Router::Accept(Message* message) { | |
77 MOJO_DCHECK(!message->has_flag(kMessageExpectsResponse)); | |
78 return connector_.Accept(message); | |
79 } | |
80 | |
81 bool Router::AcceptWithResponder(Message* message, MessageReceiver* responder) { | |
82 MOJO_DCHECK(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 MOJO_DCHECK(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 | |
OLD | NEW |