package de.tum.in.www1.jReto.routing; import java.nio.ByteBuffer; import java.nio.ByteOrder; import de.tum.in.www1.jReto.module.api.Connection; //TODO: ignores didSendData - is this ok? //TODO: might buffer lots of data if incoming connection is fast and outgoing connection is slow. /** * A ForkingConnection acts like the incomingConnection it was constructed with, but additionally forwards any data received * from the incoming connection to an additional outgoing connection and vice versa. Delegate methods will not be called for any events related to the outgoing connection. */ public class ForkingConnection implements Connection, Connection.Handler { public static interface CloseHandler { void onClose(ForkingConnection connection); } /** The ForkingConnection's incoming connection. */ private final Connection incomingConnection; /** The ForkingConnection's outgoing connection */ private final Connection outgoingConnection; /** A closure to call when the connection closes. */ private final CloseHandler closeHandler; private Connection.Handler handler; public ForkingConnection(Connection incomingConnection, Connection outgoingConnection, CloseHandler closeHandler) { this.incomingConnection = incomingConnection; this.outgoingConnection = outgoingConnection; this.closeHandler = closeHandler; this.incomingConnection.setHandler(this); this.outgoingConnection.setHandler(this); } private Connection counterpart(Connection connection) { if (connection == this.incomingConnection) return this.outgoingConnection; if (connection == this.outgoingConnection) return this.incomingConnection; System.err.println("Using invalid connection: "+connection); return null; } @Override public void onConnect(Connection connection) { System.out.println("Received onConnect in ForwardingConnection; connections should already be connected though."); } @Override public void onClose(Connection connection) { this.incomingConnection.setHandler(null); this.outgoingConnection.setHandler(null); this.counterpart(connection).close(); if (this.handler != null) this.handler.onClose(this); this.closeHandler.onClose(this); } @Override public void onDataReceived(Connection connection, ByteBuffer data) { if (connection == incomingConnection && this.handler != null) this.handler.onDataReceived(this, data.slice().order(ByteOrder.LITTLE_ENDIAN)); this.counterpart(connection).writeData(data.slice().order(ByteOrder.LITTLE_ENDIAN)); } @Override public void onDataSent(Connection connection) { if (connection == this.incomingConnection) { if (this.handler != null) this.handler.onDataSent(this); } } @Override public void setHandler(Handler handler) { this.handler = handler; } @Override public Handler getHandler() { return this.handler; } @Override public boolean isConnected() { return this.incomingConnection.isConnected() && this.outgoingConnection.isConnected(); } @Override public int getRecommendedPacketSize() { return this.incomingConnection.getRecommendedPacketSize(); } @Override public void connect() { System.err.println("Called connect on ForkingConnection. It should already be connected."); } @Override public void close() { this.incomingConnection.close(); this.outgoingConnection.close(); } @Override public void writeData(ByteBuffer data) { this.incomingConnection.writeData(data); } }