forked from I2P_Developers/i2p.i2p
* 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:
@ -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 <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.
|
||||
* -------------------------------------------------
|
||||
* </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());
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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)) )
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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))
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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).
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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(); }
|
||||
|
@ -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);
|
||||
|
@ -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(); }
|
||||
|
@ -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(); }
|
||||
|
21
history.txt
21
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
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
15
news.xml
15
news.xml
@ -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>
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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());
|
||||
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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))
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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))
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
Reference in New Issue
Block a user