New interface and context hooks for in-jvm outproxy

Support in HTTP client proxy
All preliminary, maybe better to use ClientAppManager?
This commit is contained in:
zzz
2014-01-05 00:52:00 +00:00
parent b59aa1fb69
commit d054e12952
3 changed files with 113 additions and 31 deletions

View File

@ -29,6 +29,7 @@ import net.i2p.data.DataHelper;
import net.i2p.data.Destination;
import net.i2p.data.Hash;
import net.i2p.i2ptunnel.localServer.LocalHTTPServer;
import net.i2p.outproxy.Outproxy;
import net.i2p.util.EventDispatcher;
import net.i2p.util.Log;
import net.i2p.util.PortMapper;
@ -320,6 +321,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
public static final String PROP_VIA = "i2ptunnel.httpclient.sendVia";
public static final String PROP_JUMP_SERVERS = "i2ptunnel.httpclient.jumpServers";
public static final String PROP_DISABLE_HELPER = "i2ptunnel.httpclient.disableAddressHelper";
public static final String PROP_OUTPROXY = "i2ptunnel.useLocalOutproxy";
protected void clientConnectionRun(Socket s) {
OutputStream out = null;
@ -330,6 +332,8 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
String targetRequest = null;
boolean usingWWWProxy = false;
boolean usingOutproxy = false;
Outproxy outproxy = null;
boolean usingInternalServer = false;
String internalPath = null;
String internalRawQuery = null;
@ -677,6 +681,18 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
s.close();
return;
} else if(host.contains(".") || host.startsWith("[")) {
if (Boolean.parseBoolean(getTunnel().getClientOptions().getProperty(PROP_OUTPROXY)) &&
(outproxy = _context.outproxy()) != null) {
int rPort = requestURI.getPort();
if (rPort > 0)
remotePort = rPort;
else
remotePort = 80;
usingOutproxy = true;
targetRequest = requestURI.toASCIIString();
if(_log.shouldLog(Log.DEBUG))
_log.debug(getPrefix(requestId) + " [" + host + "]: outproxy!");
} else {
if(port >= 0) {
host = host + ':' + port;
}
@ -706,6 +722,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
if(_log.shouldLog(Log.DEBUG)) {
_log.debug(getPrefix(requestId) + " [" + host + "]: wwwProxy!");
}
}
} else {
// what is left for here? a hostname with no dots, and != "i2p"
// and not a destination ???
@ -722,7 +739,8 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
return;
} // end host name processing
boolean isValid = usingWWWProxy || usingInternalServer || isSupportedAddress(host, protocol);
boolean isValid = usingOutproxy || usingWWWProxy ||
usingInternalServer || isSupportedAddress(host, protocol);
if(!isValid) {
if(_log.shouldLog(Log.INFO)) {
_log.info(getPrefix(requestId) + "notValid(" + host + ")");
@ -743,7 +761,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
// end first line processing
} else {
if(lowercaseLine.startsWith("host: ") && !usingWWWProxy) {
if(lowercaseLine.startsWith("host: ") && !usingWWWProxy && !usingOutproxy) {
// Note that we only pass the original Host: line through to the outproxy
// But we don't create a Host: line if it wasn't sent to us
line = "Host: " + host;
@ -815,7 +833,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
if(!shout) {
if(!Boolean.parseBoolean(getTunnel().getClientOptions().getProperty(PROP_USER_AGENT))) {
// let's not advertise to external sites that we are from I2P
if(usingWWWProxy) {
if(usingWWWProxy || usingOutproxy) {
newRequest.append("User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.6) Gecko/20100625 Firefox/3.6.6\r\n");
} else {
newRequest.append("User-Agent: MYOB/6.66 (AN/ON)\r\n");
@ -848,7 +866,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
_log.debug(getPrefix(requestId) + "NewRequest header: [" + newRequest.toString() + "]");
}
if(method == null || destination == null) {
if(method == null || (destination == null && !usingOutproxy)) {
//l.log("No HTTP method found in the request.");
if(out != null) {
if(protocol != null && "http".equals(protocol.toLowerCase(Locale.US))) {
@ -896,6 +914,15 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
return;
}
// no destination, going to outproxy plugin
if (usingOutproxy) {
Socket outSocket = outproxy.connect(host, remotePort);
byte[] data = newRequest.toString().getBytes("ISO-8859-1");
Runnable onTimeout = new OnTimeout(s, s.getOutputStream(), targetRequest, usingWWWProxy, currentProxy, requestId);
new I2PTunnelOutproxyRunner(s, outSocket, sockLock, data, onTimeout);
return;
}
// LOOKUP
// If the host is "i2p", the getHostName() lookup failed, don't try to
// look it up again as the naming service does not do negative caching

View File

@ -25,6 +25,7 @@ import net.i2p.crypto.TransientSessionKeyManager;
import net.i2p.data.Base64;
import net.i2p.data.RoutingKeyGenerator;
import net.i2p.internal.InternalClientManager;
import net.i2p.outproxy.Outproxy;
import net.i2p.stat.StatManager;
import net.i2p.update.UpdateManager;
import net.i2p.util.Clock;
@ -94,6 +95,7 @@ public class I2PAppContext {
private SimpleTimer _simpleTimer;
private SimpleTimer2 _simpleTimer2;
private final PortMapper _portMapper;
private Outproxy _outproxy;
private volatile boolean _statManagerInitialized;
private volatile boolean _sessionKeyManagerInitialized;
private volatile boolean _namingServiceInitialized;
@ -127,7 +129,8 @@ public class I2PAppContext {
_lock5 = new Object(), _lock6 = new Object(), _lock7 = new Object(), _lock8 = new Object(),
_lock9 = new Object(), _lock10 = new Object(), _lock11 = new Object(), _lock12 = new Object(),
_lock13 = new Object(), _lock14 = new Object(), _lock15 = new Object(), _lock16 = new Object(),
_lock17 = new Object(), _lock18 = new Object(), _lock19 = new Object(), _lock20 = new Object();
_lock17 = new Object(), _lock18 = new Object(), _lock19 = new Object(), _lock20 = new Object(),
_lock21 = new Object();
/**
* Pull the default context, creating a new one if necessary, else using
@ -1023,4 +1026,39 @@ public class I2PAppContext {
public UpdateManager updateManager() {
return null;
}
/**
* A local outproxy
* @return The outproxy if it is registered, else null
* @since 0.9.11
*/
public Outproxy outproxy() {
return _outproxy;
}
/**
* Register as the outproxy. For now, only one.
* @throws IllegalStateException if one was already registered
* @since 0.9.11
*/
public void registerOutproxy(Outproxy oproxy) {
synchronized(_lock21) {
if (_outproxy != null)
throw new IllegalStateException();
_outproxy = oproxy;
}
}
/**
* Unregister the outproxy.
* @throws IllegalStateException if it was not registered
* @since 0.9.11
*/
public void unregisterOutproxy(Outproxy oproxy) {
synchronized(_lock21) {
if (_outproxy != oproxy)
throw new IllegalStateException();
_outproxy = null;
}
}
}

View File

@ -0,0 +1,17 @@
package net.i2p.outproxy;
import java.io.IOException;
import java.net.Socket;
/**
*
* @since 0.9.11
*/
public interface Outproxy {
/**
*
*/
public Socket connect(String host, int port) throws IOException;
}