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.
5 #include "mojo/public/cpp/bindings/lib/router.h"
7 #include "mojo/public/cpp/environment/logging.h"
12 // ----------------------------------------------------------------------------
14 class ResponderThunk
: public MessageReceiver
{
16 explicit ResponderThunk(const SharedData
<Router
*>& router
)
18 ~ResponderThunk() override
{}
20 // MessageReceiver implementation:
21 bool Accept(Message
* message
) override
{
22 MOJO_DCHECK(message
->has_flag(kMessageIsResponse
));
26 Router
* router
= router_
.value();
28 result
= router
->Accept(message
);
34 SharedData
<Router
*> router_
;
37 // ----------------------------------------------------------------------------
39 Router::HandleIncomingMessageThunk::HandleIncomingMessageThunk(Router
* router
)
43 Router::HandleIncomingMessageThunk::~HandleIncomingMessageThunk() {
46 bool Router::HandleIncomingMessageThunk::Accept(Message
* message
) {
47 return router_
->HandleIncomingMessage(message
);
50 // ----------------------------------------------------------------------------
52 Router::Router(ScopedMessagePipeHandle message_pipe
,
54 const MojoAsyncWaiter
* waiter
)
56 filters_(filters
.Pass()),
57 connector_(message_pipe
.Pass(), waiter
),
59 incoming_receiver_(nullptr),
61 testing_mode_(false) {
62 filters_
.SetSink(&thunk_
);
63 connector_
.set_incoming_receiver(filters_
.GetHead());
67 weak_self_
.set_value(nullptr);
69 for (ResponderMap::const_iterator i
= responders_
.begin();
70 i
!= responders_
.end();
76 bool Router::Accept(Message
* message
) {
77 MOJO_DCHECK(!message
->has_flag(kMessageExpectsResponse
));
78 return connector_
.Accept(message
);
81 bool Router::AcceptWithResponder(Message
* message
, MessageReceiver
* responder
) {
82 MOJO_DCHECK(message
->has_flag(kMessageExpectsResponse
));
84 // Reserve 0 in case we want it to convey special meaning in the future.
85 uint64_t request_id
= next_request_id_
++;
87 request_id
= next_request_id_
++;
89 message
->set_request_id(request_id
);
90 if (!connector_
.Accept(message
))
93 // We assume ownership of |responder|.
94 responders_
[request_id
] = responder
;
98 void Router::EnableTestingMode() {
100 connector_
.set_enforce_errors_from_incoming_receiver(false);
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
);
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_
);
123 MessageReceiver
* responder
= it
->second
;
124 responders_
.erase(it
);
125 bool ok
= responder
->Accept(message
);
129 if (incoming_receiver_
)
130 return incoming_receiver_
->Accept(message
);
131 // OK to drop message on the floor.
137 // ----------------------------------------------------------------------------
139 } // namespace internal