forked from I2P_Developers/i2p.i2p
propagate from branch 'i2p.i2p.zzz.i2cp' (head d4ac8162a4ba299ac912640f19076c3c90afdc67)
to branch 'i2p.i2p' (head adc5102c93383e01c74b87f04449dc9c307f6e75)
This commit is contained in:
@@ -46,6 +46,7 @@ import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
@@ -57,6 +58,8 @@ import net.i2p.I2PException;
|
||||
import net.i2p.client.I2PClient;
|
||||
import net.i2p.client.I2PClientFactory;
|
||||
import net.i2p.client.I2PSession;
|
||||
import net.i2p.client.I2PSessionException;
|
||||
import net.i2p.client.I2PSimpleClient;
|
||||
import net.i2p.client.naming.NamingService;
|
||||
import net.i2p.data.Base64;
|
||||
import net.i2p.data.DataFormatException;
|
||||
@@ -68,6 +71,7 @@ import net.i2p.i2ptunnel.streamr.StreamrConsumer;
|
||||
import net.i2p.i2ptunnel.streamr.StreamrProducer;
|
||||
import net.i2p.util.EventDispatcherImpl;
|
||||
import net.i2p.util.Log;
|
||||
import net.i2p.util.OrderedProperties;
|
||||
|
||||
/**
|
||||
* An I2PTunnel tracks one or more I2PTunnelTasks and one or more I2PSessions.
|
||||
@@ -87,9 +91,9 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
|
||||
public boolean ownDest = false;
|
||||
|
||||
/** the I2CP port */
|
||||
/** the I2CP port, non-null */
|
||||
public String port = System.getProperty(I2PClient.PROP_TCP_PORT, "7654");
|
||||
/** the I2CP host */
|
||||
/** the I2CP host, non-null */
|
||||
public String host = System.getProperty(I2PClient.PROP_TCP_HOST, "127.0.0.1");
|
||||
/** the listen-on host. Sadly the listen-on port does not have a field. */
|
||||
public String listenHost = host;
|
||||
@@ -168,7 +172,7 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
System.out.println("Enter 'help' for help.");
|
||||
BufferedReader r = new BufferedReader(new InputStreamReader(System.in));
|
||||
while (true) {
|
||||
System.out.print("I2PTunnel>");
|
||||
System.out.print("I2PTunnel> ");
|
||||
String cmd = r.readLine();
|
||||
if (cmd == null) break;
|
||||
if (cmd.length() <= 0) continue;
|
||||
@@ -293,6 +297,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
runPing(allargs, l);
|
||||
} else if (cmdname.equals("owndest")) {
|
||||
runOwnDest(args, l);
|
||||
} else if (cmdname.equals("auth")) {
|
||||
runAuth(args, l);
|
||||
} else {
|
||||
l.log("Unknown command [" + cmdname + "]");
|
||||
}
|
||||
@@ -308,27 +314,28 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
private static void runHelp(Logging l) {
|
||||
l.log("Command list:");
|
||||
// alphabetical please...
|
||||
l.log("client <port> <pubkey>[,<pubkey,...]|file:<pubkeyfile> [<sharedClient>]");
|
||||
l.log("clientoptions[ key=value]*");
|
||||
l.log("close [forced] <jobnumber>|all");
|
||||
l.log("config <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>");
|
||||
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>");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -345,15 +352,43 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
* @param l logger to receive events and output
|
||||
*/
|
||||
public void runClientOptions(String args[], Logging l) {
|
||||
_clientOptions.clear();
|
||||
if (args != null) {
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
if (args != null && args.length > 0) {
|
||||
int i = 0;
|
||||
if (args[0].equals("-a")) {
|
||||
i++;
|
||||
} else if (args[0].equals("-c")) {
|
||||
_clientOptions.clear();
|
||||
l.log("Client options cleared");
|
||||
return;
|
||||
} else if (args[0].equals("-x")) {
|
||||
i++;
|
||||
for ( ; i < args.length; i++) {
|
||||
if (_clientOptions.remove(args[i]) != null)
|
||||
l.log("Removed " + args[i]);
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
_clientOptions.clear();
|
||||
}
|
||||
for ( ; i < args.length; i++) {
|
||||
int index = args[i].indexOf('=');
|
||||
if (index <= 0) continue;
|
||||
String key = args[i].substring(0, index);
|
||||
String val = args[i].substring(index+1);
|
||||
_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:");
|
||||
Properties p = new OrderedProperties();
|
||||
p.putAll(_clientOptions);
|
||||
for (Map.Entry<Object, Object> e : p.entrySet()) {
|
||||
l.log(" [" + e.getKey() + "] = [" + e.getValue() + ']');
|
||||
}
|
||||
}
|
||||
notifyEvent("clientoptions_onResult", "ok");
|
||||
}
|
||||
@@ -1147,18 +1182,47 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
* @param l logger to receive events and output
|
||||
*/
|
||||
private void runConfig(String args[], Logging l) {
|
||||
if (args.length == 2) {
|
||||
host = args[0];
|
||||
if (args.length >= 2) {
|
||||
int i = 0;
|
||||
if (args[0].equals("-s")) {
|
||||
_clientOptions.setProperty("i2cp.SSL", "true");
|
||||
i++;
|
||||
} else {
|
||||
_clientOptions.remove("i2cp.SSL");
|
||||
}
|
||||
host = args[i++];
|
||||
listenHost = host;
|
||||
port = args[1];
|
||||
port = args[i];
|
||||
notifyEvent("configResult", "ok");
|
||||
} else {
|
||||
l.log("config <i2phost> <i2pport>");
|
||||
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" : ""));
|
||||
notifyEvent("configResult", "error");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the i2cp username and password
|
||||
*
|
||||
* @param args {username, password}
|
||||
* @param l logger to receive events and output
|
||||
* @since 0.9.10
|
||||
*/
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify whether to use its own destination for each outgoing tunnel
|
||||
* Deprecated - only used by CLI
|
||||
@@ -1415,16 +1479,19 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
notifyEvent("lookupResult", "invalidUsage");
|
||||
} else {
|
||||
try {
|
||||
Destination dest = destFromName(args[0]);
|
||||
boolean ssl = Boolean.parseBoolean(_clientOptions.getProperty("i2cp.SSL"));
|
||||
String user = _clientOptions.getProperty("i2cp.username");
|
||||
String pw = _clientOptions.getProperty("i2cp.password");
|
||||
Destination dest = destFromName(args[0], host, port, ssl, user, pw);
|
||||
if (dest == null) {
|
||||
l.log("Unknown host");
|
||||
l.log("Unknown host: " + args[0]);
|
||||
notifyEvent("lookupResult", "unkown host");
|
||||
} else {
|
||||
l.log(dest.toBase64());
|
||||
notifyEvent("lookupResult", dest.toBase64());
|
||||
}
|
||||
} catch (DataFormatException dfe) {
|
||||
l.log("Unknown or invalid host");
|
||||
l.log("Unknown or invalid host: " + args[0]);
|
||||
notifyEvent("lookupResult", "invalid host");
|
||||
}
|
||||
}
|
||||
@@ -1441,20 +1508,19 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
*/
|
||||
private void runPing(String allargs, Logging l) {
|
||||
if (allargs.length() != 0) {
|
||||
I2PTunnelTask task;
|
||||
// pings always use the main destination
|
||||
task = new I2Ping(allargs, l, false, this, this);
|
||||
_clientOptions.setProperty(I2Ping.PROP_COMMAND, allargs);
|
||||
I2PTunnelTask task = new I2Ping(l, ownDest, this, this);
|
||||
addtask(task);
|
||||
notifyEvent("pingTaskId", Integer.valueOf(task.getId()));
|
||||
} else {
|
||||
l.log("ping <opts> <dest>");
|
||||
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 5000)\n");
|
||||
" -t timeout (ms, default 30000)\n");
|
||||
l.log(" Tests communication with peers.\n");
|
||||
notifyEvent("pingTaskId", Integer.valueOf(-1));
|
||||
}
|
||||
@@ -1599,6 +1665,19 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
* @deprecated Don't use i2ptunnel for lookup! Use I2PAppContext.getGlobalContext().namingService().lookup(name) from i2p.jar
|
||||
*/
|
||||
public static Destination destFromName(String name) throws DataFormatException {
|
||||
return destFromName(name, null, null, false, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param i2cpHost may be null
|
||||
* @param i2cpPort may be null
|
||||
* @param user may be null
|
||||
* @param pw may be null
|
||||
* @since 0.9.10
|
||||
*/
|
||||
private static Destination destFromName(String name, String i2cpHost,
|
||||
String i2cpPort, boolean isSSL,
|
||||
String user, String pw) throws DataFormatException {
|
||||
|
||||
if ((name == null) || (name.trim().length() <= 0)) throw new DataFormatException("Empty destination provided");
|
||||
|
||||
@@ -1642,8 +1721,46 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
}
|
||||
} else {
|
||||
// ask naming service
|
||||
name = name.trim();
|
||||
NamingService inst = ctx.namingService();
|
||||
return inst.lookup(name);
|
||||
boolean b32 = name.length() == 60 && name.toLowerCase(Locale.US).endsWith(".b32.i2p");
|
||||
Destination d = null;
|
||||
if (ctx.isRouterContext() || !b32) {
|
||||
// Local lookup.
|
||||
// Even though we could do b32 outside router ctx here,
|
||||
// we do it below instead so we can set the host and port,
|
||||
// which we can't do with lookup()
|
||||
d = inst.lookup(name);
|
||||
if (d != null || ctx.isRouterContext() || name.length() >= 516)
|
||||
return d;
|
||||
}
|
||||
// Outside router context only,
|
||||
// try simple session to ask the router.
|
||||
I2PClient client = new I2PSimpleClient();
|
||||
Properties opts = new Properties();
|
||||
if (i2cpHost != null)
|
||||
opts.put(I2PClient.PROP_TCP_HOST, i2cpHost);
|
||||
if (i2cpPort != null)
|
||||
opts.put(I2PClient.PROP_TCP_PORT, i2cpPort);
|
||||
opts.put("i2cp.SSL", Boolean.toString(isSSL));
|
||||
if (user != null)
|
||||
opts.put("i2cp.username", user);
|
||||
if (pw != null)
|
||||
opts.put("i2cp.password", pw);
|
||||
I2PSession session = null;
|
||||
try {
|
||||
session = client.createSession(null, opts);
|
||||
session.connect();
|
||||
d = session.lookupDest(name);
|
||||
} catch (I2PSessionException ise) {
|
||||
if (log.shouldLog(Log.WARN))
|
||||
log.warn("Lookup via router failed", ise);
|
||||
} finally {
|
||||
if (session != null) {
|
||||
try { session.destroySession(); } catch (I2PSessionException ise) {}
|
||||
}
|
||||
}
|
||||
return d;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -51,15 +51,18 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
|
||||
protected final List<I2PSocket> mySockets = new ArrayList<I2PSocket>();
|
||||
protected boolean _ownDest;
|
||||
|
||||
protected Destination dest = null;
|
||||
protected Destination dest;
|
||||
private int localPort;
|
||||
|
||||
private boolean listenerReady = false;
|
||||
/**
|
||||
* Protected for I2Ping since 0.9.10. Not for use outside package.
|
||||
*/
|
||||
protected boolean listenerReady;
|
||||
|
||||
protected ServerSocket ss;
|
||||
|
||||
private final Object startLock = new Object();
|
||||
private boolean startRunning = false;
|
||||
private boolean startRunning;
|
||||
|
||||
// private Object closeLock = new Object();
|
||||
|
||||
@@ -68,7 +71,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
|
||||
private String privKeyFile;
|
||||
|
||||
// true if we are chained from a server.
|
||||
private boolean chained = false;
|
||||
private boolean chained;
|
||||
|
||||
/** how long to wait before dropping an idle thread */
|
||||
private static final long HANDLER_KEEPALIVE_MS = 2*60*1000;
|
||||
@@ -582,7 +585,11 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
|
||||
return i2ps;
|
||||
}
|
||||
|
||||
public final void run() {
|
||||
/**
|
||||
* Non-final since 0.9.10.
|
||||
* Any overrides must set listenerReady = true.
|
||||
*/
|
||||
public void run() {
|
||||
try {
|
||||
InetAddress addr = getListenHost(l);
|
||||
if (addr == null) {
|
||||
|
@@ -6,69 +6,70 @@ package net.i2p.i2ptunnel;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.net.Socket;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.I2PException;
|
||||
import net.i2p.client.I2PSession;
|
||||
import net.i2p.client.I2PSessionException;
|
||||
import net.i2p.client.streaming.I2PSocketManager;
|
||||
import net.i2p.data.Destination;
|
||||
import net.i2p.util.EventDispatcher;
|
||||
import net.i2p.util.I2PAppThread;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
public class I2Ping extends I2PTunnelTask implements Runnable {
|
||||
private final static Log _log = new Log(I2Ping.class);
|
||||
/**
|
||||
* Warning - not necessarily a stable API.
|
||||
* Used by I2PTunnel CLI only. Consider this sample code.
|
||||
* Not for use outside this package.
|
||||
*/
|
||||
public class I2Ping extends I2PTunnelClientBase {
|
||||
|
||||
private int PING_COUNT = 3;
|
||||
public static final String PROP_COMMAND = "command";
|
||||
|
||||
private static final int PING_COUNT = 3;
|
||||
private static final int CPING_COUNT = 5;
|
||||
private static final int PING_TIMEOUT = 5000;
|
||||
private static final int PING_TIMEOUT = 30*1000;
|
||||
|
||||
private static final long PING_DISTANCE = 1000;
|
||||
|
||||
private int MAX_SIMUL_PINGS = 10; // not really final...
|
||||
|
||||
private boolean countPing = false;
|
||||
private boolean reportTimes = true;
|
||||
|
||||
private I2PSocketManager sockMgr;
|
||||
private Logging l;
|
||||
private boolean finished = false;
|
||||
private String command;
|
||||
private long timeout = PING_TIMEOUT;
|
||||
private volatile boolean finished;
|
||||
|
||||
private final Object simulLock = new Object();
|
||||
private int simulPings = 0;
|
||||
private long lastPingTime = 0;
|
||||
private int simulPings;
|
||||
private long lastPingTime;
|
||||
|
||||
private final Object lock = new Object(), slock = new Object();
|
||||
|
||||
//public I2Ping(String cmd, Logging l,
|
||||
// boolean ownDest) {
|
||||
// I2Ping(cmd, l, (EventDispatcher)null);
|
||||
//}
|
||||
|
||||
public I2Ping(String cmd, Logging l, boolean ownDest, EventDispatcher notifyThis, I2PTunnel tunnel) {
|
||||
super("I2Ping [" + cmd + "]", notifyThis, tunnel);
|
||||
this.l = l;
|
||||
command = cmd;
|
||||
synchronized (slock) {
|
||||
if (ownDest) {
|
||||
sockMgr = I2PTunnelClient.buildSocketManager(tunnel);
|
||||
} else {
|
||||
sockMgr = I2PTunnelClient.getSocketManager(tunnel);
|
||||
}
|
||||
/**
|
||||
* tunnel.getOptions must contain "command".
|
||||
* @throws IllegalArgumentException if it doesn't
|
||||
*/
|
||||
public I2Ping(Logging l, boolean ownDest, EventDispatcher notifyThis, I2PTunnel tunnel) {
|
||||
super(-1, ownDest, l, notifyThis, "I2Ping", tunnel);
|
||||
if (!tunnel.getClientOptions().containsKey(PROP_COMMAND)) {
|
||||
// todo clean up
|
||||
throw new IllegalArgumentException("Options does not contain " + PROP_COMMAND);
|
||||
}
|
||||
Thread t = new I2PAppThread(this);
|
||||
t.setName("Client");
|
||||
t.start();
|
||||
open = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides super. No client ServerSocket is created.
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
// Notify constructor that port is ready
|
||||
synchronized (this) {
|
||||
listenerReady = true;
|
||||
notify();
|
||||
}
|
||||
l.log("*** I2Ping results:");
|
||||
try {
|
||||
runCommand(command);
|
||||
runCommand(getTunnel().getClientOptions().getProperty(PROP_COMMAND));
|
||||
} catch (InterruptedException ex) {
|
||||
l.log("*** Interrupted");
|
||||
_log.error("Pinger interrupted", ex);
|
||||
@@ -76,13 +77,15 @@ public class I2Ping extends I2PTunnelTask implements Runnable {
|
||||
_log.error("Pinger exception", ex);
|
||||
}
|
||||
l.log("*** Finished.");
|
||||
synchronized (lock) {
|
||||
finished = true;
|
||||
}
|
||||
finished = true;
|
||||
close(false);
|
||||
}
|
||||
|
||||
public void runCommand(String cmd) throws InterruptedException, IOException {
|
||||
long timeout = PING_TIMEOUT;
|
||||
int count = PING_COUNT;
|
||||
boolean countPing = false;
|
||||
boolean reportTimes = true;
|
||||
while (true) {
|
||||
if (cmd.startsWith("-t ")) { // timeout
|
||||
cmd = cmd.substring(3);
|
||||
@@ -92,6 +95,9 @@ public class I2Ping extends I2PTunnelTask implements Runnable {
|
||||
return;
|
||||
} else {
|
||||
timeout = Long.parseLong(cmd.substring(0, pos));
|
||||
// convenience, convert msec to sec
|
||||
if (timeout < 100)
|
||||
timeout *= 1000;
|
||||
cmd = cmd.substring(pos + 1);
|
||||
}
|
||||
} else if (cmd.startsWith("-m ")) { // max simultaneous pings
|
||||
@@ -111,11 +117,12 @@ public class I2Ping extends I2PTunnelTask implements Runnable {
|
||||
l.log("Syntax error");
|
||||
return;
|
||||
} else {
|
||||
PING_COUNT = Integer.parseInt(cmd.substring(0, pos));
|
||||
count = Integer.parseInt(cmd.substring(0, pos));
|
||||
cmd = cmd.substring(pos + 1);
|
||||
}
|
||||
} else if (cmd.startsWith("-c ")) { // "count" ping
|
||||
countPing = true;
|
||||
count = CPING_COUNT;
|
||||
cmd = cmd.substring(3);
|
||||
} else if (cmd.equals("-h")) { // ping all hosts
|
||||
cmd = "-l hosts.txt";
|
||||
@@ -131,7 +138,9 @@ public class I2Ping extends I2PTunnelTask implements Runnable {
|
||||
if (line.indexOf("=") != -1) { // maybe file is hosts.txt?
|
||||
line = line.substring(0, line.indexOf("="));
|
||||
}
|
||||
pingHandlers.add(new PingHandler(line));
|
||||
PingHandler ph = new PingHandler(line, count, timeout, countPing, reportTimes);
|
||||
ph.start();
|
||||
pingHandlers.add(ph);
|
||||
if (++i > 1)
|
||||
reportTimes = false;
|
||||
}
|
||||
@@ -140,28 +149,28 @@ public class I2Ping extends I2PTunnelTask implements Runnable {
|
||||
t.join();
|
||||
return;
|
||||
} else {
|
||||
Thread t = new PingHandler(cmd);
|
||||
Thread t = new PingHandler(cmd, count, timeout, countPing, reportTimes);
|
||||
t.start();
|
||||
t.join();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean close(boolean forced) {
|
||||
if (!open) return true;
|
||||
synchronized (lock) {
|
||||
if (!forced && !finished) {
|
||||
l.log("There are still pings running!");
|
||||
return false;
|
||||
}
|
||||
l.log("Closing pinger " + toString());
|
||||
l.log("Pinger closed.");
|
||||
open = false;
|
||||
return true;
|
||||
super.close(forced);
|
||||
if (!forced && !finished) {
|
||||
l.log("There are still pings running!");
|
||||
return false;
|
||||
}
|
||||
l.log("Closing pinger " + toString());
|
||||
l.log("Pinger closed.");
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean ping(Destination dest) throws I2PException {
|
||||
private boolean ping(Destination dest, long timeout) throws I2PException {
|
||||
try {
|
||||
synchronized (simulLock) {
|
||||
while (simulPings >= MAX_SIMUL_PINGS) {
|
||||
@@ -186,33 +195,48 @@ public class I2Ping extends I2PTunnelTask implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
public class PingHandler extends I2PAppThread {
|
||||
private String destination;
|
||||
/**
|
||||
* Does nothing.
|
||||
* @since 0.9.10
|
||||
*/
|
||||
protected void clientConnectionRun(Socket s) {}
|
||||
|
||||
public PingHandler(String dest) {
|
||||
private class PingHandler extends I2PAppThread {
|
||||
private final String destination;
|
||||
private final int cnt;
|
||||
private final long timeout;
|
||||
private final boolean countPing;
|
||||
private final boolean reportTimes;
|
||||
|
||||
/**
|
||||
* As of 0.9.10, 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) {
|
||||
this.destination = dest;
|
||||
cnt = count;
|
||||
this.timeout = timeout;
|
||||
countPing = countPings;
|
||||
reportTimes = report;
|
||||
setName("PingHandler for " + dest);
|
||||
start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Destination dest = I2PAppContext.getGlobalContext().namingService().lookup(destination);
|
||||
Destination dest = lookup(destination);
|
||||
if (dest == null) {
|
||||
synchronized (lock) { // Logger is not thread safe
|
||||
l.log("Unresolvable: " + destination + "");
|
||||
}
|
||||
l.log("Unresolvable: " + destination);
|
||||
return;
|
||||
}
|
||||
int pass = 0;
|
||||
int fail = 0;
|
||||
long totalTime = 0;
|
||||
int cnt = countPing ? CPING_COUNT : PING_COUNT;
|
||||
StringBuilder pingResults = new StringBuilder(2 * cnt + destination.length() + 3);
|
||||
for (int i = 0; i < cnt; i++) {
|
||||
boolean sent;
|
||||
sent = ping(dest);
|
||||
sent = ping(dest, timeout);
|
||||
if (countPing) {
|
||||
if (!sent) {
|
||||
pingResults.append(i).append(" ");
|
||||
@@ -244,12 +268,35 @@ public class I2Ping extends I2PTunnelTask implements Runnable {
|
||||
pingResults.append("and ").append(fail).append(" lost for destination: ");
|
||||
}
|
||||
pingResults.append(" ").append(destination);
|
||||
synchronized (lock) { // Logger is not thread safe
|
||||
l.log(pingResults.toString());
|
||||
}
|
||||
l.log(pingResults.toString());
|
||||
} catch (I2PException ex) {
|
||||
_log.error("Error pinging " + destination, ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name b64 or b32 or host name
|
||||
* @since 0.9.10
|
||||
*/
|
||||
private Destination lookup(String name) {
|
||||
I2PAppContext ctx = I2PAppContext.getGlobalContext();
|
||||
boolean b32 = name.length() == 60 && name.toLowerCase(Locale.US).endsWith(".b32.i2p");
|
||||
if (ctx.isRouterContext() && !b32) {
|
||||
// Local lookup.
|
||||
// Even though we could do b32 outside router ctx here,
|
||||
// we do it below instead so we can use the session,
|
||||
// which we can't do with lookup()
|
||||
Destination dest = ctx.namingService().lookup(name);
|
||||
if (dest != null || ctx.isRouterContext() || name.length() >= 516)
|
||||
return dest;
|
||||
}
|
||||
try {
|
||||
I2PSession sess = sockMgr.getSession();
|
||||
return sess.lookupDest(name);
|
||||
} catch (I2PSessionException ise) {
|
||||
_log.error("Error looking up " + name, ise);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user