make persistent client dests work
This commit is contained in:
@ -552,14 +552,14 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
* Integer port number if the client is listening
|
||||
* sharedClient parameter is a String "true" or "false"
|
||||
*
|
||||
* @param args {portNumber, destinationBase64 or "file:filename"[, sharedClient]}
|
||||
* @param args {portNumber, destinationBase64 or "file:filename"[, sharedClient [, privKeyFile]]}
|
||||
* @param l logger to receive events and output
|
||||
*/
|
||||
public void runClient(String args[], Logging l) {
|
||||
boolean isShared = true;
|
||||
if (args.length == 3)
|
||||
if (args.length >= 3)
|
||||
isShared = Boolean.valueOf(args[2].trim()).booleanValue();
|
||||
if ( (args.length == 2) || (args.length == 3) ) {
|
||||
if (args.length >= 2) {
|
||||
int portNum = -1;
|
||||
try {
|
||||
portNum = Integer.parseInt(args[0]);
|
||||
@ -572,7 +572,10 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
I2PTunnelTask task;
|
||||
ownDest = !isShared;
|
||||
try {
|
||||
task = new I2PTunnelClient(portNum, args[1], l, ownDest, (EventDispatcher) this, this);
|
||||
String privateKeyFile = null;
|
||||
if (args.length >= 4)
|
||||
privateKeyFile = args[3];
|
||||
task = new I2PTunnelClient(portNum, args[1], l, ownDest, (EventDispatcher) this, this, privateKeyFile);
|
||||
addtask(task);
|
||||
notifyEvent("clientTaskId", Integer.valueOf(task.getId()));
|
||||
} catch (IllegalArgumentException iae) {
|
||||
@ -581,7 +584,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
notifyEvent("clientTaskId", Integer.valueOf(-1));
|
||||
}
|
||||
} else {
|
||||
l.log("client <port> <pubkey>[,<pubkey>]|file:<pubkeyfile>[ <sharedClient>]");
|
||||
l.log("client <port> <pubkey>[,<pubkey>]|file:<pubkeyfile>[ <sharedClient>] [<privKeyFile>]");
|
||||
l.log(" creates a client that forwards port to the pubkey.\n"
|
||||
+ " use 0 as port to get a free port assigned. If you specify\n"
|
||||
+ " a comma delimited list of pubkeys, it will rotate among them\n"
|
||||
@ -720,11 +723,11 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
* 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]}
|
||||
* @param args {portNumber,destinationBase64 or "file:filename" [, sharedClient [, privKeyFile]]}
|
||||
* @param l logger to receive events and output
|
||||
*/
|
||||
public void runIrcClient(String args[], Logging l) {
|
||||
if (args.length >= 2 && args.length <= 3) {
|
||||
if (args.length >= 2) {
|
||||
int port = -1;
|
||||
try {
|
||||
port = Integer.parseInt(args[0]);
|
||||
@ -751,7 +754,10 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
I2PTunnelTask task;
|
||||
ownDest = !isShared;
|
||||
try {
|
||||
task = new I2PTunnelIRCClient(port, args[1],l, ownDest, (EventDispatcher) this, this);
|
||||
String privateKeyFile = null;
|
||||
if (args.length >= 4)
|
||||
privateKeyFile = args[3];
|
||||
task = new I2PTunnelIRCClient(port, args[1], l, ownDest, (EventDispatcher) this, this, privateKeyFile);
|
||||
addtask(task);
|
||||
notifyEvent("ircclientTaskId", Integer.valueOf(task.getId()));
|
||||
} catch (IllegalArgumentException iae) {
|
||||
@ -760,7 +766,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
notifyEvent("ircclientTaskId", Integer.valueOf(-1));
|
||||
}
|
||||
} else {
|
||||
l.log("ircclient <port> [<sharedClient>]");
|
||||
l.log("ircclient <port> [<sharedClient> [<privKeyFile>]]");
|
||||
l.log(" creates a client that filter IRC protocol.");
|
||||
l.log(" <sharedClient> (optional) indicates if this client shares tunnels with other clients (true of false)");
|
||||
notifyEvent("ircclientTaskId", Integer.valueOf(-1));
|
||||
|
@ -31,8 +31,8 @@ public class I2PTunnelClient extends I2PTunnelClientBase {
|
||||
*/
|
||||
public I2PTunnelClient(int localPort, String destinations, Logging l,
|
||||
boolean ownDest, EventDispatcher notifyThis,
|
||||
I2PTunnel tunnel) throws IllegalArgumentException {
|
||||
super(localPort, ownDest, l, notifyThis, "SynSender", tunnel);
|
||||
I2PTunnel tunnel, String pkf) throws IllegalArgumentException {
|
||||
super(localPort, ownDest, l, notifyThis, "SynSender", tunnel, pkf);
|
||||
|
||||
if (waitEventValue("openBaseClientResult").equals("error")) {
|
||||
notifyEvent("openClientResult", "error");
|
||||
|
@ -3,6 +3,7 @@
|
||||
*/
|
||||
package net.i2p.i2ptunnel;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InterruptedIOException;
|
||||
import java.net.ConnectException;
|
||||
@ -59,6 +60,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
|
||||
private byte[] pubkey;
|
||||
|
||||
private String handlerName;
|
||||
private String privKeyFile;
|
||||
|
||||
private Object conLock = new Object();
|
||||
|
||||
@ -91,18 +93,28 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
|
||||
// I2PTunnelClientBase(localPort, ownDest, l, (EventDispatcher)null);
|
||||
//}
|
||||
|
||||
public I2PTunnelClientBase(int localPort, boolean ownDest, Logging l,
|
||||
EventDispatcher notifyThis, String handlerName,
|
||||
I2PTunnel tunnel) throws IllegalArgumentException {
|
||||
this(localPort, ownDest, l, notifyThis, handlerName, tunnel, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param privKeyFile null to generate a transient key
|
||||
*
|
||||
* @throws IllegalArgumentException if the I2CP configuration is b0rked so
|
||||
* badly that we cant create a socketManager
|
||||
*/
|
||||
public I2PTunnelClientBase(int localPort, boolean ownDest, Logging l,
|
||||
EventDispatcher notifyThis, String handlerName,
|
||||
I2PTunnel tunnel) throws IllegalArgumentException{
|
||||
I2PTunnel tunnel, String pkf) throws IllegalArgumentException{
|
||||
super(localPort + " (uninitialized)", notifyThis, tunnel);
|
||||
_clientId = ++__clientId;
|
||||
this.localPort = localPort;
|
||||
this.l = l;
|
||||
this.handlerName = handlerName + _clientId;
|
||||
this.privKeyFile = pkf;
|
||||
|
||||
|
||||
_context = tunnel.getContext();
|
||||
_context.statManager().createRateStat("i2ptunnel.client.closeBacklog", "How many pending sockets remain when we close one due to backlog?", "I2PTunnel", new long[] { 60*1000, 10*60*1000, 60*60*1000 });
|
||||
@ -195,28 +207,34 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
|
||||
private static I2PSocketManager socketManager;
|
||||
|
||||
protected synchronized I2PSocketManager getSocketManager() {
|
||||
return getSocketManager(getTunnel());
|
||||
return getSocketManager(getTunnel(), this.privKeyFile);
|
||||
}
|
||||
protected static synchronized I2PSocketManager getSocketManager(I2PTunnel tunnel) {
|
||||
return getSocketManager(tunnel, null);
|
||||
}
|
||||
protected static synchronized I2PSocketManager getSocketManager(I2PTunnel tunnel, String pkf) {
|
||||
if (socketManager != null) {
|
||||
I2PSession s = socketManager.getSession();
|
||||
if ( (s == null) || (s.isClosed()) ) {
|
||||
_log.info("Building a new socket manager since the old one closed [s=" + s + "]");
|
||||
socketManager = buildSocketManager(tunnel);
|
||||
socketManager = buildSocketManager(tunnel, pkf);
|
||||
} else {
|
||||
_log.info("Not building a new socket manager since the old one is open [s=" + s + "]");
|
||||
}
|
||||
} else {
|
||||
_log.info("Building a new socket manager since there is no other one");
|
||||
socketManager = buildSocketManager(tunnel);
|
||||
socketManager = buildSocketManager(tunnel, pkf);
|
||||
}
|
||||
return socketManager;
|
||||
}
|
||||
|
||||
protected I2PSocketManager buildSocketManager() {
|
||||
return buildSocketManager(getTunnel());
|
||||
return buildSocketManager(getTunnel(), this.privKeyFile);
|
||||
}
|
||||
protected static I2PSocketManager buildSocketManager(I2PTunnel tunnel) {
|
||||
return buildSocketManager(tunnel, null);
|
||||
}
|
||||
protected static I2PSocketManager buildSocketManager(I2PTunnel tunnel, String pkf) {
|
||||
Properties props = new Properties();
|
||||
props.putAll(tunnel.getClientOptions());
|
||||
int portNum = 7654;
|
||||
@ -230,10 +248,22 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
|
||||
|
||||
I2PSocketManager sockManager = null;
|
||||
while (sockManager == null) {
|
||||
// if persistent dest
|
||||
// sockManager = I2PSocketManagerFactory.createManager(privData, tunnel.host, portNum, props);
|
||||
// else
|
||||
if (pkf != null) {
|
||||
// Persistent client dest
|
||||
FileInputStream fis = null;
|
||||
try {
|
||||
fis = new FileInputStream(pkf);
|
||||
sockManager = I2PSocketManagerFactory.createManager(fis, tunnel.host, portNum, props);
|
||||
} catch (IOException ioe) {
|
||||
_log.error("Error opening key file", ioe);
|
||||
// this is going to loop but if we break we'll get a NPE
|
||||
} finally {
|
||||
if (fis != null)
|
||||
try { fis.close(); } catch (IOException ioe) {}
|
||||
}
|
||||
} else {
|
||||
sockManager = I2PSocketManagerFactory.createManager(tunnel.host, portNum, props);
|
||||
}
|
||||
|
||||
if (sockManager == null) {
|
||||
_log.log(Log.CRIT, "Unable to create socket manager");
|
||||
|
@ -39,12 +39,12 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
|
||||
Logging l,
|
||||
boolean ownDest,
|
||||
EventDispatcher notifyThis,
|
||||
I2PTunnel tunnel) throws IllegalArgumentException {
|
||||
I2PTunnel tunnel, String pkf) throws IllegalArgumentException {
|
||||
super(localPort,
|
||||
ownDest,
|
||||
l,
|
||||
notifyThis,
|
||||
"IRCHandler " + (++__clientId), tunnel);
|
||||
"IRCHandler " + (++__clientId), tunnel, pkf);
|
||||
|
||||
StringTokenizer tok = new StringTokenizer(destinations, ",");
|
||||
dests = new ArrayList(1);
|
||||
|
@ -192,8 +192,13 @@ public class TunnelController implements Logging {
|
||||
String listenPort = getListenPort();
|
||||
String dest = getTargetDestination();
|
||||
String sharedClient = getSharedClient();
|
||||
if (getPersistentClientKey()) {
|
||||
String privKeyFile = getPrivKeyFile();
|
||||
_tunnel.runIrcClient(new String[] { listenPort, dest, sharedClient, privKeyFile }, this);
|
||||
} else {
|
||||
_tunnel.runIrcClient(new String[] { listenPort, dest, sharedClient }, this);
|
||||
}
|
||||
}
|
||||
|
||||
private void startSocksClient() {
|
||||
setListenOn();
|
||||
@ -264,8 +269,13 @@ public class TunnelController implements Logging {
|
||||
String listenPort = getListenPort();
|
||||
String dest = getTargetDestination();
|
||||
String sharedClient = getSharedClient();
|
||||
if (getPersistentClientKey()) {
|
||||
String privKeyFile = getPrivKeyFile();
|
||||
_tunnel.runClient(new String[] { listenPort, dest, sharedClient, privKeyFile }, this);
|
||||
} else {
|
||||
_tunnel.runClient(new String[] { listenPort, dest, sharedClient }, this);
|
||||
}
|
||||
}
|
||||
|
||||
private void startServer() {
|
||||
String targetHost = getTargetHost();
|
||||
@ -395,7 +405,7 @@ public class TunnelController implements Logging {
|
||||
public String getProxyList() { return _config.getProperty("proxyList"); }
|
||||
public String getSharedClient() { return _config.getProperty("sharedClient", "true"); }
|
||||
public boolean getStartOnLoad() { return "true".equalsIgnoreCase(_config.getProperty("startOnLoad", "true")); }
|
||||
public boolean getPersistentClientKey() { return Boolean.valueOf(_config.getProperty("persistentClientKey")).booleanValue(); }
|
||||
public boolean getPersistentClientKey() { return Boolean.valueOf(_config.getProperty("option.persistentClientKey")).booleanValue(); }
|
||||
public String getMyDestination() {
|
||||
if (_tunnel != null) {
|
||||
List sessions = _tunnel.getSessions();
|
||||
|
@ -351,6 +351,7 @@
|
||||
<hr />
|
||||
</div>
|
||||
|
||||
<% if ("client".equals(tunnelType) || "ircclient".equals(tunnelType)) { %>
|
||||
<div id="optionsField" class="rowItem">
|
||||
<label for="privKeyFile" accesskey="k">
|
||||
Persistent private <span class="accessKey">k</span>ey:
|
||||
@ -365,10 +366,18 @@
|
||||
<label>File:</label>
|
||||
<input type="text" size="30" id="clientHost" name="privKeyFile" title="Path to Private Key File" value="<%=editBean.getPrivateKeyFile(curTunnel)%>" class="freetext" />
|
||||
</div>
|
||||
<div id="destinationField" class="rowItem">
|
||||
<label for="localDestination" accesskey="L">
|
||||
<span class="accessKey">L</span>ocal destination:
|
||||
</label>
|
||||
<textarea rows="1" cols="60" readonly="readonly" id="localDestination" title="Read Only: Local Destination (if known)" wrap="off"><%=editBean.getDestinationBase64(curTunnel)%></textarea>
|
||||
<span class="comment">(if known)</span>
|
||||
</div>
|
||||
|
||||
<div class="subdivider">
|
||||
<hr />
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<div id="customOptionsField" class="rowItem">
|
||||
<label for="customOptions" accesskey="u">
|
||||
|
Reference in New Issue
Block a user