| Index: mojo/bindings/java/src/org/chromium/mojo/bindings/RouterImpl.java
|
| diff --git a/mojo/bindings/java/src/org/chromium/mojo/bindings/RouterImpl.java b/mojo/bindings/java/src/org/chromium/mojo/bindings/RouterImpl.java
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..3f8457868b6fafbbe5872edfb1e1dd0c2d6e07e2
|
| --- /dev/null
|
| +++ b/mojo/bindings/java/src/org/chromium/mojo/bindings/RouterImpl.java
|
| @@ -0,0 +1,171 @@
|
| +// Copyright 2014 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +package org.chromium.mojo.bindings;
|
| +
|
| +import org.chromium.mojo.system.AsyncWaiter;
|
| +import org.chromium.mojo.system.MessagePipeHandle;
|
| +
|
| +import java.util.HashMap;
|
| +import java.util.Map;
|
| +
|
| +/**
|
| + * Implementation of Router.
|
| + */
|
| +public class RouterImpl implements Router {
|
| +
|
| + /**
|
| + * {@link MessageReceiver} used as the {@link Connector} callback.
|
| + */
|
| + private class Thunk implements MessageReceiver {
|
| +
|
| + /**
|
| + * @see MessageReceiver#accept(Message)
|
| + */
|
| + @Override
|
| + public boolean accept(Message message) {
|
| + return handleIncomingMessage(message);
|
| + }
|
| +
|
| + }
|
| +
|
| + /**
|
| + * The {@link Connector} connected to the handle.
|
| + */
|
| + private final Connector mConnector;
|
| +
|
| + /**
|
| + * The {@link MessageReceiverWithResponder} that will deserialize and use the message received
|
| + * from the pipe.
|
| + */
|
| + private MessageReceiverWithResponder mIncomingMessageReceiver;
|
| +
|
| + /**
|
| + * The id of the next request that needs a response. It is auto-incremented.
|
| + */
|
| + private long mNextRequestId = 1;
|
| +
|
| + /**
|
| + * The map from request ids to {@link MessageReceiver} of request currently in flight.
|
| + */
|
| + private Map<Long, MessageReceiver> mResponders = new HashMap<Long, MessageReceiver>();
|
| +
|
| + /**
|
| + * Constructor.
|
| + */
|
| + public RouterImpl(MessagePipeHandle messagePipeHandle) {
|
| + this(messagePipeHandle, BindingsHelper.getDefaultAsyncWaiterForHandle(messagePipeHandle));
|
| + }
|
| +
|
| + /**
|
| + * Constructor.
|
| + */
|
| + public RouterImpl(MessagePipeHandle messagePipeHandle, AsyncWaiter asyncWaiter) {
|
| + mConnector = new Connector(messagePipeHandle, asyncWaiter);
|
| + mConnector.setIncomingMessageReceiver(new Thunk());
|
| + }
|
| +
|
| + /**
|
| + * @see org.chromium.mojo.bindings.Router#start()
|
| + */
|
| + @Override
|
| + public void start() {
|
| + mConnector.start();
|
| + }
|
| +
|
| + /**
|
| + * @see Router#setIncomingMessageReceiver(MessageReceiverWithResponder)
|
| + */
|
| + @Override
|
| + public void setIncomingMessageReceiver(MessageReceiverWithResponder incomingMessageReceiver) {
|
| + this.mIncomingMessageReceiver = incomingMessageReceiver;
|
| + }
|
| +
|
| + /**
|
| + * @see MessageReceiver#accept(Message)
|
| + */
|
| + @Override
|
| + public boolean accept(Message message) {
|
| + // A message without receiver is directly forwarded to the connector.
|
| + return mConnector.accept(message);
|
| + }
|
| +
|
| + /**
|
| + * @see MessageReceiverWithResponder#acceptWithResponder(Message, MessageReceiver)
|
| + */
|
| + @Override
|
| + public boolean acceptWithResponder(Message message, MessageReceiver receiver) {
|
| + // Checking the message expects a response.
|
| + assert message.getHeader().hasFlag(MessageHeader.MESSAGE_EXPECTS_RESPONSE_FLAG);
|
| +
|
| + // Compute a request id for being able to route the response.
|
| + long requestId = mNextRequestId++;
|
| + // Reserve 0 in case we want it to convey special meaning in the future.
|
| + if (requestId == 0) {
|
| + requestId = mNextRequestId++;
|
| + }
|
| + assert !mResponders.containsKey(requestId);
|
| + MessageHeader.setRequestId(message, requestId);
|
| + if (!mConnector.accept(message)) {
|
| + return false;
|
| + }
|
| + // Only keep the receiver is the message has been accepted.
|
| + mResponders.put(requestId, receiver);
|
| + return true;
|
| + }
|
| +
|
| + /**
|
| + * @see org.chromium.mojo.bindings.HandleOwner#passHandle()
|
| + */
|
| + @Override
|
| + public MessagePipeHandle passHandle() {
|
| + return mConnector.passHandle();
|
| + }
|
| +
|
| + /**
|
| + * @see java.io.Closeable#close()
|
| + */
|
| + @Override
|
| + public void close() {
|
| + mConnector.close();
|
| + }
|
| +
|
| + /**
|
| + * @see Router#setErrorHandler(ConnectionErrorHandler)
|
| + */
|
| + @Override
|
| + public void setErrorHandler(ConnectionErrorHandler errorHandler) {
|
| + mConnector.setErrorHandler(errorHandler);
|
| + }
|
| +
|
| + /**
|
| + * Receive a message from the connector.
|
| + */
|
| + private boolean handleIncomingMessage(Message message) {
|
| + MessageHeader header = message.getHeader();
|
| + if (header.hasFlag(MessageHeader.MESSAGE_EXPECTS_RESPONSE_FLAG)) {
|
| + if (mIncomingMessageReceiver != null) {
|
| + return mIncomingMessageReceiver.acceptWithResponder(message, this);
|
| + }
|
| + // If we receive a request expecting a response when the client is not
|
| + // listening, then we have no choice but to tear down the pipe.
|
| + close();
|
| + return false;
|
| + } else if (header.hasFlag(MessageHeader.MESSAGE_IS_RESPONSE_FLAG)) {
|
| + long requestId = header.getRequestId();
|
| + MessageReceiver responder = mResponders.get(requestId);
|
| + if (responder == null) {
|
| + return false;
|
| + }
|
| + return responder.accept(message);
|
| + } else {
|
| + if (mIncomingMessageReceiver != null) {
|
| + return mIncomingMessageReceiver.accept(message);
|
| + }
|
| + // OK to drop the message.
|
| + }
|
| + return false;
|
| + }
|
| +
|
| +}
|
|
|