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 package org.chromium.mojo.bindings; |
| 6 |
| 7 import org.chromium.mojo.system.AsyncWaiter; |
| 8 import org.chromium.mojo.system.MessagePipeHandle; |
| 9 |
| 10 import java.util.HashMap; |
| 11 import java.util.Map; |
| 12 |
| 13 /** |
| 14 * Implementation of {@link Router}. |
| 15 */ |
| 16 public class RouterImpl implements Router { |
| 17 |
| 18 /** |
| 19 * {@link MessageReceiver} used as the {@link Connector} callback. |
| 20 */ |
| 21 private class ResponderThunk implements MessageReceiver { |
| 22 |
| 23 /** |
| 24 * @see MessageReceiver#accept(MessageWithHeader) |
| 25 */ |
| 26 @Override |
| 27 public boolean accept(MessageWithHeader message) { |
| 28 return handleIncomingMessage(message); |
| 29 } |
| 30 |
| 31 } |
| 32 |
| 33 /** |
| 34 * The {@link Connector} which is connected to the handle. |
| 35 */ |
| 36 private final Connector mConnector; |
| 37 |
| 38 /** |
| 39 * The {@link MessageReceiverWithResponder} that will consume the messages r
eceived from the |
| 40 * pipe. |
| 41 */ |
| 42 private MessageReceiverWithResponder mIncomingMessageReceiver; |
| 43 |
| 44 /** |
| 45 * The next id to use for a request id which needs a response. It is auto-in
cremented. |
| 46 */ |
| 47 private long mNextRequestId = 1; |
| 48 |
| 49 /** |
| 50 * The map from request ids to {@link MessageReceiver} of request currently
in flight. |
| 51 */ |
| 52 private Map<Long, MessageReceiver> mResponders = new HashMap<Long, MessageRe
ceiver>(); |
| 53 |
| 54 /** |
| 55 * Constructor that will use the default {@link AsyncWaiter}. |
| 56 * |
| 57 * @param messagePipeHandle The {@link MessagePipeHandle} to route message f
or. |
| 58 */ |
| 59 public RouterImpl(MessagePipeHandle messagePipeHandle) { |
| 60 this(messagePipeHandle, BindingsHelper.getDefaultAsyncWaiterForHandle(me
ssagePipeHandle)); |
| 61 } |
| 62 |
| 63 /** |
| 64 * Constructor. |
| 65 * |
| 66 * @param messagePipeHandle The {@link MessagePipeHandle} to route message f
or. |
| 67 * @param asyncWaiter the {@link AsyncWaiter} to use to get notification of
new messages on the |
| 68 * handle. |
| 69 */ |
| 70 public RouterImpl(MessagePipeHandle messagePipeHandle, AsyncWaiter asyncWait
er) { |
| 71 mConnector = new Connector(messagePipeHandle, asyncWaiter); |
| 72 mConnector.setIncomingMessageReceiver(new ResponderThunk()); |
| 73 } |
| 74 |
| 75 /** |
| 76 * @see org.chromium.mojo.bindings.Router#start() |
| 77 */ |
| 78 @Override |
| 79 public void start() { |
| 80 mConnector.start(); |
| 81 } |
| 82 |
| 83 /** |
| 84 * @see Router#setIncomingMessageReceiver(MessageReceiverWithResponder) |
| 85 */ |
| 86 @Override |
| 87 public void setIncomingMessageReceiver(MessageReceiverWithResponder incoming
MessageReceiver) { |
| 88 this.mIncomingMessageReceiver = incomingMessageReceiver; |
| 89 } |
| 90 |
| 91 /** |
| 92 * @see MessageReceiver#accept(MessageWithHeader) |
| 93 */ |
| 94 @Override |
| 95 public boolean accept(MessageWithHeader message) { |
| 96 // A message without responder is directly forwarded to the connector. |
| 97 return mConnector.accept(message); |
| 98 } |
| 99 |
| 100 /** |
| 101 * @see MessageReceiverWithResponder#acceptWithResponder(MessageWithHeader,
MessageReceiver) |
| 102 */ |
| 103 @Override |
| 104 public boolean acceptWithResponder(MessageWithHeader message, MessageReceive
r responder) { |
| 105 // Checking the message expects a response. |
| 106 assert message.getHeader().hasFlag(MessageHeader.MESSAGE_EXPECTS_RESPONS
E_FLAG); |
| 107 |
| 108 // Compute a request id for being able to route the response. |
| 109 long requestId = mNextRequestId++; |
| 110 // Reserve 0 in case we want it to convey special meaning in the future. |
| 111 if (requestId == 0) { |
| 112 requestId = mNextRequestId++; |
| 113 } |
| 114 if (mResponders.containsKey(requestId)) { |
| 115 throw new IllegalStateException("Unable to find a new request identi
fier."); |
| 116 } |
| 117 message.setRequestId(requestId); |
| 118 if (!mConnector.accept(message)) { |
| 119 return false; |
| 120 } |
| 121 // Only keep the responder is the message has been accepted. |
| 122 mResponders.put(requestId, responder); |
| 123 return true; |
| 124 } |
| 125 |
| 126 /** |
| 127 * @see org.chromium.mojo.bindings.HandleOwner#passHandle() |
| 128 */ |
| 129 @Override |
| 130 public MessagePipeHandle passHandle() { |
| 131 return mConnector.passHandle(); |
| 132 } |
| 133 |
| 134 /** |
| 135 * @see java.io.Closeable#close() |
| 136 */ |
| 137 @Override |
| 138 public void close() { |
| 139 mConnector.close(); |
| 140 } |
| 141 |
| 142 /** |
| 143 * @see Router#setErrorHandler(ConnectionErrorHandler) |
| 144 */ |
| 145 @Override |
| 146 public void setErrorHandler(ConnectionErrorHandler errorHandler) { |
| 147 mConnector.setErrorHandler(errorHandler); |
| 148 } |
| 149 |
| 150 /** |
| 151 * Receive a message from the connector. Returns |true| if the message has b
een handled. |
| 152 */ |
| 153 private boolean handleIncomingMessage(MessageWithHeader message) { |
| 154 MessageHeader header = message.getHeader(); |
| 155 if (header.hasFlag(MessageHeader.MESSAGE_EXPECTS_RESPONSE_FLAG)) { |
| 156 if (mIncomingMessageReceiver != null) { |
| 157 return mIncomingMessageReceiver.acceptWithResponder(message, thi
s); |
| 158 } |
| 159 // If we receive a request expecting a response when the client is n
ot |
| 160 // listening, then we have no choice but to tear down the pipe. |
| 161 close(); |
| 162 return false; |
| 163 } else if (header.hasFlag(MessageHeader.MESSAGE_IS_RESPONSE_FLAG)) { |
| 164 long requestId = header.getRequestId(); |
| 165 MessageReceiver responder = mResponders.get(requestId); |
| 166 if (responder == null) { |
| 167 return false; |
| 168 } |
| 169 return responder.accept(message); |
| 170 } else { |
| 171 if (mIncomingMessageReceiver != null) { |
| 172 return mIncomingMessageReceiver.accept(message); |
| 173 } |
| 174 // OK to drop the message. |
| 175 } |
| 176 return false; |
| 177 } |
| 178 } |
OLD | NEW |