forked from I2P_Developers/i2p.i2p
I2CP Multisession Work in progress:
Fix NPE in requestLeaseSet() Fix setting new session ID in SessionStatusMessage Fix subsession support detection Streaming: one socket manager, multiple connection managers. Change data structure for subessions in socket manager Subsession cleanup on destroy I2PTunnel: add DSA subsession for non-DSA shared client Javadocs
This commit is contained in:
@@ -31,6 +31,7 @@ import net.i2p.client.streaming.I2PSocket;
|
||||
import net.i2p.client.streaming.I2PSocketManager;
|
||||
import net.i2p.client.streaming.I2PSocketManagerFactory;
|
||||
import net.i2p.client.streaming.I2PSocketOptions;
|
||||
import net.i2p.crypto.SigType;
|
||||
import net.i2p.data.Destination;
|
||||
import net.i2p.util.EventDispatcher;
|
||||
import net.i2p.util.I2PAppThread;
|
||||
@@ -291,6 +292,10 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
|
||||
socketManager.destroySocketManager();
|
||||
// We could be here a LONG time, holding the lock
|
||||
socketManager = buildSocketManager(tunnel, pkf);
|
||||
// FIXME may not be the right place for this
|
||||
I2PSession sub = addSubsession(tunnel);
|
||||
if (sub != null && _log.shouldLog(Log.WARN))
|
||||
_log.warn("Added subsession " + sub);
|
||||
} else {
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info(tunnel.getClientOptions().getProperty("inbound.nickname") + ": Not building a new socket manager since the old one is open [s=" + s + "]");
|
||||
@@ -303,10 +308,41 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info(tunnel.getClientOptions().getProperty("inbound.nickname") + ": Building a new socket manager since there is no other one");
|
||||
socketManager = buildSocketManager(tunnel, pkf);
|
||||
I2PSession sub = addSubsession(tunnel);
|
||||
if (sub != null && _log.shouldLog(Log.WARN))
|
||||
_log.warn("Added subsession " + sub);
|
||||
}
|
||||
return socketManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a subsession to a shared client if necessary.
|
||||
*
|
||||
* @since 0.9.20
|
||||
*/
|
||||
protected static synchronized I2PSession addSubsession(I2PTunnel tunnel) {
|
||||
I2PSession sess = socketManager.getSession();
|
||||
if (sess.getMyDestination().getSigType() == SigType.DSA_SHA1)
|
||||
return null;
|
||||
Properties props = new Properties();
|
||||
props.putAll(tunnel.getClientOptions());
|
||||
String name = props.getProperty("inbound.nickname");
|
||||
if (name != null)
|
||||
props.setProperty("inbound.nickname", name + " (DSA)");
|
||||
name = props.getProperty("outbound.nickname");
|
||||
if (name != null)
|
||||
props.setProperty("outbound.nickname", name + " (DSA)");
|
||||
// TODO set sig type in props?
|
||||
try {
|
||||
return socketManager.addSubsession(null, props);
|
||||
} catch (I2PSessionException ise) {
|
||||
Log log = tunnel.getContext().logManager().getLog(I2PTunnelClientBase.class);
|
||||
if (log.shouldLog(Log.WARN))
|
||||
log.warn("Failed to add subssession", ise);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Kill the shared client, so that on restart in android
|
||||
* we won't latch onto the old one
|
||||
|
@@ -429,7 +429,8 @@ class ConnectionManager {
|
||||
// try { _connectionLock.wait(remaining); } catch (InterruptedException ie) {}
|
||||
try { Thread.sleep(remaining/4); } catch (InterruptedException ie) {}
|
||||
} else {
|
||||
con = new Connection(_context, this, _schedulerChooser, _timer, _outboundQueue, _conPacketHandler, opts, false);
|
||||
con = new Connection(_context, this, _schedulerChooser, _timer,
|
||||
_outboundQueue, _conPacketHandler, opts, false);
|
||||
con.setRemotePeer(peer);
|
||||
assignReceiveStreamId(con);
|
||||
break; // stop looping as a psuedo-wait
|
||||
|
@@ -11,7 +11,7 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
@@ -40,7 +40,7 @@ public class I2PSocketManagerFull implements I2PSocketManager {
|
||||
private final I2PAppContext _context;
|
||||
private final Log _log;
|
||||
private final I2PSession _session;
|
||||
private final List<I2PSession> _subsessions;
|
||||
private final ConcurrentHashMap<I2PSession, ConnectionManager> _subsessions;
|
||||
private final I2PServerSocketFull _serverSocket;
|
||||
private StandardServerSocket _realServerSocket;
|
||||
private final ConnectionOptions _defaultOptions;
|
||||
@@ -84,7 +84,7 @@ public class I2PSocketManagerFull implements I2PSocketManager {
|
||||
public I2PSocketManagerFull(I2PAppContext context, I2PSession session, Properties opts, String name) {
|
||||
_context = context;
|
||||
_session = session;
|
||||
_subsessions = new CopyOnWriteArrayList<I2PSession>();
|
||||
_subsessions = new ConcurrentHashMap<I2PSession, ConnectionManager>(4);
|
||||
_log = _context.logManager().getLog(I2PSocketManagerFull.class);
|
||||
|
||||
_name = name + " " + (__managerId.incrementAndGet());
|
||||
@@ -125,7 +125,6 @@ public class I2PSocketManagerFull implements I2PSocketManager {
|
||||
return _session;
|
||||
}
|
||||
|
||||
//////////// gahhh we want a socket manager, not a session
|
||||
/**
|
||||
* @return a new subsession, non-null
|
||||
* @param privateKeyStream null for transient, if non-null must have same encryption keys as primary session
|
||||
@@ -135,7 +134,17 @@ public class I2PSocketManagerFull implements I2PSocketManager {
|
||||
*/
|
||||
public I2PSession addSubsession(InputStream privateKeyStream, Properties opts) throws I2PSessionException {
|
||||
I2PSession rv = _session.addSubsession(privateKeyStream, opts);
|
||||
_subsessions.add(rv);
|
||||
ConnectionOptions defaultOptions = new ConnectionOptions(opts);
|
||||
ConnectionManager connectionManager = new ConnectionManager(_context, rv, defaultOptions);
|
||||
ConnectionManager old = _subsessions.putIfAbsent(rv, connectionManager);
|
||||
if (old != null) {
|
||||
// shouldn't happen
|
||||
_session.removeSubsession(rv);
|
||||
connectionManager.shutdown();
|
||||
throw new I2PSessionException("dup");
|
||||
}
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Added subsession " + rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -146,8 +155,15 @@ public class I2PSocketManagerFull implements I2PSocketManager {
|
||||
*/
|
||||
public void removeSubsession(I2PSession session) {
|
||||
_session.removeSubsession(session);
|
||||
_subsessions.remove(session);
|
||||
// ...
|
||||
ConnectionManager cm = _subsessions.remove(session);
|
||||
if (cm != null) {
|
||||
cm.shutdown();
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Removeed subsession " + session);
|
||||
} else {
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Subsession not found to remove " + session);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -335,6 +351,7 @@ public class I2PSocketManagerFull implements I2PSocketManager {
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("Connecting to " + peer.calculateHash().toBase64().substring(0,6)
|
||||
+ " with options: " + opts);
|
||||
// fixme pick the subsession here
|
||||
// the following blocks unless connect delay > 0
|
||||
Connection con = _connectionManager.connect(peer, opts);
|
||||
if (con == null)
|
||||
@@ -419,6 +436,12 @@ public class I2PSocketManagerFull implements I2PSocketManager {
|
||||
}
|
||||
_connectionManager.setAllowIncomingConnections(false);
|
||||
_connectionManager.shutdown();
|
||||
if (!_subsessions.isEmpty()) {
|
||||
for (I2PSession sess : _subsessions.keySet()) {
|
||||
removeSubsession(sess);
|
||||
}
|
||||
}
|
||||
|
||||
// should we destroy the _session too?
|
||||
// yes, since the old lib did (and SAM wants it to, and i dont know why not)
|
||||
if ( (_session != null) && (!_session.isClosed()) ) {
|
||||
|
Reference in New Issue
Block a user