From 07caf2e316c31a2b43f7d2765aad6762e0d85eab Mon Sep 17 00:00:00 2001
From: zzz <zzz@mail.i2p>
Date: Wed, 13 Jun 2012 19:02:09 +0000
Subject: [PATCH]  * I2PSocketEepGet: Set port to 80  * I2PTunnel:    - Pass
 port through HTTP client proxy    - HTTP server proxy sets host header to    
  the value of "spoofedhost.xx" option for port xx    - Set client options
 more efficiently

---
 .../java/src/net/i2p/i2ptunnel/I2PTunnel.java | 19 +++++++++++++++
 .../i2p/i2ptunnel/I2PTunnelHTTPClient.java    | 17 ++++++++++----
 .../i2p/i2ptunnel/I2PTunnelHTTPServer.java    | 23 +++++++++++++++----
 .../net/i2p/i2ptunnel/I2PTunnelIRCServer.java |  3 +++
 .../net/i2p/i2ptunnel/I2PTunnelServer.java    |  3 ++-
 .../net/i2p/i2ptunnel/TunnelController.java   | 17 +++++++-------
 .../i2p/client/streaming/I2PSocketEepGet.java |  2 ++
 7 files changed, 65 insertions(+), 19 deletions(-)

diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java
index d7ca0c1636..f169d05737 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 48a6a60b4b..4e7f0c257e 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 62845e3c61..58f0c2f4b4 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 da063b0d0c..b592ebcf82 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 7c231add18..60d6abf3fa 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 a2dc146d62..2386a9dbee 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 8365d07fa6..cfc0675c09 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);
-- 
GitLab