* 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.
This commit is contained in:
jrandom
2005-07-27 19:03:43 +00:00
committed by zzz
parent aeb8f02269
commit a8a866b5f6
45 changed files with 325 additions and 827 deletions

View File

@ -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.
* <p />
* <b>Implemented commands:</b>
* <pre>
* -------------------------------------------------
* lookup &lt;name&gt;\n
* --
* &lt;base64 of the destination&gt;\n
* or
* &lt;error message, usually 'Unknown host'&gt;\n
*
* Lookup the public key of a named destination (i.e. listed in hosts.txt)
* -------------------------------------------------
* genkey\n
* --
* &lt;base64 of the destination&gt;\t&lt;base64 of private data&gt;\n
*
* Generates a new public and private key pair
* -------------------------------------------------
* convertprivate &lt;base64 of privkey&gt;
* --
* &lt;base64 of destination&gt;\n
* or
* &lt;error message&gt;\n
*
* Returns the destination (pubkey) of a given private key.
* -------------------------------------------------
* listen_on &lt;ip&gt;\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 &lt;listenPort&gt; &lt;peer&gt;[ &lt;sharedClient&gt;]\n
* --
* ok [&lt;jobId&gt;]\n
* or
* ok &lt;listenPort&gt; [&lt;jobId&gt;]\n
* or
* error\n
*
* Open a tunnel on the given &lt;listenport&gt; to the destination specified
* by &lt;peer&gt;. If &lt;listenPort&gt; 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:&lt;filename&gt;' or the name of a destination listed in
* hosts.txt. The &lt;jobId&gt; returned together with "ok" and &lt;listenport&gt; can
* later be used as argument for the "close" command.
* &lt;sharedClient&gt; indicates if this httpclient shares tunnels with other
* clients or not (just use 'true' and 'false'
* -------------------------------------------------
* openhttpclient &lt;listenPort&gt; [&lt;sharedClient&gt;] [&lt;proxy&gt;]\n
* --
* ok [&lt;jobId&gt;]\n
* or
* ok &lt;listenPort&gt; [&lt;jobId&gt;]\n
* or
* error\n
*
* Open an HTTP proxy through the I2P on the given
* &lt;listenport&gt;. &lt;proxy&gt; (optional) specifies a
* destination to be used as an outbound proxy, to access normal WWW
* sites out of the .i2p domain. If &lt;listenPort&gt; is 0 a free
* port is picked and returned in the reply message. Otherwise the
* short reply message is used. &lt;proxy&gt; can be the base64 of the
* destination, a file with the public key specified as
* 'file:&lt;filename&gt;' or the name of a destination listed in
* hosts.txt. The &lt;jobId&gt; returned together with "ok" and
* &lt;listenport&gt; can later be used as argument for the "close"
* command.
* &lt;sharedClient&gt; indicates if this httpclient shares tunnels with other
* clients or not (just use 'true' and 'false'
* -------------------------------------------------
* opensockstunnel &lt;listenPort&gt;\n
* --
* ok [&lt;jobId&gt;]\n
* or
* ok &lt;listenPort&gt; [&lt;jobId&gt;]\n
* or
* error\n
*
* Open an SOCKS tunnel through the I2P on the given
* &lt;listenport&gt;. If &lt;listenPort&gt; is 0 a free port is
* picked and returned in the reply message. Otherwise the short
* reply message is used. The &lt;jobId&gt; returned together with
* "ok" and &lt;listenport&gt; can later be used as argument for the
* "close" command.
* -------------------------------------------------
* openserver &lt;serverHost&gt; &lt;serverPort&gt; &lt;serverKeys&gt;\n
* --
* ok [&lt;jobId&gt;]\n
* or
* error\n
*
* Starts receiving traffic for the destination specified by &lt;serverKeys&gt;
* and forwards it to the &lt;serverPort&gt; of &lt;serverHost&gt;.
* &lt;serverKeys&gt; is the base 64 encoded private key set of the local
* destination. The &lt;joId&gt; returned together with "ok" can later be used
* as argument for the "close" command.
* -------------------------------------------------
* close [forced] &lt;jobId&gt;\n
* or
* close [forced] all\n
* --
* ok\n
* or
* error\n
*
* Closes the job specified by &lt;jobId&gt; 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 &lt;- C:\i2pKeys\squidPriv
* [1] 8767 -&gt; HTTPClient
* [2] 7575 -&gt; file:C:\i2pKeys\squidPub
* [3] 5252 -&gt; 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.
* -------------------------------------------------
* </pre>
*
*
* @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 <name>" 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());
}
}

View File

@ -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 <hostname>", out);
} else if ("testdestination".equalsIgnoreCase(cmd)) {
if (tok.hasMoreTokens())
_mgr.processTestDestination(tok.nextToken(), out);
else
_mgr.error("Usage: testdestination <publicDestination>", out);
} else if ("convertprivate".equalsIgnoreCase(cmd)) {
if (tok.hasMoreTokens())
_mgr.processConvertPrivate(tok.nextToken(), out);
else
_mgr.error("Usage: convertprivate <privateData>", 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] <jobnumber>|all", out);
}
} else {
_mgr.processClose(closeArg, false, out);
}
} else {
_mgr.error("Usage: close [forced] <jobnumber>|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 <ip>", 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 <listenPort> <peer> <sharedClient>", 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 <listenPort> [<sharedClient>] [<proxy>]", 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 <listenPort>", 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 <listenport>", 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 <serverHost> <serverPort> <serverKeys>", out);
return;
}
serverHost = tok.nextToken();
if (!tok.hasMoreTokens()) {
_mgr.error("Usage: openserver <serverHost> <serverPort> <serverKeys>", 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 <serverHost> <serverPort> <serverKeys>", out);
return;
}
serverKeys = tok.nextToken();
_mgr.processOpenServer(serverHost, listenPort, serverKeys, out);
} else {
_mgr.unknownCommand(command, out);
}
}
}
}

View File

@ -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;
}
}

View File

@ -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)) )

View File

@ -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,27 +38,14 @@ 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);
}
}
}
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);
}
}
if (_log.shouldLog(Log.DEBUG))
_log.debug("Updated stats: " + _stats);
}
public void setExplicitFilter(String foo) { _explicitFilter = true; }
@ -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();

View File

@ -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();
}

View File

@ -28,13 +28,13 @@
<input type="hidden" name="nonce" value="<%=System.getProperty("net.i2p.router.web.ConfigNetHandler.nonce")%>" />
<input type="hidden" name="action" value="blah" />
TCP port:
<input name="port" type="text" size="4" value="<jsp:getProperty name="nethelper" property="port" />" /> <br />
UDP port: <i><jsp:getProperty name="nethelper" property="udpPort" /></i><br />
<!-- <input name="udpPort" type="text" size="5" value="<jsp:getProperty name="nethelper" property="udpPort" />" /><br /> -->
<b>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)</b><br />
TCP port: <input name="tcpPort" type="text" size="5" value="<jsp:getProperty name="nethelper" property="tcpPort" />" /> <br />
<b>You must poke a hole in your firewall or NAT (if applicable) so that you can receive inbound TCP
connections on it.</b> 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
<a href="http://www.i2p.net/roadmap">roadmap</a> and we only have so many coder-hours (but if you want
to help, please <a href="http://www.i2p.net/getinvolved">get involved!</a>)
connections on it (this requirement will be removed in i2p 0.6.1, but is necessary now)</b>
<hr />
<b>Bandwidth limiter</b><br />
@ -57,7 +57,7 @@
packets on port 123 to one of the pool.ntp.org machines (or some other SNTP server).</i>
<hr />
<input type="submit" name="save" value="Save changes" /> <input type="reset" value="Cancel" /><br />
<i>Changing the TCP port will force a 'soft restart' - dropping your connections and clients as
<i>Changing the TCP or UDP port will force a 'soft restart' - dropping your connections and clients as
if the router was stopped and restarted. <b>Please be patient</b> - it may take
a few seconds to complete.</i>
</form>
@ -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.</p>
<p>
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
<a href="configadvanced.jsp">advanced</a> config and restart the router.
</p>
</div>
</body>

View File

@ -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))

View File

@ -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);

View File

@ -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

View File

@ -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).

View File

@ -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();
try {
builder2.setPeerPublicValue(pub1);
builder1.setPeerPublicValue(pub2);
} catch (DHSessionKeyBuilder.InvalidPublicParameterException ippe) {
assertTrue(ippe.getMessage(), true);
}
SessionKey key1 = builder1.getSessionKey();
SessionKey key2 = builder2.getSessionKey();

View File

@ -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(); }

View File

@ -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);

View File

@ -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(); }

View File

@ -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(); }

View File

@ -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

View File

@ -1,12 +1,12 @@
<i2p.news date="$Date: 2005/04/06 10:43:25 $">
<i2p.release version="0.5.0.7" date="2005/04/20" minVersion="0.5.0.4"
<i2p.news date="$Date: 2005/04/20 15:14:18 $">
<i2p.release version="0.6" date="2005/07/27" minVersion="0.6"
anonurl="http://i2p/NF2RLVUxVulR3IqK0sGJR0dHQcGXAzwa6rEO4WAWYXOHw-DoZhKnlbf1nzHXwMEJoex5nFTyiNMqxJMWlY54cvU~UenZdkyQQeUSBZXyuSweflUXFqKN-y8xIoK2w9Ylq1k8IcrAFDsITyOzjUKoOPfVq34rKNDo7fYyis4kT5bAHy~2N1EVMs34pi2RFabATIOBk38Qhab57Umpa6yEoE~rbyR~suDRvD7gjBvBiIKFqhFueXsR2uSrPB-yzwAGofTXuklofK3DdKspciclTVzqbDjsk5UXfu2nTrC1agkhLyqlOfjhyqC~t1IXm-Vs2o7911k7KKLGjB4lmH508YJ7G9fLAUyjuB-wwwhejoWqvg7oWvqo4oIok8LG6ECR71C3dzCvIjY2QcrhoaazA9G4zcGMm6NKND-H4XY6tUWhpB~5GefB3YczOqMbHq4wi0O9MzBFrOJEOs3X4hwboKWANf7DT5PZKJZ5KorQPsYRSq0E3wSOsFCSsdVCKUGsAAAA/i2p/i2pupdate.sud"
publicurl="http://dev.i2p.net/i2p/i2pupdate.sud"
anonannouncement="http://i2p/NF2RLVUxVulR3IqK0sGJR0dHQcGXAzwa6rEO4WAWYXOHw-DoZhKnlbf1nzHXwMEJoex5nFTyiNMqxJMWlY54cvU~UenZdkyQQeUSBZXyuSweflUXFqKN-y8xIoK2w9Ylq1k8IcrAFDsITyOzjUKoOPfVq34rKNDo7fYyis4kT5bAHy~2N1EVMs34pi2RFabATIOBk38Qhab57Umpa6yEoE~rbyR~suDRvD7gjBvBiIKFqhFueXsR2uSrPB-yzwAGofTXuklofK3DdKspciclTVzqbDjsk5UXfu2nTrC1agkhLyqlOfjhyqC~t1IXm-Vs2o7911k7KKLGjB4lmH508YJ7G9fLAUyjuB-wwwhejoWqvg7oWvqo4oIok8LG6ECR71C3dzCvIjY2QcrhoaazA9G4zcGMm6NKND-H4XY6tUWhpB~5GefB3YczOqMbHq4wi0O9MzBFrOJEOs3X4hwboKWANf7DT5PZKJZ5KorQPsYRSq0E3wSOsFCSsdVCKUGsAAAA/pipermail/i2p/April-2005/000709.html"
publicannouncement="http://dev.i2p.net/pipermail/i2p/April-2005/000709.html" />
<i2p.notes date="2005/04/19"
anonurl="http://i2p/NF2RLVUxVulR3IqK0sGJR0dHQcGXAzwa6rEO4WAWYXOHw-DoZhKnlbf1nzHXwMEJoex5nFTyiNMqxJMWlY54cvU~UenZdkyQQeUSBZXyuSweflUXFqKN-y8xIoK2w9Ylq1k8IcrAFDsITyOzjUKoOPfVq34rKNDo7fYyis4kT5bAHy~2N1EVMs34pi2RFabATIOBk38Qhab57Umpa6yEoE~rbyR~suDRvD7gjBvBiIKFqhFueXsR2uSrPB-yzwAGofTXuklofK3DdKspciclTVzqbDjsk5UXfu2nTrC1agkhLyqlOfjhyqC~t1IXm-Vs2o7911k7KKLGjB4lmH508YJ7G9fLAUyjuB-wwwhejoWqvg7oWvqo4oIok8LG6ECR71C3dzCvIjY2QcrhoaazA9G4zcGMm6NKND-H4XY6tUWhpB~5GefB3YczOqMbHq4wi0O9MzBFrOJEOs3X4hwboKWANf7DT5PZKJZ5KorQPsYRSq0E3wSOsFCSsdVCKUGsAAAA/pipermail/i2p/April-2005/000708.html"
publicurl="http://dev.i2p.net/pipermail/i2p/April-2005/000708.html"
<i2p.notes date="2005/07/26"
anonurl="http://i2p/NF2RLVUxVulR3IqK0sGJR0dHQcGXAzwa6rEO4WAWYXOHw-DoZhKnlbf1nzHXwMEJoex5nFTyiNMqxJMWlY54cvU~UenZdkyQQeUSBZXyuSweflUXFqKN-y8xIoK2w9Ylq1k8IcrAFDsITyOzjUKoOPfVq34rKNDo7fYyis4kT5bAHy~2N1EVMs34pi2RFabATIOBk38Qhab57Umpa6yEoE~rbyR~suDRvD7gjBvBiIKFqhFueXsR2uSrPB-yzwAGofTXuklofK3DdKspciclTVzqbDjsk5UXfu2nTrC1agkhLyqlOfjhyqC~t1IXm-Vs2o7911k7KKLGjB4lmH508YJ7G9fLAUyjuB-wwwhejoWqvg7oWvqo4oIok8LG6ECR71C3dzCvIjY2QcrhoaazA9G4zcGMm6NKND-H4XY6tUWhpB~5GefB3YczOqMbHq4wi0O9MzBFrOJEOs3X4hwboKWANf7DT5PZKJZ5KorQPsYRSq0E3wSOsFCSsdVCKUGsAAAA/pipermail/i2p/2005-July/000823.html"
publicurl="http://dev.i2p.net/pipermail/i2p/2005-July/000823.html"
anonlogs="http://i2p/Nf3ab-ZFkmI-LyMt7GjgT-jfvZ3zKDl0L96pmGQXF1B82W2Bfjf0n7~288vafocjFLnQnVcmZd~-p0-Oolfo9aW2Rm-AhyqxnxyLlPBqGxsJBXjPhm1JBT4Ia8FB-VXt0BuY0fMKdAfWwN61-tj4zIcQWRxv3DFquwEf035K~Ra4SWOqiuJgTRJu7~o~DzHVljVgWIzwf8Z84cz0X33pv-mdG~~y0Bsc2qJVnYwjjR178YMcRSmNE0FVMcs6f17c6zqhMw-11qjKpY~EJfHYCx4lBWF37CD0obbWqTNUIbL~78vxqZRT3dgAgnLixog9nqTO-0Rh~NpVUZnoUi7fNR~awW5U3Cf7rU7nNEKKobLue78hjvRcWn7upHUF45QqTDuaM3yZa7OsjbcH-I909DOub2Q0Dno6vIwuA7yrysccN1sbnkwZbKlf4T6~iDdhaSLJd97QCyPOlbyUfYy9QLNExlRqKgNVJcMJRrIual~Lb1CLbnzt0uvobM57UpqSAAAA/meeting138"
publiclogs="http://www.i2p.net/meeting138" />
<h1>Congratulations on getting I2P installed!</h1>

View File

@ -4,7 +4,7 @@
<info>
<appname>i2p</appname>
<appversion>0.5.0.7</appversion>
<appversion>0.6</appversion>
<authors>
<author name="I2P" email="support@i2p.net"/>
</authors>

View File

@ -1,20 +1,15 @@
<i2p.news date="$Date: 2005/07/11 22:56:42 $">
<i2p.release version="0.5.0.7" date="2005/04/20" minVersion="0.5.0.4"
<i2p.news date="$Date: 2005/07/13 16:59:01 $">
<i2p.release version="0.7" date="2005/07/27" minVersion="0.6"
anonurl="http://i2p/NF2RLVUxVulR3IqK0sGJR0dHQcGXAzwa6rEO4WAWYXOHw-DoZhKnlbf1nzHXwMEJoex5nFTyiNMqxJMWlY54cvU~UenZdkyQQeUSBZXyuSweflUXFqKN-y8xIoK2w9Ylq1k8IcrAFDsITyOzjUKoOPfVq34rKNDo7fYyis4kT5bAHy~2N1EVMs34pi2RFabATIOBk38Qhab57Umpa6yEoE~rbyR~suDRvD7gjBvBiIKFqhFueXsR2uSrPB-yzwAGofTXuklofK3DdKspciclTVzqbDjsk5UXfu2nTrC1agkhLyqlOfjhyqC~t1IXm-Vs2o7911k7KKLGjB4lmH508YJ7G9fLAUyjuB-wwwhejoWqvg7oWvqo4oIok8LG6ECR71C3dzCvIjY2QcrhoaazA9G4zcGMm6NKND-H4XY6tUWhpB~5GefB3YczOqMbHq4wi0O9MzBFrOJEOs3X4hwboKWANf7DT5PZKJZ5KorQPsYRSq0E3wSOsFCSsdVCKUGsAAAA/i2p/i2pupdate.sud"
publicurl="http://dev.i2p.net/i2p/i2pupdate.sud"
anonannouncement="http://i2p/NF2RLVUxVulR3IqK0sGJR0dHQcGXAzwa6rEO4WAWYXOHw-DoZhKnlbf1nzHXwMEJoex5nFTyiNMqxJMWlY54cvU~UenZdkyQQeUSBZXyuSweflUXFqKN-y8xIoK2w9Ylq1k8IcrAFDsITyOzjUKoOPfVq34rKNDo7fYyis4kT5bAHy~2N1EVMs34pi2RFabATIOBk38Qhab57Umpa6yEoE~rbyR~suDRvD7gjBvBiIKFqhFueXsR2uSrPB-yzwAGofTXuklofK3DdKspciclTVzqbDjsk5UXfu2nTrC1agkhLyqlOfjhyqC~t1IXm-Vs2o7911k7KKLGjB4lmH508YJ7G9fLAUyjuB-wwwhejoWqvg7oWvqo4oIok8LG6ECR71C3dzCvIjY2QcrhoaazA9G4zcGMm6NKND-H4XY6tUWhpB~5GefB3YczOqMbHq4wi0O9MzBFrOJEOs3X4hwboKWANf7DT5PZKJZ5KorQPsYRSq0E3wSOsFCSsdVCKUGsAAAA/pipermail/i2p/2005-April/000709.html"
publicannouncement="http://dev.i2p.net/pipermail/i2p/2005-April/000709.html" />
<i2p.notes date="2005/04/19"
anonurl="http://i2p/NF2RLVUxVulR3IqK0sGJR0dHQcGXAzwa6rEO4WAWYXOHw-DoZhKnlbf1nzHXwMEJoex5nFTyiNMqxJMWlY54cvU~UenZdkyQQeUSBZXyuSweflUXFqKN-y8xIoK2w9Ylq1k8IcrAFDsITyOzjUKoOPfVq34rKNDo7fYyis4kT5bAHy~2N1EVMs34pi2RFabATIOBk38Qhab57Umpa6yEoE~rbyR~suDRvD7gjBvBiIKFqhFueXsR2uSrPB-yzwAGofTXuklofK3DdKspciclTVzqbDjsk5UXfu2nTrC1agkhLyqlOfjhyqC~t1IXm-Vs2o7911k7KKLGjB4lmH508YJ7G9fLAUyjuB-wwwhejoWqvg7oWvqo4oIok8LG6ECR71C3dzCvIjY2QcrhoaazA9G4zcGMm6NKND-H4XY6tUWhpB~5GefB3YczOqMbHq4wi0O9MzBFrOJEOs3X4hwboKWANf7DT5PZKJZ5KorQPsYRSq0E3wSOsFCSsdVCKUGsAAAA/pipermail/i2p/2005-April/000723.html"
publicurl="http://dev.i2p.net/pipermail/i2p/2005-April/000723.html"
anonurl="http://i2p/NF2RLVUxVulR3IqK0sGJR0dHQcGXAzwa6rEO4WAWYXOHw-DoZhKnlbf1nzHXwMEJoex5nFTyiNMqxJMWlY54cvU~UenZdkyQQeUSBZXyuSweflUXFqKN-y8xIoK2w9Ylq1k8IcrAFDsITyOzjUKoOPfVq34rKNDo7fYyis4kT5bAHy~2N1EVMs34pi2RFabATIOBk38Qhab57Umpa6yEoE~rbyR~suDRvD7gjBvBiIKFqhFueXsR2uSrPB-yzwAGofTXuklofK3DdKspciclTVzqbDjsk5UXfu2nTrC1agkhLyqlOfjhyqC~t1IXm-Vs2o7911k7KKLGjB4lmH508YJ7G9fLAUyjuB-wwwhejoWqvg7oWvqo4oIok8LG6ECR71C3dzCvIjY2QcrhoaazA9G4zcGMm6NKND-H4XY6tUWhpB~5GefB3YczOqMbHq4wi0O9MzBFrOJEOs3X4hwboKWANf7DT5PZKJZ5KorQPsYRSq0E3wSOsFCSsdVCKUGsAAAA/pipermail/i2p/2005-July/000823.html"
publicurl="http://dev.i2p.net/pipermail/i2p/2005-July/000823.html"
anonlogs="http://i2p/Nf3ab-ZFkmI-LyMt7GjgT-jfvZ3zKDl0L96pmGQXF1B82W2Bfjf0n7~288vafocjFLnQnVcmZd~-p0-Oolfo9aW2Rm-AhyqxnxyLlPBqGxsJBXjPhm1JBT4Ia8FB-VXt0BuY0fMKdAfWwN61-tj4zIcQWRxv3DFquwEf035K~Ra4SWOqiuJgTRJu7~o~DzHVljVgWIzwf8Z84cz0X33pv-mdG~~y0Bsc2qJVnYwjjR178YMcRSmNE0FVMcs6f17c6zqhMw-11qjKpY~EJfHYCx4lBWF37CD0obbWqTNUIbL~78vxqZRT3dgAgnLixog9nqTO-0Rh~NpVUZnoUi7fNR~awW5U3Cf7rU7nNEKKobLue78hjvRcWn7upHUF45QqTDuaM3yZa7OsjbcH-I909DOub2Q0Dno6vIwuA7yrysccN1sbnkwZbKlf4T6~iDdhaSLJd97QCyPOlbyUfYy9QLNExlRqKgNVJcMJRrIual~Lb1CLbnzt0uvobM57UpqSAAAA/meeting139"
publiclogs="http://www.i2p.net/meeting138" />
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
<a href="http://dev.i2p.net/~jrandom/ssu_test.txt">before</a>
may not always be up to date.
Welcome to the new 0.6 series of releases, using the new SSU transport!
<br />
</i2p.news>

View File

@ -15,11 +15,10 @@ listed (if not, <a href="#trouble">see below</a>). Once those are up, you can:<
<li><a href="http://duck.i2p/">duck.i2p</a>: duck's eepsite, with links to other active sites</li>
<li><a href="http://ugha.i2p/">ugha.i2p</a>: ugha's eepsite, a wiki that anyone can edit, and lots of links</li>
<li><a href="http://orion.i2p/">orion.i2p</a>: a site which tracks eepsite uptime and changes</li>
<li><a href="http://files.i2p/">files.i2p</a>: a search engine that tries to keep track of things on I2P</li>
<li><a href="http://forum.i2p/">forum.i2p</a>: a secure and anonymous connection to <a href="http://forum.i2p.net/">forum.i2p.net</a></li>
<li><a href="http://www.i2p/">www.i2p</a>: a secure and anonymous connection to <a href="http://www.i2p.net/">www.i2p.net</a></li>
<li><a href="http://dev.i2p/">dev.i2p</a>: a secure and anonymous connection to <a href="http://dev.i2p.net/">dev.i2p.net</a></li>
<li>Freenet proxies: <a href="http://fproxy.i2p/">fproxy.i2p</a> and <a href="http://freenet.eco.i2p/">freenet.eco.i2p</a></li>
<li>Freenet proxies: <a href="http://fproxy.i2p/">fproxy.i2p</a></li>
</ul>
There are many more eepsites - just follow the links from the ones you see,
bookmark your favorites, and visit them often!</li>
@ -56,7 +55,7 @@ IRC (be sure to split it into two lines, as its too long for one).</p>
<p>If the left hand side has a warning, telling you to check your NAT or firewall, please
see the <a href="/config.jsp">config page</a> and make sure that you can receive <b>inbound
TCP connections on port 8887</b> (or another port that you specify). Problems forwarding
TCP and UDP connections on port 8887</b> (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

View File

@ -1,4 +1,4 @@
<code>$Id: tunnel-alt.html,v 1.7 2005/02/16 19:48:18 jrandom Exp $</code>
<code>$Id: tunnel-alt.html,v 1.8 2005/07/07 16:16:57 jrandom Exp $</code>
<pre>
1) <a href="#tunnel.overview">Tunnel overview</a>
2) <a href="#tunnel.operation">Tunnel operation</a>
@ -173,9 +173,12 @@ the initial preprocessed data.</p>
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.</p>
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.</p>
<p>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

View File

@ -1,4 +1,4 @@
<code>$Id: udp.html,v 1.12 2005/04/09 18:15:53 jrandom Exp $</code>
<code>$Id: udp.html,v 1.13 2005/05/01 15:08:08 jrandom Exp $</code>
<h1>Secure Semireliable UDP (SSU)</h1>
<b>DRAFT</b>
@ -141,7 +141,7 @@ around briefly, to address packet loss and reordering.</p>
<li>4 byte timestamp (seconds from the epoch) for use in the DSA
signature</li>
<li>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.</li>
@ -197,7 +197,7 @@ bits 4-7: total identity fragments</pre></li>
<li>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)</li>
</ul></td></tr>
<tr><td align="right" valign="top"><b>Key used:</b></td>

View File

@ -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);

View File

@ -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");

View File

@ -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();

View File

@ -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;
}

View File

@ -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);

View File

@ -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());

View File

@ -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());

View File

@ -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;

View File

@ -98,6 +98,7 @@ public class ACKSender implements Runnable {
if ( (ackBitfields != null) && (ackBitfields.size() > 0) ) {
_context.statManager().addRateData("udp.sendACKCount", ackBitfields.size(), 0);
if (remaining > 0)
_context.statManager().addRateData("udp.sendACKRemaining", remaining, 0);
now = _context.clock().now();
if (lastSend < 0)

View File

@ -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);
}
}

View File

@ -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);

View File

@ -152,6 +152,7 @@ public class InboundMessageFragments /*implements UDPTransport.PartialACKSource
_log.info("Message received completely! " + state);
_context.statManager().addRateData("udp.receivedCompleteTime", state.getLifetime(), state.getLifetime());
if (state.getFragmentCount() > 0)
_context.statManager().addRateData("udp.receivedCompleteFragments", state.getFragmentCount(), state.getLifetime());
} else if (messageExpired) {
state.releaseResources();

View File

@ -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);

View File

@ -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,7 +414,9 @@ 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());
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();
@ -494,7 +496,9 @@ public class OutboundMessageFragments {
if (isComplete) {
_context.statManager().addRateData("udp.sendConfirmTime", state.getLifetime(), state.getLifetime());
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());

View File

@ -225,11 +225,16 @@ 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;
if (fragmentNum + 1 == _fragmentSends.length) {
int valid = _messageBuf.getValid();
if (valid <= _fragmentSize)
return valid;
else
return valid % _fragmentSize;
} else {
return _fragmentSize;
}
}
/**
* Write a part of the the message onto the specified buffer.
@ -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))

View File

@ -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);

View File

@ -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;
}

View File

@ -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 {

View File

@ -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.

View File

@ -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,7 +155,6 @@ 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
@ -168,15 +168,22 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
}
}
if (port <= 0) {
port = 1024 + _context.random().nextInt(31*1024);
port = 8887;
//port = 1024 + _context.random().nextInt(31*1024);
if (_log.shouldLog(Log.INFO))
_log.info("Selecting a random port to bind to: " + port);
_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);
}

View File

@ -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);