diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelManager.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelManager.java deleted file mode 100644 index 3b76c5e32c..0000000000 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelManager.java +++ /dev/null @@ -1,445 +0,0 @@ -/* I2PTunnel is GPL'ed (with the exception mentioned in I2PTunnel.java) - * (c) 2003 - 2004 mihi - */ - -package net.i2p.i2ptunnel; - -import java.io.IOException; -import java.io.OutputStream; -import java.net.InetAddress; -import java.net.ServerSocket; -import java.net.Socket; - -import net.i2p.data.DataFormatException; -import net.i2p.data.Destination; -import net.i2p.util.Clock; -import net.i2p.util.I2PThread; -import net.i2p.util.Log; - -/** - * Quick and dirty socket listener to control an I2PTunnel. - * Basically run this class as TunnelManager [listenHost] [listenPort] and - * then send it commands on that port. Commands are one shot deals - - * Send a command + newline, get a response plus newline, then get disconnected. - *

- * Implemented commands: - *

- * -------------------------------------------------
- * lookup <name>\n
- * --
- * <base64 of the destination>\n
- *  or
- * <error message, usually 'Unknown host'>\n
- * 
- *  Lookup the public key of a named destination (i.e. listed in hosts.txt)
- * -------------------------------------------------
- * genkey\n
- * --
- * <base64 of the destination>\t<base64 of private data>\n
- * 
- *  Generates a new public and private key pair
- * -------------------------------------------------
- * convertprivate <base64 of privkey>
- * --
- * <base64 of destination>\n
- *  or
- * <error message>\n
- *
- *  Returns the destination (pubkey) of a given private key. 
- * -------------------------------------------------
- * listen_on <ip>\n
- * --
- * ok\n
- *  or
- * error\n
- * 
- *  Sets the ip address clients will listen on. By default this is the
- *  localhost (127.0.0.1)
- * -------------------------------------------------
- * openclient <listenPort> <peer>[ <sharedClient>]\n
- * --
- * ok [<jobId>]\n
- *  or
- * ok <listenPort> [<jobId>]\n
- *  or
- * error\n
- * 
- *  Open a tunnel on the given <listenport> to the destination specified
- *  by <peer>. If <listenPort> is 0 a free port is picked and returned in
- *  the reply message. Otherwise the short reply message is used.
- *  Peer can be the base64 of the destination, a file with the public key
- *  specified as 'file:<filename>' or the name of a destination listed in
- *  hosts.txt. The <jobId> returned together with "ok" and <listenport> can
- *  later be used as argument for the "close" command.
- *  <sharedClient> indicates if this httpclient shares tunnels with other
- *  clients or not (just use 'true' and 'false'
- * -------------------------------------------------
- * openhttpclient <listenPort> [<sharedClient>] [<proxy>]\n
- * --
- * ok [<jobId>]\n
- *  or
- * ok <listenPort> [<jobId>]\n
- *  or
- * error\n
- * 
- *  Open an HTTP proxy through the I2P on the given
- *  <listenport>. <proxy> (optional) specifies a
- *  destination to be used as an outbound proxy, to access normal WWW
- *  sites out of the .i2p domain. If <listenPort> is 0 a free
- *  port is picked and returned in the reply message. Otherwise the
- *  short reply message is used.  <proxy> can be the base64 of the
- *  destination, a file with the public key specified as
- *  'file:<filename>' or the name of a destination listed in
- *  hosts.txt. The <jobId> returned together with "ok" and
- *  <listenport> can later be used as argument for the "close"
- *  command.
- *  <sharedClient> indicates if this httpclient shares tunnels with other
- *  clients or not (just use 'true' and 'false'
- * -------------------------------------------------
- * opensockstunnel <listenPort>\n
- * --
- * ok [<jobId>]\n
- *  or
- * ok <listenPort> [<jobId>]\n
- *  or
- * error\n
- * 
- *  Open an SOCKS tunnel through the I2P on the given
- *  <listenport>. If <listenPort> is 0 a free port is
- *  picked and returned in the reply message. Otherwise the short
- *  reply message is used.  The <jobId> returned together with
- *  "ok" and <listenport> can later be used as argument for the
- *  "close" command.
- * -------------------------------------------------
- * openserver <serverHost> <serverPort> <serverKeys>\n
- * --
- * ok [<jobId>]\n
- *  or
- * error\n
- * 
- *  Starts receiving traffic for the destination specified by <serverKeys>
- *  and forwards it to the <serverPort> of <serverHost>.
- *  <serverKeys> is the base 64 encoded private key set of the local
- *  destination. The <joId> returned together with "ok" can later be used
- *  as argument for the "close" command.
- * -------------------------------------------------
- * close [forced] <jobId>\n
- *  or
- * close [forced] all\n
- * --
- * ok\n
- *  or
- * error\n
- * 
- *  Closes the job specified by <jobId> or all jobs. Use the list command
- *  for a list of running jobs.
- *  Normally a connection job is not closed when it still has an active
- *  connection. Use the optional 'forced' keyword to close connections
- *  regardless of their use.
- * -------------------------------------------------
- * list\n
- * --
- *  Example output:
- * 
- * [0] i2p.dnsalias.net/69.55.226.145:5555 <- C:\i2pKeys\squidPriv
- * [1] 8767 -> HTTPClient
- * [2] 7575 -> file:C:\i2pKeys\squidPub
- * [3] 5252 -> sCcSANIO~f4AQtCNI1BvDp3ZBS~9Ag5O0k0Msm7XBWWz5eOnZWL3MQ-2rxlesucb9XnpASGhWzyYNBpWAfaIB3pux1J1xujQLOwscMIhm7T8BP76Ly5jx6BLZCYrrPj0BI0uV90XJyT~4UyQgUlC1jzFQdZ9HDgBPJDf1UI4-YjIwEHuJgdZynYlQ1oUFhgno~HhcDByXO~PDaO~1JDMDbBEfIh~v6MgmHp-Xchod1OfKFrxFrzHgcJbn7E8edTFjZA6JCi~DtFxFelQz1lSBd-QB1qJnA0g-pVL5qngNUojXJCXs4qWcQ7ICLpvIc-Fpfj-0F1gkVlGDSGkb1yLH3~8p4czYgR3W5D7OpwXzezz6clpV8kmbd~x2SotdWsXBPRhqpewO38coU4dJG3OEUbuYmdN~nJMfWbmlcM1lXzz2vBsys4sZzW6dV3hZnbvbfxNTqbdqOh-KXi1iAzXv7CVTun0ubw~CfeGpcAqutC5loRUq7Mq62ngOukyv8Z9AAAA
- *
- *  Lists descriptions of all running jobs. The exact format of the
- *  description depends on the type of job.
- * -------------------------------------------------
- * 
- * - * - * @deprecated this isn't run by default, and no one seems to use it, and has - * lots of things to maintain. so, at some point this may dissapear - * unless someone pipes up ;) - */ -public class TunnelManager implements Runnable { - private final static Log _log = new Log(TunnelManager.class); - private I2PTunnel _tunnel; - private ServerSocket _socket; - private boolean _keepAccepting; - - public TunnelManager(int listenPort) { - this(null, listenPort); - } - - public TunnelManager(String listenHost, int listenPort) { - _tunnel = new I2PTunnel(); - _keepAccepting = true; - try { - if (listenHost != null) { - _socket = new ServerSocket(listenPort, 0, InetAddress.getByName(listenHost)); - _log.info("Listening for tunnel management clients on " + listenHost + ":" + listenPort); - } else { - _socket = new ServerSocket(listenPort); - _log.info("Listening for tunnel management clients on localhost:" + listenPort); - } - } catch (Exception e) { - _log.error("Error starting up tunnel management listener on " + listenPort, e); - } - } - - public static void main(String args[]) { - int port = 7676; - String host = null; - if (args.length == 1) { - try { - port = Integer.parseInt(args[0]); - } catch (NumberFormatException nfe) { - _log.error("Usage: TunnelManager [host] [port]"); - return; - } - } else if (args.length == 2) { - host = args[0]; - try { - port = Integer.parseInt(args[1]); - } catch (NumberFormatException nfe) { - _log.error("Usage: TunnelManager [host] [port]"); - return; - } - } - - TunnelManager mgr = new TunnelManager(host, port); - Thread t = new I2PThread(mgr, "Listener"); - t.start(); - } - - public void run() { - if (_socket == null) { - _log.error("Unable to start listening, since the socket was not bound. Already running?"); - return; - } - _log.debug("Running"); - try { - while (_keepAccepting) { - Socket socket = _socket.accept(); - _log.debug("Client accepted"); - if (socket != null) { - Thread t = new I2PThread(new TunnelManagerClientRunner(this, socket)); - t.setName("TunnelManager Client"); - t.setPriority(I2PThread.MIN_PRIORITY); - t.start(); - } - } - } catch (IOException ioe) { - _log.error("Error accepting connections", ioe); - } catch (Exception e) { - _log.error("Other error?!", e); - } finally { - if (_socket != null) try { - _socket.close(); - } catch (IOException ioe) { - } - } - try { - Thread.sleep(5000); - } catch (InterruptedException ie) { - } - } - - public void error(String msg, OutputStream out) throws IOException { - out.write(msg.getBytes()); - out.write('\n'); - } - - public void processQuit(OutputStream out) throws IOException { - out.write("Nice try".getBytes()); - out.write('\n'); - } - - public void processList(OutputStream out) throws IOException { - BufferLogger buf = new BufferLogger(); - long startCommand = Clock.getInstance().now(); - _tunnel.runCommand("list", buf); - Object obj = _tunnel.waitEventValue("listDone"); - long endCommand = Clock.getInstance().now(); - String str = buf.getBuffer(); - _log.debug("ListDone complete after " + (endCommand - startCommand) + "ms: [" + str + "]"); - out.write(str.getBytes()); - out.write('\n'); - buf.ignoreFurtherActions(); - } - - public void processListenOn(String ip, OutputStream out) throws IOException { - BufferLogger buf = new BufferLogger(); - _tunnel.runCommand("listen_on " + ip, buf); - String status = (String) _tunnel.waitEventValue("listen_onResult"); - out.write((status + "\n").getBytes()); - buf.ignoreFurtherActions(); - } - - /** - * "lookup " returns with the result in base64, else "Unknown host" [or something like that], - * then a newline. - * - */ - public void processLookup(String name, OutputStream out) throws IOException { - BufferLogger buf = new BufferLogger(); - _tunnel.runCommand("lookup " + name, buf); - String rv = (String) _tunnel.waitEventValue("lookupResult"); - out.write(rv.getBytes()); - out.write('\n'); - buf.ignoreFurtherActions(); - } - - public void processTestDestination(String destKey, OutputStream out) throws IOException { - try { - Destination d = new Destination(); - d.fromBase64(destKey); - out.write("valid\n".getBytes()); - } catch (DataFormatException dfe) { - out.write("invalid\n".getBytes()); - } - out.flush(); - } - - public void processConvertPrivate(String priv, OutputStream out) throws IOException { - try { - Destination dest = new Destination(); - dest.fromBase64(priv); - String str = dest.toBase64(); - out.write(str.getBytes()); - out.write('\n'); - } catch (DataFormatException dfe) { - _log.error("Error converting private data", dfe); - out.write("Error converting private key\n".getBytes()); - } - } - - public void processClose(String which, boolean forced, OutputStream out) throws IOException { - BufferLogger buf = new BufferLogger(); - _tunnel.runCommand((forced ? "close forced " : "close ") + which, buf); - String str = (String) _tunnel.waitEventValue("closeResult"); - out.write((str + "\n").getBytes()); - buf.ignoreFurtherActions(); - } - - /** - * "genkey" returns with the base64 of the destination, followed by a tab, then the base64 of that - * destination's private keys, then a newline. - * - */ - public void processGenKey(OutputStream out) throws IOException { - BufferLogger buf = new BufferLogger(); - _tunnel.runCommand("gentextkeys", buf); - String priv = (String) _tunnel.waitEventValue("privateKey"); - String pub = (String) _tunnel.waitEventValue("publicDestination"); - out.write((pub + "\t" + priv).getBytes()); - out.write('\n'); - buf.ignoreFurtherActions(); - } - - public void processOpenClient(int listenPort, String peer, String sharedClient, OutputStream out) throws IOException { - BufferLogger buf = new BufferLogger(); - _tunnel.runCommand("client " + listenPort + " " + peer + " " + sharedClient, buf); - Integer taskId = (Integer) _tunnel.waitEventValue("clientTaskId"); - if (taskId.intValue() < 0) { - out.write("error\n".getBytes()); - buf.ignoreFurtherActions(); - return; - } - String rv = (String) _tunnel.waitEventValue("openClientResult"); - if (rv.equals("error")) { - out.write((rv + "\n").getBytes()); - buf.ignoreFurtherActions(); - return; - } - - if (listenPort != 0) { - out.write((rv + " [" + taskId.intValue() + "]\n").getBytes()); - buf.ignoreFurtherActions(); - return; - } - Integer port = (Integer) _tunnel.waitEventValue("clientLocalPort"); - out.write((rv + " " + port.intValue() + " [" + taskId.intValue() + "]\n").getBytes()); - buf.ignoreFurtherActions(); - } - - public void processOpenHTTPClient(int listenPort, String sharedClient, String proxy, OutputStream out) throws IOException { - BufferLogger buf = new BufferLogger(); - _tunnel.runCommand("httpclient " + listenPort + " " + sharedClient + " " + proxy, buf); - Integer taskId = (Integer) _tunnel.waitEventValue("httpclientTaskId"); - if (taskId.intValue() < 0) { - out.write("error\n".getBytes()); - buf.ignoreFurtherActions(); - return; - } - String rv = (String) _tunnel.waitEventValue("openHTTPClientResult"); - if (rv.equals("error")) { - out.write((rv + "\n").getBytes()); - buf.ignoreFurtherActions(); - return; - } - - if (listenPort != 0) { - out.write((rv + " [" + taskId.intValue() + "]\n").getBytes()); - buf.ignoreFurtherActions(); - return; - } - Integer port = (Integer) _tunnel.waitEventValue("clientLocalPort"); - out.write((rv + " " + port.intValue() + " [" + taskId.intValue() + "]\n").getBytes()); - buf.ignoreFurtherActions(); - } - - public void processOpenSOCKSTunnel(int listenPort, OutputStream out) throws IOException { - BufferLogger buf = new BufferLogger(); - _tunnel.runCommand("sockstunnel " + listenPort, buf); - Integer taskId = (Integer) _tunnel.waitEventValue("sockstunnelTaskId"); - if (taskId.intValue() < 0) { - out.write("error\n".getBytes()); - buf.ignoreFurtherActions(); - return; - } - String rv = (String) _tunnel.waitEventValue("openSOCKSTunnelResult"); - if (rv.equals("error")) { - out.write((rv + "\n").getBytes()); - buf.ignoreFurtherActions(); - return; - } - - if (listenPort != 0) { - out.write((rv + " [" + taskId.intValue() + "]\n").getBytes()); - buf.ignoreFurtherActions(); - return; - } - Integer port = (Integer) _tunnel.waitEventValue("clientLocalPort"); - out.write((rv + " " + port.intValue() + " [" + taskId.intValue() + "]\n").getBytes()); - buf.ignoreFurtherActions(); - } - - public void processOpenServer(String serverHost, int serverPort, String privateKeys, OutputStream out) - throws IOException { - BufferLogger buf = new BufferLogger(); - _tunnel.runCommand("textserver " + serverHost + " " + serverPort + " " + privateKeys, buf); - Integer taskId = (Integer) _tunnel.waitEventValue("serverTaskId"); - if (taskId.intValue() < 0) { - out.write("error\n".getBytes()); - buf.ignoreFurtherActions(); - return; - } - - String rv = (String) _tunnel.waitEventValue("openServerResult"); - - if (rv.equals("error")) { - out.write((rv + "\n").getBytes()); - buf.ignoreFurtherActions(); - return; - } - - out.write((rv + " [" + taskId.intValue() + "]\n").getBytes()); - buf.ignoreFurtherActions(); - } - - /** - * Frisbee. - * - */ - public void unknownCommand(String command, OutputStream out) throws IOException { - out.write("Unknown command: ".getBytes()); - out.write(command.getBytes()); - out.write("\n".getBytes()); - } -} diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelManagerClientRunner.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelManagerClientRunner.java deleted file mode 100644 index 6bd9bb730d..0000000000 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelManagerClientRunner.java +++ /dev/null @@ -1,203 +0,0 @@ -/* I2PTunnel is GPL'ed (with the exception mentioned in I2PTunnel.java) - * (c) 2003 - 2004 mihi - */ - -package net.i2p.i2ptunnel; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.net.Socket; -import java.util.StringTokenizer; - -import net.i2p.util.Log; - -/** - * Runner thread that reads commands from the socket and fires off commands to - * the TunnelManager - * - */ -class TunnelManagerClientRunner implements Runnable { - private final static Log _log = new Log(TunnelManagerClientRunner.class); - private TunnelManager _mgr; - private Socket _clientSocket; - - public TunnelManagerClientRunner(TunnelManager mgr, Socket socket) { - _clientSocket = socket; - _mgr = mgr; - } - - public void run() { - _log.debug("Client running"); - try { - BufferedReader reader = new BufferedReader(new InputStreamReader(_clientSocket.getInputStream())); - OutputStream out = _clientSocket.getOutputStream(); - - String cmd = reader.readLine(); - if (cmd != null) processCommand(cmd, out); - } catch (IOException ioe) { - _log.error("Error processing client commands", ioe); - } finally { - if (_clientSocket != null) try { - _clientSocket.close(); - } catch (IOException ioe) { - } - } - _log.debug("Client closed"); - } - - /** - * Parse the command string and fire off the appropriate tunnelManager method, - * sending the results to the output stream - */ - private void processCommand(String command, OutputStream out) throws IOException { - _log.debug("Processing [" + command + "]"); - StringTokenizer tok = new StringTokenizer(command); - if (!tok.hasMoreTokens()) { - _mgr.unknownCommand(command, out); - } else { - String cmd = tok.nextToken(); - if ("quit".equalsIgnoreCase(cmd)) { - _mgr.processQuit(out); - } else if ("lookup".equalsIgnoreCase(cmd)) { - if (tok.hasMoreTokens()) - _mgr.processLookup(tok.nextToken(), out); - else - _mgr.error("Usage: lookup ", out); - } else if ("testdestination".equalsIgnoreCase(cmd)) { - if (tok.hasMoreTokens()) - _mgr.processTestDestination(tok.nextToken(), out); - else - _mgr.error("Usage: testdestination ", out); - } else if ("convertprivate".equalsIgnoreCase(cmd)) { - if (tok.hasMoreTokens()) - _mgr.processConvertPrivate(tok.nextToken(), out); - else - _mgr.error("Usage: convertprivate ", out); - } else if ("close".equalsIgnoreCase(cmd)) { - if (tok.hasMoreTokens()) { - String closeArg; - if ((closeArg = tok.nextToken()).equals("forced")) { - if (tok.hasMoreTokens()) { - _mgr.processClose(tok.nextToken(), true, out); - } else { - _mgr.error("Usage: close [forced] |all", out); - } - } else { - _mgr.processClose(closeArg, false, out); - } - } else { - _mgr.error("Usage: close [forced] |all", out); - } - } else if ("genkey".equalsIgnoreCase(cmd)) { - _mgr.processGenKey(out); - } else if ("list".equalsIgnoreCase(cmd)) { - _mgr.processList(out); - } else if ("listen_on".equalsIgnoreCase(cmd)) { - if (tok.hasMoreTokens()) { - _mgr.processListenOn(tok.nextToken(), out); - } else { - _mgr.error("Usage: listen_on ", out); - } - } else if ("openclient".equalsIgnoreCase(cmd)) { - int listenPort = 0; - String peer = null; - String sharedClient = null; - int numTokens = tok.countTokens(); - if (numTokens < 2 || numTokens > 3) { - _mgr.error("Usage: openclient ", out); - return; - } - try { - listenPort = Integer.parseInt(tok.nextToken()); - peer = tok.nextToken(); - if (tok.hasMoreTokens()) - sharedClient = tok.nextToken(); - else - sharedClient = "true"; - _mgr.processOpenClient(listenPort, peer, sharedClient, out); - } catch (NumberFormatException nfe) { - _mgr.error("Bad listen port", out); - return; - } - } else if ("openhttpclient".equalsIgnoreCase(cmd)) { - int listenPort = 0; - String proxy = "squid.i2p"; - String sharedClient = "true"; - int numTokens = tok.countTokens(); - if (numTokens < 1 || numTokens > 3) { - _mgr.error("Usage: openhttpclient [] []", out); - return; - } - try { - listenPort = Integer.parseInt(tok.nextToken()); - if (tok.hasMoreTokens()) { - String val = tok.nextToken(); - if (tok.hasMoreTokens()) { - sharedClient = val; - proxy = tok.nextToken(); - } else { - if ( ("true".equals(val)) || ("false".equals(val)) ) { - sharedClient = val; - } else { - proxy = val; - } - } - } - _mgr.processOpenHTTPClient(listenPort, sharedClient, proxy, out); - } catch (NumberFormatException nfe) { - _mgr.error("Bad listen port", out); - return; - } - } else if ("opensockstunnel".equalsIgnoreCase(cmd)) { - int listenPort = 0; - if (!tok.hasMoreTokens()) { - _mgr.error("Usage: opensockstunnel ", out); - return; - } - try { - String portStr = tok.nextToken(); - listenPort = Integer.parseInt(portStr); - } catch (NumberFormatException nfe) { - _mgr.error("Bad listen port", out); - return; - } - if (tok.hasMoreTokens()) { - _mgr.error("Usage: opensockstunnel ", out); - return; - } - _mgr.processOpenSOCKSTunnel(listenPort, out); - } else if ("openserver".equalsIgnoreCase(cmd)) { - int listenPort = 0; - String serverHost = null; - String serverKeys = null; - if (!tok.hasMoreTokens()) { - _mgr.error("Usage: openserver ", out); - return; - } - serverHost = tok.nextToken(); - - if (!tok.hasMoreTokens()) { - _mgr.error("Usage: openserver ", out); - return; - } - try { - String portStr = tok.nextToken(); - listenPort = Integer.parseInt(portStr); - } catch (NumberFormatException nfe) { - _mgr.error("Bad listen port", out); - return; - } - if (!tok.hasMoreTokens()) { - _mgr.error("Usage: openserver ", out); - return; - } - serverKeys = tok.nextToken(); - _mgr.processOpenServer(serverHost, listenPort, serverKeys, out); - } else { - _mgr.unknownCommand(command, out); - } - } - } -} diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHandler.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHandler.java index 8cf396102e..8b039732e7 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHandler.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHandler.java @@ -28,7 +28,8 @@ public class ConfigNetHandler extends FormHandler { private boolean _reseedRequested; private boolean _saveRequested; private boolean _timeSyncEnabled; - private String _port; + private String _tcpPort; + private String _udpPort; private String _inboundRate; private String _inboundBurst; private String _outboundRate; @@ -56,8 +57,11 @@ public class ConfigNetHandler extends FormHandler { public void setHostname(String hostname) { _hostname = (hostname != null ? hostname.trim() : null); } - public void setPort(String port) { - _port = (port != null ? port.trim() : null); + public void setTcpPort(String port) { + _tcpPort = (port != null ? port.trim() : null); + } + public void setUdpPort(String port) { + _udpPort = (port != null ? port.trim() : null); } public void setInboundrate(String rate) { _inboundRate = (rate != null ? rate.trim() : null); @@ -207,14 +211,25 @@ public class ConfigNetHandler extends FormHandler { restartRequired = true; } } - if ( (_port != null) && (_port.length() > 0) ) { + if ( (_tcpPort != null) && (_tcpPort.length() > 0) ) { String oldPort = _context.router().getConfigSetting(ConfigNetHelper.PROP_I2NP_TCP_PORT); - if ( (oldPort == null) && (_port.equals("8887")) ) { + if ( (oldPort == null) && (_tcpPort.equals("8887")) ) { // still on default.. noop - } else if ( (oldPort == null) || (!oldPort.equalsIgnoreCase(_port)) ) { + } else if ( (oldPort == null) || (!oldPort.equalsIgnoreCase(_tcpPort)) ) { // its not the default OR it has changed - _context.router().setConfigSetting(ConfigNetHelper.PROP_I2NP_TCP_PORT, _port); - addFormNotice("Updating TCP port from " + oldPort + " to " + _port); + _context.router().setConfigSetting(ConfigNetHelper.PROP_I2NP_TCP_PORT, _tcpPort); + addFormNotice("Updating TCP port from " + oldPort + " to " + _tcpPort); + restartRequired = true; + } + } + if ( (_udpPort != null) && (_udpPort.length() > 0) ) { + String oldPort = _context.router().getConfigSetting(ConfigNetHelper.PROP_I2NP_UDP_PORT); + if ( (oldPort == null) && (_udpPort.equals("8887")) ) { + // still on default.. noop + } else if ( (oldPort == null) || (!oldPort.equalsIgnoreCase(_udpPort)) ) { + // its not the default OR it has changed + _context.router().setConfigSetting(ConfigNetHelper.PROP_I2NP_TCP_PORT, _udpPort); + addFormNotice("Updating UDP port from " + oldPort + " to " + _udpPort); restartRequired = true; } } diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHelper.java index fa66bac35e..12e01852a5 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHelper.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHelper.java @@ -24,11 +24,13 @@ public class ConfigNetHelper { /** copied from various private TCP components */ public final static String PROP_I2NP_TCP_HOSTNAME = "i2np.tcp.hostname"; public final static String PROP_I2NP_TCP_PORT = "i2np.tcp.port"; + public final static String PROP_I2NP_UDP_PORT = "i2np.udp.port"; + public final static String PROP_I2NP_INTERNAL_UDP_PORT = "i2np.udp.internalPort"; public String getHostname() { return _context.getProperty(PROP_I2NP_TCP_HOSTNAME); } - public String getPort() { + public String getTcpPort() { int port = 8887; String val = _context.getProperty(PROP_I2NP_TCP_PORT); if (val != null) { @@ -41,6 +43,21 @@ public class ConfigNetHelper { return "" + port; } + public String getUdpPort() { + int port = 8887; + String val = _context.getProperty(PROP_I2NP_UDP_PORT); + if (val == null) + val = _context.getProperty(PROP_I2NP_INTERNAL_UDP_PORT); + if (val != null) { + try { + port = Integer.parseInt(val); + } catch (NumberFormatException nfe) { + // ignore, use default from above + } + } + return "" + port; + } + public String getEnableTimeSyncChecked() { String disabled = _context.getProperty(Timestamper.PROP_DISABLED, "false"); if ( (disabled != null) && ("true".equalsIgnoreCase(disabled)) ) diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigStatsHandler.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigStatsHandler.java index 3aa0dd90e4..bcb2af1d58 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigStatsHandler.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigStatsHandler.java @@ -6,6 +6,7 @@ import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer; +import net.i2p.util.Log; import net.i2p.stat.StatManager; /** @@ -22,6 +23,7 @@ public class ConfigStatsHandler extends FormHandler { public ConfigStatsHandler() { super(); _stats = new ArrayList(); + _explicitFilter = false; } protected void processForm() { @@ -36,29 +38,16 @@ public class ConfigStatsHandler extends FormHandler { if (stats != null) { for (int i = 0; i < stats.length; i++) { String cur = stats[i].trim(); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Stat: [" + cur + "]"); if ( (cur.length() > 0) && (!_stats.contains(cur)) ) _stats.add(cur); } } + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Updated stats: " + _stats); } - public void setStatList(String stat) { - if (stat != null) { - if (stat.indexOf(',') != -1) { - StringTokenizer tok = new StringTokenizer(stat, ","); - while (tok.hasMoreTokens()) { - String cur = tok.nextToken().trim(); - if ( (cur.length() > 0) && (!_stats.contains(cur)) ) - _stats.add(cur); - } - } else { - stat = stat.trim(); - if ( (stat.length() > 0) && (!_stats.contains(stat)) ) - _stats.add(stat); - } - } - } - public void setExplicitFilter(String foo) { _explicitFilter = true; } public void setExplicitFilterValue(String filter) { _explicitFilterValue = filter; } @@ -74,7 +63,19 @@ public class ConfigStatsHandler extends FormHandler { if (_explicitFilter) { _stats.clear(); - setStatList(_explicitFilterValue); + + if (_explicitFilterValue.indexOf(',') != -1) { + StringTokenizer tok = new StringTokenizer(_explicitFilterValue, ","); + while (tok.hasMoreTokens()) { + String cur = tok.nextToken().trim(); + if ( (cur.length() > 0) && (!_stats.contains(cur)) ) + _stats.add(cur); + } + } else { + String stat = _explicitFilterValue.trim(); + if ( (stat.length() > 0) && (!_stats.contains(stat)) ) + _stats.add(stat); + } } StringBuffer stats = new StringBuffer(); diff --git a/apps/routerconsole/java/src/net/i2p/router/web/FormHandler.java b/apps/routerconsole/java/src/net/i2p/router/web/FormHandler.java index 9f14c8b16b..1d66037afe 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/FormHandler.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/FormHandler.java @@ -4,6 +4,7 @@ import java.util.List; import java.util.ArrayList; import net.i2p.router.RouterContext; +import net.i2p.util.Log; /** * Simple form handler base class - does not depend on servlets or jsp, @@ -16,6 +17,7 @@ import net.i2p.router.RouterContext; */ public class FormHandler { protected RouterContext _context; + protected Log _log; private String _nonce; protected String _action; private List _errors; @@ -41,6 +43,7 @@ public class FormHandler { public void setContextId(String contextId) { try { _context = ContextHelper.getContext(contextId); + _log = _context.logManager().getLog(getClass()); } catch (Throwable t) { t.printStackTrace(); } diff --git a/apps/routerconsole/jsp/config.jsp b/apps/routerconsole/jsp/config.jsp index 3209ce3f98..99735f68b7 100644 --- a/apps/routerconsole/jsp/config.jsp +++ b/apps/routerconsole/jsp/config.jsp @@ -28,13 +28,13 @@ " /> - TCP port: - " />
+ UDP port:
+ +You must poke a hole in your firewall or NAT (if applicable) to receive new inbound UDP packets on +this port from arbitrary peers (this requirement will be removed in i2p 0.6.1, but is necessary now)
+ TCP port: " />
You must poke a hole in your firewall or NAT (if applicable) so that you can receive inbound TCP - connections on it. Nothing will work if you don't. Sorry. We know how to make it so - this restriction won't be necessary, but its later on in the - roadmap and we only have so many coder-hours (but if you want - to help, please get involved!) + connections on it (this requirement will be removed in i2p 0.6.1, but is necessary now)
Bandwidth limiter
@@ -57,7 +57,7 @@ packets on port 123 to one of the pool.ntp.org machines (or some other SNTP server).

- Changing the TCP port will force a 'soft restart' - dropping your connections and clients as + Changing the TCP or UDP port will force a 'soft restart' - dropping your connections and clients as if the router was stopped and restarted. Please be patient - it may take a few seconds to complete. @@ -73,6 +73,13 @@ "i2p.reseedURL=someURL" (e.g. java -Di2p.reseedURL=http://dev.i2p.net/i2pdb/ ...). You can also do it manually by getting routerInfo-*.dat files from someone (a friend, someone on IRC, whatever) and saving them to your netDb/ directory.

+

+ With the SSU transport, the internal UDP port may be different from the external + UDP port (in case of a firewall/NAT) - the UDP port field above specifies the + external one and assumes they are the same, but if you want to set the internal + port to something else, you can add "i2np.udp.internalPort=1234" to the + advanced config and restart the router. +

diff --git a/apps/streaming/java/src/net/i2p/client/streaming/ConnectionPacketHandler.java b/apps/streaming/java/src/net/i2p/client/streaming/ConnectionPacketHandler.java index aeab27d665..710798b875 100644 --- a/apps/streaming/java/src/net/i2p/client/streaming/ConnectionPacketHandler.java +++ b/apps/streaming/java/src/net/i2p/client/streaming/ConnectionPacketHandler.java @@ -33,7 +33,7 @@ public class ConnectionPacketHandler { boolean ok = verifyPacket(packet, con); if (!ok) { if ( (!packet.isFlagSet(Packet.FLAG_RESET)) && (_log.shouldLog(Log.ERROR)) ) - _log.error("Packet does NOT verify: " + packet); + _log.error("Packet does NOT verify: " + packet + " on " + con); packet.releasePayload(); return; } @@ -305,16 +305,16 @@ public class ConnectionPacketHandler { if (packet.getSequenceNum() <= 2) { return true; } else { - if (_log.shouldLog(Log.WARN)) - _log.warn("Packet without RST or SYN where we dont know stream ID: " + if (_log.shouldLog(Log.ERROR)) + _log.error("Packet without RST or SYN where we dont know stream ID: " + packet); return false; } } } else { if (!DataHelper.eq(con.getSendStreamId(), packet.getReceiveStreamId())) { - if (_log.shouldLog(Log.WARN)) - _log.warn("Packet received with the wrong reply stream id: " + if (_log.shouldLog(Log.ERROR)) + _log.error("Packet received with the wrong reply stream id: " + con + " / " + packet); return false; } else { @@ -331,8 +331,8 @@ public class ConnectionPacketHandler { if (DataHelper.eq(con.getReceiveStreamId(), packet.getSendStreamId())) { boolean ok = packet.verifySignature(_context, packet.getOptionalFrom(), null); if (!ok) { - if (_log.shouldLog(Log.WARN)) - _log.warn("Received unsigned / forged RST on " + con); + if (_log.shouldLog(Log.ERROR)) + _log.error("Received unsigned / forged RST on " + con); return; } else { if (_log.shouldLog(Log.DEBUG)) diff --git a/core/java/src/net/i2p/CoreVersion.java b/core/java/src/net/i2p/CoreVersion.java index d587fa5faa..17d8502055 100644 --- a/core/java/src/net/i2p/CoreVersion.java +++ b/core/java/src/net/i2p/CoreVersion.java @@ -14,8 +14,8 @@ package net.i2p; * */ public class CoreVersion { - public final static String ID = "$Revision: 1.34 $ $Date: 2005/04/06 10:43:26 $"; - public final static String VERSION = "0.5.0.7"; + public final static String ID = "$Revision: 1.35 $ $Date: 2005/04/20 15:14:20 $"; + public final static String VERSION = "0.6"; public static void main(String args[]) { System.out.println("I2P Core version: " + VERSION); diff --git a/core/java/src/net/i2p/client/I2CPMessageProducer.java b/core/java/src/net/i2p/client/I2CPMessageProducer.java index 068e41dafe..9af1fbd19c 100644 --- a/core/java/src/net/i2p/client/I2CPMessageProducer.java +++ b/core/java/src/net/i2p/client/I2CPMessageProducer.java @@ -121,7 +121,7 @@ class I2CPMessageProducer { * garlic crypto added by the router) * */ - static final boolean END_TO_END_CRYPTO = true; + static final boolean END_TO_END_CRYPTO = false; /** * Create a new signed payload and send it off to the destination diff --git a/core/java/src/net/i2p/crypto/DHSessionKeyBuilder.java b/core/java/src/net/i2p/crypto/DHSessionKeyBuilder.java index 7fc4df6a74..0fda386c0f 100644 --- a/core/java/src/net/i2p/crypto/DHSessionKeyBuilder.java +++ b/core/java/src/net/i2p/crypto/DHSessionKeyBuilder.java @@ -260,7 +260,10 @@ public class DHSessionKeyBuilder { * */ public byte[] getMyPublicValueBytes() { - BigInteger bi = getMyPublicValue(); + return toByteArray(getMyPublicValue()); + } + + private static final byte[] toByteArray(BigInteger bi) { byte data[] = bi.toByteArray(); byte rv[] = new byte[256]; if (data.length == 257) // high byte has the sign bit @@ -299,6 +302,9 @@ public class DHSessionKeyBuilder { public BigInteger getPeerPublicValue() { return _peerValue; } + public byte[] getPeerPublicValueBytes() { + return toByteArray(getPeerPublicValue()); + } /** * Retrieve the session key, calculating it if necessary (and if possible). diff --git a/core/java/src/net/i2p/util/BufferedRandomSource.java b/core/java/src/net/i2p/util/BufferedRandomSource.java index 8103a56e06..e344b5a2ae 100644 --- a/core/java/src/net/i2p/util/BufferedRandomSource.java +++ b/core/java/src/net/i2p/util/BufferedRandomSource.java @@ -225,4 +225,4 @@ public class BufferedRandomSource extends RandomSource { } return buf.toString(); } -} \ No newline at end of file +} diff --git a/core/java/test/net/i2p/crypto/DHSessionKeyBuilderTest.java b/core/java/test/net/i2p/crypto/DHSessionKeyBuilderTest.java index 416954e43c..c91948d55b 100644 --- a/core/java/test/net/i2p/crypto/DHSessionKeyBuilderTest.java +++ b/core/java/test/net/i2p/crypto/DHSessionKeyBuilderTest.java @@ -25,9 +25,13 @@ public class DHSessionKeyBuilderTest extends TestCase { DHSessionKeyBuilder builder1 = new DHSessionKeyBuilder(); DHSessionKeyBuilder builder2 = new DHSessionKeyBuilder(); BigInteger pub1 = builder1.getMyPublicValue(); - builder2.setPeerPublicValue(pub1); BigInteger pub2 = builder2.getMyPublicValue(); - builder1.setPeerPublicValue(pub2); + try { + builder2.setPeerPublicValue(pub1); + builder1.setPeerPublicValue(pub2); + } catch (DHSessionKeyBuilder.InvalidPublicParameterException ippe) { + assertTrue(ippe.getMessage(), true); + } SessionKey key1 = builder1.getSessionKey(); SessionKey key2 = builder2.getSessionKey(); @@ -44,4 +48,4 @@ public class DHSessionKeyBuilderTest extends TestCase { assertEquals(origVal, tranVal); } } -} \ No newline at end of file +} diff --git a/core/java/test/net/i2p/data/MessagePayloadMessageTest.java b/core/java/test/net/i2p/data/MessagePayloadMessageTest.java index bdd71bf7d1..f818ade52d 100644 --- a/core/java/test/net/i2p/data/MessagePayloadMessageTest.java +++ b/core/java/test/net/i2p/data/MessagePayloadMessageTest.java @@ -30,9 +30,9 @@ import net.i2p.util.Log; public class MessagePayloadMessageTest extends StructureTest { public DataStructure createDataStructure() throws DataFormatException { MessagePayloadMessage msg = new MessagePayloadMessage(); - msg.setMessageId((MessageId)(new MessageIdTest()).createDataStructure()); + msg.setMessageId(123); msg.setPayload((Payload)(new PayloadTest()).createDataStructure()); - msg.setSessionId((SessionId)(new SessionIdTest()).createDataStructure()); + msg.setSessionId(321); return msg; } public DataStructure createStructureToRead() { return new MessagePayloadMessage(); } @@ -56,4 +56,4 @@ import net.i2p.util.Log; assertEquals(orig, ds); } -} \ No newline at end of file +} diff --git a/core/java/test/net/i2p/data/MessageStatusMessageTest.java b/core/java/test/net/i2p/data/MessageStatusMessageTest.java index c042fe918c..cd8aabc67a 100644 --- a/core/java/test/net/i2p/data/MessageStatusMessageTest.java +++ b/core/java/test/net/i2p/data/MessageStatusMessageTest.java @@ -22,8 +22,8 @@ import net.i2p.data.i2cp.SessionId; public class MessageStatusMessageTest extends StructureTest { public DataStructure createDataStructure() throws DataFormatException { MessageStatusMessage msg = new MessageStatusMessage(); - msg.setSessionId((SessionId)(new SessionIdTest()).createDataStructure()); - msg.setMessageId((MessageId)(new MessageIdTest()).createDataStructure()); + msg.setSessionId(42); + msg.setMessageId(41); msg.setSize(1024*1024*42L); msg.setStatus(MessageStatusMessage.STATUS_AVAILABLE); msg.setNonce(1); diff --git a/core/java/test/net/i2p/data/ReceiveMessageBeginMessageTest.java b/core/java/test/net/i2p/data/ReceiveMessageBeginMessageTest.java index 9bb09a9dae..19edd8a610 100644 --- a/core/java/test/net/i2p/data/ReceiveMessageBeginMessageTest.java +++ b/core/java/test/net/i2p/data/ReceiveMessageBeginMessageTest.java @@ -22,8 +22,8 @@ import net.i2p.data.i2cp.SessionId; public class ReceiveMessageBeginMessageTest extends StructureTest { public DataStructure createDataStructure() throws DataFormatException { ReceiveMessageBeginMessage msg = new ReceiveMessageBeginMessage(); - msg.setSessionId((SessionId)(new SessionIdTest()).createDataStructure()); - msg.setMessageId((MessageId)(new MessageIdTest()).createDataStructure()); + msg.setSessionId(321); + msg.setMessageId(123); return msg; } public DataStructure createStructureToRead() { return new ReceiveMessageBeginMessage(); } diff --git a/core/java/test/net/i2p/data/ReceiveMessageEndMessageTest.java b/core/java/test/net/i2p/data/ReceiveMessageEndMessageTest.java index 6402dcee3a..4e33406d5d 100644 --- a/core/java/test/net/i2p/data/ReceiveMessageEndMessageTest.java +++ b/core/java/test/net/i2p/data/ReceiveMessageEndMessageTest.java @@ -22,8 +22,8 @@ import net.i2p.data.i2cp.SessionId; public class ReceiveMessageEndMessageTest extends StructureTest { public DataStructure createDataStructure() throws DataFormatException { ReceiveMessageEndMessage msg = new ReceiveMessageEndMessage(); - msg.setSessionId((SessionId)(new SessionIdTest()).createDataStructure()); - msg.setMessageId((MessageId)(new MessageIdTest()).createDataStructure()); + msg.setSessionId(321); + msg.setMessageId(123); return msg; } public DataStructure createStructureToRead() { return new ReceiveMessageEndMessage(); } diff --git a/history.txt b/history.txt index c30f9e23da..599496efa2 100644 --- a/history.txt +++ b/history.txt @@ -1,4 +1,23 @@ -$Id: history.txt,v 1.216 2005/07/21 17:37:16 jrandom Exp $ +$Id: history.txt,v 1.217 2005/07/22 19:15:59 jrandom Exp $ + +* 2005-07-27 0.6 released + +2005-07-27 jrandom + * Enabled SSU as the default top priority transport, adjusting the + config.jsp page accordingly. + * Add verification fields to the SSU and TCP connection negotiation (not + compatible with previous builds) + * Enable the backwards incompatible tunnel crypto change as documented in + tunnel-alt.html (have each hop encrypt the received IV before using it, + then encrypt it again before sending it on) + * Disable the I2CP encryption, leaving in place the end to end garlic + encryption (another backwards incompatible change) + * Adjust the protocol versions on the TCP and SSU transports so that they + won't talk to older routers. + * Fix up the config stats handling again + * Fix a rare off-by-one in the SSU fragmentation + * Reduce some unnecessary netDb resending by inluding the peers queried + successfully in the store redundancy count. 2005-07-22 jrandom * Use the small thread pool for I2PTunnelHTTPServer (already used for diff --git a/initialNews.xml b/initialNews.xml index 95048d59f3..04c5c35ef4 100644 --- a/initialNews.xml +++ b/initialNews.xml @@ -1,12 +1,12 @@ - - + -

Congratulations on getting I2P installed!

diff --git a/installer/install.xml b/installer/install.xml index 567e9c2da1..4f4e9670fc 100644 --- a/installer/install.xml +++ b/installer/install.xml @@ -4,7 +4,7 @@ i2p - 0.5.0.7 + 0.6 diff --git a/news.xml b/news.xml index ae8936df23..bdab5b05d8 100644 --- a/news.xml +++ b/news.xml @@ -1,20 +1,15 @@ - - + -Thanks to those helping out with the SSU test - there have been lots -of updates lately, so upgrading to the latest CVS HEAD (currently -0.5.0.7-14 as of 2005/07/13) would be worthwhile, and the archived -i2pupdate.zip mentioned -before -may not always be up to date. +Welcome to the new 0.6 series of releases, using the new SSU transport!
diff --git a/readme.html b/readme.html index 88108d0cce..d1e36dc298 100644 --- a/readme.html +++ b/readme.html @@ -15,11 +15,10 @@ listed (if not, see below). Once those are up, you can:<
  • duck.i2p: duck's eepsite, with links to other active sites
  • ugha.i2p: ugha's eepsite, a wiki that anyone can edit, and lots of links
  • orion.i2p: a site which tracks eepsite uptime and changes
  • -
  • files.i2p: a search engine that tries to keep track of things on I2P
  • forum.i2p: a secure and anonymous connection to forum.i2p.net
  • www.i2p: a secure and anonymous connection to www.i2p.net
  • dev.i2p: a secure and anonymous connection to dev.i2p.net
  • -
  • Freenet proxies: fproxy.i2p and freenet.eco.i2p
  • +
  • Freenet proxies: fproxy.i2p
  • There are many more eepsites - just follow the links from the ones you see, bookmark your favorites, and visit them often! @@ -56,7 +55,7 @@ IRC (be sure to split it into two lines, as its too long for one).

    If the left hand side has a warning, telling you to check your NAT or firewall, please see the config page and make sure that you can receive inbound -TCP connections on port 8887 (or another port that you specify). Problems forwarding +TCP and UDP connections on port 8887 (or another port that you specify). Problems forwarding that port account for the vast majority of issues people run into. When it says "Active: 72/85", the "72" means how many peers you are connected with now, and "85" means how many you have spoken with recently - if that first number is 0, you can bet that there diff --git a/router/doc/tunnel-alt.html b/router/doc/tunnel-alt.html index 1b868e949d..8749e20280 100644 --- a/router/doc/tunnel-alt.html +++ b/router/doc/tunnel-alt.html @@ -1,4 +1,4 @@ -$Id: tunnel-alt.html,v 1.7 2005/02/16 19:48:18 jrandom Exp $ +$Id: tunnel-alt.html,v 1.8 2005/07/07 16:16:57 jrandom Exp $

     1) Tunnel overview
     2) Tunnel operation
    @@ -173,9 +173,12 @@ the initial preprocessed data.

    the same previous hop as before (initialized when the first message comes through the tunnel). If the previous peer is a different router, or if the message has already been seen, the message is dropped. The participant then encrypts the -data with AES256/CBC using the participant's layer key and the received IV, -updates the IV by encrypting it with AES256/ECB using the participant's IV key, -then forwards the tuple {nextTunnelId, nextIV, encryptedData} to the next hop.

    +received IV with AES256/ECB using their IV key to determine the current IV, uses +that IV with the participant's layer key to encrypt the data, encrypts the +current IV with AES256/ECB using their IV key again, then forwards the tuple +{nextTunnelId, nextIV, encryptedData} to the next hop. This double encryption +of the IV (both before and after use) help address a certain class of +confirmation attacks.

    Duplicate message detection is handled by a decaying Bloom filter on message IVs. Each router maintains a single Bloom filter to contain the XOR of the IV and diff --git a/router/doc/udp.html b/router/doc/udp.html index ac1eb92566..bafe3411d2 100644 --- a/router/doc/udp.html +++ b/router/doc/udp.html @@ -1,4 +1,4 @@ -$Id: udp.html,v 1.12 2005/04/09 18:15:53 jrandom Exp $ +$Id: udp.html,v 1.13 2005/05/01 15:08:08 jrandom Exp $

    Secure Semireliable UDP (SSU)

    DRAFT @@ -141,7 +141,7 @@ around briefly, to address packet loss and reordering.

  • 4 byte timestamp (seconds from the epoch) for use in the DSA signature
  • 40 byte DSA signature of the critical exchanged data - (Alice's IP + Alice's port + Bob's IP + Bob's port + Alice's + (X + Y + Alice's IP + Alice's port + Bob's IP + Bob's port + Alice's new relay tag + Bob's signed on time), encrypted with another layer of encryption using the negotiated sessionKey. The IV is reused here.
  • @@ -197,7 +197,7 @@ bits 4-7: total identity fragments
  • on the last identity fragment, the signed on time is included after the identity fragment, and the last 40 bytes contain the DSA signature of the critical exchanged - data (Alice's IP + Alice's port + Bob's IP + Bob's port + data (X + Y + Alice's IP + Alice's port + Bob's IP + Bob's port + Alice's new relay key + Alice's signed on time)
  • Key used: diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index 01616a7f68..679cbddcda 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -15,9 +15,9 @@ import net.i2p.CoreVersion; * */ public class RouterVersion { - public final static String ID = "$Revision: 1.207 $ $Date: 2005/07/21 17:37:15 $"; - public final static String VERSION = "0.5.0.7"; - public final static long BUILD = 19; + public final static String ID = "$Revision: 1.208 $ $Date: 2005/07/22 19:15:58 $"; + public final static String VERSION = "0.6"; + public final static long BUILD = 0; public static void main(String args[]) { System.out.println("I2P Router version: " + VERSION); System.out.println("Router ID: " + RouterVersion.ID); diff --git a/router/java/src/net/i2p/router/StatisticsManager.java b/router/java/src/net/i2p/router/StatisticsManager.java index e3983f655f..ff49f8e0d8 100644 --- a/router/java/src/net/i2p/router/StatisticsManager.java +++ b/router/java/src/net/i2p/router/StatisticsManager.java @@ -102,12 +102,12 @@ public class StatisticsManager implements Service { stats.putAll(_context.profileManager().summarizePeers(_publishedStats)); includeThroughput(stats); - includeRate("router.invalidMessageTime", stats, new long[] { 10*60*1000 }); + //includeRate("router.invalidMessageTime", stats, new long[] { 10*60*1000 }); includeRate("router.duplicateMessageId", stats, new long[] { 24*60*60*1000 }); - includeRate("tunnel.duplicateIV", stats, new long[] { 24*60*60*1000 }); + //includeRate("tunnel.duplicateIV", stats, new long[] { 24*60*60*1000 }); includeRate("tunnel.fragmentedDropped", stats, new long[] { 10*60*1000, 3*60*60*1000 }); - includeRate("tunnel.fullFragments", stats, new long[] { 10*60*1000, 3*60*60*1000 }); - includeRate("tunnel.smallFragments", stats, new long[] { 10*60*1000, 3*60*60*1000 }); + //includeRate("tunnel.fullFragments", stats, new long[] { 10*60*1000, 3*60*60*1000 }); + //includeRate("tunnel.smallFragments", stats, new long[] { 10*60*1000, 3*60*60*1000 }); includeRate("tunnel.testFailedTime", stats, new long[] { 60*60*1000 }); includeRate("tunnel.buildFailure", stats, new long[] { 60*60*1000 }); @@ -117,22 +117,26 @@ public class StatisticsManager implements Service { includeRate("tunnel.batchMultipleCount", stats, new long[] { 10*60*1000, 60*60*1000 }); includeRate("tunnel.corruptMessage", stats, new long[] { 60*60*1000l, 3*60*60*1000l }); - includeRate("router.throttleTunnelProbTestSlow", stats, new long[] { 60*60*1000 }); - includeRate("router.throttleTunnelProbTooFast", stats, new long[] { 60*60*1000 }); - includeRate("router.throttleTunnelProcessingTime1m", stats, new long[] { 60*60*1000 }); + //includeRate("router.throttleTunnelProbTestSlow", stats, new long[] { 60*60*1000 }); + //includeRate("router.throttleTunnelProbTooFast", stats, new long[] { 60*60*1000 }); + //includeRate("router.throttleTunnelProcessingTime1m", stats, new long[] { 60*60*1000 }); includeRate("router.fastPeers", stats, new long[] { 60*60*1000 }); includeRate("clock.skew", stats, new long[] { 10*60*1000, 3*60*60*1000, 24*60*60*1000 }); - includeRate("transport.sendProcessingTime", stats, new long[] { 60*60*1000 }); - includeRate("jobQueue.jobRunSlow", stats, new long[] { 10*60*1000l, 60*60*1000l }); + //includeRate("transport.sendProcessingTime", stats, new long[] { 60*60*1000 }); + //includeRate("jobQueue.jobRunSlow", stats, new long[] { 10*60*1000l, 60*60*1000l }); includeRate("crypto.elGamal.encrypt", stats, new long[] { 60*60*1000 }); includeRate("tunnel.participatingTunnels", stats, new long[] { 5*60*1000, 60*60*1000 }); includeRate("tunnel.testSuccessTime", stats, new long[] { 60*60*1000l, 24*60*60*1000l }); includeRate("client.sendAckTime", stats, new long[] { 60*60*1000 }, true); - includeRate("stream.con.sendDuplicateSize", stats, new long[] { 60*60*1000 }); - includeRate("stream.con.receiveDuplicateSize", stats, new long[] { 60*60*1000 }); + includeRate("udp.sendConfirmTime", stats, new long[] { 10*60*1000 }); + includeRate("udp.sendVolleyTime", stats, new long[] { 10*60*1000 }); + includeRate("udp.ignoreRecentDuplicate", stats, new long[] { 10*60*1000 }); + includeRate("udp.congestionOccurred", stats, new long[] { 10*60*1000 }); + //includeRate("stream.con.sendDuplicateSize", stats, new long[] { 60*60*1000 }); + //includeRate("stream.con.receiveDuplicateSize", stats, new long[] { 60*60*1000 }); stats.setProperty("stat_uptime", DataHelper.formatDuration(_context.router().getUptime())); stats.setProperty("stat__rateKey", "avg;maxAvg;pctLifetime;[sat;satLim;maxSat;maxSatLim;][num;lifetimeFreq;maxFreq]"); _log.debug("Publishing peer rankings"); diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/StoreJob.java b/router/java/src/net/i2p/router/networkdb/kademlia/StoreJob.java index a8359e09fa..dcdd7405f0 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/StoreJob.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/StoreJob.java @@ -281,7 +281,7 @@ class StoreJob extends JobImpl { getContext().profileManager().dbStoreSent(_peer.getIdentity().getHash(), howLong); getContext().statManager().addRateData("netDb.ackTime", howLong, howLong); - if (_state.getSuccessful().size() >= REDUNDANCY) { + if (_state.getCompleteCount() >= REDUNDANCY) { succeed(); } else { sendNext(); diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/StoreState.java b/router/java/src/net/i2p/router/networkdb/kademlia/StoreState.java index 584f3eb3a4..12520f992f 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/StoreState.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/StoreState.java @@ -21,6 +21,7 @@ class StoreState { private HashSet _successfulExploratoryPeers; private HashSet _failedPeers; private HashSet _attemptedPeers; + private int _completeCount; private volatile long _completed; private volatile long _started; @@ -34,8 +35,10 @@ class StoreState { _pendingPeers = new HashSet(16); _pendingPeerTimes = new HashMap(16); _attemptedPeers = new HashSet(16); - if (toSkip != null) + if (toSkip != null) { _attemptedPeers.addAll(toSkip); + _completeCount = toSkip.size(); + } _failedPeers = new HashSet(16); _successfulPeers = new HashSet(16); _successfulExploratoryPeers = new HashSet(16); @@ -75,6 +78,7 @@ class StoreState { if (completed) _completed = _context.clock().now(); } + public int getCompleteCount() { return _completeCount; } public long getWhenStarted() { return _started; } public long getWhenCompleted() { return _completed; } @@ -110,6 +114,7 @@ class StoreState { synchronized (_successfulPeers) { _successfulPeers.add(peer); } + _completeCount++; return rv; } diff --git a/router/java/src/net/i2p/router/transport/TransportManager.java b/router/java/src/net/i2p/router/transport/TransportManager.java index 8db02b63b9..551c9b9f35 100644 --- a/router/java/src/net/i2p/router/transport/TransportManager.java +++ b/router/java/src/net/i2p/router/transport/TransportManager.java @@ -34,6 +34,7 @@ public class TransportManager implements TransportEventListener { private final static String PROP_DISABLE_TCP = "i2np.tcp.disable"; private final static String PROP_ENABLE_UDP = "i2np.udp.enable"; + private static final String DEFAULT_ENABLE_UDP = "true"; public TransportManager(RouterContext context) { _context = context; @@ -63,7 +64,9 @@ public class TransportManager implements TransportEventListener { _transports.add(t); } String enableUDP = _context.router().getConfigSetting(PROP_ENABLE_UDP); - if ( (enableUDP != null) && (Boolean.valueOf(enableUDP).booleanValue())) { + if (enableUDP == null) + enableUDP = DEFAULT_ENABLE_UDP; + if ("true".equalsIgnoreCase(enableUDP)) { UDPTransport udp = new UDPTransport(_context); udp.setListener(this); _transports.add(udp); diff --git a/router/java/src/net/i2p/router/transport/tcp/ConnectionBuilder.java b/router/java/src/net/i2p/router/transport/tcp/ConnectionBuilder.java index c039210510..62ad79c184 100644 --- a/router/java/src/net/i2p/router/transport/tcp/ConnectionBuilder.java +++ b/router/java/src/net/i2p/router/transport/tcp/ConnectionBuilder.java @@ -529,8 +529,12 @@ public class ConnectionBuilder { return false; } + // our public == X, since we are establishing the connection + byte X[] = builder.getMyPublicValueBytes(); + byte Y[] = builder.getPeerPublicValueBytes(); + // send: routerInfo + currentTime - // + S(routerInfo + currentTime + nonce + nextTag, routerIdent.signingKey) + // + S(routerInfo + currentTime + nonce + nextTag + X + Y, routerIdent.signingKey) try { ByteArrayOutputStream baos = new ByteArrayOutputStream(512); _context.router().getRouterInfo().writeBytes(baos); @@ -540,6 +544,8 @@ public class ConnectionBuilder { baos.write(_nonce.getData()); baos.write(_nextConnectionTag.getData()); + baos.write(X); + baos.write(Y); Signature sig = _context.dsa().sign(baos.toByteArray(), _context.keyManager().getSigningPrivateKey()); @@ -556,7 +562,7 @@ public class ConnectionBuilder { } // read: routerInfo + status + properties - // + S(routerInfo + status + properties + nonce + nextTag, routerIdent.signingKey) + // + S(routerInfo + status + properties + nonce + nextTag + X + Y, routerIdent.signingKey) try { RouterInfo peer = new RouterInfo(); peer.readBytes(_rawIn); @@ -578,6 +584,8 @@ public class ConnectionBuilder { DataHelper.writeProperties(baos, props); baos.write(_nonce.getData()); baos.write(_nextConnectionTag.getData()); + baos.write(X); + baos.write(Y); ok = _context.dsa().verifySignature(sig, baos.toByteArray(), peer.getIdentity().getSigningPublicKey()); diff --git a/router/java/src/net/i2p/router/transport/tcp/ConnectionHandler.java b/router/java/src/net/i2p/router/transport/tcp/ConnectionHandler.java index 249a3265f7..e12f45ad54 100644 --- a/router/java/src/net/i2p/router/transport/tcp/ConnectionHandler.java +++ b/router/java/src/net/i2p/router/transport/tcp/ConnectionHandler.java @@ -555,8 +555,12 @@ public class ConnectionHandler { long clockSkew = 0; boolean sigOk = false; + // our public == Y, since we are receiving the connection + byte X[] = builder.getPeerPublicValueBytes(); + byte Y[] = builder.getMyPublicValueBytes(); + // read: routerInfo + currentTime - // + S(routerInfo + currentTime + nonce + nextTag, routerIdent.signingKey) + // + S(routerInfo + currentTime + nonce + nextTag + X + Y, routerIdent.signingKey) try { RouterInfo info = new RouterInfo(); info.readBytes(_rawIn); @@ -569,6 +573,8 @@ public class ConnectionHandler { DataHelper.writeDate(baos, now); baos.write(_nonce.getData()); baos.write(_nextConnectionTag.getData()); + baos.write(X); + baos.write(Y); sigOk = _context.dsa().verifySignature(sig, baos.toByteArray(), info.getIdentity().getSigningPublicKey()); @@ -589,7 +595,7 @@ public class ConnectionHandler { boolean reachable = verifyReachability(); // send: routerInfo + status + properties - // + S(routerInfo + status + properties + nonce + nextTag, routerIdent.signingKey) + // + S(routerInfo + status + properties + nonce + nextTag + X + Y, routerIdent.signingKey) try { ByteArrayOutputStream baos = new ByteArrayOutputStream(512); _context.router().getRouterInfo().writeBytes(baos); @@ -629,6 +635,8 @@ public class ConnectionHandler { baos.write(_nonce.getData()); baos.write(_nextConnectionTag.getData()); + baos.write(X); + baos.write(Y); Signature sig = _context.dsa().sign(baos.toByteArray(), _context.keyManager().getSigningPrivateKey()); diff --git a/router/java/src/net/i2p/router/transport/tcp/TCPTransport.java b/router/java/src/net/i2p/router/transport/tcp/TCPTransport.java index d6052d0382..d2ca97c075 100644 --- a/router/java/src/net/i2p/router/transport/tcp/TCPTransport.java +++ b/router/java/src/net/i2p/router/transport/tcp/TCPTransport.java @@ -89,7 +89,7 @@ public class TCPTransport extends TransportImpl { public static final int DEFAULT_ESTABLISHERS = 3; /** Ordered list of supported I2NP protocols */ - public static final int[] SUPPORTED_PROTOCOLS = new int[] { 4 }; // drop <= 0.5.0.3 + public static final int[] SUPPORTED_PROTOCOLS = new int[] { 5 }; // drop < 0.6 /** blah, people shouldnt use defaults... */ public static final int DEFAULT_LISTEN_PORT = 8887; diff --git a/router/java/src/net/i2p/router/transport/udp/ACKSender.java b/router/java/src/net/i2p/router/transport/udp/ACKSender.java index e3d424ee29..e788213f9a 100644 --- a/router/java/src/net/i2p/router/transport/udp/ACKSender.java +++ b/router/java/src/net/i2p/router/transport/udp/ACKSender.java @@ -98,7 +98,8 @@ public class ACKSender implements Runnable { if ( (ackBitfields != null) && (ackBitfields.size() > 0) ) { _context.statManager().addRateData("udp.sendACKCount", ackBitfields.size(), 0); - _context.statManager().addRateData("udp.sendACKRemaining", remaining, 0); + if (remaining > 0) + _context.statManager().addRateData("udp.sendACKRemaining", remaining, 0); now = _context.clock().now(); if (lastSend < 0) lastSend = now - 1; diff --git a/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java b/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java index b464ff6d65..76cd9a488f 100644 --- a/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java +++ b/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java @@ -63,8 +63,7 @@ public class EstablishmentManager { /** * Grab the active establishing state */ - InboundEstablishState getInboundState(InetAddress fromHost, int fromPort) { - RemoteHostId from = new RemoteHostId(fromHost.getAddress(), fromPort); + InboundEstablishState getInboundState(RemoteHostId from) { synchronized (_inboundStates) { InboundEstablishState state = (InboundEstablishState)_inboundStates.get(from); if ( (state == null) && (_log.shouldLog(Log.DEBUG)) ) @@ -73,8 +72,7 @@ public class EstablishmentManager { } } - OutboundEstablishState getOutboundState(InetAddress fromHost, int fromPort) { - RemoteHostId from = new RemoteHostId(fromHost.getAddress(), fromPort); + OutboundEstablishState getOutboundState(RemoteHostId from) { synchronized (_outboundStates) { OutboundEstablishState state = (OutboundEstablishState)_outboundStates.get(from); if ( (state == null) && (_log.shouldLog(Log.DEBUG)) ) @@ -121,12 +119,12 @@ public class EstablishmentManager { * Got a SessionRequest (initiates an inbound establishment) * */ - void receiveSessionRequest(RemoteHostId from, InetAddress host, int port, UDPPacketReader reader) { + void receiveSessionRequest(RemoteHostId from, UDPPacketReader reader) { InboundEstablishState state = null; synchronized (_inboundStates) { state = (InboundEstablishState)_inboundStates.get(from); if (state == null) { - state = new InboundEstablishState(_context, host, port, _transport.getLocalPort()); + state = new InboundEstablishState(_context, from.getIP(), from.getPort(), _transport.getLocalPort()); _inboundStates.put(from, state); } } diff --git a/router/java/src/net/i2p/router/transport/udp/InboundEstablishState.java b/router/java/src/net/i2p/router/transport/udp/InboundEstablishState.java index 8f426f442b..f39f67d473 100644 --- a/router/java/src/net/i2p/router/transport/udp/InboundEstablishState.java +++ b/router/java/src/net/i2p/router/transport/udp/InboundEstablishState.java @@ -66,10 +66,10 @@ public class InboundEstablishState { /** we have completely received all of the confirmation packets */ public static final int STATE_CONFIRMED_COMPLETELY = 4; - public InboundEstablishState(RouterContext ctx, InetAddress remoteHost, int remotePort, int localPort) { + public InboundEstablishState(RouterContext ctx, byte remoteIP[], int remotePort, int localPort) { _context = ctx; _log = ctx.logManager().getLog(InboundEstablishState.class); - _aliceIP = remoteHost.getAddress(); + _aliceIP = remoteIP; _alicePort = remotePort; _remoteHostId = new RemoteHostId(_aliceIP, _alicePort); _bobPort = localPort; @@ -141,7 +141,8 @@ public class InboundEstablishState { * new relay tag + Bob's signed on time */ private void signSessionCreated() { - byte signed[] = new byte[_aliceIP.length + 2 + byte signed[] = new byte[256 + 256 // X + Y + + _aliceIP.length + 2 + _bobIP.length + 2 + 4 // sent relay tag + 4 // signed on time @@ -149,6 +150,12 @@ public class InboundEstablishState { _sentSignedOnTime = _context.clock().now() / 1000; int off = 0; + System.arraycopy(_receivedX, 0, signed, off, _receivedX.length); + off += _receivedX.length; + if (_sentY == null) + _sentY = getSentY(); + System.arraycopy(_sentY, 0, signed, off, _sentY.length); + off += _sentY.length; System.arraycopy(_aliceIP, 0, signed, off, _aliceIP.length); off += _aliceIP.length; DataHelper.toLong(signed, off, 2, _alicePort); @@ -166,6 +173,8 @@ public class InboundEstablishState { if (_log.shouldLog(Log.DEBUG)) { StringBuffer buf = new StringBuffer(128); buf.append("Signing sessionCreated:"); + buf.append(" ReceivedX: ").append(Base64.encode(_receivedX)); + buf.append(" SentY: ").append(Base64.encode(_sentY)); buf.append(" AliceIP: ").append(Base64.encode(_aliceIP)); buf.append(" AlicePort: ").append(_alicePort); buf.append(" BobIP: ").append(Base64.encode(_bobIP)); @@ -266,13 +275,18 @@ public class InboundEstablishState { try { peer.readBytes(in); - byte signed[] = new byte[_aliceIP.length + 2 + byte signed[] = new byte[256+256 // X + Y + + _aliceIP.length + 2 + _bobIP.length + 2 + 4 // Alice's relay key + 4 // signed on time ]; off = 0; + System.arraycopy(_receivedX, 0, signed, off, _receivedX.length); + off += _receivedX.length; + System.arraycopy(_sentY, 0, signed, off, _sentY.length); + off += _sentY.length; System.arraycopy(_aliceIP, 0, signed, off, _aliceIP.length); off += _aliceIP.length; DataHelper.toLong(signed, off, 2, _alicePort); diff --git a/router/java/src/net/i2p/router/transport/udp/InboundMessageFragments.java b/router/java/src/net/i2p/router/transport/udp/InboundMessageFragments.java index 91d181b695..d5e534f374 100644 --- a/router/java/src/net/i2p/router/transport/udp/InboundMessageFragments.java +++ b/router/java/src/net/i2p/router/transport/udp/InboundMessageFragments.java @@ -152,7 +152,8 @@ public class InboundMessageFragments /*implements UDPTransport.PartialACKSource _log.info("Message received completely! " + state); _context.statManager().addRateData("udp.receivedCompleteTime", state.getLifetime(), state.getLifetime()); - _context.statManager().addRateData("udp.receivedCompleteFragments", state.getFragmentCount(), state.getLifetime()); + if (state.getFragmentCount() > 0) + _context.statManager().addRateData("udp.receivedCompleteFragments", state.getFragmentCount(), state.getLifetime()); } else if (messageExpired) { state.releaseResources(); if (_log.shouldLog(Log.WARN)) diff --git a/router/java/src/net/i2p/router/transport/udp/OutboundEstablishState.java b/router/java/src/net/i2p/router/transport/udp/OutboundEstablishState.java index f976973933..b64b796174 100644 --- a/router/java/src/net/i2p/router/transport/udp/OutboundEstablishState.java +++ b/router/java/src/net/i2p/router/transport/udp/OutboundEstablishState.java @@ -234,13 +234,18 @@ public class OutboundEstablishState { * new relay tag + Bob's signed on time */ private boolean verifySessionCreated() { - byte signed[] = new byte[_aliceIP.length + 2 + byte signed[] = new byte[256+256 // X + Y + + _aliceIP.length + 2 + _bobIP.length + 2 + 4 // sent relay tag + 4 // signed on time ]; int off = 0; + System.arraycopy(_sentX, 0, signed, off, _sentX.length); + off += _sentX.length; + System.arraycopy(_receivedY, 0, signed, off, _receivedY.length); + off += _receivedY.length; System.arraycopy(_aliceIP, 0, signed, off, _aliceIP.length); off += _aliceIP.length; DataHelper.toLong(signed, off, 2, _alicePort); @@ -287,7 +292,8 @@ public class OutboundEstablishState { public synchronized void prepareSessionConfirmed() { if (_sentSignedOnTime > 0) return; - byte signed[] = new byte[_aliceIP.length + 2 + byte signed[] = new byte[256+256 // X + Y + + _aliceIP.length + 2 + _bobIP.length + 2 + 4 // Alice's relay key + 4 // signed on time @@ -296,6 +302,10 @@ public class OutboundEstablishState { _sentSignedOnTime = _context.clock().now() / 1000; int off = 0; + System.arraycopy(_sentX, 0, signed, off, _sentX.length); + off += _sentX.length; + System.arraycopy(_receivedY, 0, signed, off, _receivedY.length); + off += _receivedY.length; System.arraycopy(_aliceIP, 0, signed, off, _aliceIP.length); off += _aliceIP.length; DataHelper.toLong(signed, off, 2, _alicePort); diff --git a/router/java/src/net/i2p/router/transport/udp/OutboundMessageFragments.java b/router/java/src/net/i2p/router/transport/udp/OutboundMessageFragments.java index da8f28af66..b20fccd5f3 100644 --- a/router/java/src/net/i2p/router/transport/udp/OutboundMessageFragments.java +++ b/router/java/src/net/i2p/router/transport/udp/OutboundMessageFragments.java @@ -35,7 +35,7 @@ public class OutboundMessageFragments { /** if we can handle more messages explicitly, set this to true */ private boolean _allowExcess; - private static final int MAX_ACTIVE = 16; + private static final int MAX_ACTIVE = 32; // don't send a packet more than 10 times static final int MAX_VOLLEYS = 10; @@ -414,8 +414,10 @@ public class OutboundMessageFragments { _log.info("Received ack of " + messageId + " by " + ackedBy.toBase64() + " after " + state.getLifetime() + " and " + numSends + " sends"); _context.statManager().addRateData("udp.sendConfirmTime", state.getLifetime(), state.getLifetime()); - _context.statManager().addRateData("udp.sendConfirmFragments", state.getFragmentCount(), state.getLifetime()); - _context.statManager().addRateData("udp.sendConfirmVolley", numSends, state.getFragmentCount()); + if (state.getFragmentCount() > 1) + _context.statManager().addRateData("udp.sendConfirmFragments", state.getFragmentCount(), state.getLifetime()); + if (numSends > 1) + _context.statManager().addRateData("udp.sendConfirmVolley", numSends, state.getFragmentCount()); _transport.succeeded(state.getMessage()); int numFragments = state.getFragmentCount(); if (state.getPeer() != null) { @@ -494,8 +496,10 @@ public class OutboundMessageFragments { if (isComplete) { _context.statManager().addRateData("udp.sendConfirmTime", state.getLifetime(), state.getLifetime()); - _context.statManager().addRateData("udp.sendConfirmFragments", state.getFragmentCount(), state.getLifetime()); - _context.statManager().addRateData("udp.sendConfirmVolley", numSends, state.getFragmentCount()); + if (state.getFragmentCount() > 1) + _context.statManager().addRateData("udp.sendConfirmFragments", state.getFragmentCount(), state.getLifetime()); + if (numSends > 1) + _context.statManager().addRateData("udp.sendConfirmVolley", numSends, state.getFragmentCount()); _transport.succeeded(state.getMessage()); if (state.getPeer() != null) { diff --git a/router/java/src/net/i2p/router/transport/udp/OutboundMessageState.java b/router/java/src/net/i2p/router/transport/udp/OutboundMessageState.java index 7ac9bf77d5..b955904e0b 100644 --- a/router/java/src/net/i2p/router/transport/udp/OutboundMessageState.java +++ b/router/java/src/net/i2p/router/transport/udp/OutboundMessageState.java @@ -225,10 +225,15 @@ public class OutboundMessageState { public boolean shouldSend(int fragmentNum) { return _fragmentSends[fragmentNum] >= (short)0; } public int fragmentSize(int fragmentNum) { if (_messageBuf == null) return -1; - if (fragmentNum + 1 == _fragmentSends.length) - return _messageBuf.getValid() % _fragmentSize; - else + if (fragmentNum + 1 == _fragmentSends.length) { + int valid = _messageBuf.getValid(); + if (valid <= _fragmentSize) + return valid; + else + return valid % _fragmentSize; + } else { return _fragmentSize; + } } /** @@ -241,10 +246,8 @@ public class OutboundMessageState { */ public int writeFragment(byte out[], int outOffset, int fragmentNum) { int start = _fragmentSize * fragmentNum; - int end = start + _fragmentSize; + int end = start + fragmentSize(fragmentNum); if (_messageBuf == null) return -1; - if (end > _messageBuf.getValid()) - end = _messageBuf.getValid(); int toSend = end - start; System.arraycopy(_messageBuf.getData(), start, out, outOffset, toSend); if (_log.shouldLog(Log.DEBUG)) diff --git a/router/java/src/net/i2p/router/transport/udp/PacketHandler.java b/router/java/src/net/i2p/router/transport/udp/PacketHandler.java index 278762ee29..503b8d5995 100644 --- a/router/java/src/net/i2p/router/transport/udp/PacketHandler.java +++ b/router/java/src/net/i2p/router/transport/udp/PacketHandler.java @@ -100,13 +100,12 @@ public class PacketHandler { private void handlePacket(UDPPacketReader reader, UDPPacket packet) { if (packet == null) return; - InetAddress remAddr = packet.getPacket().getAddress(); - int remPort = packet.getPacket().getPort(); - PeerState state = _transport.getPeerState(remAddr, remPort); + RemoteHostId rem = packet.getRemoteHost(); + PeerState state = _transport.getPeerState(rem); if (state == null) { if (_log.shouldLog(Log.DEBUG)) _log.debug("Packet received is not for a connected peer"); - InboundEstablishState est = _establisher.getInboundState(remAddr, remPort); + InboundEstablishState est = _establisher.getInboundState(rem); if (est != null) { if (_log.shouldLog(Log.DEBUG)) _log.debug("Packet received IS for an inbound establishment"); @@ -114,7 +113,7 @@ public class PacketHandler { } else { if (_log.shouldLog(Log.DEBUG)) _log.debug("Packet received is not for an inbound establishment"); - OutboundEstablishState oest = _establisher.getOutboundState(remAddr, remPort); + OutboundEstablishState oest = _establisher.getOutboundState(rem); if (oest != null) { if (_log.shouldLog(Log.DEBUG)) _log.debug("Packet received IS for an outbound establishment"); @@ -152,9 +151,7 @@ public class PacketHandler { _log.info("Validation with existing con failed, but validation as reestablish/stray passed"); packet.decrypt(_transport.getIntroKey()); } else { - InetAddress remAddr = packet.getPacket().getAddress(); - int remPort = packet.getPacket().getPort(); - InboundEstablishState est = _establisher.getInboundState(remAddr, remPort); + InboundEstablishState est = _establisher.getInboundState(packet.getRemoteHost()); if (est != null) { if (_log.shouldLog(Log.DEBUG)) _log.debug("Packet from an existing peer IS for an inbound establishment"); @@ -304,13 +301,14 @@ public class PacketHandler { _context.statManager().addRateData("udp.receivePacketSkew", skew, packet.getLifetime()); - InetAddress fromHost = packet.getPacket().getAddress(); - int fromPort = packet.getPacket().getPort(); - RemoteHostId from = new RemoteHostId(fromHost.getAddress(), fromPort); + //InetAddress fromHost = packet.getPacket().getAddress(); + //int fromPort = packet.getPacket().getPort(); + //RemoteHostId from = new RemoteHostId(fromHost.getAddress(), fromPort); + RemoteHostId from = packet.getRemoteHost(); switch (reader.readPayloadType()) { case UDPPacket.PAYLOAD_TYPE_SESSION_REQUEST: - _establisher.receiveSessionRequest(from, fromHost, fromPort, reader); + _establisher.receiveSessionRequest(from, reader); break; case UDPPacket.PAYLOAD_TYPE_SESSION_CONFIRMED: _establisher.receiveSessionConfirmed(from, reader); diff --git a/router/java/src/net/i2p/router/transport/udp/PeerState.java b/router/java/src/net/i2p/router/transport/udp/PeerState.java index 2d8c82ce30..0b36f8af81 100644 --- a/router/java/src/net/i2p/router/transport/udp/PeerState.java +++ b/router/java/src/net/i2p/router/transport/udp/PeerState.java @@ -541,10 +541,11 @@ public class PeerState { } } - _context.statManager().addRateData("udp.sendACKPartial", partialIncluded, rv.size() - partialIncluded); _lastACKSend = _context.clock().now(); if (rv == null) rv = Collections.EMPTY_LIST; + if (partialIncluded > 0) + _context.statManager().addRateData("udp.sendACKPartial", partialIncluded, rv.size() - partialIncluded); return rv; } diff --git a/router/java/src/net/i2p/router/transport/udp/UDPEndpoint.java b/router/java/src/net/i2p/router/transport/udp/UDPEndpoint.java index df8b334c18..21fe37b9d3 100644 --- a/router/java/src/net/i2p/router/transport/udp/UDPEndpoint.java +++ b/router/java/src/net/i2p/router/transport/udp/UDPEndpoint.java @@ -37,7 +37,7 @@ public class UDPEndpoint { _receiver.startup(); } catch (SocketException se) { if (_log.shouldLog(Log.ERROR)) - _log.error("Unable to bind on " + _listenPort); + _log.error("Unable to bind on " + _listenPort, se); } } @@ -45,11 +45,10 @@ public class UDPEndpoint { if (_sender != null) { _sender.shutdown(); _receiver.shutdown(); - _sender = null; - _receiver = null; } } + public void setListenPort(int newPort) { _listenPort = newPort; } public void updateListenPort(int newPort) { if (newPort == _listenPort) return; try { diff --git a/router/java/src/net/i2p/router/transport/udp/UDPPacket.java b/router/java/src/net/i2p/router/transport/udp/UDPPacket.java index ac7f600108..3443c50262 100644 --- a/router/java/src/net/i2p/router/transport/udp/UDPPacket.java +++ b/router/java/src/net/i2p/router/transport/udp/UDPPacket.java @@ -32,6 +32,7 @@ public class UDPPacket { private volatile byte[] _data; private volatile ByteArray _dataBuf; private volatile int _markedType; + private volatile RemoteHostId _remoteHost; private volatile boolean _released; private volatile Exception _releasedBy; private volatile Exception _acquiredBy; @@ -78,6 +79,7 @@ public class UDPPacket { _packet = new DatagramPacket(_data, MAX_PACKET_SIZE); _initializeTime = _context.clock().now(); _markedType = -1; + _remoteHost = null; } public void initialize(int priority, long expiration, InetAddress host, int port) { @@ -88,6 +90,7 @@ public class UDPPacket { //_packet.setLength(0); _packet.setAddress(host); _packet.setPort(port); + _remoteHost = null; _released = false; _releasedBy = null; } @@ -113,6 +116,12 @@ public class UDPPacket { */ public int getMarkedType() { verifyNotReleased(); return _markedType; } + public RemoteHostId getRemoteHost() { + if (_remoteHost == null) + _remoteHost = new RemoteHostId(_packet.getAddress().getAddress(), _packet.getPort()); + return _remoteHost; + } + /** * Validate the packet against the MAC specified, returning true if the * MAC matches, false otherwise. diff --git a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java index 63c8200139..4d00eb6fd3 100644 --- a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java +++ b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java @@ -75,7 +75,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority /** shared slow bid for unconnected peers when we want to prefer UDP */ private TransportBid _slowPreferredBid; - public static final String STYLE = "SSUv1"; + public static final String STYLE = "SSU"; public static final String PROP_INTERNAL_PORT = "i2np.udp.internalPort"; /** define this to explicitly set an external IP address */ @@ -85,11 +85,12 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority /** * If i2np.udp.alwaysPreferred is set, the UDP bids will always be under * the bid from the TCP transport - even if a TCP connection already - * exists. The default is to prefer UDP unless no UDP session exists and - * a TCP connection already exists. + * exists. If this is true (the default), it will always prefer UDP, otherwise + * it will prefer UDP unless no UDP session exists and a TCP connection + * already exists. */ public static final String PROP_ALWAYS_PREFER_UDP = "i2np.udp.alwaysPreferred"; - + private static final String DEFAULT_ALWAYS_PREFER_UDP = "true"; /** how many relays offered to us will we use at a time? */ public static final int PUBLIC_RELAY_COUNT = 3; @@ -154,29 +155,35 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority rebuildExternalAddress(); - if (_endpoint == null) { - int port = -1; - if (_externalListenPort <= 0) { - // no explicit external port, so lets try an internal one - String portStr = _context.getProperty(PROP_INTERNAL_PORT); - if (portStr != null) { - try { - port = Integer.parseInt(portStr); - } catch (NumberFormatException nfe) { - if (_log.shouldLog(Log.ERROR)) - _log.error("Invalid port specified [" + portStr + "]"); - } + int port = -1; + if (_externalListenPort <= 0) { + // no explicit external port, so lets try an internal one + String portStr = _context.getProperty(PROP_INTERNAL_PORT); + if (portStr != null) { + try { + port = Integer.parseInt(portStr); + } catch (NumberFormatException nfe) { + if (_log.shouldLog(Log.ERROR)) + _log.error("Invalid port specified [" + portStr + "]"); } - if (port <= 0) { - port = 1024 + _context.random().nextInt(31*1024); - if (_log.shouldLog(Log.INFO)) - _log.info("Selecting a random port to bind to: " + port); - } - } else { - port = _externalListenPort; - if (_log.shouldLog(Log.INFO)) - _log.info("Binding to the explicitly specified external port: " + port); } + if (port <= 0) { + port = 8887; + //port = 1024 + _context.random().nextInt(31*1024); + if (_log.shouldLog(Log.INFO)) + _log.info("Selecting an arbitrary port to bind to: " + port); + _context.router().setConfigSetting(PROP_INTERNAL_PORT, port+""); + // attempt to use it as our external port - this will be overridden by + // externalAddressReceived(...) + _context.router().setConfigSetting(PROP_EXTERNAL_PORT, port+""); + _context.router().saveConfig(); + } + } else { + port = _externalListenPort; + if (_log.shouldLog(Log.INFO)) + _log.info("Binding to the explicitly specified external port: " + port); + } + if (_endpoint == null) { try { _endpoint = new UDPEndpoint(_context, port); } catch (SocketException se) { @@ -184,6 +191,8 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority _log.log(Log.CRIT, "Unable to listen on the UDP port (" + port + ")", se); return; } + } else { + _endpoint.setListenPort(port); } if (_establisher == null) @@ -211,14 +220,14 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority } public void shutdown() { + if (_endpoint != null) + _endpoint.shutdown(); if (_flooder != null) _flooder.shutdown(); if (_refiller != null) _refiller.shutdown(); if (_handler != null) _handler.shutdown(); - if (_endpoint != null) - _endpoint.shutdown(); if (_fragments != null) _fragments.shutdown(); if (_pusher != null) @@ -268,6 +277,9 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority } } + _context.router().setConfigSetting(PROP_EXTERNAL_PORT, ourPort+""); + _context.router().saveConfig(); + if (updated) _context.router().rebuildRouterInfo(); } @@ -280,8 +292,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority * get the state for the peer at the given remote host/port, or null * if no state exists */ - public PeerState getPeerState(InetAddress remoteHost, int remotePort) { - RemoteHostId hostInfo = new RemoteHostId(remoteHost.getAddress(), remotePort); + public PeerState getPeerState(RemoteHostId hostInfo) { synchronized (_peersByRemoteHost) { return (PeerState)_peersByRemoteHost.get(hostInfo); } @@ -424,7 +435,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority } private boolean alwaysPreferUDP() { - String pref = _context.getProperty(PROP_ALWAYS_PREFER_UDP); + String pref = _context.getProperty(PROP_ALWAYS_PREFER_UDP, DEFAULT_ALWAYS_PREFER_UDP); return (pref != null) && "true".equals(pref); } diff --git a/router/java/src/net/i2p/router/tunnel/HopProcessor.java b/router/java/src/net/i2p/router/tunnel/HopProcessor.java index 5947fcc644..6a3201e0ce 100644 --- a/router/java/src/net/i2p/router/tunnel/HopProcessor.java +++ b/router/java/src/net/i2p/router/tunnel/HopProcessor.java @@ -29,7 +29,7 @@ public class HopProcessor { * and after using it at each hop so as to prevent a certain type of replay/confirmation * attack. */ - static final boolean USE_DOUBLE_IV_ENCRYPTION = false; + static final boolean USE_DOUBLE_IV_ENCRYPTION = true; static final int IV_LENGTH = 16; private static final ByteCache _cache = ByteCache.getInstance(128, IV_LENGTH);