I2P Address: [http://git.idk.i2p]

Skip to content
Snippets Groups Projects
Commit d2fc24e7 authored by jrandom's avatar jrandom Committed by zzz
Browse files

deal with no proxy available

more carefully retrieve a proxy
logging (w/ unique requestId)
parent ec52c81f
No related branches found
No related tags found
No related merge requests found
...@@ -82,6 +82,16 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable ...@@ -82,6 +82,16 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
"the following Destination:<BR><BR>") "the following Destination:<BR><BR>")
.getBytes(); .getBytes();
private final static byte[] ERR_NO_OUTPROXY =
("HTTP/1.1 503 Service Unavailable\r\n"+
"Content-Type: text/html; charset=iso-8859-1\r\n"+
"Cache-control: no-cache\r\n"+
"\r\n"+
"<html><body><H1>I2P ERROR: No outproxy found</H1>"+
"Your request was for a site outside of I2P, but you have no "+
"HTTP outproxy configured. Please configure an outproxy in I2PTunnel")
.getBytes();
/** used to assign unique IDs to the threads / clients. no logic or functionality */ /** used to assign unique IDs to the threads / clients. no logic or functionality */
private static volatile long __clientId = 0; private static volatile long __clientId = 0;
...@@ -113,23 +123,33 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable ...@@ -113,23 +123,33 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
notifyEvent("openHTTPClientResult", "ok"); notifyEvent("openHTTPClientResult", "ok");
} }
private String getPrefix() { return "Client[" + _clientId + "]: "; } private String getPrefix(long requestId) { return "Client[" + _clientId + "/" + requestId + "]: "; }
private String selectProxy() { private String selectProxy() {
if (proxyList.size() <= 0) { synchronized (proxyList) {
l.log("Proxy list is emtpy - no outproxy available"); int size = proxyList.size();
return null; if (size <= 0) {
if (_log.shouldLog(Log.INFO))
_log.info("Proxy list is empty - no outproxy available");
l.log("Proxy list is emtpy - no outproxy available");
return null;
}
int index = I2PAppContext.getGlobalContext().random().nextInt(size);
if (index >= size) index = size - 1;
if (index < 0) return null;
String proxy = (String)proxyList.get(index);
return proxy;
} }
int index = I2PAppContext.getGlobalContext().random().nextInt(proxyList.size());
return (String)proxyList.get(index);
} }
private static long __requestId = 0;
protected void clientConnectionRun(Socket s) { protected void clientConnectionRun(Socket s) {
OutputStream out = null; OutputStream out = null;
String targetRequest = null; String targetRequest = null;
boolean usingWWWProxy = false; boolean usingWWWProxy = false;
String currentProxy = null; String currentProxy = null;
InactivityTimeoutThread timeoutThread = null; InactivityTimeoutThread timeoutThread = null;
long requestId = ++__requestId;
try { try {
out = s.getOutputStream(); out = s.getOutputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream(), "ISO-8859-1")); BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream(), "ISO-8859-1"));
...@@ -137,7 +157,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable ...@@ -137,7 +157,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
StringBuffer newRequest = new StringBuffer(); StringBuffer newRequest = new StringBuffer();
while ((line = br.readLine()) != null) { while ((line = br.readLine()) != null) {
if (_log.shouldLog(Log.DEBUG)) if (_log.shouldLog(Log.DEBUG))
_log.debug(getPrefix() + "Line=[" + line + "]"); _log.debug(getPrefix(requestId) + "Line=[" + line + "]");
if (line.startsWith("Connection: ") || if (line.startsWith("Connection: ") ||
line.startsWith("Keep-Alive: ") || line.startsWith("Keep-Alive: ") ||
...@@ -146,7 +166,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable ...@@ -146,7 +166,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
if (method == null) { // first line (GET /base64/realaddr) if (method == null) { // first line (GET /base64/realaddr)
if (_log.shouldLog(Log.DEBUG)) if (_log.shouldLog(Log.DEBUG))
_log.debug(getPrefix() + "Method is null for [" + line + "]"); _log.debug(getPrefix(requestId) + "Method is null for [" + line + "]");
int pos = line.indexOf(" "); int pos = line.indexOf(" ");
if (pos == -1) break; if (pos == -1) break;
...@@ -179,11 +199,29 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable ...@@ -179,11 +199,29 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
line = method + " " + request.substring(pos); line = method + " " + request.substring(pos);
} else if (host.indexOf(".") != -1) { } else if (host.indexOf(".") != -1) {
// The request must be forwarded to a WWW proxy // The request must be forwarded to a WWW proxy
if (_log.shouldLog(Log.DEBUG))
_log.debug("Before selecting outproxy for " + host);
currentProxy = selectProxy(); currentProxy = selectProxy();
if (_log.shouldLog(Log.DEBUG))
_log.debug("After selecting outproxy for " + host + ": " + currentProxy);
if (currentProxy == null) {
if (_log.shouldLog(Log.WARN))
_log.warn(getPrefix(requestId) + "Host wants to be outproxied, but we dont have any!");
l.log("No HTTP outproxy found for the request.");
if (out != null) {
out.write(ERR_NO_OUTPROXY);
out.write("<p /><i>Generated on: ".getBytes());
out.write(new Date().toString().getBytes());
out.write("</i></body></html>\n".getBytes());
out.flush();
}
s.close();
return;
}
destination = currentProxy; destination = currentProxy;
usingWWWProxy = true; usingWWWProxy = true;
if (_log.shouldLog(Log.DEBUG)) if (_log.shouldLog(Log.DEBUG))
_log.debug(getPrefix() + "Host doesnt end with .i2p and it contains a period [" + host + "]: wwwProxy!"); _log.debug(getPrefix(requestId) + "Host doesnt end with .i2p and it contains a period [" + host + "]: wwwProxy!");
} else { } else {
request = request.substring(pos + 1); request = request.substring(pos + 1);
pos = request.indexOf("/"); pos = request.indexOf("/");
...@@ -193,27 +231,27 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable ...@@ -193,27 +231,27 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
boolean isValid = usingWWWProxy || isSupportedAddress(host, protocol); boolean isValid = usingWWWProxy || isSupportedAddress(host, protocol);
if (!isValid) { if (!isValid) {
if (_log.shouldLog(Log.INFO)) _log.info(getPrefix() + "notValid(" + host + ")"); if (_log.shouldLog(Log.INFO)) _log.info(getPrefix(requestId) + "notValid(" + host + ")");
method = null; method = null;
destination = null; destination = null;
break; break;
} else if (!usingWWWProxy) { } else if (!usingWWWProxy) {
if (_log.shouldLog(Log.INFO)) _log.info(getPrefix() + "host=getHostName(" + destination + ")"); if (_log.shouldLog(Log.INFO)) _log.info(getPrefix(requestId) + "host=getHostName(" + destination + ")");
host = getHostName(destination); // hide original host host = getHostName(destination); // hide original host
} }
if (_log.shouldLog(Log.DEBUG)) { if (_log.shouldLog(Log.DEBUG)) {
_log.debug(getPrefix() + "METHOD:" + method + ":"); _log.debug(getPrefix(requestId) + "METHOD:" + method + ":");
_log.debug(getPrefix() + "PROTOC:" + protocol + ":"); _log.debug(getPrefix(requestId) + "PROTOC:" + protocol + ":");
_log.debug(getPrefix() + "HOST :" + host + ":"); _log.debug(getPrefix(requestId) + "HOST :" + host + ":");
_log.debug(getPrefix() + "DEST :" + destination + ":"); _log.debug(getPrefix(requestId) + "DEST :" + destination + ":");
} }
} else { } else {
if (line.startsWith("Host: ") && !usingWWWProxy) { if (line.startsWith("Host: ") && !usingWWWProxy) {
line = "Host: " + host; line = "Host: " + host;
if (_log.shouldLog(Log.INFO)) if (_log.shouldLog(Log.INFO))
_log.info(getPrefix() + "Setting host = " + host); _log.info(getPrefix(requestId) + "Setting host = " + host);
} }
} }
...@@ -225,7 +263,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable ...@@ -225,7 +263,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
} }
} }
if (_log.shouldLog(Log.DEBUG)) if (_log.shouldLog(Log.DEBUG))
_log.debug(getPrefix() + "NewRequest header: [" + newRequest.toString() + "]"); _log.debug(getPrefix(requestId) + "NewRequest header: [" + newRequest.toString() + "]");
while (br.ready()) { // empty the buffer (POST requests) while (br.ready()) { // empty the buffer (POST requests)
int i = br.read(); int i = br.read();
...@@ -247,7 +285,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable ...@@ -247,7 +285,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
} }
if (_log.shouldLog(Log.DEBUG)) if (_log.shouldLog(Log.DEBUG))
_log.debug(getPrefix() + "Destination: " + destination); _log.debug(getPrefix(requestId) + "Destination: " + destination);
Destination dest = I2PTunnel.destFromName(destination); Destination dest = I2PTunnel.destFromName(destination);
if (dest == null) { if (dest == null) {
...@@ -262,25 +300,25 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable ...@@ -262,25 +300,25 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
I2PSocket i2ps = createI2PSocket(dest); I2PSocket i2ps = createI2PSocket(dest);
byte[] data = newRequest.toString().getBytes("ISO-8859-1"); byte[] data = newRequest.toString().getBytes("ISO-8859-1");
I2PTunnelRunner runner = new I2PTunnelRunner(s, i2ps, sockLock, data); I2PTunnelRunner runner = new I2PTunnelRunner(s, i2ps, sockLock, data);
timeoutThread = new InactivityTimeoutThread(runner, out, targetRequest, usingWWWProxy, currentProxy, s); timeoutThread = new InactivityTimeoutThread(runner, out, targetRequest, usingWWWProxy, currentProxy, s, requestId);
timeoutThread.start(); timeoutThread.start();
} catch (SocketException ex) { } catch (SocketException ex) {
if (timeoutThread != null) timeoutThread.disable(); if (timeoutThread != null) timeoutThread.disable();
_log.info(getPrefix() + "Error trying to connect", ex); _log.info(getPrefix(requestId) + "Error trying to connect", ex);
l.log(ex.getMessage()); l.log(ex.getMessage());
handleHTTPClientException(ex, out, targetRequest, usingWWWProxy, currentProxy); handleHTTPClientException(ex, out, targetRequest, usingWWWProxy, currentProxy, requestId);
closeSocket(s); closeSocket(s);
} catch (IOException ex) { } catch (IOException ex) {
if (timeoutThread != null) timeoutThread.disable(); if (timeoutThread != null) timeoutThread.disable();
_log.info(getPrefix() + "Error trying to connect", ex); _log.info(getPrefix(requestId) + "Error trying to connect", ex);
l.log(ex.getMessage()); l.log(ex.getMessage());
handleHTTPClientException(ex, out, targetRequest, usingWWWProxy, currentProxy); handleHTTPClientException(ex, out, targetRequest, usingWWWProxy, currentProxy, requestId);
closeSocket(s); closeSocket(s);
} catch (I2PException ex) { } catch (I2PException ex) {
if (timeoutThread != null) timeoutThread.disable(); if (timeoutThread != null) timeoutThread.disable();
_log.info("getPrefix() + Error trying to connect", ex); _log.info("getPrefix(requestId) + Error trying to connect", ex);
l.log(ex.getMessage()); l.log(ex.getMessage());
handleHTTPClientException(ex, out, targetRequest, usingWWWProxy, currentProxy); handleHTTPClientException(ex, out, targetRequest, usingWWWProxy, currentProxy, requestId);
closeSocket(s); closeSocket(s);
} }
} }
...@@ -289,18 +327,19 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable ...@@ -289,18 +327,19 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
private static volatile long __timeoutId = 0; private static volatile long __timeoutId = 0;
private class InactivityTimeoutThread extends I2PThread { private class InactivityTimeoutThread extends I2PThread {
private Socket s; private Socket s;
private I2PTunnelRunner _runner; private I2PTunnelRunner _runner;
private OutputStream _out; private OutputStream _out;
private String _targetRequest; private String _targetRequest;
private boolean _useWWWProxy; private boolean _useWWWProxy;
private String _currentProxy; private String _currentProxy;
private long _requestId;
private boolean _disabled; private boolean _disabled;
private Object _disableLock = new Object(); private Object _disableLock = new Object();
public InactivityTimeoutThread(I2PTunnelRunner runner, OutputStream out, String targetRequest, public InactivityTimeoutThread(I2PTunnelRunner runner, OutputStream out, String targetRequest,
boolean useWWWProxy, String currentProxy, Socket s) { boolean useWWWProxy, String currentProxy, Socket s, long requestId) {
this.s = s; this.s = s;
_runner = runner; _runner = runner;
_out = out; _out = out;
...@@ -308,8 +347,9 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable ...@@ -308,8 +347,9 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
_useWWWProxy = useWWWProxy; _useWWWProxy = useWWWProxy;
_currentProxy = currentProxy; _currentProxy = currentProxy;
_disabled = false; _disabled = false;
_requestId = requestId;
long timeoutId = ++__timeoutId; long timeoutId = ++__timeoutId;
setName("InactivityThread " + getPrefix() + timeoutId); setName("InactivityThread " + getPrefix(requestId) + timeoutId);
} }
public void disable() { public void disable() {
...@@ -322,13 +362,13 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable ...@@ -322,13 +362,13 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
public void run() { public void run() {
while (!_disabled) { while (!_disabled) {
if (_runner.isFinished()) { if (_runner.isFinished()) {
if (_log.shouldLog(Log.INFO)) _log.info(getPrefix() + "HTTP client request completed prior to timeout"); if (_log.shouldLog(Log.INFO)) _log.info(getPrefix(_requestId) + "HTTP client request completed prior to timeout");
return; return;
} }
if (_runner.getLastActivityOn() < Clock.getInstance().now() - INACTIVITY_TIMEOUT) { if (_runner.getLastActivityOn() < Clock.getInstance().now() - INACTIVITY_TIMEOUT) {
if (_runner.getStartedOn() < Clock.getInstance().now() - INACTIVITY_TIMEOUT) { if (_runner.getStartedOn() < Clock.getInstance().now() - INACTIVITY_TIMEOUT) {
if (_log.shouldLog(Log.WARN)) if (_log.shouldLog(Log.WARN))
_log.warn(getPrefix() + "HTTP client request timed out (lastActivity: " _log.warn(getPrefix(_requestId) + "HTTP client request timed out (lastActivity: "
+ new Date(_runner.getLastActivityOn()) + ", startedOn: " + new Date(_runner.getLastActivityOn()) + ", startedOn: "
+ new Date(_runner.getStartedOn()) + ")"); + new Date(_runner.getStartedOn()) + ")");
timeout(); timeout();
...@@ -349,7 +389,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable ...@@ -349,7 +389,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
} }
private void timeout() { private void timeout() {
_log.info(getPrefix() + "Inactivity timeout reached"); _log.info(getPrefix(_requestId) + "Inactivity timeout reached");
l.log("Inactivity timeout reached"); l.log("Inactivity timeout reached");
if (_out != null) { if (_out != null) {
try { try {
...@@ -359,16 +399,17 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable ...@@ -359,16 +399,17 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
writeErrorMessage(ERR_TIMEOUT, _out, _targetRequest, _useWWWProxy, _currentProxy); writeErrorMessage(ERR_TIMEOUT, _out, _targetRequest, _useWWWProxy, _currentProxy);
} }
} catch (IOException ioe) { } catch (IOException ioe) {
_log.warn(getPrefix() + "Error writing out the 'timeout' message", ioe); _log.warn(getPrefix(_requestId) + "Error writing out the 'timeout' message", ioe);
} }
} else { } else {
_log.warn(getPrefix() + "Client disconnected before we could say we timed out"); _log.warn(getPrefix(_requestId) + "Client disconnected before we could say we timed out");
} }
closeSocket(s); closeSocket(s);
} }
} }
private final static String getHostName(String host) { private final static String getHostName(String host) {
if (host == null) return null;
try { try {
Destination dest = I2PTunnel.destFromName(host); Destination dest = I2PTunnel.destFromName(host);
if (dest == null) return "i2p"; if (dest == null) return "i2p";
...@@ -394,18 +435,18 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable ...@@ -394,18 +435,18 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
} }
private void handleHTTPClientException(Exception ex, OutputStream out, String targetRequest, private void handleHTTPClientException(Exception ex, OutputStream out, String targetRequest,
boolean usingWWWProxy, String wwwProxy) { boolean usingWWWProxy, String wwwProxy, long requestId) {
if (_log.shouldLog(Log.WARN)) if (_log.shouldLog(Log.WARN))
_log.warn("Error sending to " + wwwProxy + " (proxy? " + usingWWWProxy + ", request: " + targetRequest, ex); _log.warn(getPrefix(requestId) + "Error sending to " + wwwProxy + " (proxy? " + usingWWWProxy + ", request: " + targetRequest, ex);
if (out != null) { if (out != null) {
try { try {
writeErrorMessage(ERR_DESTINATION_UNKNOWN, out, targetRequest, usingWWWProxy, wwwProxy); writeErrorMessage(ERR_DESTINATION_UNKNOWN, out, targetRequest, usingWWWProxy, wwwProxy);
} catch (IOException ioe) { } catch (IOException ioe) {
_log.warn(getPrefix() + "Error writing out the 'destination was unknown' " + "message", ioe); _log.warn(getPrefix(requestId) + "Error writing out the 'destination was unknown' " + "message", ioe);
} }
} else { } else {
_log.warn(getPrefix() + "Client disconnected before we could say that destination " + "was unknown", ex); _log.warn(getPrefix(requestId) + "Client disconnected before we could say that destination " + "was unknown", ex);
} }
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment