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/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 virtual bool AcceptWithResponder(Message* message, | |
34 MessageReceiver* responder) MOJO_OVERRIDE { | |
35 assert(false); // not reached! | |
36 return false; | |
37 } | |
38 | |
39 private: | |
40 SharedData<Router*> router_; | |
41 }; | |
42 | |
43 // ---------------------------------------------------------------------------- | |
44 | |
45 Router::HandleIncomingMessageThunk::HandleIncomingMessageThunk(Router* router) | |
46 : router_(router) { | |
47 } | |
48 | |
49 Router::HandleIncomingMessageThunk::~HandleIncomingMessageThunk() { | |
50 } | |
51 | |
52 bool Router::HandleIncomingMessageThunk::Accept(Message* message) { | |
53 return router_->HandleIncomingMessage(message); | |
54 } | |
55 | |
56 bool Router::HandleIncomingMessageThunk::AcceptWithResponder( | |
57 Message* message, | |
58 MessageReceiver* responder) { | |
59 assert(false); // not reached! | |
60 return false; | |
61 } | |
62 | |
63 // ---------------------------------------------------------------------------- | |
64 | |
65 Router::Router(ScopedMessagePipeHandle message_pipe, MojoAsyncWaiter* waiter) | |
66 : connector_(message_pipe.Pass(), waiter), | |
67 weak_self_(this), | |
68 incoming_receiver_(NULL), | |
69 thunk_(this), | |
70 next_request_id_(0) { | |
71 connector_.set_incoming_receiver(&thunk_); | |
72 } | |
73 | |
74 Router::~Router() { | |
75 weak_self_.set_value(NULL); | |
76 } | |
77 | |
78 bool Router::Accept(Message* message) { | |
79 assert(!message->has_flag(kMessageExpectsResponse)); | |
80 return connector_.Accept(message); | |
81 } | |
82 | |
83 bool Router::AcceptWithResponder(Message* message, | |
84 MessageReceiver* responder) { | |
85 assert(message->has_flag(kMessageExpectsResponse)); | |
86 | |
87 // Reserve 0 in case we want it to convey special meaning in the future. | |
88 uint64_t request_id = next_request_id_++; | |
89 if (request_id == 0) | |
90 request_id = next_request_id_++; | |
91 | |
92 message->set_request_id(request_id); | |
93 if (!connector_.Accept(message)) | |
94 return false; | |
95 | |
96 // We assume ownership of |responder|. | |
97 responders_[request_id] = responder; | |
98 return true; | |
99 } | |
100 | |
101 bool Router::HandleIncomingMessage(Message* message) { | |
102 if (message->has_flag(kMessageExpectsResponse)) { | |
103 if (incoming_receiver_) { | |
104 MessageReceiver* responder = new ResponderThunk(weak_self_); | |
105 bool ok = incoming_receiver_->AcceptWithResponder(message, responder); | |
106 if (!ok) | |
107 delete responder; | |
108 return ok; | |
109 } | |
110 | |
111 // If we receive a request expecting a response when the client is not | |
112 // listening, then we have no choice but to tear down the pipe. | |
113 connector_.CloseMessagePipe(); | |
114 } else if (message->has_flag(kMessageIsResponse)) { | |
115 uint64_t request_id = message->request_id(); | |
116 ResponderMap::iterator it = responders_.find(request_id); | |
117 if (it == responders_.end()) { | |
118 assert(false); | |
119 return false; | |
120 } | |
121 MessageReceiver* responder = it->second; | |
122 responders_.erase(it); | |
123 responder->Accept(message); | |
124 delete responder; | |
125 } else { | |
126 if (incoming_receiver_) | |
127 return incoming_receiver_->Accept(message); | |
128 // OK to drop message on the floor. | |
129 } | |
130 | |
131 return false; | |
132 } | |
133 | |
134 // ---------------------------------------------------------------------------- | |
135 | |
136 } // namespace internal | |
137 } // namespace mojo | |
OLD | NEW |