diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java index d7ca0c16363ea6119b219aec76274e3a2336af08..f169d05737bcc8737eef4bf12e9b016823375c5f 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java @@ -46,6 +46,7 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Locale; +import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.StringTokenizer; @@ -330,6 +331,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging { * * Sets the event "clientoptions_onResult" = "ok" after completion. * + * Deprecated use setClientOptions() + * * @param args each args[i] is a key=value pair to add to the options * @param l logger to receive events and output */ @@ -347,6 +350,22 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging { notifyEvent("clientoptions_onResult", "ok"); } + /** + * A more efficient runClientOptions() + * + * @param opts non-null + * @since 0.9.1 + */ + public void setClientOptions(Properties opts) { + _clientOptions.clear(); + for (Map.Entry e : opts.entrySet()) { + String key = (String) e.getKey(); + String val = (String) e.getValue(); + _clientOptions.setProperty(key, val); + } + notifyEvent("clientoptions_onResult", "ok"); + } + /** * Run the server pointing at the host and port specified using the private i2p * destination loaded from the specified file. <p /> diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java index 48a6a60b4b754361c296fc4ab1e8631bccc76996..4e7f0c257ec162f7b3238ae20cdbdd462cbdf056 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java @@ -330,6 +330,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn String ahelperKey = null; String userAgent = null; String authorization = null; + int remotePort = 0; while((line = reader.readLine(method)) != null) { line = line.trim(); if(_log.shouldLog(Log.DEBUG)) { @@ -486,10 +487,11 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn // Host becomes the destination's "{b32}.b32.i2p" string, or "i2p" on lookup failure host = getHostName(destination); - if(requestURI.getPort() >= 0) { - // TODO support I2P ports someday - //if (port >= 0) - // host = host + ':' + port; + int rPort = requestURI.getPort(); + if (rPort > 0) { + // Save it to put in the I2PSocketOptions, + // but strip it from the URL + remotePort = rPort; if(_log.shouldLog(Log.WARN)) { _log.warn(getPrefix(requestId) + "Removing port from [" + request + "]"); } @@ -500,6 +502,8 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn method = null; break; } + } else { + remotePort = 80; } String query = requestURI.getRawQuery(); @@ -964,7 +968,10 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn // 1 == disconnect. see ConnectionOptions in the new streaming lib, which i // dont want to hard link to here //opts.setProperty("i2p.streaming.inactivityTimeoutAction", ""+1); - I2PSocket i2ps = createI2PSocket(clientDest, getDefaultOptions(opts)); + I2PSocketOptions sktOpts = getDefaultOptions(opts); + if (remotePort > 0) + sktOpts.setPort(remotePort); + I2PSocket i2ps = createI2PSocket(clientDest, sktOpts); byte[] data = newRequest.toString().getBytes("ISO-8859-1"); Runnable onTimeout = new OnTimeout(s, s.getOutputStream(), targetRequest, usingWWWProxy, currentProxy, requestId); new I2PTunnelHTTPClientRunner(s, i2ps, sockLock, data, mySockets, onTimeout); diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPServer.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPServer.java index 62845e3c61e3f79d13b9a27b1aa0c098ff6da503..58f0c2f4b4ca3bfbeaea84da25cb413e16746d2f 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPServer.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPServer.java @@ -77,7 +77,7 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer { } private void setupI2PTunnelHTTPServer(String spoofHost) { - _spoofHost = spoofHost; + _spoofHost = (spoofHost != null && spoofHost.trim().length() > 0) ? spoofHost.trim() : null; getTunnel().getContext().statManager().createRateStat("i2ptunnel.httpserver.blockingHandleTime", "how long the blocking handle takes to complete", "I2PTunnel.HTTPServer", new long[] { 60*1000, 10*60*1000, 3*60*60*1000 }); getTunnel().getContext().statManager().createRateStat("i2ptunnel.httpNullWorkaround", "How often an http server works around a streaming lib or i2ptunnel bug", "I2PTunnel.HTTPServer", new long[] { 60*1000, 10*60*1000 }); } @@ -96,6 +96,9 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer { */ @Override protected void blockingHandle(I2PSocket socket) { + if (_log.shouldLog(Log.INFO)) + _log.info("Incoming connection to '" + toString() + "' port " + socket.getLocalPort() + + " from: " + socket.getPeerDestination().calculateHash() + " port " + socket.getPort()); long afterAccept = getTunnel().getContext().clock().now(); long afterSocket = -1; //local is fast, so synchronously. Does not need that many @@ -115,8 +118,21 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer { addEntry(headers, DEST32_HEADER, Base32.encode(socket.getPeerDestination().calculateHash().getData()) + ".b32.i2p"); addEntry(headers, DEST64_HEADER, socket.getPeerDestination().toBase64()); - if ( (_spoofHost != null) && (_spoofHost.trim().length() > 0) ) - setEntry(headers, "Host", _spoofHost); + // Port-specific spoofhost + Properties opts = getTunnel().getClientOptions(); + String spoofHost; + int ourPort = socket.getLocalPort(); + if (ourPort != 80 && ourPort > 0 && ourPort < 65535 && opts != null) { + String portSpoof = opts.getProperty("spoofedHost." + ourPort); + if (portSpoof != null) + spoofHost = portSpoof.trim(); + else + spoofHost = _spoofHost; + } else { + spoofHost = _spoofHost; + } + if (spoofHost != null) + setEntry(headers, "Host", spoofHost); setEntry(headers, "Connection", "close"); // we keep the enc sent by the browser before clobbering it, since it may have // been x-i2p-gzip @@ -134,7 +150,6 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer { // request from the socket, modifies the headers, sends the request to the // server, reads the response headers, rewriting to include Content-encoding: x-i2p-gzip // if it was one of the Accept-encoding: values, and gzip the payload - Properties opts = getTunnel().getClientOptions(); boolean allowGZIP = true; if (opts != null) { String val = opts.getProperty("i2ptunnel.gzip"); diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCServer.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCServer.java index da063b0d0cb19aa52c907cc066f17665530651ca..b592ebcf82dcc267f90ddbbb621329b6207403f1 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCServer.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCServer.java @@ -111,6 +111,9 @@ public class I2PTunnelIRCServer extends I2PTunnelServer implements Runnable { @Override protected void blockingHandle(I2PSocket socket) { + if (_log.shouldLog(Log.INFO)) + _log.info("Incoming connection to '" + toString() + "' port " + socket.getLocalPort() + + " from: " + socket.getPeerDestination().calculateHash() + " port " + socket.getPort()); try { String modifiedRegistration; if(!this.method.equals("webirc")) { diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelServer.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelServer.java index 7c231add180afc7f11daa7cec41b229bbd5c64e4..60d6abf3fa6e95d47f5030e47ba4ffc347175a35 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelServer.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelServer.java @@ -408,7 +408,8 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable { protected void blockingHandle(I2PSocket socket) { if (_log.shouldLog(Log.INFO)) - _log.info("Incoming connection to '" + toString() + "' from: " + socket.getPeerDestination().calculateHash().toBase64()); + _log.info("Incoming connection to '" + toString() + "' port " + socket.getLocalPort() + + " from: " + socket.getPeerDestination().calculateHash() + " port " + socket.getPort()); long afterAccept = I2PAppContext.getGlobalContext().clock().now(); long afterSocket = -1; //local is fast, so synchronously. Does not need that many diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelController.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelController.java index a2dc146d62f4824ae99043c2dc59e1cab42010ae..2386a9dbee459f68009942eeca2a72d674beaa62 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelController.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelController.java @@ -4,8 +4,10 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; +import java.util.HashMap; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Properties; import java.util.Random; @@ -385,19 +387,16 @@ public class TunnelController implements Logging { } private void setSessionOptions() { - List opts = new ArrayList(); - for (Iterator iter = _config.keySet().iterator(); iter.hasNext(); ) { - String key = (String)iter.next(); - String val = _config.getProperty(key); + Properties opts = new Properties(); + for (Map.Entry e : _config.entrySet()) { + String key = (String) e.getKey(); if (key.startsWith("option.")) { key = key.substring("option.".length()); - opts.add(key + "=" + val); + String val = (String) e.getValue(); + opts.setProperty(key, val); } } - String args[] = new String[opts.size()]; - for (int i = 0; i < opts.size(); i++) - args[i] = (String)opts.get(i); - _tunnel.runClientOptions(args, this); + _tunnel.setClientOptions(opts); } private void setI2CPOptions() { diff --git a/apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocketEepGet.java b/apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocketEepGet.java index 8365d07fa69e95cc7f577c1afb17a97e30cb1cab..cfc0675c095099a329f34c05410865b48ddf4db0 100644 --- a/apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocketEepGet.java +++ b/apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocketEepGet.java @@ -143,6 +143,8 @@ public class I2PSocketEepGet extends EepGet { // in the SYN packet, saving one RTT. props.setProperty(PROP_CONNECT_DELAY, CONNECT_DELAY); I2PSocketOptions opts = _socketManager.buildOptions(props); + // TODO pull port out of URL + opts.setPort(80); _socket = _socketManager.connect(dest, opts); } else { throw new IOException("Unsupported protocol: " + _actualURL);