package water;
import java.io.IOException;
import java.nio.channels.ByteChannel;
import java.nio.channels.SocketChannel;
/**
* <p>This class is a thread which exists per each new connection of type {@code TCPReceiverThread.TCP_EXTERNAL}</p>
*
* <p>It is started for the connection and waits for the {@code INIT_BYTE}. If the {@code INIT_BYTE} has been received,
* the socket channel and corresponding {@link AutoBuffer} is sent to {@link ExternalFrameHandler} to handle the
* particular request.</p>
*
* <p>The {@code INIT_BYTE} has to be sent since the connection can be reused on the caller side and we need to know
* that new bunch of requests or data is coming.</p>
*/
class ExternalFrameHandlerThread extends Thread {
private ByteChannel _sock;
private AutoBuffer _ab;
ExternalFrameHandlerThread(ByteChannel sock, AutoBuffer ab) {
super("TCP-"+sock);
_sock = sock;
_ab = ab;
setPriority(MAX_PRIORITY-1);
}
@Override
public void run() {
while (true) { // Loop, reading fresh TCP requests until the sender closes
try {
// blocking call
if(_ab.get1() != ExternalFrameHandler.INIT_BYTE){
// check whether this channel contains data for next frame task
// otherwise close the connection here
throw new IOException("This connection is idle, expected data are not available");
}
new ExternalFrameHandler().process(_sock, _ab);
// Reuse open sockets for the next task
if (!_sock.isOpen()) break;
_ab = new AutoBuffer(_sock, null);
} catch (Exception e) {
// Exceptions here are *normal*, this is an idle TCP connection and
// either the OS can time it out, or the cloud might shutdown. We
// don't care what happens to this socket.
break; // Ignore all errors; silently die if socket is closed
}
}
}
}