propagate from branch 'i2p.i2p.zzz.jetty8' (head 0a03ce60906c508b08cc84b3044954844a6ee157)

to branch 'i2p.i2p' (head d99392e09883a92b99a316b4deed0586dcf4ea5b)
This commit is contained in:
zzz
2014-02-17 14:01:13 +00:00
184 changed files with 9055 additions and 4769 deletions

View File

@@ -53,6 +53,9 @@ import java.util.StringTokenizer;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicLong;
import gnu.getopt.Getopt;
import gnu.getopt.LongOpt;
import net.i2p.I2PAppContext;
import net.i2p.I2PException;
import net.i2p.client.I2PClient;
@@ -107,18 +110,46 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
private final Set<ConnectionEventListener> listeners = new CopyOnWriteArraySet<ConnectionEventListener>();
public static void main(String[] args) throws IOException {
new I2PTunnel(args);
private static final int NOGUI = 99999;
private static final LongOpt[] longopts = new LongOpt[] {
new LongOpt("cli", LongOpt.NO_ARGUMENT, null, 'c'),
new LongOpt("die", LongOpt.NO_ARGUMENT, null, 'd'),
new LongOpt("gui", LongOpt.NO_ARGUMENT, null, 'g'),
new LongOpt("help", LongOpt.NO_ARGUMENT, null, 'h'),
new LongOpt("nocli", LongOpt.NO_ARGUMENT, null, 'w'),
new LongOpt("nogui", LongOpt.NO_ARGUMENT, null, NOGUI),
new LongOpt("wait", LongOpt.NO_ARGUMENT, null, 'w')
};
public static void main(String[] args) {
try {
new I2PTunnel(args);
} catch (IllegalArgumentException iae) {
System.err.println(iae.toString());
System.exit(1);
}
}
/**
* Standard constructor for embedded, uses args "-nocli -die" to return immediately
*/
public I2PTunnel() {
this(nocli_args);
}
/**
* See usage() for options
* @throws IllegalArgumentException
*/
public I2PTunnel(String[] args) {
this(args, null);
}
/**
* See usage() for options
* @param lsnr may be null
* @throws IllegalArgumentException
*/
public I2PTunnel(String[] args, ConnectionEventListener lsnr) {
super();
_context = I2PAppContext.getGlobalContext(); // new I2PAppContext();
@@ -134,37 +165,95 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
boolean checkRunByE = true;
boolean cli = true;
boolean dontDie = true;
for (int i = 0; i < args.length; i++) {
if (args[i].equals("-die")) {
boolean error = false;
List<String> eargs = null;
Getopt g = new Getopt("i2ptunnel", args, "d::n:c::w::e:h::", longopts);
int c;
while ((c = g.getopt()) != -1) {
switch (c) {
case 'd': // -d, -die, --die
dontDie = false;
gui = false;
cli = false;
checkRunByE = false;
} else if (args[i].equals("-nogui")) {
break;
case 'n': // -noc, -nog, -nocli, -nogui
String a = g.getOptarg();
if (a.startsWith("oc")) {
gui = false;
cli = false;
checkRunByE = false;
break;
} else if (a.startsWith("og")) {
// fall thru
} else {
error = true;
break;
}
// fall thru for -nogui only
case NOGUI: // --nogui
gui = false;
_log.warn(getPrefix() + "The `-nogui' option of I2PTunnel is deprecated.\n"
if (_log.shouldLog(Log.WARN))
_log.warn(getPrefix() + "The `-nogui' option of I2PTunnel is deprecated.\n"
+ "Use `-cli', `-nocli' (aka `-wait') or `-die' instead.");
} else if (args[i].equals("-cli")) {
case 'c': // -c, -cli, --cli
gui = false;
cli = true;
checkRunByE = false;
} else if (args[i].equals("-nocli") || args[i].equals("-wait")) {
break;
case 'w': // -w, -wait, --nocli
gui = false;
cli = false;
checkRunByE = false;
} else if (args[i].equals("-e")) {
runCommand(args[i + 1], this);
i++;
break;
case 'e':
if (eargs == null)
eargs = new ArrayList<String>(4);
eargs.add(g.getOptarg());
if (checkRunByE) {
checkRunByE = false;
cli = false;
}
} else if (new File(args[i]).exists()) {
runCommand("run " + args[i], this);
} else {
System.out.println("Unknown parameter " + args[i]);
break;
case 'h':
case '?':
case ':':
default:
error = true;
}
}
int remaining = args.length - g.getOptind();
if (error || remaining > 1) {
System.err.println(usage());
throw new IllegalArgumentException();
}
if (eargs != null) {
for (String arg : eargs) {
runCommand(arg, this);
}
}
if (remaining == 1) {
String f = args[g.getOptind()];
File file = new File(f);
// This is probably just a problem with the options, so
// throw from here
if (!file.exists()) {
System.err.println(usage());
throw new IllegalArgumentException("Command file does not exist: " + f);
}
runCommand("run " + f, this);
}
if (gui) {
new I2PTunnelGUI(this);
} else if (cli) {
@@ -185,6 +274,9 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
} catch (IOException ex) {
ex.printStackTrace();
}
} else if (eargs == null && remaining == 0 && dontDie) {
System.err.println(usage());
throw new IllegalArgumentException("Waiting for nothing! Specify gui, cli, command, command file, or die");
}
while (dontDie) {
@@ -197,6 +289,23 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
}
}
/** with newlines except for last line */
private static String usage() {
// not sure this all makes sense, just documenting what's above
return
"Usage: i2ptunnel [options] [commandFile]\n" +
" Default is to run the GUI.\n" +
" commandFile: run all commands in this file\n" +
" Options:\n" +
" -c, -cli, --cli : run the command line interface\n" +
" -d, -die, --die : exit immediately, do not wait for commands to finish\n" +
" -e 'command [args]' : run the command\n" +
" -h, --help : display this help\n" +
" -nocli, --nocli : do not run the command line interface or GUI\n" +
" -nogui, --nogui : do not run the GUI\n" +
" -w, -wait, --wait : do not run the command line interface or GUI";
}
/** @return A copy, non-null */
List<I2PSession> getSessions() {
return new ArrayList<I2PSession>(_sessions);
@@ -312,30 +421,30 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
* @param l logger to receive events and output
*/
private static void runHelp(Logging l) {
l.log("Command list:");
l.log("Command list:\n" +
// alphabetical please...
l.log(" auth <username> <password>");
l.log(" client <port> <pubkey>[,<pubkey,...]|file:<pubkeyfile> [<sharedClient>]");
l.log(" clientoptions [-acx] [key=value ]*");
l.log(" close [forced] <jobnumber>|all");
l.log(" config [-s] <i2phost> <i2pport>");
l.log(" connectclient <port> [<sharedClient>] [<proxy>]");
l.log(" genkeys <privkeyfile> [<pubkeyfile>]");
l.log(" gentextkeys");
l.log(" httpbidirserver <host> <port> <proxyport> <spoofedhost> <privkeyfile>");
l.log(" httpclient <port> [<sharedClient>] [<proxy>]");
l.log(" httpserver <host> <port> <spoofedhost> <privkeyfile>");
l.log(" ircclient <port> <pubkey>[,<pubkey,...]|file:<pubkeyfile> [<sharedClient>]");
l.log(" list");
l.log(" listen_on <ip>");
l.log(" lookup <name>");
l.log(" owndest yes|no");
l.log(" ping <args>");
l.log(" quit");
l.log(" read_timeout <msecs>");
l.log(" run <commandfile>");
l.log(" server <host> <port> <privkeyfile>");
l.log(" textserver <host> <port> <privkey>");
" auth <username> <password>\n" +
" client <port> <pubkey>[,<pubkey,...]|file:<pubkeyfile> [<sharedClient>]\n" +
" clientoptions [-acx] [key=value ]*\n" +
" close [forced] <jobnumber>|all\n" +
" config [-s] <i2phost> <i2pport>\n" +
" connectclient <port> [<sharedClient>] [<proxy>]\n" +
" genkeys <privkeyfile> [<pubkeyfile>]\n" +
" gentextkeys\n" +
" httpbidirserver <host> <port> <proxyport> <spoofedhost> <privkeyfile>\n" +
" httpclient <port> [<sharedClient>] [<proxy>]\n" +
" httpserver <host> <port> <spoofedhost> <privkeyfile>\n" +
" ircclient <port> <pubkey>[,<pubkey,...]|file:<pubkeyfile> [<sharedClient>]\n" +
" list\n" +
" listen_on <ip>\n" +
" lookup <name>\n" +
" owndest yes|no\n" +
" ping <args>\n" +
" quit\n" +
" read_timeout <msecs>\n" +
" run <commandfile>\n" +
" server <host> <port> <privkeyfile>\n" +
" textserver <host> <port> <privkey>\n");
}
/**
@@ -378,12 +487,12 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
_clientOptions.setProperty(key, val);
}
} else {
l.log("Usage:");
l.log(" clientoptions [key=value ]* // sets current options");
l.log(" clientoptions -a [key=value ]* // adds to current options");
l.log(" clientoptions -c // clears current options");
l.log(" clientoptions -x [key ]* // removes listed options");
l.log("Current options:");
l.log("Usage:\n" +
" clientoptions [key=value ]* // sets current options\n" +
" clientoptions -a [key=value ]* // adds to current options\n" +
" clientoptions -c // clears current options\n" +
" clientoptions -x [key ]* // removes listed options\n" +
"Current options:\n");
Properties p = new OrderedProperties();
p.putAll(_clientOptions);
for (Map.Entry<Object, Object> e : p.entrySet()) {
@@ -466,8 +575,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
notifyEvent("serverTaskId", Integer.valueOf(serv.getId()));
return;
} else {
l.log("server <host> <port> <privkeyfile>");
l.log(" creates a server that sends all incoming data\n" + " of its destination to host:port.");
l.log("server <host> <port> <privkeyfile>\n" +
" creates a server that sends all incoming data\n" + " of its destination to host:port.");
notifyEvent("serverTaskId", Integer.valueOf(-1));
}
}
@@ -517,8 +626,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
notifyEvent("serverTaskId", Integer.valueOf(serv.getId()));
return;
} else {
l.log("server <host> <port> <privkeyfile>");
l.log(" creates a server that sends all incoming data\n" + " of its destination to host:port.");
l.log("server <host> <port> <privkeyfile>\n" +
" creates a server that sends all incoming data\n" + " of its destination to host:port.");
notifyEvent("serverTaskId", Integer.valueOf(-1));
}
}
@@ -578,8 +687,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
notifyEvent("serverTaskId", Integer.valueOf(serv.getId()));
return;
} else {
l.log("httpserver <host> <port> <spoofedhost> <privkeyfile>");
l.log(" creates an HTTP server that sends all incoming data\n"
l.log("httpserver <host> <port> <spoofedhost> <privkeyfile>\n" +
" creates an HTTP server that sends all incoming data\n"
+ " of its destination to host:port., filtering the HTTP\n"
+ " headers so it looks like the request is to the spoofed host.");
notifyEvent("serverTaskId", Integer.valueOf(-1));
@@ -654,8 +763,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
notifyEvent("serverTaskId", Integer.valueOf(serv.getId()));
return;
} else {
l.log("httpserver <host> <port> <proxyport> <spoofedhost> <privkeyfile>");
l.log(" creates a bidirectional HTTP server that sends all incoming data\n"
l.log("httpserver <host> <port> <proxyport> <spoofedhost> <privkeyfile>\n" +
" creates a bidirectional HTTP server that sends all incoming data\n"
+ " of its destination to host:port., filtering the HTTP\n"
+ " headers so it looks like the request is to the spoofed host,"
+ " and listens to host:proxyport to proxy HTTP requests.");
@@ -707,8 +816,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
addtask(serv);
notifyEvent("serverTaskId", Integer.valueOf(serv.getId()));
} else {
l.log("textserver <host> <port> <privkey>");
l.log(" creates a server that sends all incoming data\n" + " of its destination to host:port.");
l.log("textserver <host> <port> <privkey>\n" +
" creates a server that sends all incoming data\n" + " of its destination to host:port.");
notifyEvent("textserverTaskId", Integer.valueOf(-1));
}
}
@@ -765,8 +874,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
throw iae;
}
} else {
l.log("client <port> <pubkey>[,<pubkey>]|file:<pubkeyfile>[ <sharedClient>] [<privKeyFile>]");
l.log(" creates a client that forwards port to the pubkey.\n"
l.log("client <port> <pubkey>[,<pubkey>]|file:<pubkeyfile>[ <sharedClient>] [<privKeyFile>]\n" +
" creates a client that forwards port to the pubkey.\n"
+ " use 0 as port to get a free port assigned. If you specify\n"
+ " a comma delimited list of pubkeys, it will rotate among them\n"
+ " randomlyl. sharedClient indicates if this client shares \n"
@@ -841,11 +950,11 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
throw iae;
}
} else {
l.log("httpclient <port> [<sharedClient>] [<proxy>]");
l.log(" creates a client that distributes HTTP requests.");
l.log(" <sharedClient> (optional) indicates if this client shares tunnels with other clients (true of false)");
l.log(" <proxy> (optional) indicates a proxy server to be used");
l.log(" when trying to access an address out of the .i2p domain");
l.log("httpclient <port> [<sharedClient>] [<proxy>]\n" +
" creates a client that distributes HTTP requests.\n" +
" <sharedClient> (optional) indicates if this client shares tunnels with other clients (true of false)\n" +
" <proxy> (optional) indicates a proxy server to be used\n" +
" when trying to access an address out of the .i2p domain");
notifyEvent("httpclientTaskId", Integer.valueOf(-1));
}
}
@@ -908,11 +1017,11 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
throw iae;
}
} else {
l.log("connectclient <port> [<sharedClient>] [<proxy>]");
l.log(" creates a client that for SSL/HTTPS requests.");
l.log(" <sharedClient> (optional) indicates if this client shares tunnels with other clients (true of false)");
l.log(" <proxy> (optional) indicates a proxy server to be used");
l.log(" when trying to access an address out of the .i2p domain");
l.log("connectclient <port> [<sharedClient>] [<proxy>]\n" +
" creates a client that for SSL/HTTPS requests.\n" +
" <sharedClient> (optional) indicates if this client shares tunnels with other clients (true of false)\n" +
" <proxy> (optional) indicates a proxy server to be used\n" +
" when trying to access an address out of the .i2p domain\n");
}
}
@@ -975,9 +1084,9 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
throw iae;
}
} else {
l.log("ircclient <port> [<sharedClient> [<privKeyFile>]]");
l.log(" creates a client that filter IRC protocol.");
l.log(" <sharedClient> (optional) indicates if this client shares tunnels with other clients (true of false)");
l.log("ircclient <port> [<sharedClient> [<privKeyFile>]]\n" +
" creates a client that filter IRC protocol.\n" +
" <sharedClient> (optional) indicates if this client shares tunnels with other clients (true of false)\n");
notifyEvent("ircclientTaskId", Integer.valueOf(-1));
}
}
@@ -1028,8 +1137,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
throw iae;
}
} else {
l.log("sockstunnel <port>");
l.log(" creates a tunnel that distributes SOCKS requests.");
l.log("sockstunnel <port>\n" +
" creates a tunnel that distributes SOCKS requests.");
notifyEvent("sockstunnelTaskId", Integer.valueOf(-1));
}
}
@@ -1075,8 +1184,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
throw iae;
}
} else {
l.log("socksirctunnel <port> [<sharedClient> [<privKeyFile>]]");
l.log(" creates a tunnel for SOCKS IRC.");
l.log("socksirctunnel <port> [<sharedClient> [<privKeyFile>]]\n" +
" creates a tunnel for SOCKS IRC.");
notifyEvent("sockstunnelTaskId", Integer.valueOf(-1));
}
}
@@ -1125,8 +1234,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
throw iae;
}
} else {
l.log("streamrclient <host> <port> <destination>");
l.log(" creates a tunnel that receives streaming data.");
l.log("streamrclient <host> <port> <destination>\n" +
" creates a tunnel that receives streaming data.");
notifyEvent("streamrtunnelTaskId", Integer.valueOf(-1));
}
}
@@ -1166,8 +1275,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
addtask(task);
notifyEvent("streamrtunnelTaskId", Integer.valueOf(task.getId()));
} else {
l.log("streamrserver <port> <privkeyfile>");
l.log(" creates a tunnel that sends streaming data.");
l.log("streamrserver <port> <privkeyfile>\n" +
" creates a tunnel that sends streaming data.");
notifyEvent("streamrtunnelTaskId", Integer.valueOf(-1));
}
}
@@ -1195,12 +1304,12 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
port = args[i];
notifyEvent("configResult", "ok");
} else {
l.log("Usage:");
l.log(" config [-s] <i2phost> <i2pport>");
l.log(" sets the connection to the i2p router.");
l.log("Current setting:");
boolean ssl = Boolean.parseBoolean(_clientOptions.getProperty("i2cp.SSL"));
l.log(" " + host + ' ' + port + (ssl ? " SSL" : ""));
l.log("Usage:\n" +
" config [-s] <i2phost> <i2pport>\n" +
" sets the connection to the i2p router.\n" +
"Current setting:\n" +
" " + host + ' ' + port + (ssl ? " SSL" : ""));
notifyEvent("configResult", "error");
}
}
@@ -1210,16 +1319,16 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
*
* @param args {username, password}
* @param l logger to receive events and output
* @since 0.9.10
* @since 0.9.11
*/
private void runAuth(String args[], Logging l) {
if (args.length == 2) {
_clientOptions.setProperty("i2cp.username", args[0]);
_clientOptions.setProperty("i2cp.password", args[1]);
} else {
l.log("Usage:");
l.log(" auth <username> <password>");
l.log(" Sets the i2cp credentials");
l.log("Usage:\n" +
" auth <username> <password>\n" +
" Sets the i2cp credentials");
}
}
@@ -1237,8 +1346,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
ownDest = args[0].equalsIgnoreCase("yes");
notifyEvent("owndestResult", "ok");
} else {
l.log("owndest yes|no");
l.log(" Specifies whether to use its own destination \n" + " for each outgoing tunnel");
l.log("owndest yes|no\n" +
" Specifies whether to use its own destination \n" + " for each outgoing tunnel");
notifyEvent("owndestResult", "error");
}
}
@@ -1256,8 +1365,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
listenHost = args[0];
notifyEvent("listen_onResult", "ok");
} else {
l.log("listen_on <ip>");
l.log(" sets the interface to listen for the I2PClient.");
l.log("listen_on <ip>\n" +
" sets the interface to listen for the I2PClient.");
notifyEvent("listen_onResult", "error");
}
}
@@ -1279,15 +1388,16 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
}
notifyEvent("read_timeoutResult", "ok");
} else {
l.log("read_timeout <msecs>");
l.log(" sets the read timeout (in milliseconds) for I2P connections\n"
l.log("read_timeout <msecs>\n" +
" sets the read timeout (in milliseconds) for I2P connections\n"
+" Negative values will make the connections wait forever");
notifyEvent("read_timeoutResult", "error");
}
}
/**
* Generate a new keypair
* Generate a new keypair.
* Does NOT support non-default sig types.
* Deprecated - only used by CLI
*
* Sets the event "genkeysResult" = "ok" or "error" after the generation is complete
@@ -1307,8 +1417,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
return;
}
} else if (args.length != 1) {
l.log("genkeys <privkeyfile> [<pubkeyfile>]");
l.log(" creates a new keypair and prints the public key.\n"
l.log("genkeys <privkeyfile> [<pubkeyfile>]\n" +
" creates a new keypair and prints the public key.\n"
+ " if pubkeyfile is given, saves the public key there." + "\n"
+ " if the privkeyfile already exists, just print/save" + "the pubkey.");
//notifyEvent("genkeysResult", "error");
@@ -1330,7 +1440,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
}
/**
* Generate a new keypair
* Generate a new keypair.
* Does NOT support non-default sig types.
* Deprecated - only used by CLI
*
* Sets the event "privateKey" = base64 of the privateKey stream and
@@ -1339,7 +1450,7 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
* @param l logger to receive events and output
*/
private static void runGenTextKeys(Logging l) {
ByteArrayOutputStream privkey = new ByteArrayOutputStream(512);
ByteArrayOutputStream privkey = new ByteArrayOutputStream(1024);
ByteArrayOutputStream pubkey = new ByteArrayOutputStream(512);
makeKey(privkey, pubkey, l);
l.log("Private key: " + Base64.encode(privkey.toByteArray()));
@@ -1394,8 +1505,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
*/
public void runClose(String args[], Logging l) {
if (args.length == 0 || args.length > 2) {
l.log("close [forced] <jobnumber>|all");
l.log(" stop running tasks. either only one or all.\n"
l.log("close [forced] <jobnumber>|all\n" +
" stop running tasks. either only one or all.\n"
+ " use 'forced' to also stop tasks with active connections.\n"
+ " use the 'list' command to show the job numbers");
notifyEvent("closeResult", "error");
@@ -1456,8 +1567,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
notifyEvent("runResult", "error");
}
} else {
l.log("run <commandfile>");
l.log(" loads commandfile and runs each line in it. \n"
l.log("run <commandfile>\n" +
" loads commandfile and runs each line in it. \n"
+ " You can also give the filename on the commandline.");
notifyEvent("runResult", "error");
}
@@ -1474,8 +1585,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
*/
private void runLookup(String args[], Logging l) {
if (args.length != 1) {
l.log("lookup <name>");
l.log(" try to resolve the name into a destination key");
l.log("lookup <name>\n" +
" try to resolve the name into a destination key");
notifyEvent("lookupResult", "invalidUsage");
} else {
try {
@@ -1513,15 +1624,7 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
addtask(task);
notifyEvent("pingTaskId", Integer.valueOf(task.getId()));
} else {
l.log("ping <opts> <b64dest|host>");
l.log("ping <opts> -h (pings all hosts in hosts.txt)");
l.log("ping <opts> -l <destlistfile> (pings a list of hosts in a file)");
l.log(" Options:\n" +
" -c (require 5 consecutive pings to report success)\n" +
" -m maxSimultaneousPings (default 10)\n" +
" -n numberOfPings (default 3)\n" +
" -t timeout (ms, default 30000)\n");
l.log(" Tests communication with peers.\n");
l.log(I2Ping.usage());
notifyEvent("pingTaskId", Integer.valueOf(-1));
}
}
@@ -1593,10 +1696,11 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
/**
* Create a new destination, storing the destination and its private keys where
* instructed
* instructed.
* Does NOT support non-default sig types.
* Deprecated - only used by CLI
*
* @param writeTo location to store the private keys
* @param writeTo location to store the destination and private keys
* @param pubDest location to store the destination
* @param l logger to send messages to
*/
@@ -1605,8 +1709,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
l.log("Generating new keys...");
I2PClient client = I2PClientFactory.createClient();
Destination d = client.createDestination(writeTo);
l.log("Secret key saved.");
l.log("Public key: " + d.toBase64());
l.log("Secret key saved.\n" +
"Public key: " + d.toBase64());
writeTo.flush();
writeTo.close();
writePubKey(d, pubDest, l);
@@ -1673,7 +1777,7 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
* @param i2cpPort may be null
* @param user may be null
* @param pw may be null
* @since 0.9.10
* @since 0.9.11
*/
private static Destination destFromName(String name, String i2cpHost,
String i2cpPort, boolean isSSL,

View File

@@ -55,7 +55,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
private int localPort;
/**
* Protected for I2Ping since 0.9.10. Not for use outside package.
* Protected for I2Ping since 0.9.11. Not for use outside package.
*/
protected boolean listenerReady;
@@ -586,7 +586,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
}
/**
* Non-final since 0.9.10.
* Non-final since 0.9.11.
* Any overrides must set listenerReady = true.
*/
public void run() {

View File

@@ -24,6 +24,7 @@ import net.i2p.I2PAppContext;
import net.i2p.client.streaming.I2PSocketManager;
import net.i2p.data.Base64;
import net.i2p.data.DataHelper;
import net.i2p.util.EepGet;
import net.i2p.util.EventDispatcher;
import net.i2p.util.InternalSocket;
import net.i2p.util.Log;
@@ -409,60 +410,8 @@ public abstract class I2PTunnelHTTPClientBase extends I2PTunnelClientBase implem
* @since 0.9.4
*/
private static Map<String, String> parseArgs(String args) {
Map<String, String> rv = new HashMap<String, String>(8);
char data[] = args.toCharArray();
StringBuilder buf = new StringBuilder(32);
boolean isQuoted = false;
String key = null;
for (int i = 0; i < data.length; i++) {
switch (data[i]) {
case '\"':
if (isQuoted) {
// keys never quoted
if (key != null) {
rv.put(key, buf.toString().trim());
key = null;
}
buf.setLength(0);
}
isQuoted = !isQuoted;
break;
case ' ':
case '\r':
case '\n':
case '\t':
case ',':
// whitespace - if we're in a quoted section, keep this as part of the quote,
// otherwise use it as a delim
if (isQuoted) {
buf.append(data[i]);
} else {
if (key != null) {
rv.put(key, buf.toString().trim());
key = null;
}
buf.setLength(0);
}
break;
case '=':
if (isQuoted) {
buf.append(data[i]);
} else {
key = buf.toString().trim().toLowerCase(Locale.US);
buf.setLength(0);
}
break;
default:
buf.append(data[i]);
break;
}
}
if (key != null)
rv.put(key, buf.toString().trim());
return rv;
// moved to EepGet, since it needs this too
return EepGet.parseAuthArgs(args);
}
//////// Error page stuff

View File

@@ -18,6 +18,7 @@ import javax.net.ssl.SSLException;
import net.i2p.I2PAppContext;
import net.i2p.client.streaming.I2PSocket;
import net.i2p.data.ByteArray;
import net.i2p.data.DataHelper;
import net.i2p.util.ByteCache;
import net.i2p.util.Clock;
import net.i2p.util.I2PAppThread;
@@ -137,6 +138,8 @@ public class I2PTunnelRunner extends I2PAppThread implements I2PSocket.SocketErr
protected InputStream getSocketIn() throws IOException { return s.getInputStream(); }
protected OutputStream getSocketOut() throws IOException { return s.getOutputStream(); }
private static final byte[] POST = { 'P', 'O', 'S', 'T', ' ' };
@Override
public void run() {
try {
@@ -159,8 +162,12 @@ public class I2PTunnelRunner extends I2PAppThread implements I2PSocket.SocketErr
// So we now get a fast return from flush(), and can do it here to save 250 ms.
// To make sure we are under the initial window size and don't hang waiting for accept,
// only flush if it fits in one message.
if (initialI2PData.length <= 1730) // ConnectionOptions.DEFAULT_MAX_MESSAGE_SIZE
i2pout.flush();
if (initialI2PData.length <= 1730) { // ConnectionOptions.DEFAULT_MAX_MESSAGE_SIZE
// Don't flush if POST, so we can get POST data into the initial packet
if (initialI2PData.length < 5 ||
!DataHelper.eq(POST, 0, initialI2PData, 0, 5))
i2pout.flush();
}
//}
}
if (initialSocketData != null) {

View File

@@ -11,6 +11,8 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import gnu.getopt.Getopt;
import net.i2p.I2PAppContext;
import net.i2p.I2PException;
import net.i2p.client.I2PSession;
@@ -86,48 +88,76 @@ public class I2Ping extends I2PTunnelClientBase {
int count = PING_COUNT;
boolean countPing = false;
boolean reportTimes = true;
while (true) {
if (cmd.startsWith("-t ")) { // timeout
cmd = cmd.substring(3);
int pos = cmd.indexOf(" ");
if (pos == -1) {
l.log("Syntax error");
return;
} else {
timeout = Long.parseLong(cmd.substring(0, pos));
String hostListFile = null;
int localPort = 0;
int remotePort = 0;
boolean error = false;
String[] argv = cmd.split(" ");
Getopt g = new Getopt("ping", argv, "t:m:n:chl:f:p:");
int c;
while ((c = g.getopt()) != -1) {
switch (c) {
case 't': // timeout
timeout = Long.parseLong(g.getOptarg());
// convenience, convert msec to sec
if (timeout < 100)
timeout *= 1000;
cmd = cmd.substring(pos + 1);
}
} else if (cmd.startsWith("-m ")) { // max simultaneous pings
cmd = cmd.substring(3);
int pos = cmd.indexOf(" ");
if (pos == -1) {
l.log("Syntax error");
return;
} else {
MAX_SIMUL_PINGS = Integer.parseInt(cmd.substring(0, pos));
cmd = cmd.substring(pos + 1);
}
} else if (cmd.startsWith("-n ")) { // number of pings
cmd = cmd.substring(3);
int pos = cmd.indexOf(" ");
if (pos == -1) {
l.log("Syntax error");
return;
} else {
count = Integer.parseInt(cmd.substring(0, pos));
cmd = cmd.substring(pos + 1);
}
} else if (cmd.startsWith("-c ")) { // "count" ping
break;
case 'm': // max simultaneous pings
MAX_SIMUL_PINGS = Integer.parseInt(g.getOptarg());
break;
case 'n': // number of pings
count = Integer.parseInt(g.getOptarg());
break;
case 'c': // "count" ping
countPing = true;
count = CPING_COUNT;
cmd = cmd.substring(3);
} else if (cmd.equals("-h")) { // ping all hosts
cmd = "-l hosts.txt";
} else if (cmd.startsWith("-l ")) { // ping a list of hosts
BufferedReader br = new BufferedReader(new FileReader(cmd.substring(3)));
break;
case 'h': // ping all hosts
if (hostListFile != null)
error = true;
else
hostListFile = "hosts.txt";
break;
case 'l': // ping a list of hosts
if (hostListFile != null)
error = true;
else
hostListFile = g.getOptarg();
break;
case 'f': // local port
localPort = Integer.parseInt(g.getOptarg());
break;
case 'p': // remote port
remotePort = Integer.parseInt(g.getOptarg());
break;
case '?':
case ':':
default:
error = true;
}
}
int remaining = argv.length - g.getOptind();
if (error ||
remaining > 1 ||
(remaining <= 0 && hostListFile == null) ||
(remaining > 0 && hostListFile != null)) {
System.out.println(usage());
return;
}
if (hostListFile != null) {
BufferedReader br = new BufferedReader(new FileReader(hostListFile));
String line;
List<PingHandler> pingHandlers = new ArrayList<PingHandler>();
int i = 0;
@@ -138,7 +168,8 @@ public class I2Ping extends I2PTunnelClientBase {
if (line.indexOf("=") != -1) { // maybe file is hosts.txt?
line = line.substring(0, line.indexOf("="));
}
PingHandler ph = new PingHandler(line, count, timeout, countPing, reportTimes);
PingHandler ph = new PingHandler(line, count, localPort, remotePort,
timeout, countPing, reportTimes);
ph.start();
pingHandlers.add(ph);
if (++i > 1)
@@ -148,13 +179,31 @@ public class I2Ping extends I2PTunnelClientBase {
for (Thread t : pingHandlers)
t.join();
return;
} else {
Thread t = new PingHandler(cmd, count, timeout, countPing, reportTimes);
t.start();
t.join();
return;
}
}
String host = argv[g.getOptind()];
Thread t = new PingHandler(host, count, localPort, remotePort,
timeout, countPing, reportTimes);
t.start();
t.join();
}
/**
* With newlines except for last line
* @since 0.9.12
*/
public static String usage() {
return
"ping <opts> <b64dest|host>\n" +
"ping <opts> -h (pings all hosts in hosts.txt)\n" +
"ping <opts> -l <destlistfile> (pings a list of hosts in a file)\n" +
"Options:\n" +
" -c (require 5 consecutive pings to report success)\n" +
" -m maxSimultaneousPings (default 10)\n" +
" -n numberOfPings (default 3)\n" +
" -t timeout (ms, default 30000)\n" +
" -f fromPort\n" +
" -p toPort";
}
@Override
@@ -170,7 +219,7 @@ public class I2Ping extends I2PTunnelClientBase {
return true;
}
private boolean ping(Destination dest, long timeout) throws I2PException {
private boolean ping(Destination dest, int fromPort, int toPort, long timeout) throws I2PException {
try {
synchronized (simulLock) {
while (simulPings >= MAX_SIMUL_PINGS) {
@@ -183,7 +232,7 @@ public class I2Ping extends I2PTunnelClientBase {
}
lastPingTime = System.currentTimeMillis();
}
boolean sent = sockMgr.ping(dest, timeout);
boolean sent = sockMgr.ping(dest, fromPort, toPort, timeout);
synchronized (simulLock) {
simulPings--;
simulLock.notifyAll();
@@ -197,7 +246,7 @@ public class I2Ping extends I2PTunnelClientBase {
/**
* Does nothing.
* @since 0.9.10
* @since 0.9.11
*/
protected void clientConnectionRun(Socket s) {}
@@ -207,15 +256,20 @@ public class I2Ping extends I2PTunnelClientBase {
private final long timeout;
private final boolean countPing;
private final boolean reportTimes;
private final int localPort;
private final int remotePort;
/**
* As of 0.9.10, does NOT start itself.
* As of 0.9.11, does NOT start itself.
* Caller must call start()
* @param dest b64 or b32 or host name
*/
public PingHandler(String dest, int count, long timeout, boolean countPings, boolean report) {
public PingHandler(String dest, int count, int fromPort, int toPort,
long timeout, boolean countPings, boolean report) {
this.destination = dest;
cnt = count;
localPort = fromPort;
remotePort = toPort;
this.timeout = timeout;
countPing = countPings;
reportTimes = report;
@@ -235,8 +289,7 @@ public class I2Ping extends I2PTunnelClientBase {
long totalTime = 0;
StringBuilder pingResults = new StringBuilder(2 * cnt + destination.length() + 3);
for (int i = 0; i < cnt; i++) {
boolean sent;
sent = ping(dest, timeout);
boolean sent = ping(dest, localPort, remotePort, timeout);
if (countPing) {
if (!sent) {
pingResults.append(i).append(" ");
@@ -276,7 +329,7 @@ public class I2Ping extends I2PTunnelClientBase {
/**
* @param name b64 or b32 or host name
* @since 0.9.10
* @since 0.9.11
*/
private Destination lookup(String name) {
I2PAppContext ctx = I2PAppContext.getGlobalContext();

View File

@@ -7,11 +7,13 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import net.i2p.I2PAppContext;
import net.i2p.I2PException;
import net.i2p.client.I2PClient;
import net.i2p.client.I2PClientFactory;
import net.i2p.client.I2PSession;
import net.i2p.crypto.SigType;
import net.i2p.data.Base32;
import net.i2p.data.Destination;
import net.i2p.i2ptunnel.socks.I2PSOCKSTunnel;
@@ -49,8 +51,8 @@ public class TunnelController implements Logging {
* the prefix should be used (and, in turn, that prefix should be stripped off
* before being interpreted by this controller)
*
* @param config original key=value mapping
* @param prefix beginning of key values that are relevent to this tunnel
* @param config original key=value mapping non-null
* @param prefix beginning of key values that are relevant to this tunnel
*/
public TunnelController(Properties config, String prefix) {
this(config, prefix, true);
@@ -58,6 +60,8 @@ public class TunnelController implements Logging {
/**
*
* @param config original key=value mapping non-null
* @param prefix beginning of key values that are relevant to this tunnel
* @param createKey for servers, whether we want to create a brand new destination
* with private keys at the location specified or not (does not
* overwrite existing ones)
@@ -99,7 +103,16 @@ public class TunnelController implements Logging {
FileOutputStream fos = null;
try {
fos = new SecureFileOutputStream(keyFile);
Destination dest = client.createDestination(fos);
SigType stype = I2PClient.DEFAULT_SIGTYPE;
String st = _config.getProperty("option." + I2PClient.PROP_SIGTYPE);
if (st != null) {
SigType type = SigType.parseSigType(st);
if (type != null)
stype = type;
else
log("Unsupported sig type " + st);
}
Destination dest = client.createDestination(fos, stype);
String destStr = dest.toBase64();
log("Private key created and saved in " + keyFile.getAbsolutePath());
log("You should backup this file in a secure place.");

View File

@@ -12,6 +12,7 @@ import net.i2p.client.I2PClient;
import net.i2p.client.I2PClientFactory;
import net.i2p.client.I2PSession;
import net.i2p.client.I2PSessionException;
import net.i2p.crypto.SigType;
import net.i2p.data.Destination;
import net.i2p.i2ptunnel.I2PTunnel;
import net.i2p.i2ptunnel.I2PTunnelTask;
@@ -78,8 +79,17 @@ import net.i2p.util.EventDispatcher;
I2PClient client = I2PClientFactory.createClient();
byte[] key;
try {
ByteArrayOutputStream out = new ByteArrayOutputStream(512);
client.createDestination(out);
ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
SigType stype = I2PClient.DEFAULT_SIGTYPE;
String st = tunnel.getClientOptions().getProperty(I2PClient.PROP_SIGTYPE);
if (st != null) {
SigType type = SigType.parseSigType(st);
if (type != null)
stype = type;
else
l.log("Unsupported sig type " + st);
}
client.createDestination(out, stype);
key = out.toByteArray();
} catch(Exception exc) {
throw new RuntimeException("failed to create i2p-destination", exc);

View File

@@ -14,6 +14,7 @@ import java.util.Properties;
import java.util.Set;
import java.util.TreeMap;
import net.i2p.client.I2PClient;
import net.i2p.data.Base64;
import net.i2p.data.Destination;
import net.i2p.data.PrivateKeyFile;
@@ -177,6 +178,11 @@ public class EditBean extends IndexBean {
return getBooleanProperty(tunnel, "i2cp.encryptLeaseSet");
}
/** @since 0.9.12 */
public int getSigType(int tunnel) {
return getProperty(tunnel, I2PClient.PROP_SIGTYPE, 0);
}
/** @since 0.8.9 */
public boolean getDCC(int tunnel) {
return getBooleanProperty(tunnel, I2PTunnelIRCClient.PROP_DCC);
@@ -358,6 +364,11 @@ public class EditBean extends IndexBean {
return Addresses.getAllAddresses();
}
/** @since 0.9.12 */
public boolean isAdvanced() {
return _context.getBooleanProperty("routerconsole.advanced");
}
public String getI2CPHost(int tunnel) {
if (_context.isRouterContext())
return _("internal");

View File

@@ -24,6 +24,7 @@ import java.util.concurrent.ConcurrentHashMap;
import net.i2p.I2PAppContext;
import net.i2p.app.ClientAppManager;
import net.i2p.app.Outproxy;
import net.i2p.client.I2PClient;
import net.i2p.data.Base32;
import net.i2p.data.Certificate;
import net.i2p.data.Destination;
@@ -983,6 +984,7 @@ public class IndexBean {
} catch (NumberFormatException nfe) {}
}
}
public void setCert(String val) {
if (val != null) {
try {
@@ -990,10 +992,24 @@ public class IndexBean {
} catch (NumberFormatException nfe) {}
}
}
public void setSigner(String val) {
_certSigner = val;
}
/** @since 0.9.12 */
public void setSigType(String val) {
if (val != null) {
_otherOptions.put(I2PClient.PROP_SIGTYPE, val);
if (val.equals("0"))
_certType = 0;
else
_certType = 5;
}
// TODO: Call modifyDestination??
// Otherwise this only works on a new tunnel...
}
/** Modify or create a destination */
private String modifyDestination() {
if (_privKeyFile == null || _privKeyFile.trim().length() <= 0)
@@ -1234,13 +1250,14 @@ public class IndexBean {
"outproxyUsername", "outproxyPassword",
I2PTunnelHTTPClient.PROP_JUMP_SERVERS,
I2PTunnelHTTPClientBase.PROP_AUTH,
I2PClient.PROP_SIGTYPE,
I2PTunnelHTTPClient.PROP_SSL_OUTPROXIES
};
private static final String _otherServerOpts[] = {
"i2cp.reduceIdleTime", "i2cp.reduceQuantity", "i2cp.leaseSetKey", "i2cp.accessList",
PROP_MAX_CONNS_MIN, PROP_MAX_CONNS_HOUR, PROP_MAX_CONNS_DAY,
PROP_MAX_TOTAL_CONNS_MIN, PROP_MAX_TOTAL_CONNS_HOUR, PROP_MAX_TOTAL_CONNS_DAY,
PROP_MAX_STREAMS
PROP_MAX_STREAMS, I2PClient.PROP_SIGTYPE
};
private static final String _httpServerOpts[] = {
I2PTunnelHTTPServer.OPT_POST_WINDOW,