forked from I2P_Developers/i2p.i2p
Compare commits
14 Commits
i2p.i2p.2.
...
i2ptunnel-
Author | SHA1 | Date | |
---|---|---|---|
9e64264a03 | |||
51497f4135 | |||
01171ddea6 | |||
1c369d54cd | |||
6a4cf667a6 | |||
ab4be06740 | |||
545d768403 | |||
2105ffa27f | |||
65b8004c00 | |||
c796cff025 | |||
c9dd63b256 | |||
e86561c30c | |||
49b0575d7a | |||
bb81f1a60f |
@ -78,6 +78,8 @@ import net.i2p.i2ptunnel.socks.I2PSOCKSIRCTunnel;
|
||||
import net.i2p.i2ptunnel.socks.I2PSOCKSTunnel;
|
||||
import net.i2p.i2ptunnel.streamr.StreamrConsumer;
|
||||
import net.i2p.i2ptunnel.streamr.StreamrProducer;
|
||||
import net.i2p.i2ptunnel.udpTunnel.I2PTunnelUDPClient;
|
||||
import net.i2p.i2ptunnel.udpTunnel.I2PTunnelUDPServerClient;
|
||||
import net.i2p.util.EventDispatcherImpl;
|
||||
import net.i2p.util.Log;
|
||||
import net.i2p.util.OrderedProperties;
|
||||
@ -112,6 +114,7 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
|
||||
/**
|
||||
* Absolute path to filter definition file
|
||||
*
|
||||
* @since 0.9.40
|
||||
*/
|
||||
public String filterDefinition;
|
||||
@ -135,7 +138,9 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
};
|
||||
|
||||
/** @since 0.9.17 */
|
||||
private enum CloseMode { NORMAL, FORCED, DESTROY }
|
||||
private enum CloseMode {
|
||||
NORMAL, FORCED, DESTROY
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
@ -147,7 +152,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard constructor for embedded, uses args "-nocli -die" to return immediately
|
||||
* Standard constructor for embedded, uses args "-nocli -die" to return
|
||||
* immediately
|
||||
*/
|
||||
public I2PTunnel() {
|
||||
this(nocli_args);
|
||||
@ -155,6 +161,7 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
|
||||
/**
|
||||
* New standard constructor in router, with back ref to tc
|
||||
*
|
||||
* @param tc may be null
|
||||
* @throws IllegalArgumentException
|
||||
* @since 0.9.48
|
||||
@ -165,6 +172,7 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
|
||||
/**
|
||||
* See usage() for options
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
*/
|
||||
public I2PTunnel(String[] args) {
|
||||
@ -173,6 +181,7 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
|
||||
/**
|
||||
* See usage() for options
|
||||
*
|
||||
* @param lsnr may be null
|
||||
* @throws IllegalArgumentException
|
||||
*/
|
||||
@ -308,8 +317,10 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
while (true) {
|
||||
System.out.print("I2PTunnel> ");
|
||||
String cmd = r.readLine();
|
||||
if (cmd == null) break;
|
||||
if (cmd.length() <= 0) continue;
|
||||
if (cmd == null)
|
||||
break;
|
||||
if (cmd.length() <= 0)
|
||||
continue;
|
||||
try {
|
||||
runCommand(cmd, this);
|
||||
} catch (Throwable t) {
|
||||
@ -338,8 +349,7 @@ 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" +
|
||||
return "Usage: i2ptunnel [options] [commandFile]\n" +
|
||||
" Default is to run the GUI.\n" +
|
||||
" commandFile: run all commands in this file\n" +
|
||||
" Options:\n" +
|
||||
@ -366,7 +376,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
* @param session null ok
|
||||
*/
|
||||
void addSession(I2PSession session) {
|
||||
if (session == null) return;
|
||||
if (session == null)
|
||||
return;
|
||||
boolean added = _sessions.add(session);
|
||||
if (added && _log.shouldLog(Log.INFO))
|
||||
_log.info(getPrefix() + " session added: " + session, new Exception());
|
||||
@ -376,7 +387,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
* @param session null ok
|
||||
*/
|
||||
void removeSession(I2PSession session) {
|
||||
if (session == null) return;
|
||||
if (session == null)
|
||||
return;
|
||||
boolean removed = _sessions.remove(session);
|
||||
if (removed && _log.shouldLog(Log.INFO))
|
||||
_log.info(getPrefix() + " session removed: " + session, new Exception());
|
||||
@ -385,16 +397,22 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
/**
|
||||
* Generic options used for clients and servers.
|
||||
* NOT a copy, Do NOT modify for per-connection options, make a copy.
|
||||
*
|
||||
* @return non-null, NOT a copy, do NOT modify for per-connection options
|
||||
*/
|
||||
public Properties getClientOptions() { return _clientOptions; }
|
||||
public Properties getClientOptions() {
|
||||
return _clientOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* TunnelController that constructed this, or null.
|
||||
*
|
||||
* @return controller or null
|
||||
* @since 0.9.48
|
||||
*/
|
||||
TunnelController getController() { return _controller; }
|
||||
TunnelController getController() {
|
||||
return _controller;
|
||||
}
|
||||
|
||||
private void addtask(I2PTunnelTask tsk) {
|
||||
tsk.setTunnel(this);
|
||||
@ -410,7 +428,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
}
|
||||
}
|
||||
|
||||
/** java 1.3 vs 1.4 :)
|
||||
/**
|
||||
* java 1.3 vs 1.4 :)
|
||||
*/
|
||||
private static String[] split(String src, String delim) {
|
||||
StringTokenizer tok = new StringTokenizer(src, delim);
|
||||
@ -421,7 +440,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
}
|
||||
|
||||
public void runCommand(String cmd, Logging l) {
|
||||
if (cmd.indexOf(' ') == -1) cmd += ' ';
|
||||
if (cmd.indexOf(' ') == -1)
|
||||
cmd += ' ';
|
||||
int iii = cmd.indexOf(' ');
|
||||
String cmdname = cmd.substring(0, iii).toLowerCase(Locale.US);
|
||||
String allargs = cmd.substring(iii + 1);
|
||||
@ -563,7 +583,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
}
|
||||
for (; i < args.length; i++) {
|
||||
int index = args[i].indexOf('=');
|
||||
if (index <= 0) continue;
|
||||
if (index <= 0)
|
||||
continue;
|
||||
String key = args[i].substring(0, index);
|
||||
String val = args[i].substring(index + 1);
|
||||
_clientOptions.setProperty(key, val);
|
||||
@ -590,7 +611,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
* This DOES update a running TunnelTask, but NOT the session.
|
||||
* A more efficient runClientOptions().
|
||||
*
|
||||
* Defaults in opts properties are not recommended, they may or may not be honored.
|
||||
* Defaults in opts properties are not recommended, they may or may not be
|
||||
* honored.
|
||||
*
|
||||
* @param opts non-null
|
||||
* @since 0.9.1
|
||||
@ -610,10 +632,13 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
|
||||
/**
|
||||
* Run the server pointing at the host and port specified using the private i2p
|
||||
* destination loaded from the specified file. <p>
|
||||
* destination loaded from the specified file.
|
||||
* <p>
|
||||
*
|
||||
* Sets the event "serverTaskId" = Integer(taskId) after the tunnel has been started (or -1 on error)
|
||||
* Also sets the event "openServerResult" = "ok" or "error" (displaying "Ready!" on the logger after
|
||||
* Sets the event "serverTaskId" = Integer(taskId) after the tunnel has been
|
||||
* started (or -1 on error)
|
||||
* Also sets the event "openServerResult" = "ok" or "error" (displaying "Ready!"
|
||||
* on the logger after
|
||||
* 'ok'). So, success = serverTaskId != -1 and openServerResult = ok.
|
||||
*
|
||||
* @param args {hostname, portNumber, privKeyFilename}
|
||||
@ -669,6 +694,7 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
/**
|
||||
* Same args as runServer
|
||||
* (we should stop duplicating all this code...)
|
||||
*
|
||||
* @throws IllegalArgumentException on config problem
|
||||
*/
|
||||
public void runIrcServer(String args[], Logging l) {
|
||||
@ -718,12 +744,16 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the HTTP server pointing at the host and port specified using the private i2p
|
||||
* Run the HTTP server pointing at the host and port specified using the private
|
||||
* i2p
|
||||
* destination loaded from the specified file, replacing the HTTP headers
|
||||
* so that the Host: specified is the one spoofed. <p>
|
||||
* so that the Host: specified is the one spoofed.
|
||||
* <p>
|
||||
*
|
||||
* Sets the event "serverTaskId" = Integer(taskId) after the tunnel has been started (or -1 on error)
|
||||
* Also sets the event "openServerResult" = "ok" or "error" (displaying "Ready!" on the logger after
|
||||
* Sets the event "serverTaskId" = Integer(taskId) after the tunnel has been
|
||||
* started (or -1 on error)
|
||||
* Also sets the event "openServerResult" = "ok" or "error" (displaying "Ready!"
|
||||
* on the logger after
|
||||
* 'ok'). So, success = serverTaskId != -1 and openServerResult = ok.
|
||||
*
|
||||
* @param args {hostname, portNumber, spoofedHost, privKeyFilename}
|
||||
@ -765,7 +795,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
notifyEvent("serverTaskId", Integer.valueOf(-1));
|
||||
throw new IllegalArgumentException(getPrefix() + "Cannot open private key file " + args[3]);
|
||||
}
|
||||
I2PTunnelHTTPServer serv = new I2PTunnelHTTPServer(serverHost, portNum, privKeyFile, args[3], spoofedHost, l, this, this);
|
||||
I2PTunnelHTTPServer serv = new I2PTunnelHTTPServer(serverHost, portNum, privKeyFile, args[3], spoofedHost,
|
||||
l, this, this);
|
||||
serv.setReadTimeout(readTimeout);
|
||||
serv.startRunning();
|
||||
addtask(serv);
|
||||
@ -781,16 +812,21 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the HTTP server pointing at the host and port specified using the private i2p
|
||||
* Run the HTTP server pointing at the host and port specified using the private
|
||||
* i2p
|
||||
* destination loaded from the specified file, replacing the HTTP headers
|
||||
* so that the Host: specified is the one spoofed. Also runs an HTTP proxy for
|
||||
* bidirectional communications on the same tunnel destination.<p>
|
||||
* bidirectional communications on the same tunnel destination.
|
||||
* <p>
|
||||
*
|
||||
* Sets the event "serverTaskId" = Integer(taskId) after the tunnel has been started (or -1 on error)
|
||||
* Also sets the event "openServerResult" = "ok" or "error" (displaying "Ready!" on the logger after
|
||||
* Sets the event "serverTaskId" = Integer(taskId) after the tunnel has been
|
||||
* started (or -1 on error)
|
||||
* Also sets the event "openServerResult" = "ok" or "error" (displaying "Ready!"
|
||||
* on the logger after
|
||||
* 'ok'). So, success = serverTaskId != -1 and openServerResult = ok.
|
||||
*
|
||||
* @param args {hostname, portNumber, proxyPortNumber, spoofedHost, privKeyFilename}
|
||||
* @param args {hostname, portNumber, proxyPortNumber, spoofedHost,
|
||||
* privKeyFilename}
|
||||
* @param l logger to receive events and output
|
||||
* @throws IllegalArgumentException on config problem
|
||||
*/
|
||||
@ -841,7 +877,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
throw new IllegalArgumentException(getPrefix() + "Cannot open private key file " + args[4]);
|
||||
}
|
||||
|
||||
I2PTunnelHTTPBidirServer serv = new I2PTunnelHTTPBidirServer(serverHost, portNum, port2Num, privKeyFile, args[3], spoofedHost, l, this, this);
|
||||
I2PTunnelHTTPBidirServer serv = new I2PTunnelHTTPBidirServer(serverHost, portNum, port2Num, privKeyFile,
|
||||
args[3], spoofedHost, l, this, this);
|
||||
serv.setReadTimeout(readTimeout);
|
||||
serv.startRunning();
|
||||
addtask(serv);
|
||||
@ -859,13 +896,16 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
|
||||
/**
|
||||
* Run the server pointing at the host and port specified using the private i2p
|
||||
* destination loaded from the given base64 stream. <p>
|
||||
* destination loaded from the given base64 stream.
|
||||
* <p>
|
||||
*
|
||||
* Deprecated? Why run a server with a private destination?
|
||||
* Not available from the war GUI
|
||||
*
|
||||
* Sets the event "serverTaskId" = Integer(taskId) after the tunnel has been started (or -1 on error)
|
||||
* Also sets the event "openServerResult" = "ok" or "error" (displaying "Ready!" on the logger after
|
||||
* Sets the event "serverTaskId" = Integer(taskId) after the tunnel has been
|
||||
* started (or -1 on error)
|
||||
* Also sets the event "openServerResult" = "ok" or "error" (displaying "Ready!"
|
||||
* on the logger after
|
||||
* 'ok'). So, success = serverTaskId != -1 and openServerResult = ok.
|
||||
*
|
||||
* @param args {hostname, portNumber, privKeyBase64}
|
||||
@ -911,13 +951,17 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
* Run the client on the given port number pointing at the specified destination
|
||||
* (either the base64 of the destination or file:fileNameContainingDestination).
|
||||
*
|
||||
* Sets the event "clientTaskId" = Integer(taskId) after the tunnel has been started (or -1 on error)
|
||||
* Also sets the event "openClientResult" = "error" or "ok" (before setting the value to "ok" it also
|
||||
* adds "Ready! Port #" to the logger as well). In addition, it will also set "clientLocalPort" =
|
||||
* Sets the event "clientTaskId" = Integer(taskId) after the tunnel has been
|
||||
* started (or -1 on error)
|
||||
* Also sets the event "openClientResult" = "error" or "ok" (before setting the
|
||||
* value to "ok" it also
|
||||
* adds "Ready! Port #" to the logger as well). In addition, it will also set
|
||||
* "clientLocalPort" =
|
||||
* Integer port number if the client is listening
|
||||
* sharedClient parameter is a String "true" or "false"
|
||||
*
|
||||
* @param args {portNumber, destinationBase64 or "file:filename"[, sharedClient [, privKeyFile]]}
|
||||
* @param args {portNumber, destinationBase64 or "file:filename"[, sharedClient
|
||||
* [, privKeyFile]]}
|
||||
* @param l logger to receive events and output
|
||||
* @throws IllegalArgumentException on config problem
|
||||
*/
|
||||
@ -942,19 +986,23 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
String privateKeyFile = null;
|
||||
if (args.length >= 4)
|
||||
privateKeyFile = args[3];
|
||||
I2PTunnelClientBase task = new I2PTunnelClient(portNum, args[1], l, ownDest, this, this, privateKeyFile);
|
||||
I2PTunnelClientBase task = new I2PTunnelClient(portNum, args[1], l, ownDest, this, this,
|
||||
privateKeyFile);
|
||||
task.startRunning();
|
||||
addtask(task);
|
||||
notifyEvent("clientTaskId", Integer.valueOf(task.getId()));
|
||||
} catch (IllegalArgumentException iae) {
|
||||
String msg = "Invalid I2PTunnel configuration to create a standard client tunnel connecting to the router at " + host + ':'+ port +
|
||||
String msg = "Invalid I2PTunnel configuration to create a standard client tunnel connecting to the router at "
|
||||
+ host + ':' + port +
|
||||
" and listening on " + listenHost + ':' + portNum;
|
||||
_log.error(getPrefix() + msg, iae);
|
||||
l.log(msg);
|
||||
notifyEvent("clientTaskId", Integer.valueOf(-1));
|
||||
// Since nothing listens to TaskID events, use this to propagate the error to TunnelController
|
||||
// Since nothing listens to TaskID events, use this to propagate the error to
|
||||
// TunnelController
|
||||
// Otherwise, the tunnel stays up even though the port is down
|
||||
// This doesn't work for CLI though... and the tunnel doesn't close itself after error,
|
||||
// This doesn't work for CLI though... and the tunnel doesn't close itself after
|
||||
// error,
|
||||
// so this probably leaves the tunnel open if called from the CLI
|
||||
throw iae;
|
||||
}
|
||||
@ -970,8 +1018,10 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
/**
|
||||
* Run an HTTP client on the given port number
|
||||
*
|
||||
* Sets the event "httpclientTaskId" = Integer(taskId) after the tunnel has been started (or -1 on error).
|
||||
* Also sets "httpclientStatus" = "ok" or "error" after the client tunnel has started.
|
||||
* Sets the event "httpclientTaskId" = Integer(taskId) after the tunnel has been
|
||||
* started (or -1 on error).
|
||||
* Also sets "httpclientStatus" = "ok" or "error" after the client tunnel has
|
||||
* started.
|
||||
* parameter sharedClient is a String, either "true" or "false"
|
||||
*
|
||||
* @param args {portNumber[, sharedClient][, proxy to be used for the WWW]}
|
||||
@ -1019,21 +1069,25 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
addtask(task);
|
||||
notifyEvent("httpclientTaskId", Integer.valueOf(task.getId()));
|
||||
} catch (IllegalArgumentException iae) {
|
||||
String msg = "Invalid I2PTunnel configuration to create an HTTP Proxy connecting to the router at " + host + ':'+ port +
|
||||
String msg = "Invalid I2PTunnel configuration to create an HTTP Proxy connecting to the router at "
|
||||
+ host + ':' + port +
|
||||
" and listening on " + listenHost + ':' + clientPort;
|
||||
_log.error(getPrefix() + msg, iae);
|
||||
l.log(msg);
|
||||
notifyEvent("httpclientTaskId", Integer.valueOf(-1));
|
||||
// Since nothing listens to TaskID events, use this to propagate the error to TunnelController
|
||||
// Since nothing listens to TaskID events, use this to propagate the error to
|
||||
// TunnelController
|
||||
// Otherwise, the tunnel stays up even though the port is down
|
||||
// This doesn't work for CLI though... and the tunnel doesn't close itself after error,
|
||||
// This doesn't work for CLI though... and the tunnel doesn't close itself after
|
||||
// error,
|
||||
// so this probably leaves the tunnel open if called from the CLI
|
||||
throw iae;
|
||||
}
|
||||
} else {
|
||||
l.log("httpclient <port> [<sharedClient>] [<proxy>]\n" +
|
||||
" Creates a HTTP client proxy on the specified port.\n" +
|
||||
" <sharedClient> (optional) Indicates if this client shares tunnels with other clients (true or false)\n" +
|
||||
" <sharedClient> (optional) Indicates if this client shares tunnels with other clients (true or 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));
|
||||
@ -1085,20 +1139,24 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
task.startRunning();
|
||||
addtask(task);
|
||||
} catch (IllegalArgumentException iae) {
|
||||
String msg = "Invalid I2PTunnel configuration to create a CONNECT client connecting to the router at " + host + ':'+ port +
|
||||
String msg = "Invalid I2PTunnel configuration to create a CONNECT client connecting to the router at "
|
||||
+ host + ':' + port +
|
||||
" and listening on " + listenHost + ':' + _port;
|
||||
_log.error(getPrefix() + msg, iae);
|
||||
l.log(msg);
|
||||
// Since nothing listens to TaskID events, use this to propagate the error to TunnelController
|
||||
// Since nothing listens to TaskID events, use this to propagate the error to
|
||||
// TunnelController
|
||||
// Otherwise, the tunnel stays up even though the port is down
|
||||
// This doesn't work for CLI though... and the tunnel doesn't close itself after error,
|
||||
// This doesn't work for CLI though... and the tunnel doesn't close itself after
|
||||
// error,
|
||||
// so this probably leaves the tunnel open if called from the CLI
|
||||
throw iae;
|
||||
}
|
||||
} else {
|
||||
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 or false)\n" +
|
||||
" <sharedClient> (optional) indicates if this client shares tunnels with other clients (true or false)\n"
|
||||
+
|
||||
" <proxy> (optional) indicates a proxy server to be used\n" +
|
||||
" when trying to access an address out of the .i2p domain\n");
|
||||
}
|
||||
@ -1107,11 +1165,14 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
/**
|
||||
* Run an IRC client on the given port number
|
||||
*
|
||||
* Sets the event "ircclientTaskId" = Integer(taskId) after the tunnel has been started (or -1 on error).
|
||||
* Also sets "ircclientStatus" = "ok" or "error" after the client tunnel has started.
|
||||
* Sets the event "ircclientTaskId" = Integer(taskId) after the tunnel has been
|
||||
* started (or -1 on error).
|
||||
* Also sets "ircclientStatus" = "ok" or "error" after the client tunnel has
|
||||
* started.
|
||||
* parameter sharedClient is a String, either "true" or "false"
|
||||
*
|
||||
* @param args {portNumber,destinationBase64 or "file:filename" [, sharedClient [, privKeyFile]]}
|
||||
* @param args {portNumber,destinationBase64 or "file:filename" [, sharedClient
|
||||
* [, privKeyFile]]}
|
||||
* @param l logger to receive events and output
|
||||
* @throws IllegalArgumentException on config problem
|
||||
*/
|
||||
@ -1145,19 +1206,23 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
String privateKeyFile = null;
|
||||
if (args.length >= 4)
|
||||
privateKeyFile = args[3];
|
||||
I2PTunnelClientBase task = new I2PTunnelIRCClient(_port, args[1], l, ownDest, this, this, privateKeyFile);
|
||||
I2PTunnelClientBase task = new I2PTunnelIRCClient(_port, args[1], l, ownDest, this, this,
|
||||
privateKeyFile);
|
||||
task.startRunning();
|
||||
addtask(task);
|
||||
notifyEvent("ircclientTaskId", Integer.valueOf(task.getId()));
|
||||
} catch (IllegalArgumentException iae) {
|
||||
String msg = "Invalid I2PTunnel configuration to create an IRC client connecting to the router at " + host + ':'+ port +
|
||||
String msg = "Invalid I2PTunnel configuration to create an IRC client connecting to the router at "
|
||||
+ host + ':' + port +
|
||||
" and listening on " + listenHost + ':' + _port;
|
||||
_log.error(getPrefix() + msg, iae);
|
||||
l.log(msg);
|
||||
notifyEvent("ircclientTaskId", Integer.valueOf(-1));
|
||||
// Since nothing listens to TaskID events, use this to propagate the error to TunnelController
|
||||
// Since nothing listens to TaskID events, use this to propagate the error to
|
||||
// TunnelController
|
||||
// Otherwise, the tunnel stays up even though the port is down
|
||||
// This doesn't work for CLI though... and the tunnel doesn't close itself after error,
|
||||
// This doesn't work for CLI though... and the tunnel doesn't close itself after
|
||||
// error,
|
||||
// so this probably leaves the tunnel open if called from the CLI
|
||||
throw iae;
|
||||
}
|
||||
@ -1177,7 +1242,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
* "openSOCKSTunnelResult" = "ok" or "error" after the client tunnel has
|
||||
* started.
|
||||
*
|
||||
* @param args {portNumber [, sharedClient]} or (portNumber, ignored (false), privKeyFile)
|
||||
* @param args {portNumber [, sharedClient]} or (portNumber, ignored (false),
|
||||
* privKeyFile)
|
||||
* @param l logger to receive events and output
|
||||
* @throws IllegalArgumentException on config problem
|
||||
*/
|
||||
@ -1208,7 +1274,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
addtask(task);
|
||||
notifyEvent("sockstunnelTaskId", Integer.valueOf(task.getId()));
|
||||
} catch (IllegalArgumentException iae) {
|
||||
String msg = "Invalid I2PTunnel configuration to create a SOCKS Proxy connecting to the router at " + host + ':'+ port +
|
||||
String msg = "Invalid I2PTunnel configuration to create a SOCKS Proxy connecting to the router at "
|
||||
+ host + ':' + port +
|
||||
" and listening on " + listenHost + ':' + _port;
|
||||
_log.error(getPrefix() + msg, iae);
|
||||
l.log(msg);
|
||||
@ -1222,10 +1289,11 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Run an SOCKS IRC tunnel on the given port number
|
||||
* @param args {portNumber [, sharedClient]} or (portNumber, ignored (false), privKeyFile)
|
||||
*
|
||||
* @param args {portNumber [, sharedClient]} or (portNumber, ignored (false),
|
||||
* privKeyFile)
|
||||
* @throws IllegalArgumentException on config problem
|
||||
* @since 0.7.12
|
||||
*/
|
||||
@ -1256,7 +1324,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
addtask(task);
|
||||
notifyEvent("sockstunnelTaskId", Integer.valueOf(task.getId()));
|
||||
} catch (IllegalArgumentException iae) {
|
||||
String msg = "Invalid I2PTunnel configuration to create a SOCKS IRC Proxy connecting to the router at " + host + ':'+ port +
|
||||
String msg = "Invalid I2PTunnel configuration to create a SOCKS IRC Proxy connecting to the router at "
|
||||
+ host + ':' + port +
|
||||
" and listening on " + listenHost + ':' + _port;
|
||||
_log.error(getPrefix() + msg, iae);
|
||||
l.log(msg);
|
||||
@ -1306,7 +1375,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
addtask(task);
|
||||
notifyEvent("streamrtunnelTaskId", Integer.valueOf(task.getId()));
|
||||
} catch (IllegalArgumentException iae) {
|
||||
String msg = "Invalid I2PTunnel configuration to create a Streamr Client connecting to the router at " + host + ':'+ port +
|
||||
String msg = "Invalid I2PTunnel configuration to create a Streamr Client connecting to the router at "
|
||||
+ host + ':' + port +
|
||||
" and sending to " + _host + ':' + _port;
|
||||
_log.error(getPrefix() + msg, iae);
|
||||
l.log(msg);
|
||||
@ -1361,11 +1431,153 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* UDP client
|
||||
*
|
||||
* @param args {targethost, targetport, destinationString}
|
||||
* @param l logger to receive events and output
|
||||
* @throws IllegalArgumentException on config problem
|
||||
*/
|
||||
public void runUDPClient(String[] args, Logging l) {
|
||||
if (args.length == 3) {
|
||||
if (args.length == 3) {
|
||||
InetAddress _host;
|
||||
try {
|
||||
_host = InetAddress.getByName(args[0]);
|
||||
} catch (UnknownHostException uhe) {
|
||||
l.log("unknown host");
|
||||
_log.error(getPrefix() + "Error resolving " + args[0], uhe);
|
||||
notifyEvent("udpClientTunnelId", Integer.valueOf(-1));
|
||||
return;
|
||||
}
|
||||
|
||||
int _port = -1;
|
||||
try {
|
||||
_port = Integer.parseInt(args[1]);
|
||||
} catch (NumberFormatException nfe) {
|
||||
l.log("invalid port");
|
||||
_log.error(getPrefix() + "Port specified is not valid: " + args[0], nfe);
|
||||
notifyEvent("udpClientTunnelId", Integer.valueOf(-1));
|
||||
}
|
||||
if (_port <= 0)
|
||||
throw new IllegalArgumentException(getPrefix() + "Bad port " + args[0]);
|
||||
|
||||
try {
|
||||
I2PTunnelUDPClient task = new I2PTunnelUDPClient(_host.toString(), _port, args[2], l, this, this);
|
||||
task.startRunning();
|
||||
addtask(task);
|
||||
notifyEvent("udpClientTunnelId", Integer.valueOf(task.getId()));
|
||||
} catch (IllegalArgumentException iae) {
|
||||
String msg = "Invalid I2PTunnel configuration to create a UDP Client connecting to the router at "
|
||||
+ host + ':' + port +
|
||||
" and sending to " + _host + ':' + _port;
|
||||
_log.error(getPrefix() + msg, iae);
|
||||
l.log(msg);
|
||||
notifyEvent("udpClientTunnelId", Integer.valueOf(-1));
|
||||
throw iae;
|
||||
}
|
||||
} else {
|
||||
l.log("streamrclient <host> <port> <destination>\n" +
|
||||
" creates a tunnel that receives streaming data.");
|
||||
notifyEvent("udpClientTunnelId", Integer.valueOf(-1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* UDP server
|
||||
*
|
||||
* @param args {targethost, targetproxy, transport, privkeyfile}
|
||||
* @param l logger to receive events and output
|
||||
* @throws IllegalArgumentException on config problem
|
||||
*/
|
||||
public void runUDPServer(String[] args, Logging l) {
|
||||
if (args.length == 4) {
|
||||
InetAddress _host;
|
||||
try {
|
||||
_host = InetAddress.getByName(args[0]);
|
||||
} catch (UnknownHostException uhe) {
|
||||
l.log("unknown host");
|
||||
_log.error(getPrefix() + "Error resolving " + args[0], uhe);
|
||||
notifyEvent("udpservertunnelTaskId", Integer.valueOf(-1));
|
||||
return;
|
||||
}
|
||||
int _proxyport = -1;
|
||||
try {
|
||||
_proxyport = Integer.parseInt(args[1]);
|
||||
} catch (NumberFormatException nfe) {
|
||||
l.log("invalid port");
|
||||
_log.error(getPrefix() + "Port specified is not valid: " + args[0], nfe);
|
||||
notifyEvent("udpservertunnelTaskId", Integer.valueOf(-1));
|
||||
}
|
||||
if (_proxyport <= 0)
|
||||
throw new IllegalArgumentException(getPrefix() + "Bad port " + args[0]);
|
||||
|
||||
int _rproxyport = -1;
|
||||
try {
|
||||
_rproxyport = Integer.parseInt(args[2]);
|
||||
} catch (NumberFormatException nfe) {
|
||||
l.log("invalid port");
|
||||
_log.error(getPrefix() + "Port specified is not valid: " + args[2], nfe);
|
||||
notifyEvent("udpservertunnelTaskId", Integer.valueOf(-1));
|
||||
}
|
||||
if (_rproxyport <= 0)
|
||||
throw new IllegalArgumentException(getPrefix() + "Bad port " + args[2]);
|
||||
|
||||
File privKeyFile = new File(args[3]);
|
||||
if (!privKeyFile.isAbsolute())
|
||||
privKeyFile = new File(_context.getConfigDir(), args[1]);
|
||||
if (!privKeyFile.canRead()) {
|
||||
l.log("private key file does not exist");
|
||||
_log.error(getPrefix() + "Private key file does not exist or is not readable: " + args[3]);
|
||||
notifyEvent("udpservertunnelTaskId", Integer.valueOf(-1));
|
||||
return;
|
||||
}
|
||||
|
||||
// I2PTunnelUDPServerClient(String host, int port, File privkey, String
|
||||
// privkeyname, Logging l,
|
||||
// EventDispatcher notifyThis,
|
||||
// I2PTunnel tunnel)
|
||||
|
||||
// EventDispatcher notifyThis,
|
||||
// I2PTunnel tunnel)
|
||||
|
||||
try {
|
||||
I2PTunnelUDPServerClient task = new I2PTunnelUDPServerClient(_host.toString(), _proxyport, privKeyFile,
|
||||
privKeyFile.toString(), l, this, this);
|
||||
task.startRunning();
|
||||
addtask(task);
|
||||
notifyEvent("udpServerTunnelId", Integer.valueOf(task.getId()));
|
||||
} catch (IllegalArgumentException iae) {
|
||||
String msg = "Invalid I2PTunnel configuration to create a UDP Server connecting to the router at "
|
||||
+ host + ':' + port +
|
||||
" and sending to " + _host + ':' + _proxyport;
|
||||
_log.error(getPrefix() + msg, iae);
|
||||
l.log(msg);
|
||||
notifyEvent("udpServerTunnelId", Integer.valueOf(-1));
|
||||
throw iae;
|
||||
}
|
||||
|
||||
// I2PTunnelUDPServerClient task = new I2PTunnelUDPServerClient(_port,
|
||||
// privKeyFile, args[1], l, this, this);
|
||||
// task.startRunning();
|
||||
// addtask(task);
|
||||
// notifyEvent("udpservertunnelTaskId", Integer.valueOf(task.getId()));
|
||||
} else
|
||||
|
||||
{
|
||||
l.log("streamrserver <port> <privkeyfile>\n" +
|
||||
" creates a tunnel that sends streaming data.");
|
||||
notifyEvent("udpservertunnelTaskId", Integer.valueOf(-1));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the i2cp host and port
|
||||
* Deprecated - only used by CLI
|
||||
*
|
||||
* Sets the event "configResult" = "ok" or "error" after the configuration has been specified
|
||||
* Sets the event "configResult" = "ok" or "error" after the configuration has
|
||||
* been specified
|
||||
*
|
||||
* @param args {hostname, portNumber}
|
||||
* @param l logger to receive events and output
|
||||
@ -1420,7 +1632,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
* Specify whether to use its own destination for each outgoing tunnel
|
||||
* Deprecated - only used by CLI
|
||||
*
|
||||
* Sets the event "owndestResult" = "ok" or "error" after the configuration has been specified
|
||||
* Sets the event "owndestResult" = "ok" or "error" after the configuration has
|
||||
* been specified
|
||||
*
|
||||
* @param args {yes or no}
|
||||
* @param l logger to receive events and output
|
||||
@ -1438,9 +1651,11 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the hostname / IP address of the interface that the tunnels should bind to
|
||||
* Specify the hostname / IP address of the interface that the tunnels should
|
||||
* bind to
|
||||
*
|
||||
* Sets the event "listen_onResult" = "ok" or "error" after the interface has been specified
|
||||
* Sets the event "listen_onResult" = "ok" or "error" after the interface has
|
||||
* been specified
|
||||
*
|
||||
* @param args {hostname}
|
||||
* @param l logger to receive events and output
|
||||
@ -1459,7 +1674,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
/**
|
||||
* Specify the read timeout going to be used for newly-created I2PSockets
|
||||
*
|
||||
* Sets the event "read_timeoutResult" = "ok" or "error" after the interface has been specified
|
||||
* Sets the event "read_timeoutResult" = "ok" or "error" after the interface has
|
||||
* been specified
|
||||
*
|
||||
* @param args {hostname}
|
||||
* @param l logger to receive events and output
|
||||
@ -1485,7 +1701,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
* Does NOT support non-default sig types.
|
||||
* Deprecated - only used by CLI
|
||||
*
|
||||
* Sets the event "genkeysResult" = "ok" or "error" after the generation is complete
|
||||
* Sets the event "genkeysResult" = "ok" or "error" after the generation is
|
||||
* complete
|
||||
*
|
||||
* @param args {privateKeyFilename, publicKeyFilename} or {privateKeyFilename}
|
||||
* @param l logger to receive events and output
|
||||
@ -1522,7 +1739,11 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
// notifyEvent("genkeysResult", "error");
|
||||
// _log.error(getPrefix() + "Error generating keys", ioe);
|
||||
} finally {
|
||||
if(pubdest != null) try { pubdest.close(); } catch(IOException ioe) {}
|
||||
if (pubdest != null)
|
||||
try {
|
||||
pubdest.close();
|
||||
} catch (IOException ioe) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1550,8 +1771,10 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
* running, it returns.
|
||||
* Deprecated - only used by CLI
|
||||
*
|
||||
* Sets the event "quitResult" = "error" if there are tasks running (but if there
|
||||
* aren't, well, there's no point in setting the quitResult to "ok", now is there?)
|
||||
* Sets the event "quitResult" = "error" if there are tasks running (but if
|
||||
* there
|
||||
* aren't, well, there's no point in setting the quitResult to "ok", now is
|
||||
* there?)
|
||||
*
|
||||
* @param l logger to receive events and output
|
||||
*/
|
||||
@ -1587,7 +1810,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
*
|
||||
* Sets the event "closeResult" = "ok" after the closing is complete
|
||||
*
|
||||
* @param args {jobNumber}, {"forced", jobNumber}, {"forced", "all"}, {"destroy", jobNumber}, {"destroy", "all"}
|
||||
* @param args {jobNumber}, {"forced", jobNumber}, {"forced", "all"},
|
||||
* {"destroy", jobNumber}, {"destroy", "all"}
|
||||
* @param l logger to receive events and output
|
||||
*/
|
||||
public void runClose(String args[], Logging l) {
|
||||
@ -1663,7 +1887,11 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
_log.error(getPrefix() + "Error running the file", ioe);
|
||||
notifyEvent("runResult", "error");
|
||||
} finally {
|
||||
if (br != null) try { br.close(); } catch (IOException ioe) {}
|
||||
if (br != null)
|
||||
try {
|
||||
br.close();
|
||||
} catch (IOException ioe) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
l.log("run <commandfile>\n" +
|
||||
@ -1677,7 +1905,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
* Perform a lookup of the name specified
|
||||
* Deprecated - only used by CLI
|
||||
*
|
||||
* Sets the event "lookupResult" = base64 of the destination, or an error message
|
||||
* Sets the event "lookupResult" = base64 of the destination, or an error
|
||||
* message
|
||||
*
|
||||
* @param args {name}
|
||||
* @param l logger to receive events and output
|
||||
@ -1708,7 +1937,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
}
|
||||
|
||||
/**
|
||||
* Start up a ping task with the specified args (currently supporting -ns, -h, -l)
|
||||
* Start up a ping task with the specified args (currently supporting -ns, -h,
|
||||
* -l)
|
||||
* Deprecated - only used by CLI
|
||||
*
|
||||
* Sets the event "pingTaskId" = Integer of the taskId, or -1
|
||||
@ -1741,10 +1971,12 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
|
||||
/**
|
||||
* Send a BlindingInfo message, just for testing
|
||||
*
|
||||
* @since 0.9.43
|
||||
*/
|
||||
private void runBlinding(String[] argv, Logging l) {
|
||||
// blinding [-d|p] [-k key] [-s password] [-e expires] xxx.b32.i2p // -d for DH; -p for PSK; expires in days
|
||||
// blinding [-d|p] [-k key] [-s password] [-e expires] xxx.b32.i2p // -d for DH;
|
||||
// -p for PSK; expires in days
|
||||
Getopt g = new Getopt("blinding", argv, "dpk:s:e:");
|
||||
boolean error = false;
|
||||
boolean dh = false;
|
||||
@ -1783,7 +2015,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
}
|
||||
int remaining = argv.length - g.getOptind();
|
||||
if (error || remaining != 1 || (dh && psk) || ((dh || psk) && key == null)) {
|
||||
System.out.println("Usage: blinding [-d|p] [-k key] [-s password] [-e expires] xxx.b32.i2p // -d for DH; -p for PSK; expires in days");
|
||||
System.out.println(
|
||||
"Usage: blinding [-d|p] [-k key] [-s password] [-e expires] xxx.b32.i2p // -d for DH; -p for PSK; expires in days");
|
||||
return;
|
||||
}
|
||||
String name = argv[g.getOptind()];
|
||||
@ -1833,12 +2066,18 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
session.connect();
|
||||
System.out.println("Sending: " + bd);
|
||||
session.sendBlindingInfo(bd);
|
||||
try { Thread.sleep(1000); } catch (InterruptedException ie) {}
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException ie) {
|
||||
}
|
||||
} catch (I2PSessionException ise) {
|
||||
System.out.println("Send blinding info failed: " + ise);
|
||||
} finally {
|
||||
if (session != null) {
|
||||
try { session.destroySession(); } catch (I2PSessionException ise) {}
|
||||
try {
|
||||
session.destroySession();
|
||||
} catch (I2PSessionException ise) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1906,7 +2145,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the given message (using both the logging subsystem and standard output...)
|
||||
* Log the given message (using both the logging subsystem and standard
|
||||
* output...)
|
||||
*
|
||||
*/
|
||||
public void log(String s) {
|
||||
@ -1972,7 +2212,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
* @param l logger to send messages to
|
||||
*/
|
||||
private static void writePubKey(Destination d, OutputStream o, Logging l) throws I2PException, IOException {
|
||||
if (o == null) return;
|
||||
if (o == null)
|
||||
return;
|
||||
d.writeBytes(o);
|
||||
l.log("Public key saved.");
|
||||
}
|
||||
@ -1986,7 +2227,10 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
*
|
||||
* Since file:<filename> isn't really used, this method is deprecated,
|
||||
* just call context.namingService.lookup() directly.
|
||||
* @deprecated Don't use i2ptunnel for lookup! Use I2PAppContext.getGlobalContext().namingService().lookup(name) from i2p.jar
|
||||
*
|
||||
* @deprecated Don't use i2ptunnel for lookup! Use
|
||||
* I2PAppContext.getGlobalContext().namingService().lookup(name)
|
||||
* from i2p.jar
|
||||
*/
|
||||
@Deprecated
|
||||
public static Destination destFromName(String name) throws DataFormatException {
|
||||
@ -2004,7 +2248,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
String i2cpPort, boolean isSSL,
|
||||
String user, String pw) throws DataFormatException {
|
||||
|
||||
if ((name == null) || (name.trim().length() <= 0)) throw new DataFormatException("Empty destination provided");
|
||||
if ((name == null) || (name.trim().length() <= 0))
|
||||
throw new DataFormatException("Empty destination provided");
|
||||
|
||||
I2PAppContext ctx = I2PAppContext.getGlobalContext();
|
||||
Log log = ctx.logManager().getLog(I2PTunnel.class);
|
||||
@ -2023,7 +2268,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
System.out.println(ioe.getMessage());
|
||||
return null;
|
||||
} finally {
|
||||
if (in != null) try {
|
||||
if (in != null)
|
||||
try {
|
||||
in.close();
|
||||
} catch (IOException io) {
|
||||
}
|
||||
@ -2082,7 +2328,10 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
log.warn("Lookup via router failed", ise);
|
||||
} finally {
|
||||
if (session != null) {
|
||||
try { session.destroySession(); } catch (I2PSessionException ise) {}
|
||||
try {
|
||||
session.destroySession();
|
||||
} catch (I2PSessionException ise) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return d;
|
||||
@ -2090,28 +2339,36 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
}
|
||||
|
||||
public void addConnectionEventListener(ConnectionEventListener lsnr) {
|
||||
if (lsnr == null) return;
|
||||
if (lsnr == null)
|
||||
return;
|
||||
listeners.add(lsnr);
|
||||
}
|
||||
|
||||
public void removeConnectionEventListener(ConnectionEventListener lsnr) {
|
||||
if (lsnr == null) return;
|
||||
if (lsnr == null)
|
||||
return;
|
||||
listeners.remove(lsnr);
|
||||
}
|
||||
|
||||
private String getPrefix() { return "[" + _tunnelId + "]: "; }
|
||||
private String getPrefix() {
|
||||
return "[" + _tunnelId + "]: ";
|
||||
}
|
||||
|
||||
public I2PAppContext getContext() { return _context; }
|
||||
public I2PAppContext getContext() {
|
||||
return _context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this whenever we lose touch with the router involuntarily (aka the router
|
||||
* Call this whenever we lose touch with the router involuntarily (aka the
|
||||
* router
|
||||
* is off / crashed / etc)
|
||||
*
|
||||
*/
|
||||
void routerDisconnected() {
|
||||
_log.error(getPrefix() + "Router disconnected - firing notification events");
|
||||
for (ConnectionEventListener lsnr : listeners) {
|
||||
if (lsnr != null) lsnr.routerDisconnected();
|
||||
if (lsnr != null)
|
||||
lsnr.routerDisconnected();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -167,8 +167,13 @@ public class TunnelController implements Logging {
|
||||
/** Server in the UI and I2P side but a client on the localhost side */
|
||||
public static final String TYPE_STREAMR_SERVER = "streamrserver";
|
||||
|
||||
/** UDP Client and Server */
|
||||
public static final String TYPE_UDP_CLIENT = "udpclient";
|
||||
public static final String TYPE_UDP_SERVER = "udpserver";
|
||||
|
||||
/**
|
||||
* This is guaranteed to be available.
|
||||
*
|
||||
* @since 0.9.17
|
||||
*/
|
||||
public static final SigType PREFERRED_SIGTYPE;
|
||||
@ -189,10 +194,12 @@ 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)
|
||||
*
|
||||
* If config contains the "configFile" property, it will be set as the config path
|
||||
* If config contains the "configFile" property, it will be set as the config
|
||||
* path
|
||||
* and may be retrieved with getConfigFile().
|
||||
*
|
||||
* Defaults in config properties are not recommended, they may or may not be honored.
|
||||
* Defaults in config properties are not recommended, they may or may not be
|
||||
* honored.
|
||||
*
|
||||
* @param config original key=value mapping non-null
|
||||
* @param prefix beginning of key values that are relevant to this tunnel
|
||||
@ -207,14 +214,17 @@ 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)
|
||||
*
|
||||
* If config contains the "configFile" property, it will be set as the config path
|
||||
* If config contains the "configFile" property, it will be set as the config
|
||||
* path
|
||||
* and may be retrieved with getConfigFile().
|
||||
*
|
||||
* Defaults in config properties are not recommended, they may or may not be honored.
|
||||
* Defaults in config properties are not recommended, they may or may not be
|
||||
* honored.
|
||||
*
|
||||
* @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
|
||||
* @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)
|
||||
*/
|
||||
@ -301,13 +311,18 @@ public class TunnelController implements Logging {
|
||||
log("Error writing the keys to " + keyFile.getAbsolutePath());
|
||||
return false;
|
||||
} finally {
|
||||
if (fos != null) try { fos.close(); } catch (IOException ioe) {}
|
||||
if (fos != null)
|
||||
try {
|
||||
fos.close();
|
||||
} catch (IOException ioe) {
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates alternate Destination with the same encryption keys as the primary Destination,
|
||||
* Creates alternate Destination with the same encryption keys as the primary
|
||||
* Destination,
|
||||
* but a different signing key.
|
||||
*
|
||||
* Must have already called createPrivateKey() successfully.
|
||||
@ -363,7 +378,10 @@ public class TunnelController implements Logging {
|
||||
d.writeBytes(out);
|
||||
priv.writeBytes(out);
|
||||
signingPrivKey.writeBytes(out);
|
||||
try { out.close(); } catch (IOException ioe) {}
|
||||
try {
|
||||
out.close();
|
||||
} catch (IOException ioe) {
|
||||
}
|
||||
|
||||
String destStr = d.toBase64();
|
||||
log("Alternate private key created and saved in " + altFile.getAbsolutePath());
|
||||
@ -397,7 +415,11 @@ public class TunnelController implements Logging {
|
||||
log("Error creating keys " + e);
|
||||
return false;
|
||||
} finally {
|
||||
if (out != null) try { out.close(); } catch (IOException ioe) {}
|
||||
if (out != null)
|
||||
try {
|
||||
out.close();
|
||||
} catch (IOException ioe) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -406,7 +428,11 @@ public class TunnelController implements Logging {
|
||||
if (_state != TunnelState.STOPPED && _state != TunnelState.START_ON_LOAD)
|
||||
return;
|
||||
}
|
||||
new I2PAppThread(new Runnable() { public void run() { startTunnel(); } }, "Tunnel Starter " + getName()).start();
|
||||
new I2PAppThread(new Runnable() {
|
||||
public void run() {
|
||||
startTunnel();
|
||||
}
|
||||
}, "Tunnel Starter " + getName()).start();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -492,6 +518,10 @@ public class TunnelController implements Logging {
|
||||
startIrcServer();
|
||||
} else if (TYPE_STREAMR_SERVER.equals(type)) {
|
||||
startStreamrServer();
|
||||
} else if (TYPE_UDP_CLIENT.equals(type)) {
|
||||
startUDPClient();
|
||||
} else if (TYPE_UDP_SERVER.equals(type)) {
|
||||
startUDPServer();
|
||||
} else {
|
||||
changeState(TunnelState.STOPPED);
|
||||
if (_log.shouldLog(Log.ERROR))
|
||||
@ -592,6 +622,29 @@ public class TunnelController implements Logging {
|
||||
_tunnel.runStreamrClient(new String[] { targetHost, targetPort, dest }, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* UDP server is a UDP client, use the targetPort field for listenPort
|
||||
*/
|
||||
private void startUDPServer() {
|
||||
String listenOn = getListenOnInterface();
|
||||
if ((listenOn != null) && (listenOn.length() > 0)) {
|
||||
_tunnel.runListenOn(new String[] { listenOn }, this);
|
||||
}
|
||||
String listenPort = getTargetPort();
|
||||
String privKeyFile = getPrivKeyFile();
|
||||
_tunnel.runUDPServer(new String[] { listenPort, privKeyFile }, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* UDP client is a UDP server, use the listenPort field for targetPort
|
||||
*/
|
||||
private void startUDPClient() {
|
||||
String targetHost = getTargetHost();
|
||||
String targetPort = getListenPort();
|
||||
String dest = getTargetDestination();
|
||||
_tunnel.runUDPClient(new String[] { targetHost, targetPort, dest }, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Streamr server is a UDP client, use the targetPort field for listenPort
|
||||
*/
|
||||
@ -783,7 +836,8 @@ public class TunnelController implements Logging {
|
||||
|
||||
/**
|
||||
* May be restarted with restartTunnel() or startTunnel() later.
|
||||
* This may not release all resources. In particular, the I2PSocketManager remains
|
||||
* This may not release all resources. In particular, the I2PSocketManager
|
||||
* remains
|
||||
* and it may have timer threads that continue running.
|
||||
*/
|
||||
public void stopTunnel() {
|
||||
@ -837,7 +891,10 @@ public class TunnelController implements Logging {
|
||||
}
|
||||
if (oldState != TunnelState.STOPPED) {
|
||||
long ms = _tunnel.getContext().isRouterContext() ? 100 : 500;
|
||||
try { Thread.sleep(ms); } catch (InterruptedException ie) {}
|
||||
try {
|
||||
Thread.sleep(ms);
|
||||
} catch (InterruptedException ie) {
|
||||
}
|
||||
}
|
||||
startTunnel();
|
||||
}
|
||||
@ -896,7 +953,7 @@ public class TunnelController implements Logging {
|
||||
// override UI that sets it to false
|
||||
_config.setProperty(OPT_BUNDLE_REPLY, "true");
|
||||
}
|
||||
if (type.contains("irc") || type.equals(TYPE_STREAMR_CLIENT)) {
|
||||
if (type.contains("irc") || type.equals(TYPE_STREAMR_CLIENT) || type.equals(TYPE_UDP_SERVER)) {
|
||||
// maybe a bad idea for ircclient if DCC is enabled
|
||||
if (!_config.containsKey(OPT_TAGS_SEND))
|
||||
_config.setProperty(OPT_TAGS_SEND, "20");
|
||||
@ -946,7 +1003,8 @@ public class TunnelController implements Logging {
|
||||
String p10 = _config.getProperty(OPT_POST_TOTAL_MAX, "0");
|
||||
if (p9.equals("0") && p10.equals("0")) {
|
||||
_config.setProperty(OPT_POST_MAX, Integer.toString(I2PTunnelHTTPServer.DEFAULT_POST_MAX));
|
||||
_config.setProperty(OPT_POST_TOTAL_MAX, Integer.toString(I2PTunnelHTTPServer.DEFAULT_POST_TOTAL_MAX));
|
||||
_config.setProperty(OPT_POST_TOTAL_MAX,
|
||||
Integer.toString(I2PTunnelHTTPServer.DEFAULT_POST_TOTAL_MAX));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -999,6 +1057,7 @@ public class TunnelController implements Logging {
|
||||
|
||||
/**
|
||||
* Is property p different in p1 and p2?
|
||||
*
|
||||
* @since 0.9.30
|
||||
*/
|
||||
private static boolean configChanged(Properties p1, Properties p2, String p) {
|
||||
@ -1030,30 +1089,54 @@ public class TunnelController implements Logging {
|
||||
* or as set later, or null
|
||||
* @since 0.9.42
|
||||
*/
|
||||
public File getConfigFile() { return _configFile; }
|
||||
public File getConfigFile() {
|
||||
return _configFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the config file. Only do this if previously null.
|
||||
*
|
||||
* @since 0.9.42
|
||||
*/
|
||||
public void setConfigFile(File file) { _configFile = file; }
|
||||
public void setConfigFile(File file) {
|
||||
_configFile = file;
|
||||
}
|
||||
|
||||
public String getType() { return _config.getProperty(PROP_TYPE); }
|
||||
public String getName() { return _config.getProperty(PROP_NAME); }
|
||||
public String getDescription() { return _config.getProperty(PROP_DESCR); }
|
||||
public String getI2CPHost() { return _config.getProperty(PROP_I2CP_HOST); }
|
||||
public String getI2CPPort() { return _config.getProperty(PROP_I2CP_PORT); }
|
||||
public String getType() {
|
||||
return _config.getProperty(PROP_TYPE);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return _config.getProperty(PROP_NAME);
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return _config.getProperty(PROP_DESCR);
|
||||
}
|
||||
|
||||
public String getI2CPHost() {
|
||||
return _config.getProperty(PROP_I2CP_HOST);
|
||||
}
|
||||
|
||||
public String getI2CPPort() {
|
||||
return _config.getProperty(PROP_I2CP_PORT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Absolute path to filter definition file
|
||||
*
|
||||
* @since 0.9.40
|
||||
*/
|
||||
public String getFilter() { return _config.getProperty(PROP_FILTER); }
|
||||
public String getFilter() {
|
||||
return _config.getProperty(PROP_FILTER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is it a client or server in the UI and I2P side?
|
||||
* Note that a streamr client is a UI and I2P client but a server on the localhost side.
|
||||
* Note that a streamr server is a UI and I2P server but a client on the localhost side.
|
||||
* Note that a streamr client is a UI and I2P client but a server on the
|
||||
* localhost side.
|
||||
* Note that a streamr server is a UI and I2P server but a client on the
|
||||
* localhost side.
|
||||
*
|
||||
* @since 0.9.17
|
||||
*/
|
||||
@ -1063,8 +1146,10 @@ public class TunnelController implements Logging {
|
||||
|
||||
/**
|
||||
* Is it a client or server in the UI and I2P side?
|
||||
* Note that a streamr client is a UI and I2P client but a server on the localhost side.
|
||||
* Note that a streamr server is a UI and I2P server but a client on the localhost side.
|
||||
* Note that a streamr client is a UI and I2P client but a server on the
|
||||
* localhost side.
|
||||
* Note that a streamr server is a UI and I2P server but a client on the
|
||||
* localhost side.
|
||||
*
|
||||
* @since 0.9.17 moved from IndexBean
|
||||
* @return false if type == null
|
||||
@ -1076,6 +1161,7 @@ public class TunnelController implements Logging {
|
||||
TYPE_SOCKS_IRC.equals(type) ||
|
||||
TYPE_CONNECT.equals(type) ||
|
||||
TYPE_STREAMR_CLIENT.equals(type) ||
|
||||
TYPE_UDP_CLIENT.equals(type) ||
|
||||
TYPE_IRC_CLIENT.equals(type);
|
||||
}
|
||||
|
||||
@ -1093,26 +1179,48 @@ public class TunnelController implements Logging {
|
||||
if (key.startsWith(PFX_OPTION)) {
|
||||
key = key.substring(PFX_OPTION.length());
|
||||
String val = (String) e.getValue();
|
||||
if (opts.length() > 0) opts.append(' ');
|
||||
if (opts.length() > 0)
|
||||
opts.append(' ');
|
||||
opts.append(key).append('=').append(val);
|
||||
}
|
||||
}
|
||||
return opts.toString();
|
||||
}
|
||||
|
||||
public String getListenOnInterface() { return _config.getProperty(PROP_INTFC); }
|
||||
public String getTargetHost() { return _config.getProperty(PROP_TARGET_HOST); }
|
||||
public String getTargetPort() { return _config.getProperty(PROP_TARGET_PORT); }
|
||||
public String getSpoofedHost() { return _config.getProperty(PROP_SPOOFED_HOST); }
|
||||
public String getListenOnInterface() {
|
||||
return _config.getProperty(PROP_INTFC);
|
||||
}
|
||||
|
||||
public String getTargetHost() {
|
||||
return _config.getProperty(PROP_TARGET_HOST);
|
||||
}
|
||||
|
||||
public String getTargetPort() {
|
||||
return _config.getProperty(PROP_TARGET_PORT);
|
||||
}
|
||||
|
||||
public String getSpoofedHost() {
|
||||
return _config.getProperty(PROP_SPOOFED_HOST);
|
||||
}
|
||||
|
||||
/**
|
||||
* Probably not absolute. May be null. getPrivateKeyFile() recommended.
|
||||
*/
|
||||
public String getPrivKeyFile() { return _config.getProperty(PROP_FILE); }
|
||||
public String getPrivKeyFile() {
|
||||
return _config.getProperty(PROP_FILE);
|
||||
}
|
||||
|
||||
public String getListenPort() { return _config.getProperty(PROP_LISTEN_PORT); }
|
||||
public String getTargetDestination() { return _config.getProperty(PROP_DEST); }
|
||||
public String getProxyList() { return _config.getProperty(PROP_PROXIES); }
|
||||
public String getListenPort() {
|
||||
return _config.getProperty(PROP_LISTEN_PORT);
|
||||
}
|
||||
|
||||
public String getTargetDestination() {
|
||||
return _config.getProperty(PROP_DEST);
|
||||
}
|
||||
|
||||
public String getProxyList() {
|
||||
return _config.getProperty(PROP_PROXIES);
|
||||
}
|
||||
|
||||
/** default true for clients, always false for servers */
|
||||
public String getSharedClient() {
|
||||
@ -1122,11 +1230,17 @@ public class TunnelController implements Logging {
|
||||
}
|
||||
|
||||
/** default true */
|
||||
public boolean getStartOnLoad() { return Boolean.parseBoolean(_config.getProperty(PROP_START, "true")); }
|
||||
public boolean getPersistentClientKey() { return Boolean.parseBoolean(_config.getProperty(OPT_PERSISTENT)); }
|
||||
public boolean getStartOnLoad() {
|
||||
return Boolean.parseBoolean(_config.getProperty(PROP_START, "true"));
|
||||
}
|
||||
|
||||
public boolean getPersistentClientKey() {
|
||||
return Boolean.parseBoolean(_config.getProperty(OPT_PERSISTENT));
|
||||
}
|
||||
|
||||
/**
|
||||
* Does not necessarily exist.
|
||||
*
|
||||
* @return absolute path or null if unset
|
||||
* @since 0.9.17
|
||||
*/
|
||||
@ -1136,6 +1250,7 @@ public class TunnelController implements Logging {
|
||||
|
||||
/**
|
||||
* Does not necessarily exist.
|
||||
*
|
||||
* @return absolute path or null if unset
|
||||
* @since 0.9.30
|
||||
*/
|
||||
@ -1145,6 +1260,7 @@ public class TunnelController implements Logging {
|
||||
|
||||
/**
|
||||
* Does not necessarily exist.
|
||||
*
|
||||
* @param f relative or absolute path, may be null
|
||||
* @return absolute path or null
|
||||
* @since 0.9.30
|
||||
@ -1163,6 +1279,7 @@ public class TunnelController implements Logging {
|
||||
|
||||
/**
|
||||
* Returns null if not running.
|
||||
*
|
||||
* @return Base64 or null
|
||||
*/
|
||||
public String getMyDestination() {
|
||||
@ -1174,6 +1291,7 @@ public class TunnelController implements Logging {
|
||||
|
||||
/**
|
||||
* Returns null if not running.
|
||||
*
|
||||
* @return "{52 chars}.b32.i2p" or null
|
||||
*/
|
||||
public String getMyDestHashBase32() {
|
||||
@ -1185,6 +1303,7 @@ public class TunnelController implements Logging {
|
||||
|
||||
/**
|
||||
* Returns null if not running.
|
||||
*
|
||||
* @return Destination or null
|
||||
* @since 0.9.17
|
||||
*/
|
||||
@ -1201,6 +1320,7 @@ public class TunnelController implements Logging {
|
||||
|
||||
/**
|
||||
* Returns false if not running.
|
||||
*
|
||||
* @return true if the primary session has offline keys
|
||||
* @since 0.9.40
|
||||
*/
|
||||
@ -1213,6 +1333,7 @@ public class TunnelController implements Logging {
|
||||
|
||||
/**
|
||||
* Returns false if not running.
|
||||
*
|
||||
* @return true if ANY session or subsession has offline keys
|
||||
* @since 0.9.48
|
||||
*/
|
||||
@ -1230,8 +1351,13 @@ public class TunnelController implements Logging {
|
||||
}
|
||||
|
||||
// TODO synch
|
||||
public boolean getIsRunning() { return _state == TunnelState.RUNNING; }
|
||||
public boolean getIsStarting() { return _state == TunnelState.START_ON_LOAD || _state == TunnelState.STARTING; }
|
||||
public boolean getIsRunning() {
|
||||
return _state == TunnelState.RUNNING;
|
||||
}
|
||||
|
||||
public boolean getIsStarting() {
|
||||
return _state == TunnelState.START_ON_LOAD || _state == TunnelState.STARTING;
|
||||
}
|
||||
|
||||
/** if running but no open sessions, we are in standby */
|
||||
public boolean getIsStandby() {
|
||||
@ -1254,6 +1380,7 @@ public class TunnelController implements Logging {
|
||||
|
||||
/**
|
||||
* A text description of the tunnel.
|
||||
*
|
||||
* @deprecated unused
|
||||
*/
|
||||
@Deprecated
|
||||
@ -1261,111 +1388,136 @@ public class TunnelController implements Logging {
|
||||
String type = getType();
|
||||
buf.append(type);
|
||||
/****
|
||||
if ("httpclient".equals(type))
|
||||
getHttpClientSummary(buf);
|
||||
else if ("client".equals(type))
|
||||
getClientSummary(buf);
|
||||
else if ("server".equals(type))
|
||||
getServerSummary(buf);
|
||||
else if ("httpserver".equals(type))
|
||||
getHttpServerSummary(buf);
|
||||
else
|
||||
buf.append("Unknown type ").append(type);
|
||||
* if ("httpclient".equals(type))
|
||||
* getHttpClientSummary(buf);
|
||||
* else if ("client".equals(type))
|
||||
* getClientSummary(buf);
|
||||
* else if ("server".equals(type))
|
||||
* getServerSummary(buf);
|
||||
* else if ("httpserver".equals(type))
|
||||
* getHttpServerSummary(buf);
|
||||
* else
|
||||
* buf.append("Unknown type ").append(type);
|
||||
****/
|
||||
}
|
||||
|
||||
/****
|
||||
private void getHttpClientSummary(StringBuilder buf) {
|
||||
String description = getDescription();
|
||||
if ( (description != null) && (description.trim().length() > 0) )
|
||||
buf.append("<i>").append(description).append("</i><br />\n");
|
||||
buf.append("HTTP proxy listening on port ").append(getListenPort());
|
||||
String listenOn = getListenOnInterface();
|
||||
if ("0.0.0.0".equals(listenOn))
|
||||
buf.append(" (reachable by any machine)");
|
||||
else if ("127.0.0.1".equals(listenOn))
|
||||
buf.append(" (reachable locally only)");
|
||||
else
|
||||
buf.append(" (reachable at the ").append(listenOn).append(" interface)");
|
||||
buf.append("<br />\n");
|
||||
String proxies = getProxyList();
|
||||
if ( (proxies == null) || (proxies.trim().length() <= 0) )
|
||||
buf.append("Outproxy: default [squid.i2p]<br />\n");
|
||||
else
|
||||
buf.append("Outproxy: ").append(proxies).append("<br />\n");
|
||||
getOptionSummary(buf);
|
||||
}
|
||||
|
||||
private void getClientSummary(StringBuilder buf) {
|
||||
String description = getDescription();
|
||||
if ( (description != null) && (description.trim().length() > 0) )
|
||||
buf.append("<i>").append(description).append("</i><br />\n");
|
||||
buf.append("Client tunnel listening on port ").append(getListenPort());
|
||||
buf.append(" pointing at ").append(getTargetDestination());
|
||||
String listenOn = getListenOnInterface();
|
||||
if ("0.0.0.0".equals(listenOn))
|
||||
buf.append(" (reachable by any machine)");
|
||||
else if ("127.0.0.1".equals(listenOn))
|
||||
buf.append(" (reachable locally only)");
|
||||
else
|
||||
buf.append(" (reachable at the ").append(listenOn).append(" interface)");
|
||||
buf.append("<br />\n");
|
||||
getOptionSummary(buf);
|
||||
}
|
||||
|
||||
private void getServerSummary(StringBuilder buf) {
|
||||
String description = getDescription();
|
||||
if ( (description != null) && (description.trim().length() > 0) )
|
||||
buf.append("<i>").append(description).append("</i><br />\n");
|
||||
buf.append("Server tunnel pointing at port ").append(getTargetPort());
|
||||
buf.append(" on ").append(getTargetHost());
|
||||
buf.append("<br />\n");
|
||||
buf.append("Private destination loaded from ").append(getPrivKeyFile()).append("<br />\n");
|
||||
getOptionSummary(buf);
|
||||
}
|
||||
|
||||
private void getHttpServerSummary(StringBuilder buf) {
|
||||
String description = getDescription();
|
||||
if ( (description != null) && (description.trim().length() > 0) )
|
||||
buf.append("<i>").append(description).append("</i><br />\n");
|
||||
buf.append("Server tunnel pointing at port ").append(getTargetPort());
|
||||
buf.append(" on ").append(getTargetHost());
|
||||
buf.append(" for the site ").append(getSpoofedHost());
|
||||
buf.append("<br />\n");
|
||||
buf.append("Private destination loaded from ").append(getPrivKeyFile()).append("<br />\n");
|
||||
getOptionSummary(buf);
|
||||
}
|
||||
|
||||
private void getOptionSummary(StringBuilder buf) {
|
||||
String opts = getClientOptions();
|
||||
if ( (opts != null) && (opts.length() > 0) )
|
||||
buf.append("Network options: ").append(opts).append("<br />\n");
|
||||
if (_running) {
|
||||
List<I2PSession> sessions = _tunnel.getSessions();
|
||||
for (int i = 0; i < sessions.size(); i++) {
|
||||
I2PSession session = sessions.get(i);
|
||||
Destination dest = session.getMyDestination();
|
||||
if (dest != null) {
|
||||
buf.append("Destination hash: ").append(dest.calculateHash().toBase64()).append("<br />\n");
|
||||
if ( ("server".equals(getType())) || ("httpserver".equals(getType())) ) {
|
||||
buf.append("Full destination: ");
|
||||
buf.append("<input type=\"text\" size=\"10\" onclick=\"this.select();\" ");
|
||||
buf.append("value=\"").append(dest.toBase64()).append("\" />\n");
|
||||
long val = new Random().nextLong();
|
||||
if (val < 0) val = 0 - val;
|
||||
buf.append("<br />You can <a href=\"http://temp").append(val);
|
||||
buf.append(".i2p/?i2paddresshelper=").append(dest.toBase64()).append("\">view</a>");
|
||||
buf.append(" it in a browser (only when you're using the eepProxy)\n");
|
||||
buf.append("<br />If you are going to share this on IRC, you need to split it up:<br />\n");
|
||||
String str = dest.toBase64();
|
||||
buf.append(str.substring(0, str.length()/2)).append("<br />\n");
|
||||
buf.append(str.substring(str.length()/2)).append("<br />\n");
|
||||
buf.append("You can also post it to <a href=\"http://forum.i2p/viewforum.php?f=16\">Eepsite announcement forum</a><br />");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
* private void getHttpClientSummary(StringBuilder buf) {
|
||||
* String description = getDescription();
|
||||
* if ( (description != null) && (description.trim().length() > 0) )
|
||||
* buf.append("<i>").append(description).append("</i><br />
|
||||
* \n");
|
||||
* buf.append("HTTP proxy listening on port ").append(getListenPort());
|
||||
* String listenOn = getListenOnInterface();
|
||||
* if ("0.0.0.0".equals(listenOn))
|
||||
* buf.append(" (reachable by any machine)");
|
||||
* else if ("127.0.0.1".equals(listenOn))
|
||||
* buf.append(" (reachable locally only)");
|
||||
* else
|
||||
* buf.append(" (reachable at the ").append(listenOn).append(" interface)");
|
||||
* buf.append("<br />
|
||||
* \n");
|
||||
* String proxies = getProxyList();
|
||||
* if ( (proxies == null) || (proxies.trim().length() <= 0) )
|
||||
* buf.append("Outproxy: default [squid.i2p]<br />
|
||||
* \n");
|
||||
* else
|
||||
* buf.append("Outproxy: ").append(proxies).append("<br />
|
||||
* \n");
|
||||
* getOptionSummary(buf);
|
||||
* }
|
||||
*
|
||||
* private void getClientSummary(StringBuilder buf) {
|
||||
* String description = getDescription();
|
||||
* if ( (description != null) && (description.trim().length() > 0) )
|
||||
* buf.append("<i>").append(description).append("</i><br />
|
||||
* \n");
|
||||
* buf.append("Client tunnel listening on port ").append(getListenPort());
|
||||
* buf.append(" pointing at ").append(getTargetDestination());
|
||||
* String listenOn = getListenOnInterface();
|
||||
* if ("0.0.0.0".equals(listenOn))
|
||||
* buf.append(" (reachable by any machine)");
|
||||
* else if ("127.0.0.1".equals(listenOn))
|
||||
* buf.append(" (reachable locally only)");
|
||||
* else
|
||||
* buf.append(" (reachable at the ").append(listenOn).append(" interface)");
|
||||
* buf.append("<br />
|
||||
* \n");
|
||||
* getOptionSummary(buf);
|
||||
* }
|
||||
*
|
||||
* private void getServerSummary(StringBuilder buf) {
|
||||
* String description = getDescription();
|
||||
* if ( (description != null) && (description.trim().length() > 0) )
|
||||
* buf.append("<i>").append(description).append("</i><br />
|
||||
* \n");
|
||||
* buf.append("Server tunnel pointing at port ").append(getTargetPort());
|
||||
* buf.append(" on ").append(getTargetHost());
|
||||
* buf.append("<br />
|
||||
* \n");
|
||||
* buf.append("Private destination loaded from
|
||||
* ").append(getPrivKeyFile()).append("<br />
|
||||
* \n");
|
||||
* getOptionSummary(buf);
|
||||
* }
|
||||
*
|
||||
* private void getHttpServerSummary(StringBuilder buf) {
|
||||
* String description = getDescription();
|
||||
* if ( (description != null) && (description.trim().length() > 0) )
|
||||
* buf.append("<i>").append(description).append("</i><br />
|
||||
* \n");
|
||||
* buf.append("Server tunnel pointing at port ").append(getTargetPort());
|
||||
* buf.append(" on ").append(getTargetHost());
|
||||
* buf.append(" for the site ").append(getSpoofedHost());
|
||||
* buf.append("<br />
|
||||
* \n");
|
||||
* buf.append("Private destination loaded from
|
||||
* ").append(getPrivKeyFile()).append("<br />
|
||||
* \n");
|
||||
* getOptionSummary(buf);
|
||||
* }
|
||||
*
|
||||
* private void getOptionSummary(StringBuilder buf) {
|
||||
* String opts = getClientOptions();
|
||||
* if ( (opts != null) && (opts.length() > 0) )
|
||||
* buf.append("Network options: ").append(opts).append("<br />
|
||||
* \n");
|
||||
* if (_running) {
|
||||
* List<I2PSession> sessions = _tunnel.getSessions();
|
||||
* for (int i = 0; i < sessions.size(); i++) {
|
||||
* I2PSession session = sessions.get(i);
|
||||
* Destination dest = session.getMyDestination();
|
||||
* if (dest != null) {
|
||||
* buf.append("Destination hash:
|
||||
* ").append(dest.calculateHash().toBase64()).append("<br />
|
||||
* \n");
|
||||
* if ( ("server".equals(getType())) || ("httpserver".equals(getType())) ) {
|
||||
* buf.append("Full destination: ");
|
||||
* buf.append("<input type=\"text\" size=\"10\" onclick=\"this.select();\" ");
|
||||
* buf.append("value=\"").append(dest.toBase64()).append("\" />\n");
|
||||
* long val = new Random().nextLong();
|
||||
* if (val < 0) val = 0 - val;
|
||||
* buf.append("<br />
|
||||
* You can <a href=\"http://temp").append(val);
|
||||
* buf.append(".i2p/?i2paddresshelper=").append(dest.toBase64()).append("\">view</a>");
|
||||
* buf.append(" it in a browser (only when you're using the eepProxy)\n");
|
||||
* buf.append("<br />
|
||||
* If you are going to share this on IRC, you need to split it up:<br />
|
||||
* \n");
|
||||
* String str = dest.toBase64();
|
||||
* buf.append(str.substring(0, str.length()/2)).append("<br />
|
||||
* \n");
|
||||
* buf.append(str.substring(str.length()/2)).append("<br />
|
||||
* \n");
|
||||
* buf.append("You can also post it to <a
|
||||
* href=\"http://forum.i2p/viewforum.php?f=16\">Eepsite announcement
|
||||
* forum</a><br />
|
||||
* ");
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
****/
|
||||
|
||||
/**
|
||||
@ -1416,6 +1568,7 @@ public class TunnelController implements Logging {
|
||||
|
||||
/**
|
||||
* caller must schedule
|
||||
*
|
||||
* @param f2 may be null
|
||||
*/
|
||||
public PKFChecker(File f, File f2) {
|
||||
@ -1469,9 +1622,11 @@ public class TunnelController implements Logging {
|
||||
// can't sign another LS
|
||||
String msg;
|
||||
if (remaining > 0)
|
||||
msg = "Offline signature in private key file " + f + " for tunnel expires " + DataHelper.formatTime(exp) + ", stopping the tunnel!";
|
||||
msg = "Offline signature in private key file " + f + " for tunnel expires "
|
||||
+ DataHelper.formatTime(exp) + ", stopping the tunnel!";
|
||||
else
|
||||
msg = "Offline signature in private key file " + f + " for tunnel expired " + DataHelper.formatTime(exp) + ", stopping the tunnel!";
|
||||
msg = "Offline signature in private key file " + f + " for tunnel expired "
|
||||
+ DataHelper.formatTime(exp) + ", stopping the tunnel!";
|
||||
_log.log(Log.CRIT, msg);
|
||||
_tunnel.log(msg);
|
||||
stopTunnel();
|
||||
@ -1494,7 +1649,8 @@ public class TunnelController implements Logging {
|
||||
}
|
||||
}
|
||||
if (remaining < 30 * 24 * 60 * 60 * 1000L) {
|
||||
String msg = "Offline signature in private key file " + f + " for tunnel expires in " + DataHelper.formatDuration(remaining);
|
||||
String msg = "Offline signature in private key file " + f + " for tunnel expires in "
|
||||
+ DataHelper.formatDuration(remaining);
|
||||
_log.logAlways(Log.WARN, msg);
|
||||
_tunnel.log("WARNING: " + msg);
|
||||
}
|
||||
|
@ -0,0 +1,199 @@
|
||||
package net.i2p.i2ptunnel.udpTunnel;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import net.i2p.client.I2PSession;
|
||||
import net.i2p.client.datagram.I2PDatagramDissector;
|
||||
import net.i2p.data.DataFormatException;
|
||||
import net.i2p.i2ptunnel.I2PTunnel;
|
||||
import net.i2p.i2ptunnel.Logging;
|
||||
import net.i2p.i2ptunnel.udp.I2PSink;
|
||||
import net.i2p.i2ptunnel.udp.I2PSource;
|
||||
//import net.i2p.i2ptunnel.streamr.Pinger;
|
||||
import net.i2p.i2ptunnel.udp.UDPSink;
|
||||
import net.i2p.i2ptunnel.udp.UDPSource;
|
||||
import net.i2p.util.EventDispatcher;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
/**
|
||||
*
|
||||
* Client side(I2PTunnelUDPClient.java):
|
||||
*
|
||||
* - permanent DatagramSocket at e.g. localhost:5353
|
||||
* - For EVERY incoming IP datagram request, assign a new I2CP source port,
|
||||
* store the source IP/port in a table keyed by the I2CP source port
|
||||
* - send a REPLIABLE datagram to the server with the I2CP source port
|
||||
*
|
||||
* Server side(I2PTunnelUDPServerClient.java):
|
||||
*
|
||||
* - receive request, store source I2P Dest/port associated with the request
|
||||
* - For EVERY incoming I2P datagram request, open a NEW DatagramSocket on
|
||||
* localhost with an EPHEMERAL port. Send the request out the socket and wait
|
||||
* for a single reply.
|
||||
* - Send reply as a RAW datagram to the stored I2P Dest/port. and CLOSE the
|
||||
* DatagramSocket.
|
||||
*
|
||||
* Client side:
|
||||
*
|
||||
* - receive reply on the destination I2CP port. Look up source IP/port in the
|
||||
* table by the destination I2CP port.
|
||||
* - Send reply to the stored IP/port, and remove entry from table.
|
||||
*
|
||||
* @author idk
|
||||
*/
|
||||
|
||||
public class I2PTunnelUDPClient extends I2PTunnelUDPClientBase {
|
||||
private final Log _log = new Log(I2PTunnelUDPClient.class);
|
||||
|
||||
// UDP Side
|
||||
// permanent DatagramSocket at e.g. localhost:5353
|
||||
private final DatagramSocket _socket;
|
||||
// InetAddress corresponding to local DatagramSocket
|
||||
private final InetAddress UDP_HOSTNAME;
|
||||
// UDP port corresponding to local DatagramSocket
|
||||
private final int UDP_PORT;
|
||||
private final int MAX_SIZE = 1024;
|
||||
private final UDPSink _sink;
|
||||
|
||||
// SourceIP/Port table
|
||||
private Map<Integer, InetSocketAddress> _sourceIPPortTable = new HashMap<>();
|
||||
|
||||
// Constructor, host is localhost(usually) or the host of the UDP client, port
|
||||
// is the port of the UDP client
|
||||
public I2PTunnelUDPClient(String host, int port, String destination, Logging l, EventDispatcher notifyThis,
|
||||
I2PTunnel tunnel) {
|
||||
// super(host, port,
|
||||
super(destination, l, notifyThis, tunnel);
|
||||
UDPSink sink = null;
|
||||
UDP_PORT = port;
|
||||
InetAddress udpHostname = null;
|
||||
try {
|
||||
udpHostname = InetAddress.getByName(host);
|
||||
} catch (Exception e) {
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Failed to resolve hostname, using default(localhost): " + host, e);
|
||||
udpHostname = null;
|
||||
}
|
||||
UDP_HOSTNAME = udpHostname;
|
||||
DatagramSocket socket = null;
|
||||
try {
|
||||
socket = new DatagramSocket(UDP_PORT, UDP_HOSTNAME);
|
||||
} catch (Exception e) {
|
||||
socket = null;
|
||||
}
|
||||
_socket = socket;
|
||||
if (!_socket.isBound()) {
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Failed to bind to UDP port: " + UDP_PORT);
|
||||
_socket.close();
|
||||
}
|
||||
try {
|
||||
sink = new UDPSink(socket, InetAddress.getByName(host), port);
|
||||
} catch (Exception e) {
|
||||
sink = null;
|
||||
}
|
||||
this._sink = sink;
|
||||
// this._source = new UDPSource(this._sink.getSocket());
|
||||
this.setSink(this._sink);
|
||||
}
|
||||
|
||||
private int newSourcePort() {
|
||||
int randomPort = (int) (Math.random() * 65535);
|
||||
while (_sourceIPPortTable.containsKey(randomPort)) {
|
||||
randomPort = (int) (Math.random() * 65535);
|
||||
}
|
||||
return randomPort;
|
||||
}
|
||||
|
||||
private void sendRepliableI2PDatagram(DatagramPacket packet) {
|
||||
try {
|
||||
InetSocketAddress sourceIP = new InetSocketAddress(packet.getAddress(), packet.getPort());
|
||||
int sourcePort = this.newSourcePort();
|
||||
_sourceIPPortTable.put(sourcePort, sourceIP);
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Added sourceIP/port to table: " + sourceIP.toString());
|
||||
this.send(null, sourcePort, 0, packet.getData());
|
||||
} catch (Exception e) {
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Failed to send UDP packet", e);
|
||||
}
|
||||
}
|
||||
|
||||
private DatagramPacket recieveRAWReplyPacket() {
|
||||
DatagramPacket packet = new DatagramPacket(new byte[MAX_SIZE], MAX_SIZE);
|
||||
try {
|
||||
this._socket.receive(packet);
|
||||
} catch (SocketTimeoutException ste) {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Socket timeout, no packet received");
|
||||
} catch (Exception e) {
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Failed to receive UDP packet", e);
|
||||
}
|
||||
return packet;
|
||||
}
|
||||
|
||||
private final synchronized void send() {
|
||||
while (true) {
|
||||
DatagramPacket outboundpacket = new DatagramPacket(new byte[MAX_SIZE], MAX_SIZE);
|
||||
try {
|
||||
this._socket.receive(outboundpacket);
|
||||
} catch (SocketTimeoutException ste) {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Socket timeout, no packet received");
|
||||
break;
|
||||
} catch (Exception e) {
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Failed to receive UDP packet", e);
|
||||
break;
|
||||
}
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Received UDP packet on local address: " + outboundpacket.getAddress().toString()
|
||||
+ ", Forwarding");
|
||||
this.sendRepliableI2PDatagram(outboundpacket);
|
||||
}
|
||||
}
|
||||
|
||||
private final synchronized void receive() {
|
||||
while (true) {
|
||||
DatagramPacket packet = new DatagramPacket(new byte[MAX_SIZE], MAX_SIZE);
|
||||
try {
|
||||
this._socket.receive(packet);
|
||||
} catch (SocketTimeoutException ste) {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Socket timeout, no packet received");
|
||||
break;
|
||||
} catch (Exception e) {
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Failed to receive UDP packet", e);
|
||||
break;
|
||||
}
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Received UDP packet on local address: " + packet.getAddress().toString()
|
||||
+ ", Forwarding");
|
||||
this.sendRepliableI2PDatagram(packet);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void startRunning() {
|
||||
super.startRunning();
|
||||
while (true) {
|
||||
this.send();
|
||||
this.receive();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean close(boolean forced) {
|
||||
return super.close(forced);
|
||||
}
|
||||
}
|
@ -147,11 +147,13 @@ import net.i2p.util.EventDispatcher;
|
||||
* Classes should override to close UDP side as well
|
||||
*/
|
||||
public boolean close(boolean forced) {
|
||||
if (!open) return true;
|
||||
if (!open)
|
||||
return true;
|
||||
if (_session != null) {
|
||||
try {
|
||||
_session.destroySession();
|
||||
} catch (I2PSessionException ise) {}
|
||||
} catch (I2PSessionException ise) {
|
||||
}
|
||||
}
|
||||
l.log("Closing client " + toString());
|
||||
open = false;
|
||||
|
@ -0,0 +1,175 @@
|
||||
package net.i2p.i2ptunnel.udpTunnel;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
|
||||
import net.i2p.i2ptunnel.I2PTunnel;
|
||||
import net.i2p.i2ptunnel.Logging;
|
||||
import net.i2p.i2ptunnel.streamr.Pinger;
|
||||
import net.i2p.i2ptunnel.udp.UDPSink;
|
||||
import net.i2p.i2ptunnel.udp.UDPSource;
|
||||
import net.i2p.util.EventDispatcher;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
/**
|
||||
*
|
||||
* * Client side:
|
||||
*
|
||||
* - permanent DatagramSocket at e.g. localhost:5353
|
||||
* - For EVERY incoming IP datagram request, assign a new I2CP source port,
|
||||
* store the source IP/port in a table keyed by the I2CP source port
|
||||
* - send a REPLIABLE datagram to the server with the I2CP source port
|
||||
*
|
||||
* Server side:
|
||||
*
|
||||
* - receive request, store source I2P Dest/port associated with the request
|
||||
* - For EVERY incoming I2P datagram request, open a NEW DatagramSocket on
|
||||
* localhost with an EPHEMERAL port. Send the request out the socket and wait
|
||||
* for a single reply.
|
||||
* - Send reply as a RAW datagram to the stored I2P Dest/port. and CLOSE the
|
||||
* DatagramSocket.
|
||||
*
|
||||
* Client side:
|
||||
*
|
||||
* - receive reply on the destination I2CP port. Look up source IP/port in the
|
||||
* table by the destination I2CP port.
|
||||
* - Send reply to the stored IP/port, and remove entry from table.
|
||||
*
|
||||
* @author idk
|
||||
*/
|
||||
public class I2PTunnelUDPServerClient extends I2PTunnelUDPServerBase {
|
||||
private final Log _log = new Log(I2PTunnelUDPServerClient.class);
|
||||
private final UDPSink sink;
|
||||
private final UDPSource source;
|
||||
private final InetAddress UDP_HOSTNAME;
|
||||
private final int UDP_PORT;
|
||||
private final int MAX_SIZE = 1024;
|
||||
|
||||
public I2PTunnelUDPServerClient(String host, int port, File privkey, String privkeyname, Logging l,
|
||||
EventDispatcher notifyThis,
|
||||
I2PTunnel tunnel) {
|
||||
super(privkey, privkeyname, l, notifyThis, tunnel);
|
||||
// File privkey, String privkeyname, Logging l,EventDispatcher notifyThis,
|
||||
// I2PTunnel tunnel
|
||||
InetAddress _udpHostname = null;
|
||||
try {
|
||||
_udpHostname = InetAddress.getByName(host);
|
||||
} catch (Exception e) {
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Failed to resolve hostname, using default(localhost): " + host, e);
|
||||
try {
|
||||
_udpHostname = InetAddress.getLocalHost();
|
||||
} catch (Exception crite) {
|
||||
if (_log.shouldLog(Log.ERROR))
|
||||
_log.warn("Failed to resolve localhost, UDP tunnel will fail.: " + host, crite);
|
||||
_udpHostname = null;
|
||||
}
|
||||
} finally {
|
||||
if (_udpHostname == null) {
|
||||
_log.error("Failed to resolve UDP hostname: " + host);
|
||||
}
|
||||
}
|
||||
this.UDP_HOSTNAME = _udpHostname;
|
||||
this.UDP_PORT = port;
|
||||
this.sink = new UDPSink(this.UDP_HOSTNAME, this.UDP_PORT);
|
||||
this.source = new UDPSource(this.UDP_PORT);
|
||||
this.setSink(this.sink);
|
||||
}
|
||||
|
||||
private DatagramPacket recieveRepliableDatagramFromClient() {
|
||||
byte[] buf = new byte[MAX_SIZE];
|
||||
DatagramPacket pack = new DatagramPacket(buf, buf.length);
|
||||
DatagramSocket sock = null;
|
||||
try {
|
||||
sock = new DatagramSocket(0);
|
||||
sock.receive(pack);
|
||||
} catch (Exception e) {
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Error receiving UDP datagram from client", e);
|
||||
return null;
|
||||
} finally {
|
||||
// pack.getData()
|
||||
try {
|
||||
if (sock != null)
|
||||
sock.close();
|
||||
} catch (Exception e) {
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Error closing UDP socket", e);
|
||||
}
|
||||
}
|
||||
return pack;
|
||||
}
|
||||
|
||||
private void sendRawDatagamToClient(DatagramPacket pack) {
|
||||
DatagramSocket sock = null;
|
||||
try {
|
||||
sock = new DatagramSocket();
|
||||
sock.send(pack);
|
||||
} catch (Exception e) {
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Error sending UDP datagram to client", e);
|
||||
} finally {
|
||||
// pack.getData()
|
||||
try {
|
||||
if (sock != null)
|
||||
sock.close();
|
||||
} catch (Exception e) {
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Error closing UDP socket", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void startRunning() {
|
||||
super.startRunning();
|
||||
l.log("I2PTunnelUDPServer server ready");
|
||||
while (true) {
|
||||
DatagramPacket pack = recieveRepliableDatagramFromClient();
|
||||
if (pack == null) {
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Error receiving UDP datagram from client");
|
||||
continue;
|
||||
}
|
||||
byte[] buf = pack.getData();
|
||||
int len = pack.getLength();
|
||||
if (len < 4) {
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Error receiving UDP datagram from client, length is less than 4");
|
||||
continue;
|
||||
}
|
||||
int port = ((buf[0] & 0xff) << 8) | (buf[1] & 0xff);
|
||||
int ip1 = buf[2] & 0xff;
|
||||
int ip2 = buf[3] & 0xff;
|
||||
int ip3 = buf[4] & 0xff;
|
||||
int ip4 = buf[5] & 0xff;
|
||||
InetAddress ip = null;
|
||||
try {
|
||||
ip = InetAddress.getByAddress(new byte[] { (byte) ip1, (byte) ip2, (byte) ip3, (byte) ip4 });
|
||||
} catch (Exception e) {
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Error receiving UDP datagram from client, invalid IP address", e);
|
||||
continue;
|
||||
}
|
||||
if (ip == null) {
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Error receiving UDP datagram from client, invalid IP address");
|
||||
continue;
|
||||
}
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("Received UDP datagram from client: " + ip + ":" + port);
|
||||
DatagramPacket reply = new DatagramPacket(buf, len, ip, port);
|
||||
sendRawDatagamToClient(reply);
|
||||
}
|
||||
// send subscribe-message
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean close(boolean forced) {
|
||||
// send unsubscribe-message
|
||||
this.sink.stop();
|
||||
return super.close(forced);
|
||||
}
|
||||
}
|
@ -82,8 +82,10 @@ public class GeneralHelper {
|
||||
* @return null if not found or tcg is null
|
||||
*/
|
||||
public static TunnelController getController(TunnelControllerGroup tcg, int tunnel) {
|
||||
if (tunnel < 0) return null;
|
||||
if (tcg == null) return null;
|
||||
if (tunnel < 0)
|
||||
return null;
|
||||
if (tcg == null)
|
||||
return null;
|
||||
List<TunnelController> controllers = tcg.getControllers();
|
||||
if (controllers.size() > tunnel)
|
||||
return controllers.get(tunnel);
|
||||
@ -105,7 +107,8 @@ public class GeneralHelper {
|
||||
*
|
||||
* @param context unused, taken from tcg
|
||||
*/
|
||||
public static List<String> saveTunnel(I2PAppContext context, TunnelControllerGroup tcg, int tunnel, TunnelConfig config) {
|
||||
public static List<String> saveTunnel(I2PAppContext context, TunnelControllerGroup tcg, int tunnel,
|
||||
TunnelConfig config) {
|
||||
List<String> msgs = new ArrayList<String>();
|
||||
TunnelController cur = updateTunnelConfig(tcg, tunnel, config, msgs);
|
||||
msgs.addAll(saveConfig(tcg, cur));
|
||||
@ -113,8 +116,10 @@ public class GeneralHelper {
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the config and if shared, adjust and save the config of other shared clients.
|
||||
* If a new tunnel, this will call tcg.addController(), and start it if so configured.
|
||||
* Update the config and if shared, adjust and save the config of other shared
|
||||
* clients.
|
||||
* If a new tunnel, this will call tcg.addController(), and start it if so
|
||||
* configured.
|
||||
* This does NOT save this tunnel's config. Caller must call saveConfig() also.
|
||||
*/
|
||||
protected static List<String> updateTunnelConfig(TunnelControllerGroup tcg, int tunnel, TunnelConfig config) {
|
||||
@ -124,15 +129,18 @@ public class GeneralHelper {
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the config and if shared, adjust and save the config of other shared clients.
|
||||
* If a new tunnel, this will call tcg.addController(), and start it if so configured.
|
||||
* Update the config and if shared, adjust and save the config of other shared
|
||||
* clients.
|
||||
* If a new tunnel, this will call tcg.addController(), and start it if so
|
||||
* configured.
|
||||
* This does NOT save this tunnel's config. Caller must call saveConfig() also.
|
||||
*
|
||||
* @param msgs out parameter, messages will be added
|
||||
* @return the old or new controller, non-null.
|
||||
* @since 0.9.49
|
||||
*/
|
||||
private static TunnelController updateTunnelConfig(TunnelControllerGroup tcg, int tunnel, TunnelConfig config, List<String> msgs) {
|
||||
private static TunnelController updateTunnelConfig(TunnelControllerGroup tcg, int tunnel, TunnelConfig config,
|
||||
List<String> msgs) {
|
||||
// Get current tunnel controller
|
||||
TunnelController cur = getController(tcg, tunnel);
|
||||
|
||||
@ -141,7 +149,8 @@ public class GeneralHelper {
|
||||
String type = props.getProperty(TunnelController.PROP_TYPE);
|
||||
if (TunnelController.TYPE_STD_CLIENT.equals(type) || TunnelController.TYPE_IRC_CLIENT.equals(type)) {
|
||||
//
|
||||
// If we switch to SSL, create the keystore here, so we can store the new properties.
|
||||
// If we switch to SSL, create the keystore here, so we can store the new
|
||||
// properties.
|
||||
// Down in I2PTunnelClientBase it's very hard to save the config.
|
||||
//
|
||||
if (Boolean.parseBoolean(props.getProperty(OPT + I2PTunnelClientBase.PROP_USE_SSL))) {
|
||||
@ -199,7 +208,8 @@ public class GeneralHelper {
|
||||
TunnelController c = controllers.get(i);
|
||||
|
||||
// Current tunnel modified by user, skip
|
||||
if (c == cur) continue;
|
||||
if (c == cur)
|
||||
continue;
|
||||
|
||||
// Only modify this non-current tunnel
|
||||
// if it belongs to a shared destination, and is of supported type
|
||||
@ -221,6 +231,7 @@ public class GeneralHelper {
|
||||
* I2CP/Dest/LS options affecting shared client tunnels.
|
||||
* Streaming options should not be here, each client gets its own SocketManger.
|
||||
* All must be prefixed with "option."
|
||||
*
|
||||
* @since 0.9.46
|
||||
*/
|
||||
private static final String[] SHARED_OPTIONS = {
|
||||
@ -236,6 +247,7 @@ public class GeneralHelper {
|
||||
|
||||
/**
|
||||
* Copy relevant options over
|
||||
*
|
||||
* @since 0.9.46 pulled out of updateTunnelConfig
|
||||
*/
|
||||
private static void copySharedOptions(TunnelConfig fromConfig, Properties from,
|
||||
@ -301,6 +313,7 @@ public class GeneralHelper {
|
||||
public List<String> deleteTunnel(int tunnel, String privKeyFile) {
|
||||
return deleteTunnel(_context, _group, tunnel, privKeyFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the tunnel, delete from config,
|
||||
* rename the private key file if in the default directory
|
||||
@ -493,23 +506,29 @@ public class GeneralHelper {
|
||||
|
||||
public int getTunnelStatus(int tunnel) {
|
||||
TunnelController tun = getController(tunnel);
|
||||
if (tun == null) return NOT_RUNNING;
|
||||
if (tun == null)
|
||||
return NOT_RUNNING;
|
||||
if (tun.getIsRunning()) {
|
||||
if (tun.isClient() && tun.getIsStandby())
|
||||
return STANDBY;
|
||||
else
|
||||
return RUNNING;
|
||||
} else if (tun.getIsStarting()) return STARTING;
|
||||
else return NOT_RUNNING;
|
||||
} else if (tun.getIsStarting())
|
||||
return STARTING;
|
||||
else
|
||||
return NOT_RUNNING;
|
||||
}
|
||||
|
||||
public String getClientDestination(int tunnel) {
|
||||
TunnelController tun = getController(tunnel);
|
||||
if (tun == null) return "";
|
||||
if (tun == null)
|
||||
return "";
|
||||
String rv;
|
||||
if (TunnelController.TYPE_STD_CLIENT.equals(tun.getType()) ||
|
||||
TunnelController.TYPE_IRC_CLIENT.equals(tun.getType()) ||
|
||||
TunnelController.TYPE_STREAMR_CLIENT.equals(tun.getType()))
|
||||
TunnelController.TYPE_STREAMR_CLIENT.equals(tun.getType()) ||
|
||||
TunnelController.TYPE_UDP_CLIENT.equals(tun.getType()) ||
|
||||
TunnelController.TYPE_UDP_SERVER.equals(tun.getType()))
|
||||
rv = tun.getTargetDestination();
|
||||
else
|
||||
rv = tun.getProxyList();
|
||||
@ -518,6 +537,7 @@ public class GeneralHelper {
|
||||
|
||||
/**
|
||||
* Works even if tunnel is not running.
|
||||
*
|
||||
* @return Destination or null
|
||||
*/
|
||||
public Destination getDestination(int tunnel) {
|
||||
@ -535,7 +555,8 @@ public class GeneralHelper {
|
||||
if (rv != null)
|
||||
return rv;
|
||||
} catch (I2PException e) {
|
||||
} catch (IOException e) {}
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@ -543,6 +564,7 @@ public class GeneralHelper {
|
||||
|
||||
/**
|
||||
* Works even if tunnel is not running.
|
||||
*
|
||||
* @return Destination or null
|
||||
* @since 0.9.30
|
||||
*/
|
||||
@ -558,7 +580,8 @@ public class GeneralHelper {
|
||||
if (rv != null)
|
||||
return rv;
|
||||
} catch (I2PException e) {
|
||||
} catch (IOException e) {}
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@ -566,6 +589,7 @@ public class GeneralHelper {
|
||||
|
||||
/**
|
||||
* Works even if tunnel is not running.
|
||||
*
|
||||
* @return true if offline keys
|
||||
* @since 0.9.40
|
||||
*/
|
||||
@ -724,6 +748,7 @@ public class GeneralHelper {
|
||||
/**
|
||||
* List of b64 name : b64key
|
||||
* Pubkeys for DH, privkeys for PSK
|
||||
*
|
||||
* @param isDH true for DH, false for PSK
|
||||
* @return non-null
|
||||
* @since 0.9.41
|
||||
@ -772,6 +797,7 @@ public class GeneralHelper {
|
||||
TunnelController.TYPE_SOCKS_IRC.equals(ttype) ||
|
||||
TunnelController.TYPE_SOCKS.equals(ttype) ||
|
||||
TunnelController.TYPE_STREAMR_CLIENT.equals(ttype) ||
|
||||
TunnelController.TYPE_UDP_CLIENT.equals(ttype) ||
|
||||
TunnelController.TYPE_STD_CLIENT.equals(ttype) ||
|
||||
TunnelController.TYPE_CONNECT.equals(ttype) ||
|
||||
TunnelController.TYPE_HTTP_CLIENT.equals(ttype))
|
||||
@ -804,7 +830,8 @@ public class GeneralHelper {
|
||||
dflt = "4,0";
|
||||
} else if (TunnelController.TYPE_HTTP_SERVER.equals(type) ||
|
||||
TunnelController.TYPE_IRC_SERVER.equals(type) ||
|
||||
TunnelController.TYPE_STREAMR_SERVER.equals(type)) {
|
||||
TunnelController.TYPE_STREAMR_SERVER.equals(type) ||
|
||||
TunnelController.TYPE_UDP_SERVER.equals(type)) {
|
||||
dflt = "4,0";
|
||||
} else {
|
||||
dflt = "0";
|
||||
@ -997,7 +1024,8 @@ public class GeneralHelper {
|
||||
}
|
||||
|
||||
public int getTotalMinute(int tunnel) {
|
||||
return getProperty(tunnel, TunnelController.PROP_MAX_TOTAL_CONNS_MIN, TunnelController.DEFAULT_MAX_TOTAL_CONNS_MIN);
|
||||
return getProperty(tunnel, TunnelController.PROP_MAX_TOTAL_CONNS_MIN,
|
||||
TunnelController.DEFAULT_MAX_TOTAL_CONNS_MIN);
|
||||
}
|
||||
|
||||
public int getTotalHour(int tunnel) {
|
||||
@ -1014,6 +1042,7 @@ public class GeneralHelper {
|
||||
|
||||
/**
|
||||
* POST limits
|
||||
*
|
||||
* @since 0.9.9
|
||||
*/
|
||||
public int getPostMax(int tunnel) {
|
||||
@ -1029,11 +1058,13 @@ public class GeneralHelper {
|
||||
}
|
||||
|
||||
public int getPostBanTime(int tunnel) {
|
||||
return getProperty(tunnel, I2PTunnelHTTPServer.OPT_POST_BAN_TIME, I2PTunnelHTTPServer.DEFAULT_POST_BAN_TIME) / 60;
|
||||
return getProperty(tunnel, I2PTunnelHTTPServer.OPT_POST_BAN_TIME, I2PTunnelHTTPServer.DEFAULT_POST_BAN_TIME)
|
||||
/ 60;
|
||||
}
|
||||
|
||||
public int getPostTotalBanTime(int tunnel) {
|
||||
return getProperty(tunnel, I2PTunnelHTTPServer.OPT_POST_TOTAL_BAN_TIME, I2PTunnelHTTPServer.DEFAULT_POST_TOTAL_BAN_TIME) / 60;
|
||||
return getProperty(tunnel, I2PTunnelHTTPServer.OPT_POST_TOTAL_BAN_TIME,
|
||||
I2PTunnelHTTPServer.DEFAULT_POST_TOTAL_BAN_TIME) / 60;
|
||||
}
|
||||
|
||||
public boolean getRejectInproxy(int tunnel) {
|
||||
@ -1063,7 +1094,8 @@ public class GeneralHelper {
|
||||
TunnelController tun = getController(tunnel);
|
||||
if (tun != null) {
|
||||
Properties opts = tun.getClientOptionProps();
|
||||
if (opts == null) return "";
|
||||
if (opts == null)
|
||||
return "";
|
||||
boolean isMD5Proxy = TunnelController.TYPE_HTTP_CLIENT.equals(tun.getType()) ||
|
||||
TunnelController.TYPE_CONNECT.equals(tun.getType());
|
||||
Map<String, String> sorted = new TreeMap<String, String>();
|
||||
@ -1113,10 +1145,12 @@ public class GeneralHelper {
|
||||
Properties opts = tun.getClientOptionProps();
|
||||
if (opts != null) {
|
||||
String s = opts.getProperty(prop);
|
||||
if (s == null) return def;
|
||||
if (s == null)
|
||||
return def;
|
||||
try {
|
||||
return Integer.parseInt(s);
|
||||
} catch (NumberFormatException nfe) {}
|
||||
} catch (NumberFormatException nfe) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return def;
|
||||
|
@ -107,6 +107,7 @@ public class TunnelConfig {
|
||||
public void setType(String type) {
|
||||
_type = (type != null ? type.trim() : null);
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return _type;
|
||||
}
|
||||
@ -115,70 +116,85 @@ public class TunnelConfig {
|
||||
public void setName(String name) {
|
||||
_name = (name != null ? name.trim() : null);
|
||||
}
|
||||
|
||||
/** one line description */
|
||||
public void setDescription(String description) {
|
||||
// '#' will blow up DataHelper.storeProps()
|
||||
_description = (description != null ? description.replace('#', ' ').trim() : null);
|
||||
}
|
||||
|
||||
/** I2CP host the router is on, ignored when in router context */
|
||||
public void setClientHost(String host) {
|
||||
_i2cpHost = (host != null ? host.trim() : null);
|
||||
}
|
||||
|
||||
/** I2CP port the router is on, ignored when in router context */
|
||||
public void setClientPort(String port) {
|
||||
_i2cpPort = (port != null ? port.trim() : null);
|
||||
}
|
||||
|
||||
/** how many hops to use for inbound tunnels
|
||||
/**
|
||||
* how many hops to use for inbound tunnels
|
||||
* In or both in/out
|
||||
*/
|
||||
public void setTunnelDepth(int tunnelDepth) {
|
||||
_tunnelDepth = tunnelDepth;
|
||||
}
|
||||
|
||||
/** how many parallel inbound tunnels to use
|
||||
/**
|
||||
* how many parallel inbound tunnels to use
|
||||
* In or both in/out
|
||||
*/
|
||||
public void setTunnelQuantity(int tunnelQuantity) {
|
||||
_tunnelQuantity = tunnelQuantity;
|
||||
}
|
||||
|
||||
/** how much randomisation to apply to the depth of tunnels
|
||||
/**
|
||||
* how much randomisation to apply to the depth of tunnels
|
||||
* In or both in/out
|
||||
*/
|
||||
public void setTunnelVariance(int tunnelVariance) {
|
||||
_tunnelVariance = tunnelVariance;
|
||||
}
|
||||
|
||||
/** how many tunnels to hold in reserve to guard against failures
|
||||
/**
|
||||
* how many tunnels to hold in reserve to guard against failures
|
||||
* In or both in/out
|
||||
*/
|
||||
public void setTunnelBackupQuantity(int tunnelBackupQuantity) {
|
||||
_tunnelBackupQuantity = tunnelBackupQuantity;
|
||||
}
|
||||
|
||||
/** how many hops to use for outbound tunnels
|
||||
/**
|
||||
* how many hops to use for outbound tunnels
|
||||
*
|
||||
* @since 0.9.33
|
||||
*/
|
||||
public void setTunnelDepthOut(int tunnelDepth) {
|
||||
_tunnelDepthOut = tunnelDepth;
|
||||
}
|
||||
|
||||
/** how many parallel outbound tunnels to use
|
||||
/**
|
||||
* how many parallel outbound tunnels to use
|
||||
*
|
||||
* @since 0.9.33
|
||||
*/
|
||||
public void setTunnelQuantityOut(int tunnelQuantity) {
|
||||
_tunnelQuantityOut = tunnelQuantity;
|
||||
}
|
||||
|
||||
/** how much randomisation to apply to the depth of tunnels
|
||||
/**
|
||||
* how much randomisation to apply to the depth of tunnels
|
||||
*
|
||||
* @since 0.9.33
|
||||
*/
|
||||
public void setTunnelVarianceOut(int tunnelVariance) {
|
||||
_tunnelVarianceOut = tunnelVariance;
|
||||
}
|
||||
|
||||
/** how many tunnels to hold in reserve to guard against failures
|
||||
/**
|
||||
* how many tunnels to hold in reserve to guard against failures
|
||||
*
|
||||
* @since 0.9.33
|
||||
*/
|
||||
public void setTunnelBackupQuantityOut(int tunnelBackupQuantity) {
|
||||
@ -189,46 +205,56 @@ public class TunnelConfig {
|
||||
public void setCustomOptions(String customOptions) {
|
||||
_customOptions = (customOptions != null ? customOptions.trim() : null);
|
||||
}
|
||||
|
||||
/** what HTTP outproxies should be used (httpclient specific) */
|
||||
public void setProxyList(String proxyList) {
|
||||
_proxyList = (proxyList != null ? proxyList.trim() : null);
|
||||
}
|
||||
|
||||
/** what port should this client/httpclient/ircclient listen on */
|
||||
public void setPort(int port) {
|
||||
_port = port;
|
||||
}
|
||||
|
||||
/**
|
||||
* what interface should this client/httpclient/ircclient listen on
|
||||
*/
|
||||
public void setReachableBy(String reachableBy) {
|
||||
_reachableBy = (reachableBy != null ? reachableBy.trim() : null);
|
||||
}
|
||||
|
||||
/** What peer does this client tunnel point at */
|
||||
public void setTargetDestination(String dest) {
|
||||
_targetDestination = (dest != null ? dest.trim() : null);
|
||||
}
|
||||
|
||||
/** What host does this server tunnel point at */
|
||||
public void setTargetHost(String host) {
|
||||
_targetHost = (host != null ? host.trim() : null);
|
||||
}
|
||||
|
||||
/** What port does this server tunnel point at */
|
||||
public void setTargetPort(int port) {
|
||||
_targetPort = port;
|
||||
}
|
||||
|
||||
/** What host does this http server tunnel spoof */
|
||||
public void setSpoofedHost(String host) {
|
||||
_spoofedHost = (host != null ? host.trim() : null);
|
||||
}
|
||||
|
||||
/** What filename is this server tunnel's private keys stored in */
|
||||
public void setPrivKeyFile(String file) {
|
||||
_privKeyFile = (file != null ? file.trim() : null);
|
||||
}
|
||||
|
||||
public String getPrivKeyFile() {
|
||||
return _privKeyFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* What filename is this server tunnel's alternate private keys stored in
|
||||
*
|
||||
* @since 0.9.30
|
||||
*/
|
||||
public void setAltPrivKeyFile(String file) {
|
||||
@ -243,12 +269,15 @@ public class TunnelConfig {
|
||||
public void setStartOnLoad(boolean val) {
|
||||
_startOnLoad = val;
|
||||
}
|
||||
|
||||
public void setShared(boolean val) {
|
||||
_sharedClient = val;
|
||||
}
|
||||
|
||||
public void setConnectDelay(boolean val) {
|
||||
_connectDelay = val;
|
||||
}
|
||||
|
||||
public void setProfile(String profile) {
|
||||
_profile = profile;
|
||||
}
|
||||
@ -259,12 +288,14 @@ public class TunnelConfig {
|
||||
else
|
||||
_booleanOptions.remove("i2cp.reduceOnIdle");
|
||||
}
|
||||
|
||||
public void setClose(boolean val) {
|
||||
if (val)
|
||||
_booleanOptions.add("i2cp.closeOnIdle");
|
||||
else
|
||||
_booleanOptions.remove("i2cp.closeOnIdle");
|
||||
}
|
||||
|
||||
public void setEncrypt(boolean val) {
|
||||
if (val)
|
||||
_booleanOptions.add("i2cp.encryptLeaseSet");
|
||||
@ -288,6 +319,7 @@ public class TunnelConfig {
|
||||
|
||||
/**
|
||||
* Multiple entries in form
|
||||
*
|
||||
* @since 0.9.41
|
||||
*/
|
||||
public void addClientNames(String[] s) {
|
||||
@ -297,6 +329,7 @@ public class TunnelConfig {
|
||||
/**
|
||||
* Multiple entries in form
|
||||
* Handles either order addClientName/addClientKey
|
||||
*
|
||||
* @since 0.9.41
|
||||
*/
|
||||
public void addClientKeys(String[] s) {
|
||||
@ -305,6 +338,7 @@ public class TunnelConfig {
|
||||
|
||||
/**
|
||||
* Multiple entries in form
|
||||
*
|
||||
* @since 0.9.41
|
||||
*/
|
||||
public void revokeClients(String[] s) {
|
||||
@ -312,12 +346,14 @@ public class TunnelConfig {
|
||||
for (String k : s) {
|
||||
try {
|
||||
_clientRevocations.add(Integer.valueOf(Integer.parseInt(k)));
|
||||
} catch (NumberFormatException nfe) {}
|
||||
} catch (NumberFormatException nfe) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles either order newClientName/newClientKey
|
||||
*
|
||||
* @since 0.9.41
|
||||
*/
|
||||
public void newClientName(String s) {
|
||||
@ -326,6 +362,7 @@ public class TunnelConfig {
|
||||
|
||||
/**
|
||||
* Handles either order newClientName/newClientKey
|
||||
*
|
||||
* @since 0.9.41
|
||||
*/
|
||||
public void newClientKey(String s) {
|
||||
@ -345,12 +382,14 @@ public class TunnelConfig {
|
||||
else
|
||||
_booleanOptions.remove(I2PTunnelIRCClient.PROP_DCC);
|
||||
}
|
||||
|
||||
public void setUseSSL(boolean val) {
|
||||
if (val)
|
||||
_booleanOptions.add(I2PTunnelServer.PROP_USE_SSL);
|
||||
else
|
||||
_booleanOptions.remove(I2PTunnelServer.PROP_USE_SSL);
|
||||
}
|
||||
|
||||
public void setRejectInproxy(boolean val) {
|
||||
if (val)
|
||||
_booleanOptions.add(I2PTunnelHTTPServer.OPT_REJECT_INPROXY);
|
||||
@ -437,7 +476,8 @@ public class TunnelConfig {
|
||||
* <p>
|
||||
* If {@link #setClose(boolean)} is set to false then mode 1 == mode 0.
|
||||
*
|
||||
* @param mode 0 for new dest on restart, 1 for new dest on resume from idle, 2 for persistent key
|
||||
* @param mode 0 for new dest on restart, 1 for new dest on resume from idle, 2
|
||||
* for persistent key
|
||||
*/
|
||||
public void setNewDest(int mode) {
|
||||
switch (mode) {
|
||||
@ -458,9 +498,11 @@ public class TunnelConfig {
|
||||
public void setReduceTime(int val) {
|
||||
_otherOptions.put("i2cp.reduceIdleTime", Integer.toString(val * 60 * 1000));
|
||||
}
|
||||
|
||||
public void setReduceCount(int val) {
|
||||
_otherOptions.put("i2cp.reduceQuantity", Integer.toString(val));
|
||||
}
|
||||
|
||||
public void setEncryptKey(String val) {
|
||||
if (val != null)
|
||||
_otherOptions.put("i2cp.leaseSetKey", val.trim());
|
||||
@ -492,7 +534,8 @@ public class TunnelConfig {
|
||||
|
||||
public void setJumpList(String val) {
|
||||
if (val != null)
|
||||
_otherOptions.put(I2PTunnelHTTPClient.PROP_JUMP_SERVERS, val.trim().replace("\r\n", ",").replace("\n", ",").replace(" ", ","));
|
||||
_otherOptions.put(I2PTunnelHTTPClient.PROP_JUMP_SERVERS,
|
||||
val.trim().replace("\r\n", ",").replace("\n", ",").replace(" ", ","));
|
||||
}
|
||||
|
||||
public void setCloseTime(int val) {
|
||||
@ -505,18 +548,21 @@ public class TunnelConfig {
|
||||
else
|
||||
_booleanOptions.remove(I2PTunnelHTTPClient.PROP_USER_AGENT);
|
||||
}
|
||||
|
||||
public void setAllowReferer(boolean val) {
|
||||
if (val)
|
||||
_booleanOptions.add(I2PTunnelHTTPClient.PROP_REFERER);
|
||||
else
|
||||
_booleanOptions.remove(I2PTunnelHTTPClient.PROP_REFERER);
|
||||
}
|
||||
|
||||
public void setAllowAccept(boolean val) {
|
||||
if (val)
|
||||
_booleanOptions.add(I2PTunnelHTTPClient.PROP_ACCEPT);
|
||||
else
|
||||
_booleanOptions.remove(I2PTunnelHTTPClient.PROP_ACCEPT);
|
||||
}
|
||||
|
||||
public void setAllowInternalSSL(boolean val) {
|
||||
if (val)
|
||||
_booleanOptions.add(I2PTunnelHTTPClient.PROP_INTERNAL_SSL);
|
||||
@ -656,6 +702,7 @@ public class TunnelConfig {
|
||||
|
||||
/**
|
||||
* Adds to existing, comma separated
|
||||
*
|
||||
* @since 0.9.44
|
||||
*/
|
||||
public void setEncType(String val) {
|
||||
@ -711,7 +758,8 @@ public class TunnelConfig {
|
||||
updateConfigGeneric(config);
|
||||
|
||||
if ((TunnelController.isClient(_type) && !TunnelController.TYPE_STREAMR_CLIENT.equals(_type)) ||
|
||||
TunnelController.TYPE_STREAMR_SERVER.equals(_type)) {
|
||||
!TunnelController.TYPE_UDP_CLIENT.equals(_type) || TunnelController.TYPE_STREAMR_SERVER.equals(_type) ||
|
||||
TunnelController.TYPE_UDP_SERVER.equals(_type)) {
|
||||
// streamrserver uses interface
|
||||
if (_reachableBy != null)
|
||||
config.setProperty(TunnelController.PROP_INTFC, _reachableBy);
|
||||
@ -815,7 +863,8 @@ public class TunnelConfig {
|
||||
|
||||
if (TunnelController.TYPE_IRC_CLIENT.equals(_type) ||
|
||||
TunnelController.TYPE_STD_CLIENT.equals(_type) ||
|
||||
TunnelController.TYPE_STREAMR_CLIENT.equals(_type)) {
|
||||
TunnelController.TYPE_STREAMR_CLIENT.equals(_type) ||
|
||||
TunnelController.TYPE_UDP_CLIENT.equals(_type)) {
|
||||
if (_targetDestination != null)
|
||||
config.setProperty(TunnelController.PROP_DEST, _targetDestination);
|
||||
} else if (TunnelController.TYPE_HTTP_SERVER.equals(_type) ||
|
||||
@ -826,7 +875,9 @@ public class TunnelConfig {
|
||||
if (_otherOptions.containsKey(p))
|
||||
config.setProperty(OPT + p, _otherOptions.get(p));
|
||||
}
|
||||
if (TunnelController.TYPE_HTTP_BIDIR_SERVER.equals(_type)) {
|
||||
if (TunnelController.TYPE_HTTP_BIDIR_SERVER.equals(_type) ||
|
||||
TunnelController.TYPE_UDP_SERVER.equals(_type) ||
|
||||
TunnelController.TYPE_UDP_CLIENT.equals(_type)) {
|
||||
if (_port >= 0)
|
||||
config.setProperty(TunnelController.PROP_LISTEN_PORT, Integer.toString(_port));
|
||||
if (_reachableBy != null)
|
||||
@ -927,6 +978,7 @@ public class TunnelConfig {
|
||||
|
||||
/**
|
||||
* Servers only.
|
||||
*
|
||||
* @since 0.9.41 pulled out from getConfig() above
|
||||
*/
|
||||
private void processEncryptMode(Properties config) {
|
||||
@ -1053,7 +1105,8 @@ public class TunnelConfig {
|
||||
if (name.length() > 0)
|
||||
name = Base64.encode(DataHelper.getUTF8(name));
|
||||
else
|
||||
name = Base64.encode(DataHelper.getUTF8(GeneralHelper._t("Client", _context) + ' ' + (clientAuth.size() + 1)));
|
||||
name = Base64.encode(
|
||||
DataHelper.getUTF8(GeneralHelper._t("Client", _context) + ' ' + (clientAuth.size() + 1)));
|
||||
String key;
|
||||
if (_encryptMode == 6 || _encryptMode == 7) {
|
||||
byte[] b = new byte[32];
|
||||
@ -1080,6 +1133,7 @@ public class TunnelConfig {
|
||||
/**
|
||||
* Servers only.
|
||||
* Also sets/clears i2cp.leaseSetType
|
||||
*
|
||||
* @since 0.9.41
|
||||
*/
|
||||
private void addLeaseSetPrivKey(Properties config, boolean isBlinded) {
|
||||
@ -1164,7 +1218,8 @@ public class TunnelConfig {
|
||||
};
|
||||
|
||||
/**
|
||||
* do NOT add these to noShoOpts, we must leave them in for HTTPClient and ConnectCLient
|
||||
* do NOT add these to noShoOpts, we must leave them in for HTTPClient and
|
||||
* ConnectCLient
|
||||
* so they will get migrated to MD5
|
||||
* TODO migrate socks to MD5
|
||||
*/
|
||||
@ -1238,7 +1293,8 @@ public class TunnelConfig {
|
||||
// This was 1 which doesn't make much sense
|
||||
// The real way to make it interactive is to make the streaming lib
|
||||
// MessageInputStream flush faster but there's no option for that yet,
|
||||
// Setting it to 16 instead of the default but not sure what good that is either.
|
||||
// Setting it to 16 instead of the default but not sure what good that is
|
||||
// either.
|
||||
config.setProperty("option.i2p.streaming.maxWindowSize", "16");
|
||||
else
|
||||
config.remove("option.i2p.streaming.maxWindowSize");
|
||||
@ -1361,33 +1417,33 @@ public class TunnelConfig {
|
||||
}
|
||||
|
||||
/****
|
||||
private static String[] tests = {
|
||||
"", "foo", "foo=bar",
|
||||
"f=b x", "x f=b",
|
||||
" aaa=bbb ccc=ddd ",
|
||||
"aaa=bbb ccc=ddd x",
|
||||
"aaa=bbb ccc=ddd x=",
|
||||
"a=\"w x y z\" b c= d='1 2 3 4'",
|
||||
"klsjdf owi=\"w\tx y\tz\"",
|
||||
"z= aaa= ",
|
||||
"=", " = ", "=foo", " =fpp ",
|
||||
"a=\"\", b='', c='xxx\" d='aaa'",
|
||||
"xx=\"missingquote",
|
||||
"'zxw=123'",
|
||||
"'zxw=123",
|
||||
"'zxw=123' a=b c d e",
|
||||
"x====", "x====x",
|
||||
"aaa=b=cc====dddddd====",
|
||||
};
|
||||
|
||||
public static void main(String[] args) {
|
||||
for (int i = 0; i < tests.length; i++) {
|
||||
Map<String, String> m = parseCustomOptions(tests[i]);
|
||||
System.out.println("\nTest \"" + tests[i] + '"');
|
||||
for (Map.Entry<String, String> e : m.entrySet()) {
|
||||
System.out.println(" \"" + e.getKey() + "\" = \"" + e.getValue() + '"');
|
||||
}
|
||||
}
|
||||
}
|
||||
* private static String[] tests = {
|
||||
* "", "foo", "foo=bar",
|
||||
* "f=b x", "x f=b",
|
||||
* " aaa=bbb ccc=ddd ",
|
||||
* "aaa=bbb ccc=ddd x",
|
||||
* "aaa=bbb ccc=ddd x=",
|
||||
* "a=\"w x y z\" b c= d='1 2 3 4'",
|
||||
* "klsjdf owi=\"w\tx y\tz\"",
|
||||
* "z= aaa= ",
|
||||
* "=", " = ", "=foo", " =fpp ",
|
||||
* "a=\"\", b='', c='xxx\" d='aaa'",
|
||||
* "xx=\"missingquote",
|
||||
* "'zxw=123'",
|
||||
* "'zxw=123",
|
||||
* "'zxw=123' a=b c d e",
|
||||
* "x====", "x====x",
|
||||
* "aaa=b=cc====dddddd====",
|
||||
* };
|
||||
*
|
||||
* public static void main(String[] args) {
|
||||
* for (int i = 0; i < tests.length; i++) {
|
||||
* Map<String, String> m = parseCustomOptions(tests[i]);
|
||||
* System.out.println("\nTest \"" + tests[i] + '"');
|
||||
* for (Map.Entry<String, String> e : m.entrySet()) {
|
||||
* System.out.println(" \"" + e.getKey() + "\" = \"" + e.getValue() + '"');
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
****/
|
||||
}
|
||||
|
@ -75,7 +75,7 @@
|
||||
String phdisabled = (canChangePort && isShared) ? "" : tstopFirst;
|
||||
%>
|
||||
<th colspan="2" <%=phdisabled%>>
|
||||
<% if ("streamrclient".equals(tunnelType)) { %>
|
||||
<% if ("streamrclient".equals(tunnelType) || "udpclient".equals(tunnelType)) { %>
|
||||
<%=intl._t("Target")%>
|
||||
<% } else { %>
|
||||
<%=intl._t("Access Point")%>
|
||||
@ -98,7 +98,7 @@
|
||||
<input type="text" size="6" maxlength="5" name="port" title="<%=ptext%>" value="<%=editBean.getClientPort(curTunnel)%>" class="freetext port" placeholder="required" <%=pdisabled%>/>
|
||||
</td>
|
||||
<%
|
||||
if ("streamrclient".equals(tunnelType)) {
|
||||
if ("streamrclient".equals(tunnelType) || "udpclient".equals(tunnelType)) {
|
||||
%>
|
||||
<td>
|
||||
<b><%=intl._t("Host")%>:</b>
|
||||
@ -192,7 +192,7 @@
|
||||
</td>
|
||||
</tr>
|
||||
<%
|
||||
} else if ("client".equals(tunnelType) || "ircclient".equals(tunnelType) || "streamrclient".equals(tunnelType)) {
|
||||
} else if ("client".equals(tunnelType) || "ircclient".equals(tunnelType) || "streamrclient".equals(tunnelType) || "udpclient".equals(tunnelType)) {
|
||||
%>
|
||||
<tr>
|
||||
<th colspan="2">
|
||||
@ -210,7 +210,7 @@
|
||||
<input type="text" size="30" id="targetDestination" name="targetDestination" title="<%=intl._t("Specify the .i2p address or destination (b32 or b64) of the tunnel here.")%> <%=intl._t("For a random selection from a pool, separate with commas e.g. server1.i2p,server2.i2p")%>" value="<%=editBean.getClientDestination(curTunnel)%>" class="freetext destination" placeholder="required" />
|
||||
<%=intl._t("name, name:port, or destination")%>
|
||||
<%
|
||||
if ("streamrclient".equals(tunnelType)) {
|
||||
if ("streamrclient".equals(tunnelType) || "udpclient".equals(tunnelType)) {
|
||||
/* deferred resolution unimplemented in streamr client */
|
||||
%>
|
||||
- <%=intl._t("b32 not recommended")%>
|
||||
@ -222,7 +222,7 @@
|
||||
<%
|
||||
}
|
||||
|
||||
if (!"streamrclient".equals(tunnelType)) {
|
||||
if (!"streamrclient".equals(tunnelType) && !"udpclient".equals(tunnelType)) {
|
||||
%>
|
||||
<tr>
|
||||
<th colspan="2" <%=phdisabled%>>
|
||||
@ -270,7 +270,7 @@
|
||||
</table>
|
||||
<h3><%=intl._t("Advanced networking options")%></h3>
|
||||
<%
|
||||
if (!"streamrclient".equals(tunnelType) && (canChangePort || isShared)) {
|
||||
if (!"streamrclient".equals(tunnelType) && !"udpclient".equals(tunnelType) && (canChangePort || isShared)) {
|
||||
// no shared client tunnels for streamr
|
||||
// If running and not shared, this doesn't apply.
|
||||
%>
|
||||
@ -393,7 +393,7 @@
|
||||
} // client
|
||||
%>
|
||||
<%
|
||||
if (!"streamrclient".equals(tunnelType)) {
|
||||
if (!"streamrclient".equals(tunnelType) && !"udpclient".equals(tunnelType)) {
|
||||
// streamr client sends pings so it will never be idle
|
||||
%>
|
||||
<tr>
|
||||
|
@ -66,8 +66,9 @@
|
||||
String tstopFirst = " title=\"" + stopFirst + "\" ";
|
||||
boolean canChangeDest = editBean.canChangePort(curTunnel);
|
||||
boolean isStreamrServer = "streamrserver".equals(tunnelType);
|
||||
boolean isUDPServer = "udpserver".equals(tunnelType);
|
||||
boolean isBidirServer = "httpbidirserver".equals(tunnelType);
|
||||
boolean canChangePort = canChangeDest || !(isStreamrServer || isBidirServer);
|
||||
boolean canChangePort = canChangeDest || !(isStreamrServer || isBidirServer || isUDPServer);
|
||||
String phdisabled = canChangePort ? "" : tstopFirst;
|
||||
%>
|
||||
<th colspan="2" <%=phdisabled%>>
|
||||
@ -101,7 +102,7 @@
|
||||
String pdisabled = canChangePort ? "" : " readonly=\"readonly\" ";
|
||||
%>
|
||||
<input type="text" size="6" maxlength="5" id="targetPort" name="targetPort" title="<%=ptext%>" value="<%=editBean.getTargetPort(curTunnel)%>" class="freetext port" placeholder="required" <%=pdisabled%>/>
|
||||
<% if (!isStreamrServer) { %>
|
||||
<% if (!isStreamrServer && !isUDPServer) { %>
|
||||
<label title="<%=intl._t("To avoid traffic sniffing if connecting to a remote server, you can enable an SSL connection. Note that the target server must be configured to accept SSL connections.")%>"><input value="1" type="checkbox" name="useSSL"<%=(editBean.isSSLEnabled(curTunnel) ? " checked=\"checked\"" : "")%> class="tickbox" />
|
||||
<%=intl._t("Use SSL to connect to target")%></label>
|
||||
<% } /* !streamrserver */ %>
|
||||
@ -155,7 +156,7 @@
|
||||
</td>
|
||||
<% } /* httpbidirserver || streamrserver */ %>
|
||||
</tr>
|
||||
<% if ("httpserver".equals(tunnelType) || isBidirServer) {
|
||||
<% if ("httpserver".equals(tunnelType) || isBidirServer || isUDPServer) {
|
||||
%>
|
||||
<tr>
|
||||
<th>
|
||||
@ -717,7 +718,7 @@
|
||||
<%
|
||||
/* alternate dest, only if current dest is set and is DSA_SHA1 */
|
||||
|
||||
if (currentSigType == 0 && !"".equals(b64) && !isStreamrServer) {
|
||||
if (currentSigType == 0 && !"".equals(b64) && (!isStreamrServer && !isUDPServer)) {
|
||||
String attitle = canChangeEncType ? "" : tstopFirst;
|
||||
String atitle = canChangeEncType ? intl._t("Path to Private Key File") : stopFirst;
|
||||
String adisabled = canChangeEncType ? "" : " readonly=\"readonly\" ";
|
||||
@ -867,7 +868,7 @@
|
||||
</th>
|
||||
</tr>
|
||||
<%
|
||||
if (!isStreamrServer) {
|
||||
if (!isStreamrServer && !isUDPServer) {
|
||||
%>
|
||||
<tr>
|
||||
<th colspan="5">
|
||||
|
@ -1,27 +1,42 @@
|
||||
<%@include file="headers.jsi"
|
||||
%><%@page pageEncoding="UTF-8"
|
||||
%><%@page trimDirectiveWhitespaces="true"
|
||||
%><%@page contentType="text/html" import="net.i2p.i2ptunnel.web.IndexBean"
|
||||
%><?xml version="1.0" encoding="UTF-8"?>
|
||||
%>
|
||||
<%@page pageEncoding="UTF-8"
|
||||
%>
|
||||
<%@page trimDirectiveWhitespaces="true"
|
||||
%>
|
||||
<%@page contentType="text/html" import="net.i2p.i2ptunnel.web.IndexBean"
|
||||
%>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<jsp:useBean class="net.i2p.i2ptunnel.web.IndexBean" id="indexBean" scope="request" />
|
||||
<jsp:setProperty name="indexBean" property="tunnel" /><%-- must be set before key1-4 --%>
|
||||
<jsp:setProperty name="indexBean" property="tunnel" />
|
||||
<%-- must be set before key1-4 --%>
|
||||
<jsp:setProperty name="indexBean" property="*" />
|
||||
<jsp:useBean class="net.i2p.i2ptunnel.ui.Messages" id="intl" scope="request" />
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
|
||||
<head>
|
||||
<title><%=intl._t("Hidden Services Manager")%></title>
|
||||
<title>
|
||||
<%=intl._t("Hidden Services Manager")%>
|
||||
</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<link href="/themes/console/images/favicon.ico" type="image/x-icon" rel="shortcut icon" />
|
||||
<link href="<%=indexBean.getTheme()%>i2ptunnel.css?<%=net.i2p.CoreVersion.VERSION%>" rel="stylesheet" type="text/css" />
|
||||
<script src="js/copy.js?<%=net.i2p.CoreVersion.VERSION%>" type="text/javascript"></script>
|
||||
<noscript><style> .jsonly { display: none } </style></noscript>
|
||||
</head><body id="tunnelListPage">
|
||||
<div class="panel" id="overview"><h2><%=intl._t("Hidden Services Manager")%></h2><p>
|
||||
</head>
|
||||
|
||||
<body id="tunnelListPage">
|
||||
<div class="panel" id="overview">
|
||||
<h2>
|
||||
<%=intl._t("Hidden Services Manager")%>
|
||||
</h2>
|
||||
<p>
|
||||
<%=intl._t("These are the local services provided by your router.")%>
|
||||
|
||||
<%=intl._t("By default, most of your client services (email, HTTP proxy, IRC) will share the same set of tunnels and be listed as \"Shared Clients\".")%>
|
||||
</p></div>
|
||||
</p>
|
||||
</div>
|
||||
<%
|
||||
boolean isInitialized = indexBean.isInitialized();
|
||||
String nextNonce = isInitialized ? net.i2p.i2ptunnel.web.IndexBean.getNextNonce() : null;
|
||||
@ -32,19 +47,26 @@
|
||||
if (msgs.length() > 0) {
|
||||
%>
|
||||
<div class="panel" id="messages">
|
||||
<h2><%=intl._t("Status Messages")%></h2>
|
||||
<h2>
|
||||
<%=intl._t("Status Messages")%>
|
||||
</h2>
|
||||
<table id="statusMessagesTable">
|
||||
<tr>
|
||||
<td id="tunnelMessages">
|
||||
<textarea id="statusMessages" rows="4" cols="60" readonly="readonly"><%=msgs%></textarea>
|
||||
</td>
|
||||
</tr><tr>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="buttons">
|
||||
<a class="control" href="list"><%=intl._t("Refresh")%></a>
|
||||
<a class="control" href="list">
|
||||
<%=intl._t("Refresh")%>
|
||||
</a>
|
||||
<%
|
||||
if (isInitialized) {
|
||||
%>
|
||||
<a class="control" href="list?action=Clear&msgid=<%=lastID%>&nonce=<%=nextNonce%>"><%=intl._t("Clear")%></a>
|
||||
<a class="control" href="list?action=Clear&msgid=<%=lastID%>&nonce=<%=nextNonce%>">
|
||||
<%=intl._t("Clear")%>
|
||||
</a>
|
||||
<%
|
||||
} // isInitialized
|
||||
%>
|
||||
@ -57,32 +79,58 @@
|
||||
if (isInitialized) {
|
||||
%>
|
||||
<div class="panel" id="globalTunnelControl">
|
||||
<h2><%=intl._t("Global Tunnel Control")%></h2>
|
||||
<h2>
|
||||
<%=intl._t("Global Tunnel Control")%>
|
||||
</h2>
|
||||
<table>
|
||||
<tr>
|
||||
<td class="buttons">
|
||||
<a class="control" href="wizard"><%=intl._t("Tunnel Wizard")%></a>
|
||||
<a class="control" href="list?nonce=<%=nextNonce%>&action=Stop%20all"><%=intl._t("Stop All")%></a>
|
||||
<a class="control" href="list?nonce=<%=nextNonce%>&action=Start%20all"><%=intl._t("Start All")%></a>
|
||||
<a class="control" href="list?nonce=<%=nextNonce%>&action=Restart%20all"><%=intl._t("Restart All")%></a>
|
||||
<a class="control" href="wizard">
|
||||
<%=intl._t("Tunnel Wizard")%>
|
||||
</a>
|
||||
<a class="control" href="list?nonce=<%=nextNonce%>&action=Stop%20all">
|
||||
<%=intl._t("Stop All")%>
|
||||
</a>
|
||||
<a class="control" href="list?nonce=<%=nextNonce%>&action=Start%20all">
|
||||
<%=intl._t("Start All")%>
|
||||
</a>
|
||||
<a class="control" href="list?nonce=<%=nextNonce%>&action=Restart%20all">
|
||||
<%=intl._t("Restart All")%>
|
||||
</a>
|
||||
<%--
|
||||
//this is really bad because it stops and restarts all tunnels, which is probably not what you want
|
||||
<a class="control" href="list?nonce=<%=nextNonce%>&action=Reload%20configuration"><%=intl._t("Reload Config")%></a>
|
||||
<a class="control" href="list?nonce=<%=nextNonce%>&action=Reload%20configuration">
|
||||
<%=intl._t("Reload Config")%>
|
||||
</a>
|
||||
--%>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="panel" id="servers">
|
||||
<h2><%=intl._t("I2P Hidden Services")%></h2>
|
||||
<h2>
|
||||
<%=intl._t("I2P Hidden Services")%>
|
||||
</h2>
|
||||
<table id="serverTunnels">
|
||||
<tr>
|
||||
<th class="tunnelName"><%=intl._t("Name")%></th>
|
||||
<th class="tunnelType"><%=intl._t("Type")%></th>
|
||||
<th class="tunnelLocation"><%=intl._t("Points at")%></th>
|
||||
<th class="tunnelPreview"><%=intl._t("Preview")%></th>
|
||||
<th class="tunnelStatus"><%=intl._t("Status")%></th>
|
||||
<th class="tunnelControl"><%=intl._t("Control")%></th>
|
||||
<th class="tunnelName">
|
||||
<%=intl._t("Name")%>
|
||||
</th>
|
||||
<th class="tunnelType">
|
||||
<%=intl._t("Type")%>
|
||||
</th>
|
||||
<th class="tunnelLocation">
|
||||
<%=intl._t("Points at")%>
|
||||
</th>
|
||||
<th class="tunnelPreview">
|
||||
<%=intl._t("Preview")%>
|
||||
</th>
|
||||
<th class="tunnelStatus">
|
||||
<%=intl._t("Status")%>
|
||||
</th>
|
||||
<th class="tunnelControl">
|
||||
<%=intl._t("Control")%>
|
||||
</th>
|
||||
</tr>
|
||||
<%
|
||||
for (int curServer = 0; curServer < indexBean.getTunnelCount(); curServer++) {
|
||||
@ -90,19 +138,28 @@
|
||||
%>
|
||||
<tr class="tunnelProperties">
|
||||
<td class="tunnelName">
|
||||
<a href="edit?tunnel=<%=curServer%>" title="<%=intl._t("Edit Server Tunnel Settings for")%> <%=indexBean.getTunnelName(curServer)%>"><%=indexBean.getTunnelName(curServer)%></a>
|
||||
</td><td class="tunnelType"><%=indexBean.getTunnelType(curServer)%>
|
||||
</td><td class="tunnelLocation">
|
||||
<a href="edit?tunnel=<%=curServer%>" title="<%=intl._t(" Edit Server Tunnel Settings for ")%> <%=indexBean.getTunnelName(curServer)%>">
|
||||
<%=indexBean.getTunnelName(curServer)%>
|
||||
</a>
|
||||
</td>
|
||||
<td class="tunnelType">
|
||||
<%=indexBean.getTunnelType(curServer)%>
|
||||
</td>
|
||||
<td class="tunnelLocation">
|
||||
<%
|
||||
if (indexBean.isServerTargetLinkValid(curServer)) {
|
||||
if (indexBean.isSSLEnabled(curServer)) { %>
|
||||
<a href="https://<%=indexBean.getServerTarget(curServer)%>/" title="<%=intl._t("Test HTTPS server, bypassing I2P")%>" target="_top"><%=indexBean.getServerTarget(curServer)%> SSL</a>
|
||||
<a href="https://<%=indexBean.getServerTarget(curServer)%>/" title="<%=intl._t(" Test HTTPS server, bypassing I2P ")%>" target="_top">
|
||||
<%=indexBean.getServerTarget(curServer)%> SSL</a>
|
||||
<% } else { %>
|
||||
<a href="http://<%=indexBean.getServerTarget(curServer)%>/" title="<%=intl._t("Test HTTP server, bypassing I2P")%>" target="_top"><%=indexBean.getServerTarget(curServer)%></a>
|
||||
<a href="http://<%=indexBean.getServerTarget(curServer)%>/" title="<%=intl._t(" Test HTTP server, bypassing I2P ")%>" target="_top">
|
||||
<%=indexBean.getServerTarget(curServer)%>
|
||||
</a>
|
||||
<%
|
||||
}
|
||||
} else {
|
||||
%><%=indexBean.getServerTarget(curServer)%>
|
||||
%>
|
||||
<%=indexBean.getServerTarget(curServer)%>
|
||||
<%
|
||||
if (indexBean.isSSLEnabled(curServer)) { %>
|
||||
SSL
|
||||
@ -110,42 +167,66 @@
|
||||
}
|
||||
}
|
||||
%>
|
||||
</td><td class="tunnelPreview">
|
||||
</td>
|
||||
<td class="tunnelPreview">
|
||||
<%
|
||||
if (("httpserver".equals(indexBean.getInternalType(curServer)) || ("httpbidirserver".equals(indexBean.getInternalType(curServer)))) && indexBean.getTunnelStatus(curServer) == IndexBean.RUNNING) {
|
||||
%>
|
||||
<a class="control" title="<%=intl._t("Test HTTP server through I2P")%>" href="http://<%=indexBean.getDestHashBase32(curServer)%>" target="_top"><%=intl._t("Preview")%></a>
|
||||
<a class="control" title="<%=intl._t(" Test HTTP server through I2P ")%>" href="http://<%=indexBean.getDestHashBase32(curServer)%>" target="_top">
|
||||
<%=intl._t("Preview")%>
|
||||
</a>
|
||||
<%
|
||||
} else {
|
||||
%><%=intl._t("No Preview")%>
|
||||
%>
|
||||
<%=intl._t("No Preview")%>
|
||||
<%
|
||||
}
|
||||
%>
|
||||
</td><td class="tunnelStatus">
|
||||
</td>
|
||||
<td class="tunnelStatus">
|
||||
<%
|
||||
switch (indexBean.getTunnelStatus(curServer)) {
|
||||
case IndexBean.STARTING:
|
||||
%><div class="statusStarting text" title="<%=intl._t("Starting...")%>"><%=intl._t("Starting...")%></div>
|
||||
</td><td class="tunnelControl">
|
||||
<a class="control" title="<%=intl._t("Stop this Tunnel")%>" href="list?nonce=<%=nextNonce%>&action=stop&tunnel=<%=curServer%>"><%=intl._t("Stop")%></a>
|
||||
%>
|
||||
<div class="statusStarting text" title="<%=intl._t(" Starting... ")%>">
|
||||
<%=intl._t("Starting...")%>
|
||||
</div>
|
||||
</td>
|
||||
<td class="tunnelControl">
|
||||
<a class="control" title="<%=intl._t(" Stop this Tunnel ")%>" href="list?nonce=<%=nextNonce%>&action=stop&tunnel=<%=curServer%>">
|
||||
<%=intl._t("Stop")%>
|
||||
</a>
|
||||
<%
|
||||
break;
|
||||
case IndexBean.RUNNING:
|
||||
%><div class="statusRunning text" title="<%=intl._t("Running")%>"><%=intl._t("Running")%></div>
|
||||
</td><td class="tunnelControl">
|
||||
<a class="control" title="<%=intl._t("Stop this Tunnel")%>" href="list?nonce=<%=nextNonce%>&action=stop&tunnel=<%=curServer%>"><%=intl._t("Stop")%></a>
|
||||
%>
|
||||
<div class="statusRunning text" title="<%=intl._t(" Running ")%>">
|
||||
<%=intl._t("Running")%>
|
||||
</div>
|
||||
</td>
|
||||
<td class="tunnelControl">
|
||||
<a class="control" title="<%=intl._t(" Stop this Tunnel ")%>" href="list?nonce=<%=nextNonce%>&action=stop&tunnel=<%=curServer%>">
|
||||
<%=intl._t("Stop")%>
|
||||
</a>
|
||||
<%
|
||||
break;
|
||||
case IndexBean.NOT_RUNNING:
|
||||
%><div class="statusNotRunning text" title="<%=intl._t("Stopped")%>"><%=intl._t("Stopped")%></div>
|
||||
</td><td class="tunnelControl">
|
||||
<a class="control" title="<%=intl._t("Start this Tunnel")%>" href="list?nonce=<%=nextNonce%>&action=start&tunnel=<%=curServer%>"><%=intl._t("Start")%></a>
|
||||
%>
|
||||
<div class="statusNotRunning text" title="<%=intl._t(" Stopped ")%>">
|
||||
<%=intl._t("Stopped")%>
|
||||
</div>
|
||||
</td>
|
||||
<td class="tunnelControl">
|
||||
<a class="control" title="<%=intl._t(" Start this Tunnel ")%>" href="list?nonce=<%=nextNonce%>&action=start&tunnel=<%=curServer%>">
|
||||
<%=intl._t("Start")%>
|
||||
</a>
|
||||
<%
|
||||
break;
|
||||
}
|
||||
%>
|
||||
</td>
|
||||
</tr><tr>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tunnelDestination" colspan="6">
|
||||
<span class="tunnelDestinationLabel">
|
||||
<%
|
||||
@ -154,15 +235,9 @@
|
||||
name = indexBean.getTunnelName(curServer);
|
||||
out.write("<b>");
|
||||
out.write(intl._t("Destination"));
|
||||
out.write(":</b></span> ");
|
||||
out.write(indexBean.getDestHashBase32(curServer));
|
||||
} else {
|
||||
out.write("<b>");
|
||||
out.write(":</b></span> "); out.write(indexBean.getDestHashBase32(curServer)); } else { out.write("<b>");
|
||||
out.write(intl._t("Hostname"));
|
||||
out.write(":</b></span> ");
|
||||
out.write(name);
|
||||
}
|
||||
%>
|
||||
out.write(":</b></span> "); out.write(name); } %>
|
||||
</td>
|
||||
</tr>
|
||||
<%
|
||||
@ -189,7 +264,8 @@
|
||||
<%
|
||||
} else {
|
||||
// needed to make the spacing look right
|
||||
%> <%
|
||||
%>
|
||||
<%
|
||||
} // descr
|
||||
%>
|
||||
</td>
|
||||
@ -239,6 +315,7 @@
|
||||
<option value="httpbidirserver">HTTP bidir</option>
|
||||
<option value="ircserver">IRC</option>
|
||||
<option value="streamrserver">Streamr</option>
|
||||
<option value="udpserver">UDP Server/Client(Bidirectional)</option>
|
||||
</select>
|
||||
<input class="control" type="submit" value="<%=intl._t(" Create ")%>" />
|
||||
</form>
|
||||
@ -247,15 +324,29 @@
|
||||
</table>
|
||||
</div>
|
||||
<div class="panel" id="clients">
|
||||
<h2><%=intl._t("I2P Client Tunnels")%></h2>
|
||||
<h2>
|
||||
<%=intl._t("I2P Client Tunnels")%>
|
||||
</h2>
|
||||
<table id="clientTunnels">
|
||||
<tr>
|
||||
<th class="tunnelName"><%=intl._t("Name")%></th>
|
||||
<th class="tunnelType"><%=intl._t("Type")%></th>
|
||||
<th class="tunnelInterface"><%=intl._t("Interface")%></th>
|
||||
<th class="tunnelPort"><%=intl._t("Port")%></th>
|
||||
<th class="tunnelStatus"><%=intl._t("Status")%></th>
|
||||
<th class="tunnelControl"><%=intl._t("Control")%></th>
|
||||
<th class="tunnelName">
|
||||
<%=intl._t("Name")%>
|
||||
</th>
|
||||
<th class="tunnelType">
|
||||
<%=intl._t("Type")%>
|
||||
</th>
|
||||
<th class="tunnelInterface">
|
||||
<%=intl._t("Interface")%>
|
||||
</th>
|
||||
<th class="tunnelPort">
|
||||
<%=intl._t("Port")%>
|
||||
</th>
|
||||
<th class="tunnelStatus">
|
||||
<%=intl._t("Status")%>
|
||||
</th>
|
||||
<th class="tunnelControl">
|
||||
<%=intl._t("Control")%>
|
||||
</th>
|
||||
</tr>
|
||||
<%
|
||||
for (int curClient = 0; curClient < indexBean.getTunnelCount(); curClient++) {
|
||||
@ -263,9 +354,14 @@
|
||||
%>
|
||||
<tr class="tunnelProperties">
|
||||
<td class="tunnelName">
|
||||
<a href="edit?tunnel=<%=curClient%>" title="<%=intl._t("Edit Tunnel Settings for")%> <%=indexBean.getTunnelName(curClient)%>"><%=indexBean.getTunnelName(curClient)%></a>
|
||||
</td><td class="tunnelType"><%=indexBean.getTunnelType(curClient)%>
|
||||
</td><td class="tunnelInterface">
|
||||
<a href="edit?tunnel=<%=curClient%>" title="<%=intl._t(" Edit Tunnel Settings for ")%> <%=indexBean.getTunnelName(curClient)%>">
|
||||
<%=indexBean.getTunnelName(curClient)%>
|
||||
</a>
|
||||
</td>
|
||||
<td class="tunnelType">
|
||||
<%=indexBean.getTunnelType(curClient)%>
|
||||
</td>
|
||||
<td class="tunnelInterface">
|
||||
<%
|
||||
/* should only happen for streamr client */
|
||||
String cHost= indexBean.getClientInterface(curClient);
|
||||
@ -277,44 +373,71 @@
|
||||
out.write(cHost);
|
||||
}
|
||||
%>
|
||||
</td><td class="tunnelPort">
|
||||
</td>
|
||||
<td class="tunnelPort">
|
||||
<%
|
||||
String cPort= indexBean.getClientPort2(curClient);
|
||||
out.write(cPort);
|
||||
if (indexBean.isSSLEnabled(curClient))
|
||||
out.write(" SSL");
|
||||
%>
|
||||
</td><td class="tunnelStatus">
|
||||
</td>
|
||||
<td class="tunnelStatus">
|
||||
<%
|
||||
switch (indexBean.getTunnelStatus(curClient)) {
|
||||
case IndexBean.STARTING:
|
||||
%><div class="statusStarting text" title="<%=intl._t("Starting...")%>"><%=intl._t("Starting...")%></div>
|
||||
</td><td class="tunnelControl">
|
||||
<a class="control" title="<%=intl._t("Stop this Tunnel")%>" href="list?nonce=<%=nextNonce%>&action=stop&tunnel=<%=curClient%>"><%=intl._t("Stop")%></a>
|
||||
%>
|
||||
<div class="statusStarting text" title="<%=intl._t(" Starting... ")%>">
|
||||
<%=intl._t("Starting...")%>
|
||||
</div>
|
||||
</td>
|
||||
<td class="tunnelControl">
|
||||
<a class="control" title="<%=intl._t(" Stop this Tunnel ")%>" href="list?nonce=<%=nextNonce%>&action=stop&tunnel=<%=curClient%>">
|
||||
<%=intl._t("Stop")%>
|
||||
</a>
|
||||
<%
|
||||
break;
|
||||
case IndexBean.STANDBY:
|
||||
%><div class="statusStarting text" title="<%=intl._t("Standby")%>"><%=intl._t("Standby")%></div>
|
||||
</td><td class="tunnelControl">
|
||||
<a class="control" title="Stop this Tunnel" href="list?nonce=<%=nextNonce%>&action=stop&tunnel=<%=curClient%>"><%=intl._t("Stop")%></a>
|
||||
%>
|
||||
<div class="statusStarting text" title="<%=intl._t(" Standby ")%>">
|
||||
<%=intl._t("Standby")%>
|
||||
</div>
|
||||
</td>
|
||||
<td class="tunnelControl">
|
||||
<a class="control" title="Stop this Tunnel" href="list?nonce=<%=nextNonce%>&action=stop&tunnel=<%=curClient%>">
|
||||
<%=intl._t("Stop")%>
|
||||
</a>
|
||||
<%
|
||||
break;
|
||||
case IndexBean.RUNNING:
|
||||
%><div class="statusRunning text" title="<%=intl._t("Running")%>"><%=intl._t("Running")%></div>
|
||||
</td><td class="tunnelControl">
|
||||
<a class="control" title="Stop this Tunnel" href="list?nonce=<%=nextNonce%>&action=stop&tunnel=<%=curClient%>"><%=intl._t("Stop")%></a>
|
||||
%>
|
||||
<div class="statusRunning text" title="<%=intl._t(" Running ")%>">
|
||||
<%=intl._t("Running")%>
|
||||
</div>
|
||||
</td>
|
||||
<td class="tunnelControl">
|
||||
<a class="control" title="Stop this Tunnel" href="list?nonce=<%=nextNonce%>&action=stop&tunnel=<%=curClient%>">
|
||||
<%=intl._t("Stop")%>
|
||||
</a>
|
||||
<%
|
||||
break;
|
||||
case IndexBean.NOT_RUNNING:
|
||||
%><div class="statusNotRunning text" title="<%=intl._t("Stopped")%>"><%=intl._t("Stopped")%></div>
|
||||
</td><td class="tunnelControl">
|
||||
<a class="control" title="<%=intl._t("Start this Tunnel")%>" href="list?nonce=<%=nextNonce%>&action=start&tunnel=<%=curClient%>"><%=intl._t("Start")%></a>
|
||||
%>
|
||||
<div class="statusNotRunning text" title="<%=intl._t(" Stopped ")%>">
|
||||
<%=intl._t("Stopped")%>
|
||||
</div>
|
||||
</td>
|
||||
<td class="tunnelControl">
|
||||
<a class="control" title="<%=intl._t(" Start this Tunnel ")%>" href="list?nonce=<%=nextNonce%>&action=start&tunnel=<%=curClient%>">
|
||||
<%=intl._t("Start")%>
|
||||
</a>
|
||||
<%
|
||||
break;
|
||||
}
|
||||
%>
|
||||
</td>
|
||||
</tr><tr>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tunnelDestination" colspan="6">
|
||||
<span class="tunnelDestinationLabel">
|
||||
<% if ("httpclient".equals(indexBean.getInternalType(curClient)) || "connectclient".equals(indexBean.getInternalType(curClient)) ||
|
||||
@ -326,15 +449,23 @@
|
||||
</span>
|
||||
<%
|
||||
if (indexBean.getIsUsingOutproxyPlugin(curClient)) {
|
||||
%><%=intl._t("internal plugin")%><%
|
||||
%>
|
||||
<%=intl._t("internal plugin")%>
|
||||
<%
|
||||
} else {
|
||||
String cdest = indexBean.getClientDestination(curClient);
|
||||
if (cdest.length() > 70) { // Probably a B64 (a B32 is 60 chars) so truncate
|
||||
%><%=cdest.substring(0, 45)%>…<%=cdest.substring(cdest.length() - 15, cdest.length())%><%
|
||||
%>
|
||||
<%=cdest.substring(0, 45)%>…
|
||||
<%=cdest.substring(cdest.length() - 15, cdest.length())%>
|
||||
<%
|
||||
} else if (cdest.length() > 0) {
|
||||
%><%=cdest%><%
|
||||
%>
|
||||
<%=cdest%>
|
||||
<%
|
||||
} else {
|
||||
%><i><%=intl._t("none")%></i><%
|
||||
%><i><%=intl._t("none")%></i>
|
||||
<%
|
||||
}
|
||||
} %>
|
||||
</td>
|
||||
@ -355,13 +486,19 @@
|
||||
%><b><%=intl._t("Description")%><%
|
||||
}
|
||||
if (descr != null && descr.length() > 0) {
|
||||
%>:</b></span> <%=descr%><%
|
||||
%>:</b></span>
|
||||
<%=descr%>
|
||||
<%
|
||||
} else {
|
||||
%></b></span><%
|
||||
%>
|
||||
</b>
|
||||
</span>
|
||||
<%
|
||||
}
|
||||
} else {
|
||||
// needed to make the spacing look right
|
||||
%> <%
|
||||
%>
|
||||
<%
|
||||
} // descr
|
||||
%>
|
||||
</td>
|
||||
@ -381,6 +518,7 @@
|
||||
<option value="socksirctunnel">SOCKS IRC</option>
|
||||
<option value="connectclient">CONNECT</option>
|
||||
<option value="streamrclient">Streamr</option>
|
||||
<option value="udpclient">UDP Client(Recieve-Only)</option>
|
||||
</select>
|
||||
<input class="control" type="submit" value="<%=intl._t(" Create ")%>" />
|
||||
</form>
|
||||
@ -393,4 +531,6 @@
|
||||
} // isInitialized()
|
||||
|
||||
%>
|
||||
</body></html>
|
||||
</body>
|
||||
|
||||
</html>
|
Reference in New Issue
Block a user