diff --git a/htroot/proxymsg/error.html b/htroot/proxymsg/error.html index 3f277c5bd..58a812396 100644 --- a/htroot/proxymsg/error.html +++ b/htroot/proxymsg/error.html @@ -45,15 +45,15 @@ #[httpStatus]#
- #(errorMessageType)#
+ #(errorMessageType)#
unspecified error
- ::
+ ::
not-yet-assigned error
- ::
+ ::
You don't have an active internet connection. Please go online.
- ::
+ ::
Could not load resource. The file is not available.
- ::
+ ::
#[detailedErrorMsg]#
#(/errorMessageType)#
diff --git a/source/de/anomic/http/httpc.java b/source/de/anomic/http/httpc.java
index e9afc1900..807bd1129 100644
--- a/source/de/anomic/http/httpc.java
+++ b/source/de/anomic/http/httpc.java
@@ -63,6 +63,7 @@ import java.net.SocketException;
import java.net.URL;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
+import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.GregorianCalendar;
@@ -113,12 +114,13 @@ public final class httpc {
// class variables
private Socket socket = null; // client socket for commands
+ private Long socketOwnerID = null;
private String host = null;
private long timeout;
private long handle;
// output and input streams for client control connection
- private PushbackInputStream clientInput = null;
+ PushbackInputStream clientInput = null;
private OutputStream clientOutput = null;
private boolean remoteProxyUse = false;
@@ -163,6 +165,8 @@ public final class httpc {
* @see serverByteBuffer
*/
final serverByteBuffer readLineBuffer = new serverByteBuffer(100);
+
+ private static final Hashtable openSocketLookupTable = new Hashtable();
public String toString() {
return (this.savedRemoteHost == null) ? "Disconnected" : "Connected to " + this.savedRemoteHost +
@@ -316,19 +320,31 @@ public final class httpc {
hostip = dnsResolve(server);
if (hostip == null) throw new UnknownHostException(server);
}
- if (ssl)
- socket = SSLSocketFactory.getDefault().createSocket(hostip, port);
- else
- socket = new Socket(hostip, port);
+
+ // opening the socket
+ socket = (ssl) ? SSLSocketFactory.getDefault().createSocket(hostip, port)
+ : new Socket(hostip, port);
+
+ // registering the socket
+ this.socketOwnerID = this.registerOpenSocket(socket);
+
+ // setting socket timeout and keep alive behaviour
socket.setSoTimeout(timeout); // waiting time for write
//socket.setSoLinger(true, timeout); // waiting time for read
socket.setKeepAlive(true); //
+
+ // getting input and output streams
clientInput = new PushbackInputStream(socket.getInputStream());
clientOutput = socket.getOutputStream();
// if we reached this point, we should have a connection
} catch (UnknownHostException e) {
+ if (this.socket != null) {
+ this.unregisterOpenSocket(this.socket,this.socketOwnerID);
+ }
+ this.socket = null;
+ this.socketOwnerID = null;
throw new IOException("unknown host: " + server);
- }
+ }
}
void reset() {
@@ -342,7 +358,9 @@ public final class httpc {
}
if (this.socket != null) {
try {this.socket.close();} catch (Exception e) {}
+ this.unregisterOpenSocket(this.socket,this.socketOwnerID);
this.socket = null;
+ this.socketOwnerID = null;
}
this.host = null;
@@ -1085,8 +1103,109 @@ do upload
while (i.hasMoreElements()) System.out.println((String) i.nextElement());
}
+ /**
+ * To register an open socket.
+ * This adds the socket to the list of open sockets where the current thread
+ * is is the owner.
+ * @param openedSocket the socket that should be registered
+ * @return the id of the current thread
+ */
+ private Long registerOpenSocket(Socket openedSocket) {
+ Long currentThreadId = new Long(Thread.currentThread().getId());
+ synchronized (openSocketLookupTable) {
+ ArrayList openSockets = null;
+ if (openSocketLookupTable.containsKey(currentThreadId)) {
+ openSockets = (ArrayList) openSocketLookupTable.get(currentThreadId);
+ } else {
+ openSockets = new ArrayList(1);
+ openSocketLookupTable.put(currentThreadId,openSockets);
+ }
+ synchronized (openSockets) {
+ openSockets.add(openedSocket);
+ }
+ return currentThreadId;
+ }
+ }
+ /**
+ * Closing all sockets that were opened in the context of the thread
+ * with the given thread id
+ * @param threadId
+ */
+ public static int closeOpenSockets(Long threadId) {
+
+ // getting all still opened sockets
+ ArrayList openSockets = httpc.getRegisteredOpenSockets(threadId);
+ int closedSocketCount = 0;
+
+ synchronized (openSockets) {
+ // looping through the list of sockets and close each one
+ for (int socketCount = 0; socketCount < openSockets.size(); socketCount++) {
+ Socket openSocket = (Socket) openSockets.get(0);
+ try {
+ // closing the socket
+ if (!openSocket.isClosed()) {
+ openSocket.close();
+ closedSocketCount++;
+ }
+ // unregistering the socket
+ httpc.unregisterOpenSocket(openSocket,threadId);
+ } catch (Exception ex) {}
+ }
+ }
+
+ return closedSocketCount;
+ }
+ /**
+ * Unregistering the socket.
+ * The socket will be removed from the list of sockets where the thread with the
+ * given thread id is the owner.
+ * @param closedSocket the socket that should be unregistered
+ * @param threadId the id of the owner thread
+ */
+ public static void unregisterOpenSocket(Socket closedSocket, Long threadId) {
+ synchronized (openSocketLookupTable) {
+ ArrayList openSockets = null;
+ if (openSocketLookupTable.containsKey(threadId)) {
+ openSockets = (ArrayList) openSocketLookupTable.get(threadId);
+ synchronized (openSockets) {
+ openSockets.remove(closedSocket);
+ if (openSockets.size() == 0) {
+ openSocketLookupTable.remove(threadId);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Getting a list of open sockets where the current thread is
+ * the owner
+ * @return the list of open sockets
+ */
+ public static ArrayList getRegisteredOpenSockets() {
+ Long currentThreadId = new Long(Thread.currentThread().getId());
+ return getRegisteredOpenSockets(currentThreadId);
+ }
+
+ /**
+ * Getting a list of open sockets where the thread with the given
+ * thread id is the owner
+ * @param threadId the thread id of the owner thread
+ * @return the list of open sockets
+ */
+ public static ArrayList getRegisteredOpenSockets(Long threadId) {
+ synchronized (openSocketLookupTable) {
+ ArrayList openSockets = null;
+ if (openSocketLookupTable.containsKey(threadId)) {
+ openSockets = (ArrayList) openSocketLookupTable.get(threadId);
+ } else {
+ openSockets = new ArrayList(0);
+ }
+ return openSockets;
+ }
+ }
}
diff --git a/source/de/anomic/http/httpd.java b/source/de/anomic/http/httpd.java
index 46e951125..806a85698 100644
--- a/source/de/anomic/http/httpd.java
+++ b/source/de/anomic/http/httpd.java
@@ -1072,10 +1072,8 @@ public final class httpd implements serverHandler {
) throws IOException {
FileInputStream fis = null;
+ ByteArrayOutputStream o = null;
try {
-
- File htRootPath = new File(switchboard.getRootPath(), switchboard.getConfig("htRootPath","htroot"));
-
// setting the proper http status message
String httpVersion = conProp.getProperty(httpd.CONNECTION_PROP_HTTP_VER,"HTTP/1.1");
if ((httpStatusText == null)||(httpStatusText.length()==0)) {
@@ -1107,8 +1105,12 @@ public final class httpd implements serverHandler {
// set rewrite values
serverObjects tp = new serverObjects();
+// tp.put("host", serverCore.publicIP().getHostAddress());
+// tp.put("port", switchboard.getConfig("port", "8080"));
tp.put("host", serverCore.publicIP().getHostAddress());
- tp.put("port", switchboard.getConfig("port", "8080"));
+ tp.put("port", (serverCore.portForwardingEnabled && (serverCore.portForwarding != null))
+ ? Integer.toString(serverCore.portForwarding.getPort())
+ : switchboard.getConfig("port", "8080"));
tp.put("errorMessageType", errorcase);
tp.put("httpStatus", Integer.toString(httpStatusCode) + " " + httpStatusText);
@@ -1117,27 +1119,32 @@ public final class httpd implements serverHandler {
tp.put("errorMessageType_detailedErrorMsg",(detailedErrorMsg != null) ? detailedErrorMsg : "");
// building the stacktrace
- if (stackTrace != null) {
+ if (stackTrace != null) {
+ tp.put("printStackTrace",1);
+
serverByteBuffer errorMsg = new serverByteBuffer(100);
- errorMsg.append("Exception occurred:\r\n\r\n")
+ errorMsg.append("Exception occurred: ")
.append(stackTrace.toString())
- .append("\r\n")
- .append("TRACE: ");
+ .append("\r\n\r\n")
+ .append("TRACE:\r\n");
stackTrace.printStackTrace(new PrintStream(errorMsg));
- errorMsg.write(("\r\n").getBytes());
- tp.put("printStackTrace",1);
+ errorMsg.append("\r\n");
+
tp.put("printStackTrace_stacktrace",errorMsg.toString().replaceAll("\n","
"));
} else {
tp.put("printStackTrace",0);
}
// rewrite the file
- File file = new File(htRootPath, "/proxymsg/error.html");
- byte[] result;
- ByteArrayOutputStream o = new ByteArrayOutputStream();
- fis = new FileInputStream(file);
- httpTemplate.writeTemplate(fis, o, tp, "-UNRESOLVED_PATTERN-".getBytes());
- result = o.toByteArray();
+ File htRootPath = new File(switchboard.getRootPath(), switchboard.getConfig("htRootPath","htroot"));
+
+ httpTemplate.writeTemplate(
+ fis = new FileInputStream(new File(htRootPath, "/proxymsg/error.html")),
+ o = new ByteArrayOutputStream(),
+ tp,
+ "-UNRESOLVED_PATTERN-".getBytes()
+ );
+ byte[] result = o.toByteArray();
o.close(); o = null;
httpHeader header = new httpHeader();
@@ -1154,6 +1161,7 @@ public final class httpd implements serverHandler {
throw new IOException(e.getMessage());
} finally {
if (fis != null) try { fis.close(); } catch (Exception e) {}
+ if (o != null) try { o.close(); } catch (Exception e) {}
}
}
diff --git a/source/de/anomic/http/httpdAbstractHandler.java b/source/de/anomic/http/httpdAbstractHandler.java
index 21bfcc2c4..0ebfebbfb 100644
--- a/source/de/anomic/http/httpdAbstractHandler.java
+++ b/source/de/anomic/http/httpdAbstractHandler.java
@@ -52,21 +52,28 @@
package de.anomic.http;
import java.text.SimpleDateFormat;
+import java.util.Properties;
-public abstract class httpdAbstractHandler {
+import de.anomic.server.logging.serverLog;
+public abstract class httpdAbstractHandler {
+
// static tools
-
+
private static int fileCounter = 0; // for unique file names
private static SimpleDateFormat DateFileNameFormatter =
- new SimpleDateFormat("yyyyMMddHHmmss");
-
+ new SimpleDateFormat("yyyyMMddHHmmss");
+
protected static String uniqueDateString() {
- String c = "" + fileCounter;
- fileCounter++; if (fileCounter>9999) fileCounter = 0;
- while (c.length() < 4) { c = "0" + c; }
- return "FILE" + DateFileNameFormatter.format(httpc.nowDate()) + c;
+ String c = "" + fileCounter;
+ fileCounter++; if (fileCounter>9999) fileCounter = 0;
+ while (c.length() < 4) { c = "0" + c; }
+ return "FILE" + DateFileNameFormatter.format(httpc.nowDate()) + c;
}
+ protected Properties connectionProperties = null;
+
+ protected serverLog theLogger;
+
}
diff --git a/source/de/anomic/http/httpdFileHandler.java b/source/de/anomic/http/httpdFileHandler.java
index c13f879f7..8a16d5a0b 100644
--- a/source/de/anomic/http/httpdFileHandler.java
+++ b/source/de/anomic/http/httpdFileHandler.java
@@ -117,14 +117,14 @@ public final class httpdFileHandler extends httpdAbstractHandler implements http
private serverSwitch switchboard;
private String adminAccountBase64MD5;
- private Properties connectionProperties = null;
private MessageDigest md5Digest = null;
- private final serverLog theLogger = new serverLog("FILEHANDLER");
-
public httpdFileHandler(serverSwitch switchboard) {
this.switchboard = switchboard;
+ // creating a logger
+ this.theLogger = new serverLog("FILEHANDLER");
+
if (this.mimeTable == null) {
// load the mime table
this.mimeTable = new Properties();
@@ -476,37 +476,58 @@ public final class httpdFileHandler extends httpdAbstractHandler implements http
serverFileUtils.write(result, out);
} else {
httpd.sendRespondError(conProp,out,3,404,"File not Found",null,null);
- //textMessage(out, 404, "404 File not Found\r\n"); // would be a possible vuln to return original the original path
+ return;
}
} catch (Exception e) {
- if (e instanceof InterruptedException) {
- this.theLogger.logInfo("Interruption detected while processing query: " + path +
- "\nClient: " + conProp.getProperty(httpd.CONNECTION_PROP_CLIENTIP,"unknown") +
- "\nReason: " + e.toString());
- if (!conProp.containsKey(httpd.CONNECTION_PROP_PROXY_RESPOND_HEADER)) {
- httpd.sendRespondError(conProp,out, 4, 503, null, "Exception with query: " + path + "; Service unavailable because of server shutdown.",e);
- } else {
- conProp.put(httpd.CONNECTION_PROP_PERSISTENT,"close");
- }
- } else {
- String errorMsg = e.getMessage();
- if ((errorMsg != null) && (errorMsg.startsWith("Broken pipe") || errorMsg.startsWith("Connection reset"))) {
- // client closed the connection, so we just end silently
- this.theLogger.logInfo("Client unexpectedly closed connection while processing query " + path +
- "\nClient: " + conProp.getProperty(httpd.CONNECTION_PROP_CLIENTIP,"unknown")+
- "\nReason: " + e.toString());
- conProp.put(httpd.CONNECTION_PROP_PERSISTENT,"close");
+ try {
+ // doing some errorhandling ...
+ int httpStatusCode = 400;
+ String httpStatusText = null;
+ StringBuffer errorMessage = new StringBuffer();
+ Exception errorExc = null;
+
+ if (e instanceof InterruptedException) {
+ errorMessage.append("Interruption detected while processing query.");
+ httpStatusCode = 503;
} else {
- this.theLogger.logError("ERROR: Exception with query: " + path +
- "\nClient: " + conProp.getProperty(httpd.CONNECTION_PROP_CLIENTIP,"unknown") +
- "\nReason: " + e.toString());
- if (!conProp.containsKey(httpd.CONNECTION_PROP_PROXY_RESPOND_HEADER)) {
- httpd.sendRespondError(conProp,out, 4, 503, null, "Exception with query: " + path + "; '" + e.toString() + ":" + ((errorMsg ==null)?"":e.getMessage()) + "'",e);
+ String errorMsg = e.getMessage();
+ if ((errorMsg != null) &&
+ (
+ errorMsg.startsWith("Broken pipe") ||
+ errorMsg.startsWith("Connection reset") ||
+ errorMsg.startsWith("Software caused connection abort")
+ )) {
+ // client closed the connection, so we just end silently
+ errorMessage.append("Client unexpectedly closed connection while processing query.");
} else {
- conProp.put(httpd.CONNECTION_PROP_PERSISTENT,"close");
+ errorMessage.append("Unexpected error while processing query.");
+ httpStatusCode = 500;
+ errorExc = e;
}
}
- }
+
+ errorMessage.append("\nQuery: ").append(path)
+ .append("\nClient: ").append(conProp.getProperty(httpd.CONNECTION_PROP_CLIENTIP,"unknown"))
+ .append("\nReason: ").append(e.toString());
+
+ if (!conProp.containsKey(httpd.CONNECTION_PROP_PROXY_RESPOND_HEADER)) {
+ // sending back an error message to the client
+ // if we have not already send an http header
+ httpd.sendRespondError(conProp,out, 4, httpStatusCode, httpStatusText, errorMessage.toString(),errorExc);
+ } else {
+ // otherwise we close the connection
+ this.forceConnectionClose();
+ }
+
+ // if it is an unexpected error we log it
+ if (httpStatusCode == 500) {
+ this.theLogger.logWarning(errorMessage.toString(),e);
+ }
+
+ } catch (Exception ee) {
+ this.forceConnectionClose();
+ }
+
} finally {
try {out.flush();}catch (Exception e) {}
if (!(requestHeader.get(httpHeader.CONNECTION, "close").equals("keep-alive"))) {
@@ -516,6 +537,12 @@ public final class httpdFileHandler extends httpdAbstractHandler implements http
}
}
+ private void forceConnectionClose() {
+ if (this.connectionProperties != null) {
+ this.connectionProperties.setProperty(httpd.CONNECTION_PROP_PERSISTENT,"close");
+ }
+ }
+
private static HashMap loadTemplates(File path) {
// reads all templates from a path
// we use only the folder from the given file path
diff --git a/source/de/anomic/http/httpdProxyHandler.java b/source/de/anomic/http/httpdProxyHandler.java
index 9bfb98f38..08f99162a 100644
--- a/source/de/anomic/http/httpdProxyHandler.java
+++ b/source/de/anomic/http/httpdProxyHandler.java
@@ -126,9 +126,6 @@ public final class httpdProxyHandler extends httpdAbstractHandler implements htt
public static final String userAgent = "yacy (" + httpc.systemOST +") yacy.net";
private File htRootPath = null;
- private serverLog theLogger;
- private Properties currentConProp = null;
-
private static boolean doAccessLogging = false;
/**
* Do logging configuration for special proxy access log file
@@ -348,12 +345,12 @@ public final class httpdProxyHandler extends httpdAbstractHandler implements htt
*/
public void doGet(Properties conProp, httpHeader requestHeader, OutputStream respond) throws IOException {
- this.currentConProp = conProp;
+ this.connectionProperties = conProp;
try {
// remembering the starting time of the request
Date requestDate = new Date(); // remember the time...
- this.currentConProp.put(httpd.CONNECTION_PROP_REQUEST_START,new Long(requestDate.getTime()));
+ this.connectionProperties.put(httpd.CONNECTION_PROP_REQUEST_START,new Long(requestDate.getTime()));
if (yacyTrigger) de.anomic.yacy.yacyCore.triggerOnlineAction();
// using an ByteCount OutputStream to count the send bytes (needed for the logfile)
@@ -476,8 +473,8 @@ public final class httpdProxyHandler extends httpdAbstractHandler implements htt
try { respond.flush(); } catch (Exception e) {}
if (respond instanceof httpdByteCountOutputStream) ((httpdByteCountOutputStream)respond).finish();
- this.currentConProp.put(httpd.CONNECTION_PROP_REQUEST_END,new Long(System.currentTimeMillis()));
- this.currentConProp.put(httpd.CONNECTION_PROP_PROXY_RESPOND_SIZE,new Long(((httpdByteCountOutputStream)respond).getCount()));
+ this.connectionProperties.put(httpd.CONNECTION_PROP_REQUEST_END,new Long(System.currentTimeMillis()));
+ this.connectionProperties.put(httpd.CONNECTION_PROP_PROXY_RESPOND_SIZE,new Long(((httpdByteCountOutputStream)respond).getCount()));
this.logProxyAccess();
}
}
@@ -637,7 +634,7 @@ public final class httpdProxyHandler extends httpdAbstractHandler implements htt
cacheEntry.cacheArray = cacheArray;
cacheManager.push(cacheEntry); // necessary update, write response header to cache
conProp.setProperty(httpd.CONNECTION_PROP_PROXY_RESPOND_CODE,"TCP_REFRESH_MISS");
- }
+ }
} else {
// the file is too big to cache it in the ram, or the size is unknown
// write to file right here.
@@ -649,14 +646,17 @@ public final class httpdProxyHandler extends httpdAbstractHandler implements htt
// totally fresh file
cacheEntry.status = plasmaHTCache.CACHE_FILL; // it's an insert
cacheManager.push(cacheEntry);
+ conProp.setProperty(httpd.CONNECTION_PROP_PROXY_RESPOND_CODE,"TCP_MISS");
} else if (sizeBeforeDelete == cacheFile.length()) {
// before we came here we deleted a cache entry
cacheEntry.status = plasmaHTCache.CACHE_STALE_RELOAD_BAD;
cacheManager.push(cacheEntry); // unnecessary update
+ conProp.setProperty(httpd.CONNECTION_PROP_PROXY_RESPOND_CODE,"TCP_REF_FAIL_HIT");
} else {
// before we came here we deleted a cache entry
cacheEntry.status = plasmaHTCache.CACHE_STALE_RELOAD_GOOD;
cacheManager.push(cacheEntry); // necessary update, write response header to cache
+ conProp.setProperty(httpd.CONNECTION_PROP_PROXY_RESPOND_CODE,"TCP_REFRESH_MISS");
}
// beware! all these writings will not fill the cacheEntry.cacheArray
// that means they are not available for the indexer (except they are scraped before)
@@ -675,6 +675,7 @@ public final class httpdProxyHandler extends httpdAbstractHandler implements htt
cacheEntry.status = plasmaHTCache.CACHE_STALE_NO_RELOAD;
cacheManager.push(cacheEntry);
}
+ conProp.setProperty(httpd.CONNECTION_PROP_PROXY_RESPOND_CODE,"TCP_MISS");
}
if (gzippedOut != null) {
@@ -685,9 +686,10 @@ public final class httpdProxyHandler extends httpdAbstractHandler implements htt
chunkedOut.flush();
}
} catch (Exception e) {
- // this may happen if the targeted host does not exist or anything with the
- // remote server was wrong.
- // in any case, sending a 404 is appropriate
+ // this may happen if
+ // - the targeted host does not exist
+ // - anything with the remote server was wrong.
+ // - the client unexpectedly closed the connection ...
try {
// deleting cached content
@@ -713,7 +715,8 @@ public final class httpdProxyHandler extends httpdAbstractHandler implements htt
// just do nothing, we leave it this way
this.theLogger.logDebug("ignoring bad gzip trail for URL " + url + " (" + e.getMessage() + ")");
this.forceConnectionClose();
- } else if ((remote != null)&&(remote.isClosed())) { // TODO: query for broken pipe
+ } else if ((remote != null)&&(remote.isClosed())) {
+ // TODO: query for broken pipe
errorMessage = "destination host unexpectedly closed connection";
} else {
errorMessage = "Unexpected Error. " + e.getClass().getName() + ": " + e.getMessage();
@@ -849,13 +852,13 @@ public final class httpdProxyHandler extends httpdAbstractHandler implements htt
}
private void forceConnectionClose() {
- if (this.currentConProp != null) {
- this.currentConProp.setProperty(httpd.CONNECTION_PROP_PERSISTENT,"close");
+ if (this.connectionProperties != null) {
+ this.connectionProperties.setProperty(httpd.CONNECTION_PROP_PERSISTENT,"close");
}
}
public void doHead(Properties conProp, httpHeader requestHeader, OutputStream respond) throws IOException {
- this.currentConProp = conProp;
+ this.connectionProperties = conProp;
String method = conProp.getProperty("METHOD");
String host = conProp.getProperty("HOST");
@@ -937,12 +940,12 @@ public final class httpdProxyHandler extends httpdAbstractHandler implements htt
public void doPost(Properties conProp, httpHeader requestHeader, OutputStream respond, PushbackInputStream body) throws IOException {
- this.currentConProp = conProp;
+ this.connectionProperties = conProp;
try {
// remembering the starting time of the request
Date requestDate = new Date(); // remember the time...
- this.currentConProp.put(httpd.CONNECTION_PROP_REQUEST_START,new Long(requestDate.getTime()));
+ this.connectionProperties.put(httpd.CONNECTION_PROP_REQUEST_START,new Long(requestDate.getTime()));
// using an ByteCount OutputStream to count the send bytes
respond = new httpdByteCountOutputStream(respond,conProp.getProperty(httpd.CONNECTION_PROP_REQUESTLINE).length() + 2);
@@ -1022,14 +1025,14 @@ public final class httpdProxyHandler extends httpdAbstractHandler implements htt
respond.flush();
if (respond instanceof httpdByteCountOutputStream) ((httpdByteCountOutputStream)respond).finish();
- this.currentConProp.put(httpd.CONNECTION_PROP_REQUEST_END,new Long(System.currentTimeMillis()));
- this.currentConProp.put(httpd.CONNECTION_PROP_PROXY_RESPOND_SIZE,new Long(((httpdByteCountOutputStream)respond).getCount()));
+ this.connectionProperties.put(httpd.CONNECTION_PROP_REQUEST_END,new Long(System.currentTimeMillis()));
+ this.connectionProperties.put(httpd.CONNECTION_PROP_PROXY_RESPOND_SIZE,new Long(((httpdByteCountOutputStream)respond).getCount()));
this.logProxyAccess();
}
}
public void doConnect(Properties conProp, de.anomic.http.httpHeader requestHeader, InputStream clientIn, OutputStream clientOut) throws IOException {
- this.currentConProp = conProp;
+ this.connectionProperties = conProp;
String host = conProp.getProperty("HOST");
int port = Integer.parseInt(conProp.getProperty("PORT"));
@@ -1222,8 +1225,8 @@ public final class httpdProxyHandler extends httpdAbstractHandler implements htt
this.logMessage.append(' ');
// Elapsed time
- Long requestStart = (Long) this.currentConProp.get(httpd.CONNECTION_PROP_REQUEST_START);
- Long requestEnd = (Long) this.currentConProp.get(httpd.CONNECTION_PROP_REQUEST_END);
+ Long requestStart = (Long) this.connectionProperties.get(httpd.CONNECTION_PROP_REQUEST_START);
+ Long requestEnd = (Long) this.connectionProperties.get(httpd.CONNECTION_PROP_REQUEST_END);
String elapsed = Long.toString(requestEnd.longValue()-requestStart.longValue());
for (int i=0; i<6-elapsed.length(); i++) this.logMessage.append(' ');
@@ -1231,28 +1234,30 @@ public final class httpdProxyHandler extends httpdAbstractHandler implements htt
this.logMessage.append(' ');
// Remote Host
- String clientIP = this.currentConProp.getProperty(httpd.CONNECTION_PROP_CLIENTIP);
+ String clientIP = this.connectionProperties.getProperty(httpd.CONNECTION_PROP_CLIENTIP);
this.logMessage.append(clientIP);
this.logMessage.append(' ');
// Code/Status
- String respondStatus = this.currentConProp.getProperty(httpd.CONNECTION_PROP_PROXY_RESPOND_STATUS);
- this.logMessage.append("UNKNOWN/");
+ String respondStatus = this.connectionProperties.getProperty(httpd.CONNECTION_PROP_PROXY_RESPOND_STATUS);
+ String respondCode = this.connectionProperties.getProperty(httpd.CONNECTION_PROP_PROXY_RESPOND_CODE,"UNKNOWN");
+ this.logMessage.append(respondCode);
+ this.logMessage.append("/");
this.logMessage.append(respondStatus);
this.logMessage.append(' ');
// Bytes
- Long bytes = (Long) this.currentConProp.get(httpd.CONNECTION_PROP_PROXY_RESPOND_SIZE);
+ Long bytes = (Long) this.connectionProperties.get(httpd.CONNECTION_PROP_PROXY_RESPOND_SIZE);
this.logMessage.append(bytes.toString());
this.logMessage.append(' ');
// Method
- String requestMethod = this.currentConProp.getProperty(httpd.CONNECTION_PROP_METHOD);
+ String requestMethod = this.connectionProperties.getProperty(httpd.CONNECTION_PROP_METHOD);
this.logMessage.append(requestMethod);
this.logMessage.append(' ');
// URL
- String requestURL = this.currentConProp.getProperty(httpd.CONNECTION_PROP_URL);
+ String requestURL = this.connectionProperties.getProperty(httpd.CONNECTION_PROP_URL);
this.logMessage.append(requestURL);
this.logMessage.append(' ');
@@ -1261,15 +1266,15 @@ public final class httpdProxyHandler extends httpdAbstractHandler implements htt
this.logMessage.append(' ');
// Peerstatus/Peerhost
- String host = this.currentConProp.getProperty(httpd.CONNECTION_PROP_HOST);
+ String host = this.connectionProperties.getProperty(httpd.CONNECTION_PROP_HOST);
this.logMessage.append("DIRECT/");
this.logMessage.append(host);
this.logMessage.append(' ');
// Type
String mime = "-";
- if (this.currentConProp.containsKey(httpd.CONNECTION_PROP_PROXY_RESPOND_HEADER)) {
- httpHeader proxyRespondHeader = (httpHeader) this.currentConProp.get(httpd.CONNECTION_PROP_PROXY_RESPOND_HEADER);
+ if (this.connectionProperties.containsKey(httpd.CONNECTION_PROP_PROXY_RESPOND_HEADER)) {
+ httpHeader proxyRespondHeader = (httpHeader) this.connectionProperties.get(httpd.CONNECTION_PROP_PROXY_RESPOND_HEADER);
mime = proxyRespondHeader.mime();
if (mime.indexOf(";") != -1) {
mime = mime.substring(0,mime.indexOf(";"));
diff --git a/source/de/anomic/server/serverCore.java b/source/de/anomic/server/serverCore.java
index 7a57b3885..c05a996b4 100644
--- a/source/de/anomic/server/serverCore.java
+++ b/source/de/anomic/server/serverCore.java
@@ -76,6 +76,7 @@ import javax.net.ssl.SSLServerSocketFactory;
import org.apache.commons.pool.impl.GenericObjectPool;
import org.apache.commons.pool.impl.GenericObjectPool.Config;
+import de.anomic.http.httpc;
import de.anomic.http.httpd;
import de.anomic.server.logging.serverLog;
import de.anomic.yacy.yacyCore;
@@ -405,7 +406,7 @@ public final class serverCore extends serverAbstractThread implements serverThre
this.log.logInfo("SLOWING DOWN ACCESS FOR BRUTE-FORCE PREVENTION FROM " + cIP);
// add a delay to make brute-force harder
announceThreadBlockApply();
- try {Thread.currentThread().sleep(3000);} catch (InterruptedException e) {}
+ try {Thread.sleep(3000);} catch (InterruptedException e) {}
announceThreadBlockRelease();
}
@@ -434,13 +435,6 @@ public final class serverCore extends serverAbstractThread implements serverThre
}
}
- // close the session pool
- try {
- this.theSessionPool.close();
- } catch (Exception e) {
- this.log.logWarning("Unable to close the session pool.");
- }
-
// closing the serverchannel and socket
try {
this.socket.close();
@@ -448,6 +442,13 @@ public final class serverCore extends serverAbstractThread implements serverThre
this.log.logWarning("Unable to close the server socket.");
}
+ // closing the session pool
+ try {
+ this.theSessionPool.close();
+ } catch (Exception e) {
+ this.log.logWarning("Unable to close the session pool.");
+ }
+
this.log.logSystem("* terminated");
}
@@ -501,8 +502,6 @@ public final class serverCore extends serverAbstractThread implements serverThre
/*
* shutdown all still running session threads ...
*/
- // interrupting all still running or pooled threads ...
- serverCore.this.theSessionThreadGroup.interrupt();
/* waiting for all threads to finish */
int threadCount = serverCore.this.theSessionThreadGroup.activeCount();
@@ -515,26 +514,28 @@ public final class serverCore extends serverAbstractThread implements serverThre
for ( int currentThreadIdx = 0; currentThreadIdx < threadCount; currentThreadIdx++ ) {
((Session)threadList[currentThreadIdx]).setStopped(true);
}
+
+ // interrupting all still running or pooled threads ...
+ serverCore.this.log.logInfo("Sending interruption signal to " + threadCount + " remaining session threads ...");
+ serverCore.this.theSessionThreadGroup.interrupt();
// waiting a frew ms for the session objects to continue processing
Thread.sleep(500);
// if there are some sessions that are blocking in IO, we simply close the socket
for ( int currentThreadIdx = 0; currentThreadIdx < threadCount; currentThreadIdx++ ) {
- Session currentSession = (Session)threadList[currentThreadIdx];
- if (currentSession.isAlive()) {
- try {
- if ((currentSession.controlSocket != null)&&(currentSession.controlSocket.isConnected())) {
- currentSession.controlSocket.close();
- serverCore.this.log.logInfo("Closing socket of thread '" + currentSession.getName() + "'");
- }
- } catch (IOException e) {}
- }
+ serverCore.this.log.logInfo("Trying to shutdown session thread '" + threadList[currentThreadIdx].getName() + "' [ID=" + threadList[currentThreadIdx].getId() + "].");
+ ((Session)threadList[currentThreadIdx]).close();
}
// we need to use a timeout here because of missing interruptable session threads ...
for ( int currentThreadIdx = 0; currentThreadIdx < threadCount; currentThreadIdx++ ) {
- if (threadList[currentThreadIdx].isAlive()) threadList[currentThreadIdx].join(500);
+ if (threadList[currentThreadIdx].isAlive()) {
+ serverCore.this.log.logDebug("Waiting for session thread '" + threadList[currentThreadIdx].getName() + "' [ID=" + threadList[currentThreadIdx].getId() + "] to finish shutdown.");
+ try {
+ threadList[currentThreadIdx].join(500);
+ } catch (Exception ex) {}
+ }
}
} catch (InterruptedException e) {
serverCore.this.log.logWarning("Interruption while trying to shutdown all remaining session threads.");
@@ -657,6 +658,27 @@ public final class serverCore extends serverAbstractThread implements serverThre
public void setStopped(boolean stopped) {
this.stopped = stopped;
}
+
+ public void close() {
+ if (this.isAlive()) {
+ try {
+ // trying to close all still open httpc-Sockets first
+ int closedSockets = httpc.closeOpenSockets(new Long(this.getId()));
+ if (closedSockets > 0) {
+ serverCore.this.log.logInfo(closedSockets + " http-client sockets of thread '" + this.getName() + "' closed.");
+ }
+
+ // waiting some time
+ this.join(300);
+
+ // closing the socket to the client
+ if ((this.controlSocket != null)&&(this.controlSocket.isConnected())) {
+ this.controlSocket.close();
+ serverCore.this.log.logInfo("Closing main socket of thread '" + this.getName() + "'");
+ }
+ } catch (Exception e) {}
+ }
+ }
public void execute(Socket controlSocket, int socketTimeout) {
this.execute(controlSocket, socketTimeout, null);
@@ -765,7 +787,7 @@ public final class serverCore extends serverAbstractThread implements serverThre
} finally {
reset();
- if (!this.stopped && !this.isInterrupted()) {
+ if (!this.stopped && !this.isInterrupted() && !serverCore.this.theSessionPool.isClosed) {
try {
this.setName("Session_inPool");
serverCore.this.theSessionPool.returnObject(this);
@@ -857,7 +879,7 @@ public final class serverCore extends serverAbstractThread implements serverThre
this.request = new String(requestBytes);
//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";
diff --git a/source/de/anomic/server/serverPortForwardingSch.java b/source/de/anomic/server/serverPortForwardingSch.java
index 6bc747d2f..6cd1b0cdb 100644
--- a/source/de/anomic/server/serverPortForwardingSch.java
+++ b/source/de/anomic/server/serverPortForwardingSch.java
@@ -140,6 +140,7 @@ public class serverPortForwardingSch implements serverPortForwarding{
this.log.logDebug("Deploying port forwarding session watcher thread.");
this.switchboard.deployThread("portForwardingWatcher", "Remote Port Forwarding Watcher", "this thread is used to detect broken connections and to re-establish it if necessary.",
sessionWatcher = new serverInstantThread(this, "reconnect", null), 30000,30000,30000,1000);
+ sessionWatcher.setSyncObject(new Object());
}
this.log.logInfo("Remote port forwarding connection established: " +
diff --git a/source/de/anomic/yacy/yacyClient.java b/source/de/anomic/yacy/yacyClient.java
index d01783503..dc8c965cc 100644
--- a/source/de/anomic/yacy/yacyClient.java
+++ b/source/de/anomic/yacy/yacyClient.java
@@ -110,7 +110,11 @@ public class yacyClient {
yacyCore.seedDB.sb.remoteProxyPort,
obj));
} catch (Exception e) {
- yacyCore.log.logDebug("yacyClient.publishMySeed exception:" + e.getMessage());
+ if (Thread.currentThread().isInterrupted()) {
+ yacyCore.log.logDebug("yacyClient.publishMySeed thread '" + Thread.currentThread().getName() + "' interrupted.");
+ } else {
+ yacyCore.log.logDebug("yacyClient.publishMySeed exception:" + e.getMessage());
+ }
return -1;
}
if ((result == null) || (result.size() < 3)) {
diff --git a/source/de/anomic/yacy/yacyCore.java b/source/de/anomic/yacy/yacyCore.java
index 939b5bbd5..c844be8d7 100644
--- a/source/de/anomic/yacy/yacyCore.java
+++ b/source/de/anomic/yacy/yacyCore.java
@@ -70,6 +70,7 @@ import java.util.LinkedList;
import java.util.List;
import java.util.TimeZone;
+import de.anomic.http.httpc;
import de.anomic.net.natLib;
import de.anomic.plasma.plasmaSwitchboard;
import de.anomic.server.serverSemaphore;
@@ -466,27 +467,39 @@ public class yacyCore {
peerActions.saveMySeed();
return 0;
} catch (InterruptedException e) {
+ try {
log.logInfo("publish: Interruption detected while publishing my seed.");
+ // consuming the theads interrupted signal
+ Thread.interrupted();
+
// interrupt all already started publishThreads
- log.logInfo("publish: Trying to shutdown all remaining publishing threads ...");
+ log.logInfo("publish: Signaling shutdown to all remaining publishing threads ...");
yacyCore.publishThreadGroup.interrupt();
- // waiting some time for the publishThreads to finish handshake
+ // waiting some time for the publishThreads to finish execution
+ Thread.sleep(500);
+
int threadCount = yacyCore.publishThreadGroup.activeCount();
Thread[] threadList = new Thread[threadCount];
threadCount = yacyCore.publishThreadGroup.enumerate(threadList);
- try {
+
// we need to use a timeout here because of missing interruptable session threads ...
for ( int currentThreadIdx = 0; currentThreadIdx < threadCount; currentThreadIdx++ ) {
- if (threadList[currentThreadIdx].isAlive()) {
+ Thread currentThread = threadList[currentThreadIdx];
+ Long currentThreadID = new Long(currentThread.getId());
+
+ if (currentThread.isAlive()) {
+ log.logInfo("publish: Closing socket of publishing thread '" + threadList[currentThreadIdx].getName() + "'.");
+ httpc.closeOpenSockets(currentThreadID);
+
log.logInfo("publish: Waiting for remaining publishing thread '" + threadList[currentThreadIdx].getName() + "' to finish shutdown");
- threadList[currentThreadIdx].join(500);
+ try { threadList[currentThreadIdx].join(500); }catch (Exception ex) {}
}
}
}
catch (InterruptedException ee) {
- log.logWarning("Interruption while trying to shutdown all remaining publishing threads.");
+ log.logWarning("publish: Interruption while trying to shutdown all remaining publishing threads.");
}
return 0;
diff --git a/source/de/anomic/yacy/yacyPeerActions.java b/source/de/anomic/yacy/yacyPeerActions.java
index fb4e9474c..a94150191 100644
--- a/source/de/anomic/yacy/yacyPeerActions.java
+++ b/source/de/anomic/yacy/yacyPeerActions.java
@@ -145,6 +145,7 @@ public class yacyPeerActions {
// - use the superseed to further fill up the seedDB
int ssc = 0;
for (int i = 0; i < superseed.size(); i++) {
+ if (Thread.currentThread().isInterrupted()) break;
seedListFileURL = (String) superseed.any();
if (seedListFileURL.startsWith("http://")) {
// load the seed list