package org.webpieces.asyncserver.impl;
import java.nio.ByteBuffer;
import org.webpieces.nio.api.channels.Channel;
import org.webpieces.nio.api.channels.ChannelSession;
import org.webpieces.nio.api.channels.TCPChannel;
import org.webpieces.nio.api.handlers.AsyncDataListener;
import org.webpieces.nio.api.handlers.DataListener;
public class ProxyDataListener implements DataListener {
private static final String EXISTING_PROXY_CHANNEL = "_existingProxyChannel";
private ConnectedChannels connectedChannels;
private AsyncDataListener dataListener;
public ProxyDataListener(ConnectedChannels connectedChannels, AsyncDataListener dataListener) {
this.connectedChannels = connectedChannels;
this.dataListener = dataListener;
}
@Override
public void incomingData(Channel channel, ByteBuffer b) {
TCPChannel proxy = lookupExistingOrCreateNew(channel);
dataListener.incomingData(proxy, b);
}
@Override
public void farEndClosed(Channel channel) {
connectedChannels.removeChannel((TCPChannel) channel);
TCPChannel proxy = lookupExistingOrCreateNew(channel);
dataListener.farEndClosed(proxy);
}
@Override
public void failure(Channel channel, ByteBuffer data, Exception e) {
TCPChannel proxy = lookupExistingOrCreateNew(channel);
dataListener.failure(proxy, data, e);
}
/**
* We have two choices here.
* 1. implement equals and hashCode in ProxyTCPChannel to delegate to TCPChannel so as we
* create new ones, they are equal if the Channel they wrap is equal
* 2. re-use the same proxy we created for this channel by sticking it in the channel session
* which avoids creating new objects that need to be garbage collected every time data
* comes in
*
* @param channel
* @return
*/
private TCPChannel lookupExistingOrCreateNew(Channel channel) {
ChannelSession session = channel.getSession();
//This is garbage collected when the TCPChannel and it's ChannelSession are garbage
//collected...
ProxyTCPChannel existingProxy = (ProxyTCPChannel) session.get(EXISTING_PROXY_CHANNEL);
if(existingProxy == null) {
existingProxy = new ProxyTCPChannel((TCPChannel) channel, connectedChannels);
session.put(EXISTING_PROXY_CHANNEL, existingProxy);
}
return existingProxy;
}
@Override
public void applyBackPressure(Channel channel) {
TCPChannel proxy = lookupExistingOrCreateNew(channel);
dataListener.applyBackPressure(proxy);
}
@Override
public void releaseBackPressure(Channel channel) {
TCPChannel proxy = lookupExistingOrCreateNew(channel);
dataListener.releaseBackPressure(proxy);
}
public void connectionOpened(Channel channel, boolean isReadyForWrites) {
TCPChannel proxy = lookupExistingOrCreateNew(channel);
dataListener.connectionOpened(proxy, isReadyForWrites);
}
}