diff --git a/source/de/anomic/server/serverCore.java b/source/de/anomic/server/serverCore.java index 94ee0616d..479323ecb 100644 --- a/source/de/anomic/server/serverCore.java +++ b/source/de/anomic/server/serverCore.java @@ -1,4 +1,4 @@ -// serverCore.java +// serverCore.java // ------------------------------------------- // (C) by Michael Peter Christen; mc@yacy.net // first published on http://www.anomic.de @@ -64,7 +64,6 @@ import net.yacy.kelondro.logging.Log; import net.yacy.kelondro.util.ByteBuffer; import net.yacy.kelondro.workflow.AbstractBusyThread; import net.yacy.kelondro.workflow.BusyThread; - import de.anomic.tools.PKCS12Tool; public final class serverCore extends AbstractBusyThread implements BusyThread { @@ -96,22 +95,22 @@ public final class serverCore extends AbstractBusyThread implements BusyThread { public static final long startupTime = System.currentTimeMillis(); private static final ThreadGroup sessionThreadGroup = new ThreadGroup("sessionThreadGroup"); private static final Map commandObjMethodCache = new ConcurrentHashMap(5); - + /** * will be increased with each session and is used to return a hash code */ static int sessionCounter = 0; - + // static variables private static final long keepAliveTimeout = 60000; // time that a connection is kept alive if requested with a keepAlive statement public static final Boolean TERMINATE_CONNECTION = Boolean.FALSE; public static final Boolean RESUME_CONNECTION = Boolean.TRUE; - + /** * for brute-force prevention */ public static final Map bfHost = new ConcurrentHashMap(); - + // class variables /** * the port, which is visible from outside (in most cases bind-port) @@ -125,49 +124,49 @@ public final class serverCore extends AbstractBusyThread implements BusyThread { * specifies if the server should try to do a restart */ boolean forceRestart = false; - + public static boolean useStaticIP = false; protected Log log; private SSLSocketFactory sslSocketFactory = null; private ServerSocket socket; // listener private final int timeout; // connection time-out of the socket - serverHandler handlerPrototype; // the command class (a serverHandler) + serverHandler handlerPrototype; // the command class (a serverHandler) private final serverSwitch switchboard; // the command class switchboard - private Map denyHost; + private final Map denyHost; int commandMaxLength; private int maxBusySessions; private long lastAutoTermination; - - public final void terminateOldSessions(long minage) { - if (System.currentTimeMillis() - lastAutoTermination < 3000) return; + + public final void terminateOldSessions(final long minage) { + if (System.currentTimeMillis() - this.lastAutoTermination < 3000) return; this.lastAutoTermination = System.currentTimeMillis(); //if (serverCore.getJobCount() < maxBusySessions - 10) return; // don't panic - - for (Session s: getJobList()) { + + for (final Session s: getJobList()) { if (!s.isAlive()) continue; if (s.getTime() < minage) continue; - + // stop thread this.log.logInfo("check for " + s.getName() + ": " + s.getTime() + " ms alive, stopping thread"); - + // trying to stop session s.setStopped(true); try { Thread.sleep(10); } catch (final InterruptedException ex) {} - + // trying to interrupt session synchronized (s) { s.notify(); } s.interrupt(); - + // trying to close socket if (s.isAlive()) { s.close(); } } } - + public static String clientAddress(final Socket s) { final InetAddress uAddr = s.getInetAddress(); if (uAddr.isAnyLocalAddress()) return "127.0.0.1"; @@ -177,21 +176,21 @@ public final class serverCore extends AbstractBusyThread implements BusyThread { } // class initializer - public serverCore( + public serverCore( final int timeout, final boolean blockAttack, - final serverHandler handlerPrototype, + final serverHandler handlerPrototype, final serverSwitch switchboard, final int commandMaxLength ) { super(Long.MIN_VALUE, Long.MAX_VALUE, Long.MIN_VALUE, Long.MAX_VALUE); this.timeout = timeout; - + this.commandMaxLength = commandMaxLength; this.denyHost = (blockAttack) ? new ConcurrentHashMap() : null; this.handlerPrototype = handlerPrototype; this.switchboard = switchboard; - + // initialize logger this.log = new Log("SERVER"); @@ -200,70 +199,70 @@ public final class serverCore extends AbstractBusyThread implements BusyThread { // init session parameter this.maxBusySessions = Math.max(1, Integer.parseInt(switchboard.getConfig("httpdMaxBusySessions","100"))); - + this.lastAutoTermination = System.currentTimeMillis(); - + // init servercore init(); } - + public boolean withSSL() { return this.sslSocketFactory != null; } - + public synchronized void init() { this.log.logInfo("Initializing serverCore ..."); - + // read some config values this.extendedPort = this.switchboard.getConfig("port", "8090").trim(); this.bindPort = this.switchboard.getConfig("bindPort", "").trim(); - + // Open a new server-socket channel try { - // bind the ServerSocket to a specific address + // bind the ServerSocket to a specific address // InetSocketAddress bindAddress = null; this.socket = new ServerSocket(); - if (bindPort == null || bindPort.equals("")) { - this.log.logInfo("Trying to bind server to port " + extendedPort); - this.socket.bind(/*bindAddress = */generateSocketAddress(extendedPort)); + if (this.bindPort == null || this.bindPort.equals("")) { + this.log.logInfo("Trying to bind server to port " + this.extendedPort); + this.socket.bind(/*bindAddress = */generateSocketAddress(this.extendedPort)); } else { //bindPort set, use another port to bind than the port reachable from outside - this.log.logInfo("Trying to bind server to port " + bindPort+ " with "+ extendedPort + "as seedPort."); - this.socket.bind(/*bindAddress = */generateSocketAddress(bindPort)); + this.log.logInfo("Trying to bind server to port " + this.bindPort+ " with "+ this.extendedPort + "as seedPort."); + this.socket.bind(/*bindAddress = */generateSocketAddress(this.bindPort)); } // updating the port information - //yacyCore.seedDB.mySeed.put(yacySeed.PORT,Integer.toString(bindAddress.getPort())); + //yacyCore.seedDB.mySeed.put(yacySeed.PORT,Integer.toString(bindAddress.getPort())); //yacyCore.seedDB.mySeed().put(yacySeed.PORT, extendedPort); } catch (final Exception e) { final String errorMsg = "FATAL ERROR: " + e.getMessage() + " - probably root access rights needed. check port number"; this.log.logSevere(errorMsg); - System.out.println(errorMsg); + System.out.println(errorMsg); System.exit(0); } } - + public static int getPortNr(String extendedPortString) { int pos = -1; if ((pos = extendedPortString.indexOf(':'))!= -1) { extendedPortString = extendedPortString.substring(pos+1); } - return Integer.parseInt(extendedPortString); + return Integer.parseInt(extendedPortString); } - + public InetSocketAddress generateSocketAddress(String extendedPortString) throws SocketException { - + // parsing the port configuration String bindIP = null; int bindPort; - + int pos = -1; if ((pos = extendedPortString.indexOf(':'))!= -1) { bindIP = extendedPortString.substring(0,pos).trim(); - extendedPortString = extendedPortString.substring(pos+1); - + extendedPortString = extendedPortString.substring(pos+1); + if (bindIP.length() > 0 && bindIP.charAt(0) == '#') { final String interfaceName = bindIP.substring(1); String hostName = null; - if (this.log.isFine()) this.log.logFine("Trying to determine IP address of interface '" + interfaceName + "'."); + if (this.log.isFine()) this.log.logFine("Trying to determine IP address of interface '" + interfaceName + "'."); final Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); if (interfaces != null) { @@ -290,39 +289,39 @@ public final class serverCore extends AbstractBusyThread implements BusyThread { this.log.logInfo("Binding server to interface '" + interfaceName + "' with IP '" + hostName + "'."); bindIP = hostName; } - } + } } - bindPort = Integer.parseInt(extendedPortString); - - return (bindIP == null) + bindPort = Integer.parseInt(extendedPortString); + + return (bindIP == null) ? new InetSocketAddress(bindPort) : new InetSocketAddress(bindIP, bindPort); } - + public void open() { this.log.logConfig("* server started on " + Domains.myPublicLocalIP() + ":" + this.extendedPort); } - + public void freemem() { // FIXME: can we something here to flush memory? Idea: Reduce the size of some of our various caches. } - + // class body public boolean job() throws Exception { try { // prepare for new connection // idleThreadCheck(); - int jobCount = getJobCount(); + final int jobCount = getJobCount(); this.switchboard.handleBusyState(jobCount); if (this.log.isFinest()) this.log.logFinest("* waiting for connections, " + jobCount + " sessions running"); - + announceThreadBlockApply(); - + // wait for new connection Socket controlSocket = this.socket.accept(); - + announceThreadBlockRelease(); - + if (jobCount >= this.maxBusySessions) { terminateOldSessions(3000); this.log.logInfo("termination of old sessions: before = " + jobCount + ", after = " + getJobCount()); @@ -334,13 +333,13 @@ public final class serverCore extends AbstractBusyThread implements BusyThread { if (getJobCount() >= this.maxBusySessions) { // immediately close connection if too much sessions are still running this.log.logWarning("* connections (" + getJobCount() + ") exceeding limit (" + this.maxBusySessions + ")" + ", closing new incoming connection from "+ controlSocket.getRemoteSocketAddress()); - + controlSocket.close(); return false; - + } */ - + final String cIP = clientAddress(controlSocket); //System.out.println("server bfHosts=" + bfHost.toString()); /* @@ -358,36 +357,36 @@ public final class serverCore extends AbstractBusyThread implements BusyThread { } } */ - + if ((this.denyHost == null) || (this.denyHost.get(cIP) == null)) { // setting the timeout properly assert this.timeout >= 1000; controlSocket.setSoTimeout(this.timeout); - + // wrap this socket if (this.sslSocketFactory != null) { controlSocket = new serverCoreSocket(controlSocket); // if the current connection is SSL we need to do a handshake - if (((serverCoreSocket)controlSocket).isSSL()) { - controlSocket = negotiateSSL(controlSocket); - } + if (((serverCoreSocket)controlSocket).isSSL()) { + controlSocket = negotiateSSL(controlSocket); + } } // keep-alive: if set to true, the server frequently sends keep-alive packets to the client which the client must respond to // we set this to false to prevent that a missing ack from the client forces the server to close the connection - controlSocket.setKeepAlive(false); - + controlSocket.setKeepAlive(false); + // disable Nagle's algorithm (waiting for more data until packet is full) // controlSocket.setTcpNoDelay(true); - + // set a non-zero linger, that means that a socket.close() blocks until all data is written controlSocket.setSoLinger(false, this.timeout); - + // ensure that MTU-48 is not exceeded to prevent that routers cannot handle large data packets // read http://www.cisco.com/warp/public/105/38.shtml for explanation //controlSocket.setSendBufferSize(1440); //controlSocket.setReceiveBufferSize(1440); - + // create session final Session connection = new Session(sessionThreadGroup, controlSocket, this.timeout); //terminateOldSessions(60000); @@ -395,12 +394,12 @@ public final class serverCore extends AbstractBusyThread implements BusyThread { } else { this.log.logWarning("ACCESS FROM " + cIP + " DENIED"); } - + return true; } catch (final SocketException e) { if (this.forceRestart) { // reinitialize serverCore - init(); + init(); this.forceRestart = false; return true; } @@ -411,7 +410,7 @@ public final class serverCore extends AbstractBusyThread implements BusyThread { public synchronized void close() { // consuming the isInterrupted Flag. Otherwise we could not properly close the session pool Thread.interrupted(); - + // shut down all busySessions for (final Session session: getJobList()) { if (session == null) continue; @@ -423,13 +422,13 @@ public final class serverCore extends AbstractBusyThread implements BusyThread { Log.logException(e); } } - + // close the serverchannel and socket try { this.log.logInfo("Closing server socket ..."); this.socket.close(); } catch (final Exception e) { - this.log.logWarning("Unable to close the server socket."); + this.log.logWarning("Unable to close the server socket."); } // close all sessions @@ -438,15 +437,15 @@ public final class serverCore extends AbstractBusyThread implements BusyThread { session.interrupt(); //session.close(); } - + this.log.logConfig("* terminated"); } - + public List getJobList() { - final Thread[] threadList = new Thread[sessionThreadGroup.activeCount()]; + final Thread[] threadList = new Thread[sessionThreadGroup.activeCount()]; serverCore.sessionThreadGroup.enumerate(threadList, false); - ArrayList l = new ArrayList(); - for (Thread t: threadList) { + final ArrayList l = new ArrayList(); + for (final Thread t: threadList) { if (t == null) continue; if (!(t instanceof Session)) { //log.logSevere("serverCore.getJobList - thread is not Session: " + t.getClass().getName()); @@ -456,12 +455,12 @@ public final class serverCore extends AbstractBusyThread implements BusyThread { } return l; } - + public int getJobCount() { - final Thread[] threadList = new Thread[sessionThreadGroup.activeCount()]; + final Thread[] threadList = new Thread[sessionThreadGroup.activeCount()]; serverCore.sessionThreadGroup.enumerate(threadList, false); int c = 0; - for (Thread t: threadList) { + for (final Thread t: threadList) { if (t == null) continue; if (!(t instanceof Session)) { //log.logSevere("serverCore.getJobList - thread is not Session: " + t.getClass().getName()); @@ -475,9 +474,9 @@ public final class serverCore extends AbstractBusyThread implements BusyThread { // idle sensor: the thread is idle if there are no sessions running public boolean idle() { // idleThreadCheck(); - final Thread[] threadList = new Thread[sessionThreadGroup.activeCount()]; + final Thread[] threadList = new Thread[sessionThreadGroup.activeCount()]; serverCore.sessionThreadGroup.enumerate(threadList, false); - for (Thread t: threadList) { + for (final Thread t: threadList) { if (t == null) continue; if (!(t instanceof Session)) { //log.logSevere("serverCore.getJobList - thread is not Session: " + t.getClass().getName()); @@ -488,11 +487,11 @@ public final class serverCore extends AbstractBusyThread implements BusyThread { return true; //return (getJobCount() == 0); } - + public int getMaxSessionCount() { return this.maxBusySessions; } - + public void setMaxSessionCount(final int count) { this.maxBusySessions = count; } @@ -502,18 +501,18 @@ public final class serverCore extends AbstractBusyThread implements BusyThread { //boolean destroyed = false; private boolean runningsession = false; private boolean stopped = false; - + private long start; // startup time private serverHandler commandObj; - + private String request; // current command line private int commandCounter; // for logging: number of commands in this session private String identity; // a string that identifies the client (i.e. ftp: account name) //private boolean promiscuous; // if true, no lines are read and streams are only passed - + public Socket controlSocket; // dialog socket public InetAddress userAddress; // the address of the client - public int userPort; // the ip port used by the client + public int userPort; // the ip port used by the client public PushbackInputStream in; // on control input stream public OutputStream out; // on control output stream, auto-flush public int socketTimeout; @@ -521,7 +520,7 @@ public final class serverCore extends AbstractBusyThread implements BusyThread { public Session(final ThreadGroup theThreadGroup, final Socket controlSocket, final int socketTimeout) { super(theThreadGroup, controlSocket.getInetAddress().toString() + "@" + Long.toString(System.currentTimeMillis())); - this.setPriority(Thread.MAX_PRIORITY); + setPriority(Thread.MAX_PRIORITY); this.socketTimeout = socketTimeout; this.controlSocket = controlSocket; this.hashIndex = sessionCounter; @@ -532,72 +531,72 @@ public final class serverCore extends AbstractBusyThread implements BusyThread { // return a hash code so it is possible to store objects of httpc objects in a HashSet return this.hashIndex; } - + public int getCommandCount() { return this.commandCounter; } - + public String getCommandLine() { return this.request; } - + public serverHandler getCommandObj() { return this.commandObj; } - + public InetAddress getUserAddress() { return this.userAddress; } - + public int getUserPort() { return this.userPort; } - + public void setStopped(final boolean stopped) { - this.stopped = stopped; + this.stopped = stopped; } - + public boolean isStopped() { return this.stopped; } - + public void close() { // closing the socket to the client if (this.controlSocket != null) try { this.controlSocket.close(); - log.logInfo("Closing main socket of thread '" + this.getName() + "'"); + serverCore.this.log.logInfo("Closing main socket of thread '" + getName() + "'"); this.controlSocket = null; } catch (final Exception e) {} } - + public long getRequestStartTime() { return this.start; } - + public long getTime() { return System.currentTimeMillis() - this.start; } - + public void setIdentity(final String id) { this.identity = id; } - + public void log(final boolean outgoing, final String request) { - if (log.isFine()) log.logFine(this.userAddress.getHostAddress() + "/" + this.identity + " " + + if (serverCore.this.log.isFine()) serverCore.this.log.logFine(this.userAddress.getHostAddress() + "/" + this.identity + " " + "[" + getJobCount() + ", " + this.commandCounter + ((outgoing) ? "] > " : "] < ") + request); } - + public void writeLine(final String messg) throws IOException { send(this.out, messg); log(true, messg); } - + public byte[] readLine() { - return receive(this.in, commandMaxLength, true); + return receive(this.in, serverCore.this.commandMaxLength, true); } - + /** * reads a line from the input socket * this function is provided by the server through a passed method on initialization @@ -607,36 +606,36 @@ public final class serverCore extends AbstractBusyThread implements BusyThread { final byte[] l = readLine(); return (l == null) ? null: UTF8.String(l); } - + /** * @return whether the {@link Thread} is currently running */ public boolean isRunning() { return this.runningsession; } - + /** - * - * + * + * * @see java.lang.Thread#run() */ public void run() { this.runningsession = true; - + try { // setting the session startup time - this.start = System.currentTimeMillis(); - + this.start = System.currentTimeMillis(); + // set the session identity this.identity = "-"; - + // getting some client information this.userAddress = this.controlSocket.getInetAddress(); this.userPort = this.controlSocket.getPort(); - this.setName("Session_" + this.userAddress.getHostAddress() + ":" + this.controlSocket.getPort()); - + setName("Session_" + this.userAddress.getHostAddress() + ":" + this.controlSocket.getPort()); + // TODO: check if we want to allow this socket to connect us - + // getting input and output stream for communication with client if (this.controlSocket.getInputStream() instanceof PushbackInputStream) { this.in = (PushbackInputStream) this.controlSocket.getInputStream(); @@ -647,7 +646,7 @@ public final class serverCore extends AbstractBusyThread implements BusyThread { // reseting the command counter this.commandCounter = 0; - + // listen for commands listen(); } catch (final IOException e) { @@ -659,18 +658,18 @@ public final class serverCore extends AbstractBusyThread implements BusyThread { if ((this.controlSocket != null) && (! this.controlSocket.isClosed())) { // flush data this.out.flush(); - + // maybe this doesn't work for all SSL socket implementations if (!(this.controlSocket instanceof SSLSocket)) { this.controlSocket.shutdownInput(); this.controlSocket.shutdownOutput(); } - + // close streams - this.in.close(); - this.out.close(); - - // close everything + this.in.close(); + this.out.close(); + + // close everything this.controlSocket.close(); } } catch (final IOException e) { @@ -679,9 +678,9 @@ public final class serverCore extends AbstractBusyThread implements BusyThread { this.controlSocket = null; } } - + } - + private void listen() { try { // start dialog @@ -689,26 +688,26 @@ public final class serverCore extends AbstractBusyThread implements BusyThread { boolean terminate = false; String reqCmd; String reqProtocol = "HTTP"; - long situationDependentKeepAliveTimeout = keepAliveTimeout; + final long situationDependentKeepAliveTimeout = keepAliveTimeout; while (this.in != null && this.controlSocket != null && this.controlSocket.isConnected() && (this.commandCounter == 0 || System.currentTimeMillis() - this.start < situationDependentKeepAliveTimeout) && (requestBytes = readLine()) != null) { - this.setName("Session_" + this.userAddress.getHostAddress() + - ":" + this.controlSocket.getPort() + - "#" + this.commandCounter); - this.request = UTF8.String(requestBytes); + setName("Session_" + this.userAddress.getHostAddress() + + ":" + this.controlSocket.getPort() + + "#" + this.commandCounter + "_" + this.request); + //this.log.logDebug("* session " + handle + " received command '" + request + "'. time = " + (System.currentTimeMillis() - handle)); log(false, this.request); - try { + try { // if we can not determine the proper command string we try to call function emptyRequest // of the commandObject if (this.request.trim().length() == 0) this.request = "EMPTY"; - + final Object[] parameter = new Object[2]; - + // get the rest of the request parameters final int pos = this.request.indexOf(' '); if (pos < 0) { @@ -719,25 +718,25 @@ public final class serverCore extends AbstractBusyThread implements BusyThread { parameter[0] = this.request.substring(pos).trim(); } parameter[1] = this; - + // now we need to initialize the session if (this.commandCounter == 0) { // first we need to determine the proper protocol handler if (this.request.indexOf("HTTP") >= 0) reqProtocol = "HTTP"; - else reqProtocol = null; - + else reqProtocol = null; + if (this.request == null) break; if (reqProtocol != null && reqProtocol.equals("HTTP")) { - this.commandObj = handlerPrototype.clone(); + this.commandObj = serverCore.this.handlerPrototype.clone(); } } - + // count the amount of requests that were processed by this session until yet this.commandCounter++; - + // setting the socket timeout for reading of the request content this.controlSocket.setSoTimeout(this.socketTimeout); - + // exec command and return value Method commandMethod = commandObjMethodCache.get(reqProtocol + "_" + reqCmd); if (commandMethod == null) { @@ -749,33 +748,33 @@ public final class serverCore extends AbstractBusyThread implements BusyThread { parameter[0] = this.request.trim(); } } - + Object result = null; try { result = commandMethod.invoke(this.commandObj, parameter); - } catch (OutOfMemoryError e) { - log.logWarning("commandMethod.invoke: OutOfMemoryError / 1 (retry1 follows)"); + } catch (final OutOfMemoryError e) { + serverCore.this.log.logWarning("commandMethod.invoke: OutOfMemoryError / 1 (retry1 follows)"); // try again terminateOldSessions(2000); try { result = commandMethod.invoke(this.commandObj, parameter); - } catch (OutOfMemoryError e2) { - log.logWarning("commandMethod.invoke: OutOfMemoryError / 2 (retry2 follows)"); + } catch (final OutOfMemoryError e2) { + serverCore.this.log.logWarning("commandMethod.invoke: OutOfMemoryError / 2 (retry2 follows)"); // try again Thread.sleep(1000); result = commandMethod.invoke(this.commandObj, parameter); } } - + //announceMoreExecTime(commandStart - System.currentTimeMillis()); // shall be negative! //this.log.logDebug("* session " + handle + " completed command '" + request + "'. time = " + (System.currentTimeMillis() - handle)); this.out.flush(); if (result != null) { if (result instanceof Boolean) { if (((Boolean) result).equals(TERMINATE_CONNECTION)) break; - - /* - * setting timeout to a very high level. + + /* + * setting timeout to a very high level. * this is needed because of persistent connection * support. */ @@ -797,33 +796,33 @@ public final class serverCore extends AbstractBusyThread implements BusyThread { } } if (terminate) break; - - + + } catch (final InvocationTargetException e) { - log.logSevere("command execution, target exception " + e.getMessage() + " for client " + this.userAddress.getHostAddress(), e); + serverCore.this.log.logSevere("command execution, target exception " + e.getMessage() + " for client " + this.userAddress.getHostAddress(), e); // we extract a target exception writeLine(this.commandObj.error(e.getTargetException())); break; } catch (final NoSuchMethodException e) { - log.logSevere("command execution, method exception " + e.getMessage() + " for client " + this.userAddress.getHostAddress(), e); + serverCore.this.log.logSevere("command execution, method exception " + e.getMessage() + " for client " + this.userAddress.getHostAddress(), e); if (!this.userAddress.isSiteLocalAddress()) { - if (denyHost != null) { - denyHost.put(this.userAddress.getHostAddress(), "deny"); // block client: hacker attempt + if (serverCore.this.denyHost != null) { + serverCore.this.denyHost.put(this.userAddress.getHostAddress(), "deny"); // block client: hacker attempt } } break; } catch (final IllegalAccessException e) { - log.logSevere("command execution, illegal access exception " + e.getMessage() + " for client " + this.userAddress.getHostAddress(), e); + serverCore.this.log.logSevere("command execution, illegal access exception " + e.getMessage() + " for client " + this.userAddress.getHostAddress(), e); // wrong parameters: this can only be an internal problem writeLine(this.commandObj.error(e)); break; } catch (final ClassCastException e) { - log.logSevere("command execution, cast exception " + e.getMessage() + " for client " + this.userAddress.getHostAddress(), e); + serverCore.this.log.logSevere("command execution, cast exception " + e.getMessage() + " for client " + this.userAddress.getHostAddress(), e); // ?? writeLine(this.commandObj.error(e)); break; } catch (final Exception e) { - log.logSevere("command execution, generic exception " + e.getMessage() + " for client " + this.userAddress.getHostAddress(), e); + serverCore.this.log.logSevere("command execution, generic exception " + e.getMessage() + " for client " + this.userAddress.getHostAddress(), e); // whatever happens: the thread has to survive! writeLine("UNKNOWN REASON:" + ((this.commandObj == null) ? "no command object" : this.commandObj.error(e))); break; @@ -837,7 +836,7 @@ public final class serverCore extends AbstractBusyThread implements BusyThread { */ } // end of while } catch (final IOException e) { - log.logSevere("command execution, IO exception " + e.getMessage() + " for client " + this.userAddress.getHostAddress(), e); + serverCore.this.log.logSevere("command execution, IO exception " + e.getMessage() + " for client " + this.userAddress.getHostAddress(), e); } //announceMoreExecTime(System.currentTimeMillis() - this.start); } @@ -845,7 +844,7 @@ public final class serverCore extends AbstractBusyThread implements BusyThread { public boolean isSSL() { return this.controlSocket != null && this.controlSocket instanceof SSLSocket; } - + } /** @@ -855,12 +854,12 @@ public final class serverCore extends AbstractBusyThread implements BusyThread { * Illegal control characters will be stripped from the result. * Besides the valid line ending CRLF a single LF is treated as a * line ending as well to avoid errors with buggy server. - * + * * @param pbis The stream to read from. * @param maxSize maximum number of bytes to read in one run. * @param logerr log error messages if true, be silent otherwise. - * - * @return A byte array representing one line of the input or + * + * @return A byte array representing one line of the input or * null if EOS reached. */ public static byte[] receive(final PushbackInputStream pbis, final int maxSize, final boolean logerr) { @@ -874,7 +873,7 @@ public final class serverCore extends AbstractBusyThread implements BusyThread { // resulting readLineBuffer doesn't include CRLF or illegal control chars while (bufferSize < maxSize) { b = pbis.read(); - + if ((b > 31 && b != 127) || b == HT) { // add legal chars to the result readLineBuffer.append(b); @@ -901,15 +900,15 @@ public final class serverCore extends AbstractBusyThread implements BusyThread { return readLineBuffer.getBytes(); } catch (final ClosedByInterruptException e) { if (logerr) Log.logWarning("SERVER", "receive interrupted"); - return null; + return null; } catch (final IOException e) { - String message = e.getMessage(); + final String message = e.getMessage(); if (logerr && !message.equals("Socket closed") && !message.equals("Connection reset") && !message.equals("Read timed out")) Log.logWarning("SERVER", "receive closed by IOException: " + e.getMessage()); return null; } finally { try { readLineBuffer.close(); - } catch (IOException e) { + } catch (final IOException e) { Log.logException(e); } } @@ -920,13 +919,13 @@ public final class serverCore extends AbstractBusyThread implements BusyThread { os.write(CRLF); os.flush(); } - + public static void send(final OutputStream os, final byte[] buf) throws IOException { os.write(buf); os.write(CRLF); os.flush(); } - + public static String send(final OutputStream os, final InputStream is) throws IOException { final int bufferSize = is.available(); final byte[] buffer = new byte[((bufferSize < 1) || (bufferSize > 4096)) ? 4096 : bufferSize]; @@ -937,20 +936,20 @@ public final class serverCore extends AbstractBusyThread implements BusyThread { if (bufferSize > 80) return ""; return UTF8.String(buffer); } - + public static final void checkInterruption() throws InterruptedException { final Thread currentThread = Thread.currentThread(); - if (currentThread.isInterrupted()) throw new InterruptedException(); + if (currentThread.isInterrupted()) throw new InterruptedException(); if ((currentThread instanceof serverCore.Session) && ((serverCore.Session)currentThread).isStopped()) throw new InterruptedException(); } - + public void reconnect(final int delay) { final Thread restart = new Restarter(delay); restart.start(); } - + // restarting the serverCore - public class Restarter extends Thread { + public class Restarter extends Thread { public serverCore theServerCore = null; public int delay = 5000; public Restarter(final int delay) { @@ -959,34 +958,34 @@ public final class serverCore extends AbstractBusyThread implements BusyThread { public void run() { // waiting for a while try { - Thread.sleep(delay); + Thread.sleep(this.delay); } catch (final InterruptedException e) { Log.logException(e); } catch (final Exception e) { Log.logException(e); } - + // signaling restart - forceRestart = true; - + serverCore.this.forceRestart = true; + // closing socket to notify the thread close(); } } - + private SSLSocketFactory initSSLFactory() { - + // getting the keystore file name - String keyStoreFileName = this.switchboard.getConfig("keyStore", "").trim(); - + String keyStoreFileName = this.switchboard.getConfig("keyStore", "").trim(); + // getting the keystore pwd final String keyStorePwd = this.switchboard.getConfig("keyStorePassword", "").trim(); - + // take a look if we have something to import final String pkcs12ImportFile = this.switchboard.getConfig("pkcs12ImportFile", "").trim(); if (pkcs12ImportFile.length() > 0) { this.log.logInfo("Import certificates from import file '" + pkcs12ImportFile + "'."); - + try { // getting the password final String pkcs12ImportPwd = this.switchboard.getConfig("pkcs12ImportPwd", "").trim(); @@ -998,74 +997,74 @@ public final class serverCore extends AbstractBusyThread implements BusyThread { if (keyStoreFileName.length() == 0) { // using the default keystore name keyStoreFileName = "DATA/SETTINGS/myPeerKeystore"; - + // creating an empty java keystore final KeyStore ks = KeyStore.getInstance("JKS"); ks.load(null,keyStorePwd.toCharArray()); final FileOutputStream ksOut = new FileOutputStream(keyStoreFileName); ks.store(ksOut, keyStorePwd.toCharArray()); ksOut.close(); - + // storing path to keystore into config file this.switchboard.setConfig("keyStore", keyStoreFileName); } // importing certificate pkcsTool.importToJKS(keyStoreFileName, keyStorePwd); - + // removing entries from config file this.switchboard.setConfig("pkcs12ImportFile", ""); this.switchboard.setConfig("keyStorePassword", ""); - + // deleting original import file // TODO: should we do this - + } catch (final Exception e) { this.log.logSevere("Unable to import certificate from import file '" + pkcs12ImportFile + "'.",e); } } else if (keyStoreFileName.length() == 0) return null; - - + + // get the ssl context try { this.log.logInfo("Initializing SSL support ..."); - + // creating a new keystore instance of type (java key store) if (this.log.isFine()) this.log.logFine("Initializing keystore ..."); final KeyStore ks = KeyStore.getInstance("JKS"); - + // loading keystore data from file if (this.log.isFine()) this.log.logFine("Loading keystore file " + keyStoreFileName); - final FileInputStream stream = new FileInputStream(keyStoreFileName); + final FileInputStream stream = new FileInputStream(keyStoreFileName); ks.load(stream, keyStorePwd.toCharArray()); stream.close(); - + // creating a keystore factory if (this.log.isFine()) this.log.logFine("Initializing key manager factory ..."); final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); kmf.init(ks,keyStorePwd.toCharArray()); - + // initializing the ssl context if (this.log.isFine()) this.log.logFine("Initializing SSL context ..."); final SSLContext sslcontext = SSLContext.getInstance("TLS"); sslcontext.init(kmf.getKeyManagers(), null, null); - - final SSLSocketFactory factory = sslcontext.getSocketFactory(); + + final SSLSocketFactory factory = sslcontext.getSocketFactory(); this.log.logInfo("SSL support initialized successfully"); return factory; } catch (final Exception e) { final String errorMsg = "FATAL ERROR: Unable to initialize the SSL Socket factory. " + e.getMessage(); this.log.logSevere(errorMsg); - System.out.println(errorMsg); - System.exit(0); + System.out.println(errorMsg); + System.exit(0); return null; } } - + public Socket negotiateSSL(final Socket sock) throws Exception { SSLSocket sslsock; - + try { sslsock=(SSLSocket)this.sslSocketFactory.createSocket( sock, @@ -1086,19 +1085,19 @@ public final class serverCore extends AbstractBusyThread implements BusyThread { "\t PeerHost " + event.getSession().getPeerHost()); } } - ); - + ); + sslsock.setUseClientMode(false); final String[] suites = sslsock.getSupportedCipherSuites(); sslsock.setEnabledCipherSuites(suites); // start handshake sslsock.startHandshake(); - + //String cipherSuite = sslsock.getSession().getCipherSuite(); - + return sslsock; } catch (final Exception e) { throw e; } - } + } }