forked from I2P_Developers/i2p.i2p
I2CP Multisession - Work in progress:
Fix sending CreateSessionMessage for subsession New AliasedTunnelPool for subsessions, don't reuse TunnelPool, so it has its own settings Fix addAlias() Simplify refreshSettings() Send status message on subsession create failure Fix settings for subsession
This commit is contained in:
@ -647,6 +647,8 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa
|
||||
// now send CreateSessionMessages for all subsessions, one at a time, must wait for each response
|
||||
synchronized(_subsessionLock) {
|
||||
for (SubSession ss : _subsessions) {
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info(getPrefix() + "Connecting subsession " + ss);
|
||||
_producer.connect(ss);
|
||||
}
|
||||
}
|
||||
|
@ -114,7 +114,8 @@ class SubSession extends I2PSessionMuxedImpl {
|
||||
*/
|
||||
@Override
|
||||
public boolean isClosed() {
|
||||
return getSessionId() == null || _primary.isClosed();
|
||||
// FIXME
|
||||
return /* getSessionId() == null || */ _primary.isClosed();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -248,9 +248,18 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi
|
||||
SessionConfig cfg = new SessionConfig(dest);
|
||||
cfg.setSignature(in.getSignature());
|
||||
Properties props = new Properties();
|
||||
props.putAll(in.getOptions());
|
||||
cfg.setOptions(props);
|
||||
boolean isPrimary = _runner.getSessionIds().isEmpty();
|
||||
if (!isPrimary) {
|
||||
// all the primary options, then the overrides from the alias
|
||||
SessionConfig pcfg = _runner.getPrimaryConfig();
|
||||
if (pcfg != null) {
|
||||
props.putAll(pcfg.getOptions());
|
||||
} else {
|
||||
_log.error("no primary config?");
|
||||
}
|
||||
}
|
||||
props.putAll(inProps);
|
||||
cfg.setOptions(props);
|
||||
// this sets the session id
|
||||
int status = _runner.sessionEstablished(cfg);
|
||||
if (status != SessionStatusMessage.STATUS_CREATED) {
|
||||
@ -269,28 +278,27 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi
|
||||
}
|
||||
// get the new session ID
|
||||
id = _runner.getSessionId(dest.calculateHash());
|
||||
sendStatusMessage(id, status);
|
||||
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("Session " + id + " established for " + dest.calculateHash());
|
||||
if (isPrimary) {
|
||||
sendStatusMessage(id, status);
|
||||
startCreateSessionJob(cfg);
|
||||
} else {
|
||||
SessionConfig pcfg = _runner.getPrimaryConfig();
|
||||
if (pcfg != null) {
|
||||
///////////
|
||||
// new tunnel name etc.
|
||||
ClientTunnelSettings settings = new ClientTunnelSettings(dest.calculateHash());
|
||||
// all the primary options, then the overrides from the alias
|
||||
props.putAll(pcfg.getOptions());
|
||||
props.putAll(props);
|
||||
settings.readFromProperties(props);
|
||||
boolean ok = _context.tunnelManager().addAlias(dest, settings, pcfg.getDestination());
|
||||
if (!ok) {
|
||||
_log.error("Add alias failed");
|
||||
// send status message...
|
||||
status = SessionStatusMessage.STATUS_REFUSED;
|
||||
}
|
||||
} else {
|
||||
_log.error("no primary config?");
|
||||
status = SessionStatusMessage.STATUS_INVALID;
|
||||
}
|
||||
sendStatusMessage(id, status);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,141 @@
|
||||
package net.i2p.router.tunnel.pool;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.i2p.data.Hash;
|
||||
import net.i2p.data.LeaseSet;
|
||||
import net.i2p.data.TunnelId;
|
||||
import net.i2p.router.RouterContext;
|
||||
import net.i2p.router.TunnelInfo;
|
||||
import net.i2p.router.TunnelPoolSettings;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
/**
|
||||
* A tunnel pool with its own settings and Destination,
|
||||
* but uses another pool for its tunnels.
|
||||
*
|
||||
* @since 0.9.20
|
||||
*/
|
||||
public class AliasedTunnelPool extends TunnelPool {
|
||||
|
||||
private final TunnelPool _aliasOf;
|
||||
|
||||
AliasedTunnelPool(RouterContext ctx, TunnelPoolManager mgr, TunnelPoolSettings settings, TunnelPool aliasOf) {
|
||||
super(ctx, mgr, settings, null);
|
||||
if (settings.isExploratory())
|
||||
throw new IllegalArgumentException();
|
||||
if (settings.getAliasOf() == null)
|
||||
throw new IllegalArgumentException();
|
||||
_aliasOf = aliasOf;
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized void startup() {
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info(toString() + ": Startup() called, was already alive? " + _alive, new Exception());
|
||||
_alive = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized void shutdown() {
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn(toString() + ": Shutdown called");
|
||||
_alive = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
TunnelInfo selectTunnel() {
|
||||
return _aliasOf.selectTunnel();
|
||||
}
|
||||
|
||||
@Override
|
||||
TunnelInfo selectTunnel(Hash closestTo) {
|
||||
return _aliasOf.selectTunnel(closestTo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TunnelInfo getTunnel(TunnelId gatewayId) {
|
||||
return _aliasOf.getTunnel(gatewayId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TunnelInfo> listTunnels() {
|
||||
return _aliasOf.listTunnels();
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean needFallback() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PooledTunnelCreatorConfig> listPending() {
|
||||
return _aliasOf.listPending();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAlive() {
|
||||
return _alive && _aliasOf.isAlive();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return _aliasOf.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
void addTunnel(TunnelInfo info) {
|
||||
_aliasOf.addTunnel(info);
|
||||
}
|
||||
|
||||
@Override
|
||||
void removeTunnel(TunnelInfo info) {
|
||||
_aliasOf.removeTunnel(info);
|
||||
}
|
||||
|
||||
@Override
|
||||
void tunnelFailed(TunnelInfo cfg) {
|
||||
_aliasOf.tunnelFailed(cfg);
|
||||
}
|
||||
|
||||
@Override
|
||||
void tunnelFailed(TunnelInfo cfg, Hash blamePeer) {
|
||||
_aliasOf.tunnelFailed(cfg, blamePeer);
|
||||
}
|
||||
|
||||
@Override
|
||||
void refreshLeaseSet() {}
|
||||
|
||||
@Override
|
||||
boolean buildFallback() {
|
||||
return _aliasOf.buildFallback();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LeaseSet locked_buildNewLeaseSet() {
|
||||
return _context.netDb().lookupLeaseSetLocally(_aliasOf.getSettings().getDestination());
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLifetimeProcessed() {
|
||||
return _aliasOf.getLifetimeProcessed();
|
||||
}
|
||||
|
||||
@Override
|
||||
int countHowManyToBuild() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
PooledTunnelCreatorConfig configureNewTunnel() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
void buildComplete(PooledTunnelCreatorConfig cfg) {}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Aliased " + super.toString();
|
||||
}
|
||||
}
|
@ -31,13 +31,13 @@ import net.i2p.util.Log;
|
||||
*/
|
||||
public class TunnelPool {
|
||||
private final List<PooledTunnelCreatorConfig> _inProgress = new ArrayList<PooledTunnelCreatorConfig>();
|
||||
private final RouterContext _context;
|
||||
private final Log _log;
|
||||
protected final RouterContext _context;
|
||||
protected final Log _log;
|
||||
private TunnelPoolSettings _settings;
|
||||
private final List<TunnelInfo> _tunnels;
|
||||
private final TunnelPeerSelector _peerSelector;
|
||||
private final TunnelPoolManager _manager;
|
||||
private volatile boolean _alive;
|
||||
protected volatile boolean _alive;
|
||||
private long _lifetimeProcessed;
|
||||
private TunnelInfo _lastSelected;
|
||||
private long _lastSelectionPeriod;
|
||||
@ -119,11 +119,9 @@ public class TunnelPool {
|
||||
}
|
||||
}
|
||||
|
||||
void refreshSettings() {
|
||||
if (!_settings.isExploratory()) {
|
||||
private void refreshSettings() {
|
||||
if (!_settings.isExploratory())
|
||||
return; // don't override client specified settings
|
||||
} else {
|
||||
if (_settings.isExploratory()) {
|
||||
Properties props = new Properties();
|
||||
props.putAll(_context.router().getConfigMap());
|
||||
if (_settings.isInbound())
|
||||
@ -131,8 +129,6 @@ public class TunnelPool {
|
||||
else
|
||||
_settings.readFromProperties(TunnelPoolSettings.PREFIX_OUTBOUND_EXPLORATORY, props);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* when selecting tunnels, stick with the same one for a brief
|
||||
@ -413,11 +409,15 @@ public class TunnelPool {
|
||||
public List<PooledTunnelCreatorConfig> listPending() { synchronized (_inProgress) { return new ArrayList<PooledTunnelCreatorConfig>(_inProgress); } }
|
||||
|
||||
/** duplicate of size(), let's pick one */
|
||||
int getTunnelCount() { synchronized (_tunnels) { return _tunnels.size(); } }
|
||||
int getTunnelCount() { return size(); }
|
||||
|
||||
public TunnelPoolSettings getSettings() { return _settings; }
|
||||
|
||||
void setSettings(TunnelPoolSettings settings) {
|
||||
if (settings != null && _settings != null) {
|
||||
settings.getAliases().addAll(_settings.getAliases());
|
||||
settings.setAliasOf(_settings.getAliasOf());
|
||||
}
|
||||
_settings = settings;
|
||||
if (_settings != null) {
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
@ -717,7 +717,7 @@ public class TunnelPool {
|
||||
*
|
||||
* @return null on failure
|
||||
*/
|
||||
private LeaseSet locked_buildNewLeaseSet() {
|
||||
protected LeaseSet locked_buildNewLeaseSet() {
|
||||
if (!_alive)
|
||||
return null;
|
||||
|
||||
|
@ -451,14 +451,35 @@ public class TunnelPoolManager implements TunnelManagerFacade {
|
||||
Hash h = dest.calculateHash();
|
||||
Hash e = existingClient.calculateHash();
|
||||
synchronized(this) {
|
||||
TunnelPool inbound = _clientInboundPools.get(e);
|
||||
TunnelPool outbound = _clientOutboundPools.get(e);
|
||||
/////// gah same tunnel pool or different?
|
||||
if (inbound == null || outbound == null)
|
||||
TunnelPool inbound = _clientInboundPools.get(h);
|
||||
TunnelPool outbound = _clientOutboundPools.get(h);
|
||||
if (inbound != null || outbound != null) {
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("already have alias " + dest);
|
||||
return false;
|
||||
}
|
||||
TunnelPool eInbound = _clientInboundPools.get(e);
|
||||
TunnelPool eOutbound = _clientOutboundPools.get(e);
|
||||
if (eInbound == null || eOutbound == null) {
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("primary not found " + existingClient);
|
||||
return false;
|
||||
}
|
||||
eInbound.getSettings().getAliases().add(h);
|
||||
eOutbound.getSettings().getAliases().add(h);
|
||||
TunnelPoolSettings newIn = settings.getInboundSettings();
|
||||
TunnelPoolSettings newOut = settings.getOutboundSettings();
|
||||
newIn.setAliasOf(e);
|
||||
newOut.setAliasOf(e);
|
||||
inbound = new AliasedTunnelPool(_context, this, newIn, eInbound);
|
||||
outbound = new AliasedTunnelPool(_context, this, newOut, eOutbound);
|
||||
_clientInboundPools.put(h, inbound);
|
||||
_clientOutboundPools.put(h, outbound);
|
||||
inbound.startup();
|
||||
outbound.startup();
|
||||
}
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Added " + h + " as alias for " + e + " with settings " + settings);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -483,9 +504,9 @@ public class TunnelPoolManager implements TunnelManagerFacade {
|
||||
}
|
||||
TunnelPool outbound = _clientOutboundPools.remove(h);
|
||||
if (outbound != null) {
|
||||
Hash p = inbound.getSettings().getAliasOf();
|
||||
Hash p = outbound.getSettings().getAliasOf();
|
||||
if (p != null) {
|
||||
TunnelPool pri = _clientInboundPools.get(p);
|
||||
TunnelPool pri = _clientOutboundPools.get(p);
|
||||
if (pri != null) {
|
||||
Set<Hash> aliases = pri.getSettings().getAliases();
|
||||
if (aliases != null)
|
||||
|
Reference in New Issue
Block a user