forked from I2P_Developers/i2p.i2p
I2CP: Periodically send a SetDate message to external clients
so they stay in sync
This commit is contained in:
@@ -19,6 +19,7 @@ import java.util.Set;
|
|||||||
import java.util.concurrent.LinkedBlockingQueue;
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import net.i2p.CoreVersion;
|
||||||
import net.i2p.client.I2PSessionException;
|
import net.i2p.client.I2PSessionException;
|
||||||
import net.i2p.crypto.SessionKeyManager;
|
import net.i2p.crypto.SessionKeyManager;
|
||||||
import net.i2p.data.Destination;
|
import net.i2p.data.Destination;
|
||||||
@@ -26,11 +27,13 @@ import net.i2p.data.Hash;
|
|||||||
import net.i2p.data.LeaseSet;
|
import net.i2p.data.LeaseSet;
|
||||||
import net.i2p.data.Payload;
|
import net.i2p.data.Payload;
|
||||||
import net.i2p.data.i2cp.I2CPMessage;
|
import net.i2p.data.i2cp.I2CPMessage;
|
||||||
|
import net.i2p.data.i2cp.I2CPMessageException;
|
||||||
import net.i2p.data.i2cp.MessageId;
|
import net.i2p.data.i2cp.MessageId;
|
||||||
import net.i2p.data.i2cp.MessageStatusMessage;
|
import net.i2p.data.i2cp.MessageStatusMessage;
|
||||||
import net.i2p.data.i2cp.SessionConfig;
|
import net.i2p.data.i2cp.SessionConfig;
|
||||||
import net.i2p.data.i2cp.SessionId;
|
import net.i2p.data.i2cp.SessionId;
|
||||||
import net.i2p.data.i2cp.SessionStatusMessage;
|
import net.i2p.data.i2cp.SessionStatusMessage;
|
||||||
|
import net.i2p.data.i2cp.SetDateMessage;
|
||||||
import net.i2p.internal.I2CPMessageQueue;
|
import net.i2p.internal.I2CPMessageQueue;
|
||||||
import net.i2p.router.ClientManagerFacade;
|
import net.i2p.router.ClientManagerFacade;
|
||||||
import net.i2p.router.ClientMessage;
|
import net.i2p.router.ClientMessage;
|
||||||
@@ -39,6 +42,7 @@ import net.i2p.router.JobImpl;
|
|||||||
import net.i2p.router.RouterContext;
|
import net.i2p.router.RouterContext;
|
||||||
import net.i2p.util.I2PThread;
|
import net.i2p.util.I2PThread;
|
||||||
import net.i2p.util.Log;
|
import net.i2p.util.Log;
|
||||||
|
import net.i2p.util.SimpleTimer2;
|
||||||
import net.i2p.util.SystemVersion;
|
import net.i2p.util.SystemVersion;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -61,6 +65,7 @@ class ClientManager {
|
|||||||
protected final RouterContext _ctx;
|
protected final RouterContext _ctx;
|
||||||
protected final int _port;
|
protected final int _port;
|
||||||
protected volatile boolean _isStarted;
|
protected volatile boolean _isStarted;
|
||||||
|
private final SimpleTimer2.TimedEvent _clientTimestamper;
|
||||||
|
|
||||||
/** Disable external interface, allow internal clients only @since 0.8.3 */
|
/** Disable external interface, allow internal clients only @since 0.8.3 */
|
||||||
private static final String PROP_DISABLE_EXTERNAL = "i2cp.disableInterface";
|
private static final String PROP_DISABLE_EXTERNAL = "i2cp.disableInterface";
|
||||||
@@ -96,6 +101,7 @@ class ClientManager {
|
|||||||
_pendingRunners = new HashSet<ClientConnectionRunner>();
|
_pendingRunners = new HashSet<ClientConnectionRunner>();
|
||||||
_runnerSessionIds = new HashSet<SessionId>();
|
_runnerSessionIds = new HashSet<SessionId>();
|
||||||
_port = port;
|
_port = port;
|
||||||
|
_clientTimestamper = new ClientTimestamper();
|
||||||
// following are for RequestLeaseSetJob
|
// following are for RequestLeaseSetJob
|
||||||
_ctx.statManager().createRateStat("client.requestLeaseSetSuccess", "How frequently the router requests successfully a new leaseSet?", "ClientMessages", new long[] { 60*60*1000 });
|
_ctx.statManager().createRateStat("client.requestLeaseSetSuccess", "How frequently the router requests successfully a new leaseSet?", "ClientMessages", new long[] { 60*60*1000 });
|
||||||
_ctx.statManager().createRateStat("client.requestLeaseSetTimeout", "How frequently the router requests a new leaseSet but gets no reply?", "ClientMessages", new long[] { 60*60*1000 });
|
_ctx.statManager().createRateStat("client.requestLeaseSetTimeout", "How frequently the router requests a new leaseSet but gets no reply?", "ClientMessages", new long[] { 60*60*1000 });
|
||||||
@@ -107,7 +113,10 @@ class ClientManager {
|
|||||||
startListeners();
|
startListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Todo: Start a 3rd listener for IPV6? */
|
/**
|
||||||
|
* Call from synchronized method
|
||||||
|
* Todo: Start a 3rd listener for IPV6?
|
||||||
|
*/
|
||||||
protected void startListeners() {
|
protected void startListeners() {
|
||||||
ClientListenerRunner listener;
|
ClientListenerRunner listener;
|
||||||
if (SystemVersion.isAndroid()) {
|
if (SystemVersion.isAndroid()) {
|
||||||
@@ -125,6 +134,7 @@ class ClientManager {
|
|||||||
Thread t = new I2PThread(listener, "ClientListener:" + _port, true);
|
Thread t = new I2PThread(listener, "ClientListener:" + _port, true);
|
||||||
t.start();
|
t.start();
|
||||||
_listeners.add(listener);
|
_listeners.add(listener);
|
||||||
|
_clientTimestamper.schedule(ClientTimestamper.LOOP_TIME);
|
||||||
}
|
}
|
||||||
_isStarted = true;
|
_isStarted = true;
|
||||||
}
|
}
|
||||||
@@ -162,6 +172,7 @@ class ClientManager {
|
|||||||
runner.disconnectClient(msg, Log.WARN);
|
runner.disconnectClient(msg, Log.WARN);
|
||||||
}
|
}
|
||||||
_runnersByHash.clear();
|
_runnersByHash.clear();
|
||||||
|
_clientTimestamper.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -600,4 +611,41 @@ class ClientManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tell external clients the time periodically
|
||||||
|
*
|
||||||
|
* @since 0.9.20
|
||||||
|
*/
|
||||||
|
private class ClientTimestamper extends SimpleTimer2.TimedEvent {
|
||||||
|
|
||||||
|
public static final long LOOP_TIME = 10*60*1000;
|
||||||
|
|
||||||
|
/** must call schedule() later */
|
||||||
|
public ClientTimestamper() {
|
||||||
|
super(_ctx.simpleTimer2());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void timeReached() {
|
||||||
|
if (!_isStarted)
|
||||||
|
return;
|
||||||
|
for (ClientConnectionRunner runner : _runners.values()) {
|
||||||
|
if (runner instanceof QueuedClientConnectionRunner)
|
||||||
|
continue;
|
||||||
|
if (runner.isDead())
|
||||||
|
continue;
|
||||||
|
if (runner.getConfig() == null)
|
||||||
|
continue; // simple session or no session yet
|
||||||
|
if (runner.getLeaseSet() == null)
|
||||||
|
continue; // don't confuse client while waiting for CreateLeaseSet msg
|
||||||
|
try {
|
||||||
|
// only send version if the client can handle it (0.8.7 or greater)
|
||||||
|
runner.doSend(new SetDateMessage(runner.getClientVersion() != null ?
|
||||||
|
CoreVersion.VERSION : null));
|
||||||
|
} catch (I2CPMessageException ime) {}
|
||||||
|
}
|
||||||
|
if (_isStarted)
|
||||||
|
schedule(LOOP_TIME);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user