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
|
* Integer port number if the client is listening
|
||||||
* sharedClient parameter is a String "true" or "false"
|
* 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
|
* @param l logger to receive events and output
|
||||||
*/
|
*/
|
||||||
public void runClient(String args[], Logging l) {
|
public void runClient(String args[], Logging l) {
|
||||||
boolean isShared = true;
|
boolean isShared = true;
|
||||||
if (args.length == 3)
|
if (args.length >= 3)
|
||||||
isShared = Boolean.valueOf(args[2].trim()).booleanValue();
|
isShared = Boolean.valueOf(args[2].trim()).booleanValue();
|
||||||
if ( (args.length == 2) || (args.length == 3) ) {
|
if (args.length >= 2) {
|
||||||
int portNum = -1;
|
int portNum = -1;
|
||||||
try {
|
try {
|
||||||
portNum = Integer.parseInt(args[0]);
|
portNum = Integer.parseInt(args[0]);
|
||||||
@ -572,7 +572,10 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
|||||||
I2PTunnelTask task;
|
I2PTunnelTask task;
|
||||||
ownDest = !isShared;
|
ownDest = !isShared;
|
||||||
try {
|
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);
|
addtask(task);
|
||||||
notifyEvent("clientTaskId", Integer.valueOf(task.getId()));
|
notifyEvent("clientTaskId", Integer.valueOf(task.getId()));
|
||||||
} catch (IllegalArgumentException iae) {
|
} catch (IllegalArgumentException iae) {
|
||||||
@ -581,7 +584,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
|||||||
notifyEvent("clientTaskId", Integer.valueOf(-1));
|
notifyEvent("clientTaskId", Integer.valueOf(-1));
|
||||||
}
|
}
|
||||||
} else {
|
} 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"
|
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"
|
+ " 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"
|
+ " 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.
|
* Also sets "ircclientStatus" = "ok" or "error" after the client tunnel has started.
|
||||||
* parameter sharedClient is a String, either "true" or "false"
|
* 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
|
* @param l logger to receive events and output
|
||||||
*/
|
*/
|
||||||
public void runIrcClient(String args[], Logging l) {
|
public void runIrcClient(String args[], Logging l) {
|
||||||
if (args.length >= 2 && args.length <= 3) {
|
if (args.length >= 2) {
|
||||||
int port = -1;
|
int port = -1;
|
||||||
try {
|
try {
|
||||||
port = Integer.parseInt(args[0]);
|
port = Integer.parseInt(args[0]);
|
||||||
@ -751,7 +754,10 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
|||||||
I2PTunnelTask task;
|
I2PTunnelTask task;
|
||||||
ownDest = !isShared;
|
ownDest = !isShared;
|
||||||
try {
|
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);
|
addtask(task);
|
||||||
notifyEvent("ircclientTaskId", Integer.valueOf(task.getId()));
|
notifyEvent("ircclientTaskId", Integer.valueOf(task.getId()));
|
||||||
} catch (IllegalArgumentException iae) {
|
} catch (IllegalArgumentException iae) {
|
||||||
@ -760,7 +766,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
|||||||
notifyEvent("ircclientTaskId", Integer.valueOf(-1));
|
notifyEvent("ircclientTaskId", Integer.valueOf(-1));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
l.log("ircclient <port> [<sharedClient>]");
|
l.log("ircclient <port> [<sharedClient> [<privKeyFile>]]");
|
||||||
l.log(" creates a client that filter IRC protocol.");
|
l.log(" creates a client that filter IRC protocol.");
|
||||||
l.log(" <sharedClient> (optional) indicates if this client shares tunnels with other clients (true of false)");
|
l.log(" <sharedClient> (optional) indicates if this client shares tunnels with other clients (true of false)");
|
||||||
notifyEvent("ircclientTaskId", Integer.valueOf(-1));
|
notifyEvent("ircclientTaskId", Integer.valueOf(-1));
|
||||||
|
@ -31,8 +31,8 @@ public class I2PTunnelClient extends I2PTunnelClientBase {
|
|||||||
*/
|
*/
|
||||||
public I2PTunnelClient(int localPort, String destinations, Logging l,
|
public I2PTunnelClient(int localPort, String destinations, Logging l,
|
||||||
boolean ownDest, EventDispatcher notifyThis,
|
boolean ownDest, EventDispatcher notifyThis,
|
||||||
I2PTunnel tunnel) throws IllegalArgumentException {
|
I2PTunnel tunnel, String pkf) throws IllegalArgumentException {
|
||||||
super(localPort, ownDest, l, notifyThis, "SynSender", tunnel);
|
super(localPort, ownDest, l, notifyThis, "SynSender", tunnel, pkf);
|
||||||
|
|
||||||
if (waitEventValue("openBaseClientResult").equals("error")) {
|
if (waitEventValue("openBaseClientResult").equals("error")) {
|
||||||
notifyEvent("openClientResult", "error");
|
notifyEvent("openClientResult", "error");
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
*/
|
*/
|
||||||
package net.i2p.i2ptunnel;
|
package net.i2p.i2ptunnel;
|
||||||
|
|
||||||
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InterruptedIOException;
|
import java.io.InterruptedIOException;
|
||||||
import java.net.ConnectException;
|
import java.net.ConnectException;
|
||||||
@ -59,6 +60,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
|
|||||||
private byte[] pubkey;
|
private byte[] pubkey;
|
||||||
|
|
||||||
private String handlerName;
|
private String handlerName;
|
||||||
|
private String privKeyFile;
|
||||||
|
|
||||||
private Object conLock = new Object();
|
private Object conLock = new Object();
|
||||||
|
|
||||||
@ -91,18 +93,28 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
|
|||||||
// I2PTunnelClientBase(localPort, ownDest, l, (EventDispatcher)null);
|
// 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
|
* @throws IllegalArgumentException if the I2CP configuration is b0rked so
|
||||||
* badly that we cant create a socketManager
|
* badly that we cant create a socketManager
|
||||||
*/
|
*/
|
||||||
public I2PTunnelClientBase(int localPort, boolean ownDest, Logging l,
|
public I2PTunnelClientBase(int localPort, boolean ownDest, Logging l,
|
||||||
EventDispatcher notifyThis, String handlerName,
|
EventDispatcher notifyThis, String handlerName,
|
||||||
I2PTunnel tunnel) throws IllegalArgumentException{
|
I2PTunnel tunnel, String pkf) throws IllegalArgumentException{
|
||||||
super(localPort + " (uninitialized)", notifyThis, tunnel);
|
super(localPort + " (uninitialized)", notifyThis, tunnel);
|
||||||
_clientId = ++__clientId;
|
_clientId = ++__clientId;
|
||||||
this.localPort = localPort;
|
this.localPort = localPort;
|
||||||
this.l = l;
|
this.l = l;
|
||||||
this.handlerName = handlerName + _clientId;
|
this.handlerName = handlerName + _clientId;
|
||||||
|
this.privKeyFile = pkf;
|
||||||
|
|
||||||
|
|
||||||
_context = tunnel.getContext();
|
_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 });
|
_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;
|
private static I2PSocketManager socketManager;
|
||||||
|
|
||||||
protected synchronized I2PSocketManager getSocketManager() {
|
protected synchronized I2PSocketManager getSocketManager() {
|
||||||
return getSocketManager(getTunnel());
|
return getSocketManager(getTunnel(), this.privKeyFile);
|
||||||
}
|
}
|
||||||
protected static synchronized I2PSocketManager getSocketManager(I2PTunnel tunnel) {
|
protected static synchronized I2PSocketManager getSocketManager(I2PTunnel tunnel) {
|
||||||
|
return getSocketManager(tunnel, null);
|
||||||
|
}
|
||||||
|
protected static synchronized I2PSocketManager getSocketManager(I2PTunnel tunnel, String pkf) {
|
||||||
if (socketManager != null) {
|
if (socketManager != null) {
|
||||||
I2PSession s = socketManager.getSession();
|
I2PSession s = socketManager.getSession();
|
||||||
if ( (s == null) || (s.isClosed()) ) {
|
if ( (s == null) || (s.isClosed()) ) {
|
||||||
_log.info("Building a new socket manager since the old one closed [s=" + s + "]");
|
_log.info("Building a new socket manager since the old one closed [s=" + s + "]");
|
||||||
socketManager = buildSocketManager(tunnel);
|
socketManager = buildSocketManager(tunnel, pkf);
|
||||||
} else {
|
} else {
|
||||||
_log.info("Not building a new socket manager since the old one is open [s=" + s + "]");
|
_log.info("Not building a new socket manager since the old one is open [s=" + s + "]");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_log.info("Building a new socket manager since there is no other one");
|
_log.info("Building a new socket manager since there is no other one");
|
||||||
socketManager = buildSocketManager(tunnel);
|
socketManager = buildSocketManager(tunnel, pkf);
|
||||||
}
|
}
|
||||||
return socketManager;
|
return socketManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected I2PSocketManager buildSocketManager() {
|
protected I2PSocketManager buildSocketManager() {
|
||||||
return buildSocketManager(getTunnel());
|
return buildSocketManager(getTunnel(), this.privKeyFile);
|
||||||
}
|
}
|
||||||
protected static I2PSocketManager buildSocketManager(I2PTunnel tunnel) {
|
protected static I2PSocketManager buildSocketManager(I2PTunnel tunnel) {
|
||||||
|
return buildSocketManager(tunnel, null);
|
||||||
|
}
|
||||||
|
protected static I2PSocketManager buildSocketManager(I2PTunnel tunnel, String pkf) {
|
||||||
Properties props = new Properties();
|
Properties props = new Properties();
|
||||||
props.putAll(tunnel.getClientOptions());
|
props.putAll(tunnel.getClientOptions());
|
||||||
int portNum = 7654;
|
int portNum = 7654;
|
||||||
@ -230,10 +248,22 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
|
|||||||
|
|
||||||
I2PSocketManager sockManager = null;
|
I2PSocketManager sockManager = null;
|
||||||
while (sockManager == null) {
|
while (sockManager == null) {
|
||||||
// if persistent dest
|
if (pkf != null) {
|
||||||
// sockManager = I2PSocketManagerFactory.createManager(privData, tunnel.host, portNum, props);
|
// Persistent client dest
|
||||||
// else
|
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);
|
sockManager = I2PSocketManagerFactory.createManager(tunnel.host, portNum, props);
|
||||||
|
}
|
||||||
|
|
||||||
if (sockManager == null) {
|
if (sockManager == null) {
|
||||||
_log.log(Log.CRIT, "Unable to create socket manager");
|
_log.log(Log.CRIT, "Unable to create socket manager");
|
||||||
|
@ -39,12 +39,12 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
|
|||||||
Logging l,
|
Logging l,
|
||||||
boolean ownDest,
|
boolean ownDest,
|
||||||
EventDispatcher notifyThis,
|
EventDispatcher notifyThis,
|
||||||
I2PTunnel tunnel) throws IllegalArgumentException {
|
I2PTunnel tunnel, String pkf) throws IllegalArgumentException {
|
||||||
super(localPort,
|
super(localPort,
|
||||||
ownDest,
|
ownDest,
|
||||||
l,
|
l,
|
||||||
notifyThis,
|
notifyThis,
|
||||||
"IRCHandler " + (++__clientId), tunnel);
|
"IRCHandler " + (++__clientId), tunnel, pkf);
|
||||||
|
|
||||||
StringTokenizer tok = new StringTokenizer(destinations, ",");
|
StringTokenizer tok = new StringTokenizer(destinations, ",");
|
||||||
dests = new ArrayList(1);
|
dests = new ArrayList(1);
|
||||||
|
@ -192,8 +192,13 @@ public class TunnelController implements Logging {
|
|||||||
String listenPort = getListenPort();
|
String listenPort = getListenPort();
|
||||||
String dest = getTargetDestination();
|
String dest = getTargetDestination();
|
||||||
String sharedClient = getSharedClient();
|
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);
|
_tunnel.runIrcClient(new String[] { listenPort, dest, sharedClient }, this);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void startSocksClient() {
|
private void startSocksClient() {
|
||||||
setListenOn();
|
setListenOn();
|
||||||
@ -264,8 +269,13 @@ public class TunnelController implements Logging {
|
|||||||
String listenPort = getListenPort();
|
String listenPort = getListenPort();
|
||||||
String dest = getTargetDestination();
|
String dest = getTargetDestination();
|
||||||
String sharedClient = getSharedClient();
|
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);
|
_tunnel.runClient(new String[] { listenPort, dest, sharedClient }, this);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void startServer() {
|
private void startServer() {
|
||||||
String targetHost = getTargetHost();
|
String targetHost = getTargetHost();
|
||||||
@ -395,7 +405,7 @@ public class TunnelController implements Logging {
|
|||||||
public String getProxyList() { return _config.getProperty("proxyList"); }
|
public String getProxyList() { return _config.getProperty("proxyList"); }
|
||||||
public String getSharedClient() { return _config.getProperty("sharedClient", "true"); }
|
public String getSharedClient() { return _config.getProperty("sharedClient", "true"); }
|
||||||
public boolean getStartOnLoad() { return "true".equalsIgnoreCase(_config.getProperty("startOnLoad", "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() {
|
public String getMyDestination() {
|
||||||
if (_tunnel != null) {
|
if (_tunnel != null) {
|
||||||
List sessions = _tunnel.getSessions();
|
List sessions = _tunnel.getSessions();
|
||||||
|
@ -351,6 +351,7 @@
|
|||||||
<hr />
|
<hr />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<% if ("client".equals(tunnelType) || "ircclient".equals(tunnelType)) { %>
|
||||||
<div id="optionsField" class="rowItem">
|
<div id="optionsField" class="rowItem">
|
||||||
<label for="privKeyFile" accesskey="k">
|
<label for="privKeyFile" accesskey="k">
|
||||||
Persistent private <span class="accessKey">k</span>ey:
|
Persistent private <span class="accessKey">k</span>ey:
|
||||||
@ -365,10 +366,18 @@
|
|||||||
<label>File:</label>
|
<label>File:</label>
|
||||||
<input type="text" size="30" id="clientHost" name="privKeyFile" title="Path to Private Key File" value="<%=editBean.getPrivateKeyFile(curTunnel)%>" class="freetext" />
|
<input type="text" size="30" id="clientHost" name="privKeyFile" title="Path to Private Key File" value="<%=editBean.getPrivateKeyFile(curTunnel)%>" class="freetext" />
|
||||||
</div>
|
</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">
|
<div class="subdivider">
|
||||||
<hr />
|
<hr />
|
||||||
</div>
|
</div>
|
||||||
|
<% } %>
|
||||||
|
|
||||||
<div id="customOptionsField" class="rowItem">
|
<div id="customOptionsField" class="rowItem">
|
||||||
<label for="customOptions" accesskey="u">
|
<label for="customOptions" accesskey="u">
|
||||||
|
Reference in New Issue
Block a user