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
)
19 virtual ~ResponderThunk() {
22 // MessageReceiver implementation:
23 virtual bool Accept(Message
* message
) MOJO_OVERRIDE
{
24 MOJO_DCHECK(message
->has_flag(kMessageIsResponse
));
28 Router
* router
= router_
.value();
30 result
= router
->Accept(message
);
36 SharedData
<Router
*> router_
;
39 // ----------------------------------------------------------------------------
41 Router::HandleIncomingMessageThunk::HandleIncomingMessageThunk(Router
* router
)
45 Router::HandleIncomingMessageThunk::~HandleIncomingMessageThunk() {
48 bool Router::HandleIncomingMessageThunk::Accept(Message
* message
) {
49 return router_
->HandleIncomingMessage(message
);
52 // ----------------------------------------------------------------------------
54 Router::Router(ScopedMessagePipeHandle message_pipe
,
56 const MojoAsyncWaiter
* waiter
)
58 filters_(filters
.Pass()),
59 connector_(message_pipe
.Pass(), waiter
),
61 incoming_receiver_(NULL
),
63 testing_mode_(false) {
64 filters_
.SetSink(&thunk_
);
65 connector_
.set_incoming_receiver(filters_
.GetHead());
69 weak_self_
.set_value(NULL
);
71 for (ResponderMap::const_iterator i
= responders_
.begin();
72 i
!= responders_
.end(); ++i
) {
77 bool Router::Accept(Message
* message
) {
78 MOJO_DCHECK(!message
->has_flag(kMessageExpectsResponse
));
79 return connector_
.Accept(message
);
82 bool Router::AcceptWithResponder(Message
* message
,
83 MessageReceiver
* responder
) {
84 MOJO_DCHECK(message
->has_flag(kMessageExpectsResponse
));
86 // Reserve 0 in case we want it to convey special meaning in the future.
87 uint64_t request_id
= next_request_id_
++;
89 request_id
= next_request_id_
++;
91 message
->set_request_id(request_id
);
92 if (!connector_
.Accept(message
))
95 // We assume ownership of |responder|.
96 responders_
[request_id
] = responder
;
100 void Router::EnableTestingMode() {
101 testing_mode_
= true;
102 connector_
.set_enforce_errors_from_incoming_receiver(false);
105 bool Router::HandleIncomingMessage(Message
* message
) {
106 if (message
->has_flag(kMessageExpectsResponse
)) {
107 if (incoming_receiver_
) {
108 MessageReceiver
* responder
= new ResponderThunk(weak_self_
);
109 bool ok
= incoming_receiver_
->AcceptWithResponder(message
, responder
);
115 // If we receive a request expecting a response when the client is not
116 // listening, then we have no choice but to tear down the pipe.
117 connector_
.CloseMessagePipe();
118 } else if (message
->has_flag(kMessageIsResponse
)) {
119 uint64_t request_id
= message
->request_id();
120 ResponderMap::iterator it
= responders_
.find(request_id
);
121 if (it
== responders_
.end()) {
122 MOJO_DCHECK(testing_mode_
);
125 MessageReceiver
* responder
= it
->second
;
126 responders_
.erase(it
);
127 bool ok
= responder
->Accept(message
);
131 if (incoming_receiver_
)
132 return incoming_receiver_
->Accept(message
);
133 // OK to drop message on the floor.
139 // ----------------------------------------------------------------------------
141 } // namespace internal