package edu.washington.cs.oneswarm.f2f.servicesharing; import java.nio.ByteBuffer; import java.util.logging.Level; import java.util.logging.Logger; import com.aelitis.azureus.core.networkmanager.IncomingMessageQueue.MessageQueueListener; import com.aelitis.azureus.core.networkmanager.NetworkConnection; import com.aelitis.azureus.core.networkmanager.NetworkConnection.ConnectionListener; import com.aelitis.azureus.core.peermanager.messaging.Message; import edu.washington.cs.oneswarm.f2f.network.LowLatencyMessageWriter; public class ServiceSharingLoopback { public final static Logger logger = Logger.getLogger(ServiceSharingLoopback.class.getName()); private final NetworkConnection incomingConnection; private final SharedService sharedService; private NetworkConnection serviceConnection; public ServiceSharingLoopback(SharedService sharedService, NetworkConnection incomingConnection) { this.sharedService = sharedService; this.incomingConnection = incomingConnection; } public void connect() { serviceConnection = sharedService.createConnection(); logger.info("forwarding connection to service: " + sharedService + " address=" + serviceConnection.getEndpoint().getNotionalAddress()); incomingConnection.connect(true, new ServiceConnectionListener(false)); serviceConnection.connect(true, new ServiceConnectionListener(true)); } public void close() { incomingConnection.close(); serviceConnection.close(); logger.info("closed loopback connection"); } private class ServiceConnectionListener implements ConnectionListener { private final boolean outgoing; public ServiceConnectionListener(boolean outgoing) { this.outgoing = outgoing; } @Override public void connectFailure(Throwable failure_msg) { logger.info("incoming: connect failure to " + sharedService + " " + failure_msg.getClass().getName() + "::" + failure_msg.getMessage()); } @Override public void connectStarted() { logger.info("connect started to " + sharedService); } @Override public void connectSuccess(ByteBuffer remaining_initial_data) { logger.info("connect success to " + sharedService); if (outgoing) { startMessageProcessing(); } } @Override public void exceptionThrown(Throwable error) { logger.info("Exception in " + sharedService + " " + error.getClass().getName() + "::" + error.getMessage()); close(); } @Override public String getDescription() { return "loopback connect listener"; } } private void startMessageProcessing() { incomingConnection.getIncomingMessageQueue().registerQueueListener( new MessageQueueListener() { @Override public void dataBytesReceived(int byte_count) { } @Override public boolean messageReceived(Message message) { if (logger.isLoggable(Level.FINEST)) { logger.finest("From client: " + message.getDescription()); } transferMessage(serviceConnection, (DataMessage) message); return true; } @Override public void protocolBytesReceived(int byte_count) { } }); serviceConnection.getIncomingMessageQueue().registerQueueListener( new MessageQueueListener() { @Override public void dataBytesReceived(int byte_count) { } @Override public boolean messageReceived(Message message) { if (logger.isLoggable(Level.FINEST)) { logger.finest("From server: " + message.getDescription()); } transferMessage(incomingConnection, (DataMessage) message); return true; } @Override public void protocolBytesReceived(int byte_count) { } }); serviceConnection.startMessageProcessing(); incomingConnection.startMessageProcessing(); serviceConnection.enableEnhancedMessageProcessing(true); serviceConnection.getOutgoingMessageQueue().registerQueueListener( new LowLatencyMessageWriter(serviceConnection)); incomingConnection.enableEnhancedMessageProcessing(true); incomingConnection.getOutgoingMessageQueue().registerQueueListener( new LowLatencyMessageWriter(incomingConnection)); } private void transferMessage(NetworkConnection target, DataMessage message) { target.getOutgoingMessageQueue().addMessage(new DataMessage(message.transferPayload()), false); } }