package org.webpieces.frontend2.impl;
import java.nio.ByteBuffer;
import org.webpieces.data.api.DataWrapperGenerator;
import org.webpieces.data.api.DataWrapperGeneratorFactory;
import org.webpieces.nio.api.channels.Channel;
import org.webpieces.nio.api.channels.TCPChannel;
import org.webpieces.nio.api.handlers.AsyncDataListener;
public class Layer1ServerListener implements AsyncDataListener {
private static final DataWrapperGenerator dataGen = DataWrapperGeneratorFactory.createDataWrapperGenerator();
private static final String FRONTEND_SOCKET = "__frontendSocket";
private Layer2Http1_1Handler http1_1Handler;
private Layer2Http2Handler http2Handler;
public Layer1ServerListener(
Layer2Http1_1Handler http1_1Listener,
Layer2Http2Handler http2Listener) {
this.http1_1Handler = http1_1Listener;
this.http2Handler = http2Listener;
}
@Override
public void incomingData(Channel channel, ByteBuffer b) {
FrontendSocketImpl socket = getSocket(channel);
switch (socket.getProtocol()) {
case HTTP2:
http2Handler.incomingData(socket, b);
break;
case HTTP1_1:
http1_1Handler.incomingData(socket, b);
break;
case UNKNOWN:
initialData(b, socket);
break;
default:
throw new IllegalStateException("Unknown protocol="+socket.getProtocol());
}
}
private void initialData(ByteBuffer b, FrontendSocketImpl socket) {
InitiationResult initialData = http1_1Handler.initialData(socket, b);
if(initialData == null)
return; //nothing to do, we don't know protocol yet
else if(initialData.getInitialStatus() == InitiationStatus.HTTP1_1) {
socket.setProtocol(ProtocolType.HTTP1_1);
} else if(initialData.getInitialStatus() == InitiationStatus.PREFACE) {
socket.setProtocol(ProtocolType.HTTP2);
http2Handler.initialize(socket);
//process any leftover data next
http2Handler.incomingData(socket, initialData.getLeftOverData());
} else {
throw new UnsupportedOperationException("Did not implement case="+initialData.getInitialStatus()+" yet");
}
}
@Override
public void farEndClosed(Channel channel) {
FrontendSocketImpl socket = getSocket(channel);
//when a channel is SSL, we can tell right away IF ALPN is installed
//boolean isHttp2 = channel.getAlpnDetails().isHttp2();
switch (socket.getProtocol()) {
case HTTP2:
http2Handler.farEndClosed(socket);
break;
case HTTP1_1:
http1_1Handler.farEndClosed(socket);
break;
case UNKNOWN:
//timeoutHandler.connectionClosedBeforeRequest(socket);
break;
default:
throw new IllegalStateException("Unknown protocol="+socket.getProtocol());
}
}
@Override
public void failure(Channel channel, ByteBuffer data, Exception e) {
}
@Override
public void applyBackPressure(Channel channel) {
}
@Override
public void releaseBackPressure(Channel channel) {
}
@Override
public void connectionOpened(TCPChannel channel, boolean isReadyForWrites) {
//when a channel is SSL, we can tell right away IF ALPN is installed
//boolean isHttp2 = channel.getAlpnDetails().isHttp2();
FrontendSocketImpl socket = new FrontendSocketImpl(channel, ProtocolType.UNKNOWN);
channel.getSession().put(FRONTEND_SOCKET, socket);
http1_1Handler.socketOpened(socket, isReadyForWrites);
}
FrontendSocketImpl getSocket(Channel channel) {
return (FrontendSocketImpl) channel.getSession().get(FRONTEND_SOCKET);
}
}