/* This code is part of Freenet. It is distributed under the GNU General * Public License, version 2 (or at your option any later version). See * http://www.gnu.org/ for further details of the GPL. */ package freenet.clients.fcp; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import org.tanukisoftware.wrapper.WrapperManager; import freenet.support.LogThresholdCallback; import freenet.support.Logger; import freenet.support.SimpleFieldSet; import freenet.support.Logger.LogLevel; import freenet.support.io.Closer; import freenet.support.io.LineReadingInputStream; import freenet.support.io.TooLongException; public class FCPConnectionInputHandler implements Runnable { private static volatile boolean logMINOR; private static volatile boolean logDEBUG; static { Logger.registerLogThresholdCallback(new LogThresholdCallback() { @Override public void shouldUpdate() { logMINOR = Logger.shouldLog(LogLevel.MINOR, this); logDEBUG = Logger.shouldLog(LogLevel.DEBUG, this); } }); } final FCPConnectionHandler handler; FCPConnectionInputHandler(FCPConnectionHandler handler) { this.handler = handler; } void start() { if (handler.sock == null) return; handler.server.node.executor.execute(this, "FCP input handler for "+handler.sock.getRemoteSocketAddress()); } @Override public void run() { freenet.support.Logger.OSThread.logPID(this); try { realRun(); } catch (TooLongException e) { Logger.normal(this, "Caught "+e.getMessage(), e); } catch (IOException e) { if(logMINOR) Logger.minor(this, "Caught "+e, e); } catch (Throwable t) { Logger.error(this, "Caught "+t, t); t.printStackTrace(); } handler.close(); handler.closedInput(); } public void realRun() throws IOException { InputStream is = new BufferedInputStream(handler.sock.getInputStream(), 4096); LineReadingInputStream lis = new LineReadingInputStream(is); boolean firstMessage = true; while(true) { SimpleFieldSet fs; if(WrapperManager.hasShutdownHookBeenTriggered()) { FCPMessage msg = new ProtocolErrorMessage(ProtocolErrorMessage.SHUTTING_DOWN,true,"The node is shutting down","Node",false); handler.outputHandler.queue(msg); Closer.close(is); return; } // Read a message String messageType = lis.readLine(128, 128, true); if(messageType == null) { Closer.close(is); return; } if(messageType.equals("")) continue; fs = new SimpleFieldSet(lis, 4096, 128, true, true, true); // check for valid endmarker if (!firstMessage && fs.getEndMarker() != null && (!fs.getEndMarker().startsWith("End")) && (!"Data".equals(fs.getEndMarker()))) { FCPMessage err = new ProtocolErrorMessage(ProtocolErrorMessage.MESSAGE_PARSE_ERROR, false, "Invalid end marker: "+fs.getEndMarker(), fs.get("Identifer"), fs.getBoolean("Global", false)); handler.outputHandler.queue(err); continue; } FCPMessage msg; try { if(logDEBUG) Logger.debug(this, "Incoming FCP message:\n"+messageType+'\n'+fs.toString()); msg = FCPMessage.create(messageType, fs, handler.bf, handler.server.core.persistentTempBucketFactory); if(msg == null) continue; } catch (MessageInvalidException e) { if(firstMessage) { FCPMessage err = new ProtocolErrorMessage(ProtocolErrorMessage.CLIENT_HELLO_MUST_BE_FIRST_MESSAGE, true, null, null, false); handler.outputHandler.queue(err); handler.close(); Closer.close(is); return; } else { FCPMessage err = new ProtocolErrorMessage(e.protocolCode, false, e.getMessage(), e.ident, e.global); handler.outputHandler.queue(err); } continue; } if(firstMessage && !(msg instanceof ClientHelloMessage)) { FCPMessage err = new ProtocolErrorMessage(ProtocolErrorMessage.CLIENT_HELLO_MUST_BE_FIRST_MESSAGE, true, null, null, false); handler.outputHandler.queue(err); handler.close(); Closer.close(is); return; } if(msg instanceof BaseDataCarryingMessage) { // FIXME tidy up - coalesce with above and below try { } catch (MIE) {}'s? try { ((BaseDataCarryingMessage)msg).readFrom(lis, handler.bf, handler.server); } catch (MessageInvalidException e) { FCPMessage err = new ProtocolErrorMessage(e.protocolCode, false, e.getMessage(), e.ident, e.global); handler.outputHandler.queue(err); continue; } } if((!firstMessage) && (msg instanceof ClientHelloMessage)) { FCPMessage err = new ProtocolErrorMessage(ProtocolErrorMessage.NO_LATE_CLIENT_HELLOS, false, null, null, false); handler.outputHandler.queue(err); continue; } try { if(logDEBUG) Logger.debug(this, "Parsed message: "+msg+" for "+handler); msg.run(handler, handler.server.node); } catch (MessageInvalidException e) { FCPMessage err = new ProtocolErrorMessage(e.protocolCode, false, e.getMessage(), e.ident, e.global); handler.outputHandler.queue(err); continue; } firstMessage = false; if(handler.isClosed()) { Closer.close(is); return; } } } }