* I2PTunnel:

- More client options cleanups
   - Options changes now propagate to running
     socket managers and sessions, and through to the router
 * SocketManager:
   - Simplify factory, use 4-arg constructor,
     make fields final, deprecate 0-arg constructor
   - Improve how options are updated
   - Javadocs
This commit is contained in:
zzz
2012-06-14 19:44:47 +00:00
parent 64221fb3fb
commit e522ffad4e
10 changed files with 255 additions and 115 deletions

View File

@@ -193,7 +193,7 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
}
}
/** @return non-null */
/** @return A copy, non-null */
List<I2PSession> getSessions() {
return new ArrayList(_sessions);
}
@@ -208,6 +208,10 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
_sessions.remove(session);
}
/**
* Generic options used for clients and servers
* @return not a copy
*/
public Properties getClientOptions() { return _clientOptions; }
private void addtask(I2PTunnelTask tsk) {
@@ -327,11 +331,13 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
/**
* Configure the extra I2CP options to use in any subsequent I2CP sessions.
* Generic options used for clients and servers
* Usage: "clientoptions[ key=value]*" .
*
* Sets the event "clientoptions_onResult" = "ok" after completion.
*
* Deprecated use setClientOptions()
* Deprecated To be made private, use setClientOptions().
* This does NOT update a running TunnelTask.
*
* @param args each args[i] is a key=value pair to add to the options
* @param l logger to receive events and output
@@ -351,17 +357,22 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
}
/**
* A more efficient runClientOptions()
* Generic options used for clients and servers.
* This DOES update a running TunnelTask, but NOT the session.
* A more efficient runClientOptions().
*
* @param opts non-null
* @since 0.9.1
*/
public void setClientOptions(Properties opts) {
_clientOptions.clear();
for (Map.Entry e : opts.entrySet()) {
String key = (String) e.getKey();
String val = (String) e.getValue();
_clientOptions.setProperty(key, val);
for (Iterator iter = _clientOptions.keySet().iterator(); iter.hasNext();) {
Object key = iter.next();
if (!opts.containsKey(key))
iter.remove();
}
_clientOptions.putAll(opts);
for (I2PTunnelTask task : tasks) {
task.optionsUpdated(this);
}
notifyEvent("clientoptions_onResult", "ok");
}

View File

@@ -495,6 +495,22 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
return opts;
}
/**
* Update the I2PSocketManager.
*
* @since 0.9.1
*/
@Override
public void optionsUpdated(I2PTunnel tunnel) {
if (getTunnel() != tunnel)
return;
I2PSocketManager sm = _ownDest ? sockMgr : socketManager;
if (sm == null)
return;
Properties props = tunnel.getClientOptions();
sm.setDefaultOptions(sockMgr.buildOptions(props));
}
/**
* Create a new I2PSocket towards to the specified destination,
* adding it to the list of connections actually managed by this

View File

@@ -295,6 +295,19 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
}
}
/**
* Update the I2PSocketManager.
*
* @since 0.9.1
*/
@Override
public void optionsUpdated(I2PTunnel tunnel) {
if (getTunnel() != tunnel || sockMgr == null)
return;
Properties props = tunnel.getClientOptions();
sockMgr.setDefaultOptions(sockMgr.buildOptions(props));
}
protected int getHandlerCount() {
int rv = DEFAULT_HANDLER_COUNT;
String cnt = getTunnel().getClientOptions().getProperty(PROP_HANDLER_COUNT);

View File

@@ -58,6 +58,15 @@ public abstract class I2PTunnelTask extends EventDispatcherImpl {
public abstract boolean close(boolean forced);
/**
* Notify the task that I2PTunnel's options have been updated.
* Extending classes should override and call I2PTunnel.getClientOptions(),
* then update the I2PSocketManager.
*
* @since 0.9.1
*/
public void optionsUpdated(I2PTunnel tunnel) {}
/**
* For tasks that don't call I2PTunnel.addSession() directly
* @since 0.8.13

View File

@@ -328,6 +328,7 @@ public class TunnelController implements Logging {
_log.info("Releasing session " + s);
TunnelControllerGroup.getInstance().release(this, s);
}
// _sessions.clear() ????
} else {
if (_log.shouldLog(Log.WARN))
_log.warn("No sessions to release? for " + getName());
@@ -386,7 +387,13 @@ public class TunnelController implements Logging {
}
}
private void setSessionOptions() {
/**
* These are the ones stored with a prefix of "option."
*
* @return keys with the "option." prefix stripped
* @since 0.9.1 Much better than getClientOptions()
*/
public Properties getClientOptionProps() {
Properties opts = new Properties();
for (Map.Entry e : _config.entrySet()) {
String key = (String) e.getKey();
@@ -396,7 +403,11 @@ public class TunnelController implements Logging {
opts.setProperty(key, val);
}
}
_tunnel.setClientOptions(opts);
return opts;
}
private void setSessionOptions() {
_tunnel.setClientOptions(getClientOptionProps());
}
private void setI2CPOptions() {
@@ -430,25 +441,37 @@ public class TunnelController implements Logging {
startTunnel();
}
/**
* As of 0.9.1, updates the options on an existing session
*/
public void setConfig(Properties config, String prefix) {
Properties props = new Properties();
for (Iterator iter = config.keySet().iterator(); iter.hasNext(); ) {
String key = (String)iter.next();
String val = config.getProperty(key);
for (Map.Entry e : config.entrySet()) {
String key = (String) e.getKey();
if (key.startsWith(prefix)) {
key = key.substring(prefix.length());
String val = (String) e.getValue();
props.setProperty(key, val);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Set prop [" + key + "] to [" + val + "]");
}
}
_config = props;
// tell i2ptunnel, who will tell the TunnelTask, who will tell the SocketManager
setSessionOptions();
if (_running && _sessions != null) {
for (I2PSession s : _sessions) {
// tell the router via the session
if (!s.isClosed()) {
s.updateOptions(_tunnel.getClientOptions());
}
}
}
}
public Properties getConfig(String prefix) {
Properties rv = new Properties();
for (Iterator iter = _config.keySet().iterator(); iter.hasNext(); ) {
String key = (String)iter.next();
String val = _config.getProperty(key);
for (Map.Entry e : _config.entrySet()) {
String key = (String) e.getKey();
String val = (String) e.getValue();
rv.setProperty(prefix + key, val);
}
return rv;
@@ -459,19 +482,27 @@ public class TunnelController implements Logging {
public String getDescription() { return _config.getProperty("description"); }
public String getI2CPHost() { return _config.getProperty("i2cpHost"); }
public String getI2CPPort() { return _config.getProperty("i2cpPort"); }
/**
* These are the ones with a prefix of "option."
*
* @return one big string of "key=val key=val ..."
* @deprecated why would you want this? Use getClientOptionProps() instead
*/
public String getClientOptions() {
StringBuilder opts = new StringBuilder(64);
for (Iterator iter = _config.keySet().iterator(); iter.hasNext(); ) {
String key = (String)iter.next();
String val = _config.getProperty(key);
for (Map.Entry e : _config.entrySet()) {
String key = (String) e.getKey();
if (key.startsWith("option.")) {
key = key.substring("option.".length());
String val = (String) e.getValue();
if (opts.length() > 0) opts.append(' ');
opts.append(key).append('=').append(val);
}
}
return opts.toString();
}
public String getListenOnInterface() { return _config.getProperty("interface"); }
public String getTargetHost() { return _config.getProperty("targetHost"); }
public String getTargetPort() { return _config.getProperty("targetPort"); }
@@ -485,6 +516,7 @@ public class TunnelController implements Logging {
/** default true */
public boolean getStartOnLoad() { return Boolean.valueOf(_config.getProperty("startOnLoad", "true")).booleanValue(); }
public boolean getPersistentClientKey() { return Boolean.valueOf(_config.getProperty("option.persistentClientKey")).booleanValue(); }
public String getMyDestination() {
if (_tunnel != null) {
List<I2PSession> sessions = _tunnel.getSessions();

View File

@@ -376,18 +376,6 @@ public class EditBean extends IndexBean {
*/
private static Properties getOptions(TunnelController controller) {
if (controller == null) return null;
String opts = controller.getClientOptions();
StringTokenizer tok = new StringTokenizer(opts);
Properties props = new Properties();
while (tok.hasMoreTokens()) {
String pair = tok.nextToken();
int eq = pair.indexOf('=');
if ( (eq <= 0) || (eq >= pair.length()) )
continue;
String key = pair.substring(0, eq);
String val = pair.substring(eq+1);
props.setProperty(key, val);
}
return props;
return controller.getClientOptionProps();
}
}