|
|
|
@ -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 {
|
|
|
|
@ -134,17 +133,17 @@ public final class serverCore extends AbstractBusyThread implements BusyThread {
|
|
|
|
|
serverHandler handlerPrototype; // the command class (a serverHandler)
|
|
|
|
|
|
|
|
|
|
private final serverSwitch switchboard; // the command class switchboard
|
|
|
|
|
private Map<String, String> denyHost;
|
|
|
|
|
private final Map<String, String> 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;
|
|
|
|
|
|
|
|
|
@ -223,12 +222,12 @@ public final class serverCore extends AbstractBusyThread implements BusyThread {
|
|
|
|
|
// 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()));
|
|
|
|
@ -312,7 +311,7 @@ public final class serverCore extends AbstractBusyThread implements BusyThread {
|
|
|
|
|
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");
|
|
|
|
|
|
|
|
|
@ -445,8 +444,8 @@ public final class serverCore extends AbstractBusyThread implements BusyThread {
|
|
|
|
|
public List<Session> getJobList() {
|
|
|
|
|
final Thread[] threadList = new Thread[sessionThreadGroup.activeCount()];
|
|
|
|
|
serverCore.sessionThreadGroup.enumerate(threadList, false);
|
|
|
|
|
ArrayList<Session> l = new ArrayList<Session>();
|
|
|
|
|
for (Thread t: threadList) {
|
|
|
|
|
final ArrayList<Session> l = new ArrayList<Session>();
|
|
|
|
|
for (final Thread t: threadList) {
|
|
|
|
|
if (t == null) continue;
|
|
|
|
|
if (!(t instanceof Session)) {
|
|
|
|
|
//log.logSevere("serverCore.getJobList - thread is not Session: " + t.getClass().getName());
|
|
|
|
@ -461,7 +460,7 @@ public final class serverCore extends AbstractBusyThread implements BusyThread {
|
|
|
|
|
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());
|
|
|
|
@ -477,7 +476,7 @@ public final class serverCore extends AbstractBusyThread implements BusyThread {
|
|
|
|
|
// idleThreadCheck();
|
|
|
|
|
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());
|
|
|
|
@ -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;
|
|
|
|
@ -565,7 +564,7 @@ public final class serverCore extends AbstractBusyThread implements BusyThread {
|
|
|
|
|
// 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) {}
|
|
|
|
|
}
|
|
|
|
@ -583,7 +582,7 @@ public final class serverCore extends AbstractBusyThread implements BusyThread {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
@ -595,7 +594,7 @@ public final class serverCore extends AbstractBusyThread implements BusyThread {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public byte[] readLine() {
|
|
|
|
|
return receive(this.in, commandMaxLength, true);
|
|
|
|
|
return receive(this.in, serverCore.this.commandMaxLength, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
@ -633,7 +632,7 @@ public final class serverCore extends AbstractBusyThread implements BusyThread {
|
|
|
|
|
// 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
|
|
|
|
|
|
|
|
|
@ -689,17 +688,17 @@ 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.request = UTF8.String(requestBytes);
|
|
|
|
|
setName("Session_" + this.userAddress.getHostAddress() +
|
|
|
|
|
":" + this.controlSocket.getPort() +
|
|
|
|
|
"#" + this.commandCounter);
|
|
|
|
|
"#" + this.commandCounter + "_" + this.request);
|
|
|
|
|
|
|
|
|
|
this.request = UTF8.String(requestBytes);
|
|
|
|
|
//this.log.logDebug("* session " + handle + " received command '" + request + "'. time = " + (System.currentTimeMillis() - handle));
|
|
|
|
|
log(false, this.request);
|
|
|
|
|
try {
|
|
|
|
@ -728,7 +727,7 @@ public final class serverCore extends AbstractBusyThread implements BusyThread {
|
|
|
|
|
|
|
|
|
|
if (this.request == null) break;
|
|
|
|
|
if (reqProtocol != null && reqProtocol.equals("HTTP")) {
|
|
|
|
|
this.commandObj = handlerPrototype.clone();
|
|
|
|
|
this.commandObj = serverCore.this.handlerPrototype.clone();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -753,14 +752,14 @@ public final class serverCore extends AbstractBusyThread implements BusyThread {
|
|
|
|
|
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);
|
|
|
|
@ -800,30 +799,30 @@ public final class serverCore extends AbstractBusyThread implements BusyThread {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} 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);
|
|
|
|
|
}
|
|
|
|
@ -903,13 +902,13 @@ public final class serverCore extends AbstractBusyThread implements BusyThread {
|
|
|
|
|
if (logerr) Log.logWarning("SERVER", "receive interrupted");
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -959,7 +958,7 @@ 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) {
|
|
|
|
@ -967,7 +966,7 @@ public final class serverCore extends AbstractBusyThread implements BusyThread {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// signaling restart
|
|
|
|
|
forceRestart = true;
|
|
|
|
|
serverCore.this.forceRestart = true;
|
|
|
|
|
|
|
|
|
|
// closing socket to notify the thread
|
|
|
|
|
close();
|
|
|
|
|