forked from I2P_Developers/i2p.i2p
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:
@ -29,6 +29,7 @@ import net.i2p.data.DataHelper;
|
|||||||
import net.i2p.data.Destination;
|
import net.i2p.data.Destination;
|
||||||
import net.i2p.data.Hash;
|
import net.i2p.data.Hash;
|
||||||
import net.i2p.i2ptunnel.localServer.LocalHTTPServer;
|
import net.i2p.i2ptunnel.localServer.LocalHTTPServer;
|
||||||
|
import net.i2p.outproxy.Outproxy;
|
||||||
import net.i2p.util.EventDispatcher;
|
import net.i2p.util.EventDispatcher;
|
||||||
import net.i2p.util.Log;
|
import net.i2p.util.Log;
|
||||||
import net.i2p.util.PortMapper;
|
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_VIA = "i2ptunnel.httpclient.sendVia";
|
||||||
public static final String PROP_JUMP_SERVERS = "i2ptunnel.httpclient.jumpServers";
|
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_DISABLE_HELPER = "i2ptunnel.httpclient.disableAddressHelper";
|
||||||
|
public static final String PROP_OUTPROXY = "i2ptunnel.useLocalOutproxy";
|
||||||
|
|
||||||
protected void clientConnectionRun(Socket s) {
|
protected void clientConnectionRun(Socket s) {
|
||||||
OutputStream out = null;
|
OutputStream out = null;
|
||||||
@ -330,6 +332,8 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
|
|||||||
String targetRequest = null;
|
String targetRequest = null;
|
||||||
|
|
||||||
boolean usingWWWProxy = false;
|
boolean usingWWWProxy = false;
|
||||||
|
boolean usingOutproxy = false;
|
||||||
|
Outproxy outproxy = null;
|
||||||
boolean usingInternalServer = false;
|
boolean usingInternalServer = false;
|
||||||
String internalPath = null;
|
String internalPath = null;
|
||||||
String internalRawQuery = null;
|
String internalRawQuery = null;
|
||||||
@ -677,34 +681,47 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
|
|||||||
s.close();
|
s.close();
|
||||||
return;
|
return;
|
||||||
} else if(host.contains(".") || host.startsWith("[")) {
|
} else if(host.contains(".") || host.startsWith("[")) {
|
||||||
if(port >= 0) {
|
if (Boolean.parseBoolean(getTunnel().getClientOptions().getProperty(PROP_OUTPROXY)) &&
|
||||||
host = host + ':' + port;
|
(outproxy = _context.outproxy()) != null) {
|
||||||
}
|
int rPort = requestURI.getPort();
|
||||||
// The request must be forwarded to a WWW proxy
|
if (rPort > 0)
|
||||||
if(_log.shouldLog(Log.DEBUG)) {
|
remotePort = rPort;
|
||||||
_log.debug("Before selecting outproxy for " + host);
|
else
|
||||||
}
|
remotePort = 80;
|
||||||
currentProxy = selectProxy();
|
usingOutproxy = true;
|
||||||
if(_log.shouldLog(Log.DEBUG)) {
|
targetRequest = requestURI.toASCIIString();
|
||||||
_log.debug("After selecting outproxy for " + host + ": " + currentProxy);
|
if(_log.shouldLog(Log.DEBUG))
|
||||||
}
|
_log.debug(getPrefix(requestId) + " [" + host + "]: outproxy!");
|
||||||
if(currentProxy == null) {
|
} else {
|
||||||
if(_log.shouldLog(Log.WARN)) {
|
if(port >= 0) {
|
||||||
_log.warn(getPrefix(requestId) + "Host wants to be outproxied, but we dont have any!");
|
host = host + ':' + port;
|
||||||
}
|
}
|
||||||
l.log("No HTTP outproxy found for the request.");
|
// The request must be forwarded to a WWW proxy
|
||||||
if(out != null) {
|
if(_log.shouldLog(Log.DEBUG)) {
|
||||||
out.write(getErrorPage("noproxy", _ERR_NO_OUTPROXY));
|
_log.debug("Before selecting outproxy for " + host);
|
||||||
writeFooter(out);
|
}
|
||||||
|
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(getErrorPage("noproxy", _ERR_NO_OUTPROXY));
|
||||||
|
writeFooter(out);
|
||||||
|
}
|
||||||
|
s.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
destination = currentProxy;
|
||||||
|
usingWWWProxy = true;
|
||||||
|
targetRequest = requestURI.toASCIIString();
|
||||||
|
if(_log.shouldLog(Log.DEBUG)) {
|
||||||
|
_log.debug(getPrefix(requestId) + " [" + host + "]: wwwProxy!");
|
||||||
}
|
}
|
||||||
s.close();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
destination = currentProxy;
|
|
||||||
usingWWWProxy = true;
|
|
||||||
targetRequest = requestURI.toASCIIString();
|
|
||||||
if(_log.shouldLog(Log.DEBUG)) {
|
|
||||||
_log.debug(getPrefix(requestId) + " [" + host + "]: wwwProxy!");
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// what is left for here? a hostname with no dots, and != "i2p"
|
// what is left for here? a hostname with no dots, and != "i2p"
|
||||||
@ -722,7 +739,8 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
|
|||||||
return;
|
return;
|
||||||
} // end host name processing
|
} // end host name processing
|
||||||
|
|
||||||
boolean isValid = usingWWWProxy || usingInternalServer || isSupportedAddress(host, protocol);
|
boolean isValid = usingOutproxy || usingWWWProxy ||
|
||||||
|
usingInternalServer || isSupportedAddress(host, protocol);
|
||||||
if(!isValid) {
|
if(!isValid) {
|
||||||
if(_log.shouldLog(Log.INFO)) {
|
if(_log.shouldLog(Log.INFO)) {
|
||||||
_log.info(getPrefix(requestId) + "notValid(" + host + ")");
|
_log.info(getPrefix(requestId) + "notValid(" + host + ")");
|
||||||
@ -743,7 +761,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
|
|||||||
// end first line processing
|
// end first line processing
|
||||||
|
|
||||||
} else {
|
} 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
|
// 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
|
// But we don't create a Host: line if it wasn't sent to us
|
||||||
line = "Host: " + host;
|
line = "Host: " + host;
|
||||||
@ -815,7 +833,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
|
|||||||
if(!shout) {
|
if(!shout) {
|
||||||
if(!Boolean.parseBoolean(getTunnel().getClientOptions().getProperty(PROP_USER_AGENT))) {
|
if(!Boolean.parseBoolean(getTunnel().getClientOptions().getProperty(PROP_USER_AGENT))) {
|
||||||
// let's not advertise to external sites that we are from I2P
|
// 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");
|
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 {
|
} else {
|
||||||
newRequest.append("User-Agent: MYOB/6.66 (AN/ON)\r\n");
|
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() + "]");
|
_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.");
|
//l.log("No HTTP method found in the request.");
|
||||||
if(out != null) {
|
if(out != null) {
|
||||||
if(protocol != null && "http".equals(protocol.toLowerCase(Locale.US))) {
|
if(protocol != null && "http".equals(protocol.toLowerCase(Locale.US))) {
|
||||||
@ -896,6 +914,15 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
|
|||||||
return;
|
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
|
// LOOKUP
|
||||||
// If the host is "i2p", the getHostName() lookup failed, don't try to
|
// 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
|
// look it up again as the naming service does not do negative caching
|
||||||
|
@ -25,6 +25,7 @@ import net.i2p.crypto.TransientSessionKeyManager;
|
|||||||
import net.i2p.data.Base64;
|
import net.i2p.data.Base64;
|
||||||
import net.i2p.data.RoutingKeyGenerator;
|
import net.i2p.data.RoutingKeyGenerator;
|
||||||
import net.i2p.internal.InternalClientManager;
|
import net.i2p.internal.InternalClientManager;
|
||||||
|
import net.i2p.outproxy.Outproxy;
|
||||||
import net.i2p.stat.StatManager;
|
import net.i2p.stat.StatManager;
|
||||||
import net.i2p.update.UpdateManager;
|
import net.i2p.update.UpdateManager;
|
||||||
import net.i2p.util.Clock;
|
import net.i2p.util.Clock;
|
||||||
@ -94,6 +95,7 @@ public class I2PAppContext {
|
|||||||
private SimpleTimer _simpleTimer;
|
private SimpleTimer _simpleTimer;
|
||||||
private SimpleTimer2 _simpleTimer2;
|
private SimpleTimer2 _simpleTimer2;
|
||||||
private final PortMapper _portMapper;
|
private final PortMapper _portMapper;
|
||||||
|
private Outproxy _outproxy;
|
||||||
private volatile boolean _statManagerInitialized;
|
private volatile boolean _statManagerInitialized;
|
||||||
private volatile boolean _sessionKeyManagerInitialized;
|
private volatile boolean _sessionKeyManagerInitialized;
|
||||||
private volatile boolean _namingServiceInitialized;
|
private volatile boolean _namingServiceInitialized;
|
||||||
@ -127,7 +129,8 @@ public class I2PAppContext {
|
|||||||
_lock5 = new Object(), _lock6 = new Object(), _lock7 = new Object(), _lock8 = new Object(),
|
_lock5 = new Object(), _lock6 = new Object(), _lock7 = new Object(), _lock8 = new Object(),
|
||||||
_lock9 = new Object(), _lock10 = new Object(), _lock11 = new Object(), _lock12 = 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(),
|
_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
|
* Pull the default context, creating a new one if necessary, else using
|
||||||
@ -1023,4 +1026,39 @@ public class I2PAppContext {
|
|||||||
public UpdateManager updateManager() {
|
public UpdateManager updateManager() {
|
||||||
return null;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
17
core/java/src/net/i2p/outproxy/Outproxy.java
Normal file
17
core/java/src/net/i2p/outproxy/Outproxy.java
Normal 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;
|
||||||
|
|
||||||
|
}
|
Reference in New Issue
Block a user