forked from I2P_Developers/i2p.i2p
propagate from branch 'i2p.i2p.zzz.test' (head ea09c1bd1791674541854e77592153db6678aabb)
to branch 'i2p.i2p' (head 7ea5131c7a02f28ac2d3e23a8bf22558effb30ee)
This commit is contained in:
@ -17,17 +17,20 @@ import net.i2p.util.Log;
|
||||
public class Timestamper implements Runnable {
|
||||
private I2PAppContext _context;
|
||||
private Log _log;
|
||||
private List _servers;
|
||||
private List _listeners;
|
||||
private List<String> _servers;
|
||||
private List<String> _priorityServers;
|
||||
private List<UpdateListener> _listeners;
|
||||
private int _queryFrequency;
|
||||
private int _concurringServers;
|
||||
private volatile boolean _disabled;
|
||||
private boolean _daemon;
|
||||
private boolean _initialized;
|
||||
private boolean _wellSynced;
|
||||
|
||||
private static final int MIN_QUERY_FREQUENCY = 5*60*1000;
|
||||
private static final int DEFAULT_QUERY_FREQUENCY = 5*60*1000;
|
||||
private static final String DEFAULT_SERVER_LIST = "0.pool.ntp.org,1.pool.ntp.org,2.pool.ntp.org";
|
||||
private static final boolean DEFAULT_DISABLED = true;
|
||||
private static final String DEFAULT_DISABLED = "true";
|
||||
/** how many times do we have to query if we are changing the clock? */
|
||||
private static final int DEFAULT_CONCURRING_SERVERS = 3;
|
||||
|
||||
@ -35,6 +38,7 @@ public class Timestamper implements Runnable {
|
||||
public static final String PROP_SERVER_LIST = "time.sntpServerList";
|
||||
public static final String PROP_DISABLED = "time.disabled";
|
||||
public static final String PROP_CONCURRING_SERVERS = "time.concurringServers";
|
||||
public static final String PROP_IP_COUNTRY = "i2np.lastCountry";
|
||||
|
||||
/** if different SNTP servers differ by more than 10s, someone is b0rked */
|
||||
private static final int MAX_VARIANCE = 10*1000;
|
||||
@ -50,7 +54,8 @@ public class Timestamper implements Runnable {
|
||||
_context = ctx;
|
||||
_daemon = daemon;
|
||||
_initialized = false;
|
||||
_servers = new ArrayList(1);
|
||||
_wellSynced = false;
|
||||
_servers = new ArrayList(3);
|
||||
_listeners = new ArrayList(1);
|
||||
if (lsnr != null)
|
||||
_listeners.add(lsnr);
|
||||
@ -115,36 +120,47 @@ public class Timestamper implements Runnable {
|
||||
_log = _context.logManager().getLog(Timestamper.class);
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("Starting timestamper");
|
||||
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("Starting up timestamper");
|
||||
boolean lastFailed = false;
|
||||
try {
|
||||
while (true) {
|
||||
updateConfig();
|
||||
if (!_disabled) {
|
||||
String serverList[] = null;
|
||||
synchronized (_servers) {
|
||||
serverList = new String[_servers.size()];
|
||||
for (int i = 0; i < serverList.length; i++)
|
||||
serverList[i] = (String)_servers.get(i);
|
||||
// first the servers for our country, if we know what country we're in...
|
||||
if (_priorityServers != null) {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Querying servers " + _priorityServers);
|
||||
try {
|
||||
lastFailed = !queryTime(_priorityServers.toArray(new String[_priorityServers.size()]));
|
||||
} catch (IllegalArgumentException iae) {
|
||||
if ( (!lastFailed) && (_log.shouldLog(Log.WARN)) )
|
||||
_log.warn("Unable to reach country-specific NTP servers");
|
||||
lastFailed = true;
|
||||
}
|
||||
}
|
||||
// ... and then the global list, if that failed
|
||||
if (_priorityServers == null || lastFailed) {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Querying servers " + _servers);
|
||||
try {
|
||||
lastFailed = !queryTime(serverList);
|
||||
lastFailed = !queryTime(_servers.toArray(new String[_servers.size()]));
|
||||
} catch (IllegalArgumentException iae) {
|
||||
if ( (!lastFailed) && (_log.shouldLog(Log.ERROR)) )
|
||||
_log.error("Unable to reach any of the NTP servers - network disconnected?");
|
||||
lastFailed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_initialized = true;
|
||||
synchronized (this) { notifyAll(); }
|
||||
long sleepTime = _context.random().nextInt(_queryFrequency) + _queryFrequency;
|
||||
if (lastFailed)
|
||||
long sleepTime;
|
||||
if (lastFailed) {
|
||||
sleepTime = 30*1000;
|
||||
} else {
|
||||
sleepTime = _context.random().nextInt(_queryFrequency) + _queryFrequency;
|
||||
if (_wellSynced)
|
||||
sleepTime *= 3;
|
||||
}
|
||||
try { Thread.sleep(sleepTime); } catch (InterruptedException ie) {}
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
@ -160,6 +176,7 @@ public class Timestamper implements Runnable {
|
||||
long found[] = new long[_concurringServers];
|
||||
long now = -1;
|
||||
long expectedDelta = 0;
|
||||
_wellSynced = false;
|
||||
for (int i = 0; i < _concurringServers; i++) {
|
||||
try { Thread.sleep(10*1000); } catch (InterruptedException ie) {}
|
||||
now = NtpClient.currentTime(serverList);
|
||||
@ -169,6 +186,8 @@ public class Timestamper implements Runnable {
|
||||
if (Math.abs(delta) < MAX_VARIANCE) {
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("a single SNTP query was within the tolerance (" + delta + "ms)");
|
||||
// If less than a half second on the first try, we're in good shape
|
||||
_wellSynced = Math.abs(delta) < 500;
|
||||
break;
|
||||
} else {
|
||||
// outside the tolerance, lets iterate across the concurring queries
|
||||
@ -224,9 +243,19 @@ public class Timestamper implements Runnable {
|
||||
*/
|
||||
private void updateConfig() {
|
||||
String serverList = _context.getProperty(PROP_SERVER_LIST);
|
||||
if ( (serverList == null) || (serverList.trim().length() <= 0) )
|
||||
if ( (serverList == null) || (serverList.trim().length() <= 0) ) {
|
||||
serverList = DEFAULT_SERVER_LIST;
|
||||
synchronized (_servers) {
|
||||
String country = _context.getProperty(PROP_IP_COUNTRY);
|
||||
if (country != null) {
|
||||
_priorityServers = new ArrayList(3);
|
||||
for (int i = 0; i < 3; i++)
|
||||
_priorityServers.add(i + "." + country + ".pool.ntp.org");
|
||||
} else {
|
||||
_priorityServers = null;
|
||||
}
|
||||
} else {
|
||||
_priorityServers = null;
|
||||
}
|
||||
_servers.clear();
|
||||
StringTokenizer tok = new StringTokenizer(serverList, ", ");
|
||||
while (tok.hasMoreTokens()) {
|
||||
@ -235,45 +264,15 @@ public class Timestamper implements Runnable {
|
||||
if (val.length() > 0)
|
||||
_servers.add(val);
|
||||
}
|
||||
}
|
||||
|
||||
String freq = _context.getProperty(PROP_QUERY_FREQUENCY);
|
||||
if ( (freq == null) || (freq.trim().length() <= 0) )
|
||||
freq = DEFAULT_QUERY_FREQUENCY + "";
|
||||
try {
|
||||
int ms = Integer.parseInt(freq);
|
||||
if (ms > 60*1000) {
|
||||
_queryFrequency = ms;
|
||||
} else {
|
||||
if ( (_log != null) && (_log.shouldLog(Log.ERROR)) )
|
||||
_log.error("Query frequency once every " + ms + "ms is too fast!");
|
||||
_queryFrequency = DEFAULT_QUERY_FREQUENCY;
|
||||
}
|
||||
} catch (NumberFormatException nfe) {
|
||||
if ( (_log != null) && (_log.shouldLog(Log.WARN)) )
|
||||
_log.warn("Invalid query frequency [" + freq + "], falling back on " + DEFAULT_QUERY_FREQUENCY);
|
||||
_queryFrequency = DEFAULT_QUERY_FREQUENCY;
|
||||
}
|
||||
_queryFrequency = Math.max(MIN_QUERY_FREQUENCY,
|
||||
_context.getProperty(PROP_QUERY_FREQUENCY, DEFAULT_QUERY_FREQUENCY));
|
||||
|
||||
String disabled = _context.getProperty(PROP_DISABLED);
|
||||
if (disabled == null)
|
||||
disabled = DEFAULT_DISABLED + "";
|
||||
String disabled = _context.getProperty(PROP_DISABLED, DEFAULT_DISABLED);
|
||||
_disabled = Boolean.valueOf(disabled).booleanValue();
|
||||
|
||||
String concurring = _context.getProperty(PROP_CONCURRING_SERVERS);
|
||||
if (concurring == null) {
|
||||
_concurringServers = DEFAULT_CONCURRING_SERVERS;
|
||||
} else {
|
||||
try {
|
||||
int servers = Integer.parseInt(concurring);
|
||||
if ( (servers > 0) && (servers < 5) )
|
||||
_concurringServers = servers;
|
||||
else
|
||||
_concurringServers = DEFAULT_CONCURRING_SERVERS;
|
||||
} catch (NumberFormatException nfe) {
|
||||
_concurringServers = DEFAULT_CONCURRING_SERVERS;
|
||||
}
|
||||
}
|
||||
_concurringServers = Math.min(4, Math.max(1,
|
||||
_context.getProperty(PROP_CONCURRING_SERVERS, DEFAULT_CONCURRING_SERVERS)));
|
||||
}
|
||||
|
||||
public static void main(String args[]) {
|
||||
|
@ -58,6 +58,7 @@ class DummyNetworkDatabaseFacade extends NetworkDatabaseFacade {
|
||||
_routers.remove(dbEntry);
|
||||
}
|
||||
|
||||
public Set<Hash> getAllRouters() { return new HashSet(_routers.keySet()); }
|
||||
public Set findNearestRouters(Hash key, int maxNumRouters, Set peersToIgnore) { return new HashSet(_routers.values()); }
|
||||
|
||||
public void renderStatusHTML(Writer out) throws IOException {}
|
||||
|
@ -55,6 +55,7 @@ public abstract class NetworkDatabaseFacade implements Service {
|
||||
public abstract void unpublish(LeaseSet localLeaseSet);
|
||||
public abstract void fail(Hash dbEntry);
|
||||
|
||||
public abstract Set<Hash> getAllRouters();
|
||||
public int getKnownRouters() { return 0; }
|
||||
public int getKnownLeaseSets() { return 0; }
|
||||
public void renderRouterInfoHTML(Writer out, String s) throws IOException {}
|
||||
|
@ -311,7 +311,7 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
|
||||
}
|
||||
|
||||
/** get the hashes for all known routers */
|
||||
Set getAllRouters() {
|
||||
public Set<Hash> getAllRouters() {
|
||||
if (!_initialized) return new HashSet(0);
|
||||
Set keys = _ds.getKeys();
|
||||
Set rv = new HashSet(keys.size());
|
||||
|
@ -76,6 +76,7 @@ public class ProfileOrganizer {
|
||||
*/
|
||||
public static final String PROP_MINIMUM_FAST_PEERS = "profileOrganizer.minFastPeers";
|
||||
public static final int DEFAULT_MINIMUM_FAST_PEERS = 8;
|
||||
private static final int DEFAULT_MAXIMUM_FAST_PEERS = 16;
|
||||
/**
|
||||
* Defines the minimum number of 'high capacity' peers that the organizer should
|
||||
* select when using the mean - if less than this many are available, select the
|
||||
@ -1141,10 +1142,14 @@ public class ProfileOrganizer {
|
||||
* This parameter should help deal with a lack of diversity in the tunnels created when some
|
||||
* peers are particularly fast.
|
||||
*
|
||||
* Increase default by two for every local destination, up to a max.
|
||||
*
|
||||
* @return minimum number of peers to be placed in the 'fast' group
|
||||
*/
|
||||
protected int getMinimumFastPeers() {
|
||||
return _context.getProperty(PROP_MINIMUM_FAST_PEERS, DEFAULT_MINIMUM_FAST_PEERS);
|
||||
int def = Math.min(DEFAULT_MAXIMUM_FAST_PEERS,
|
||||
(2 *_context.clientManager().listClients().size()) + DEFAULT_MINIMUM_FAST_PEERS - 2);
|
||||
return _context.getProperty(PROP_MINIMUM_FAST_PEERS, def);
|
||||
}
|
||||
|
||||
|
||||
|
@ -375,15 +375,13 @@ public class CommSystemFacadeImpl extends CommSystemFacade {
|
||||
/**
|
||||
* Collect the IPs for all routers in the DB, and queue them for lookup,
|
||||
* then fire off the periodic lookup task for the first time.
|
||||
*
|
||||
* We could use getAllRouters() if it were public, and that would be faster, but
|
||||
* we only do this once.
|
||||
*/
|
||||
private class QueueAll implements SimpleTimer.TimedEvent {
|
||||
public void timeReached() {
|
||||
Set routers = _context.netDb().findNearestRouters(_context.routerHash(), _context.netDb().getKnownRouters(), null);
|
||||
for (Iterator iter = routers.iterator(); iter.hasNext(); ) {
|
||||
RouterInfo ri = (RouterInfo) iter.next();
|
||||
for (Iterator<Hash> iter = _context.netDb().getAllRouters().iterator(); iter.hasNext(); ) {
|
||||
RouterInfo ri = _context.netDb().lookupRouterInfoLocally(iter.next());
|
||||
if (ri == null)
|
||||
continue;
|
||||
String host = getIPString(ri);
|
||||
if (host == null)
|
||||
continue;
|
||||
@ -406,6 +404,8 @@ public class CommSystemFacadeImpl extends CommSystemFacade {
|
||||
/**
|
||||
* Uses the transport IP first because that lookup is fast,
|
||||
* then the SSU IP from the netDb.
|
||||
*
|
||||
* @return two-letter lower-case country code or null
|
||||
*/
|
||||
public String getCountry(Hash peer) {
|
||||
byte[] ip = TransportImpl.getIP(peer);
|
||||
|
@ -15,8 +15,8 @@ import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.data.DataHelper;
|
||||
import net.i2p.router.RouterContext;
|
||||
import net.i2p.util.ConcurrentHashSet;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
@ -37,14 +37,14 @@ import net.i2p.util.Log;
|
||||
*/
|
||||
public class GeoIP {
|
||||
private Log _log;
|
||||
private I2PAppContext _context;
|
||||
private RouterContext _context;
|
||||
private final Map<String, String> _codeToName;
|
||||
private final Map<Long, String> _IPToCountry;
|
||||
private final Set<Long> _pendingSearch;
|
||||
private final Set<Long> _notFound;
|
||||
private final AtomicBoolean _lock;
|
||||
|
||||
public GeoIP(I2PAppContext context) {
|
||||
public GeoIP(RouterContext context) {
|
||||
_context = context;
|
||||
_log = context.logManager().getLog(GeoIP.class);
|
||||
_codeToName = new ConcurrentHashMap();
|
||||
@ -59,6 +59,7 @@ public class GeoIP {
|
||||
static final String GEOIP_DIR_DEFAULT = "geoip";
|
||||
static final String GEOIP_FILE_DEFAULT = "geoip.txt";
|
||||
static final String COUNTRY_FILE_DEFAULT = "countries.txt";
|
||||
public static final String PROP_IP_COUNTRY = "i2np.lastCountry";
|
||||
|
||||
/**
|
||||
* Fire off a thread to lookup all pending IPs.
|
||||
@ -87,6 +88,7 @@ public class GeoIP {
|
||||
}
|
||||
LookupJob j = new LookupJob();
|
||||
j.run();
|
||||
updateOurCountry();
|
||||
}
|
||||
|
||||
private class LookupJob implements Runnable {
|
||||
@ -232,6 +234,19 @@ public class GeoIP {
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put our country code in the config, where others (such as Timestamper) can get it,
|
||||
* and it will be there next time at startup.
|
||||
*/
|
||||
private void updateOurCountry() {
|
||||
String oldCountry = _context.router().getConfigSetting(PROP_IP_COUNTRY);
|
||||
String country = _context.commSystem().getCountry(_context.routerHash());
|
||||
if (country != null && !country.equals(oldCountry)) {
|
||||
_context.router().setConfigSetting(PROP_IP_COUNTRY, country);
|
||||
_context.router().saveConfig();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add to the list needing lookup
|
||||
*/
|
||||
@ -296,6 +311,7 @@ public class GeoIP {
|
||||
return _codeToName.get(code);
|
||||
}
|
||||
|
||||
/*** doesn't work since switched to RouterContext above
|
||||
public static void main(String args[]) {
|
||||
GeoIP g = new GeoIP(new I2PAppContext());
|
||||
String tests[] = {"0.0.0.0", "0.0.0.1", "0.0.0.2", "0.0.0.255", "1.0.0.0",
|
||||
@ -309,4 +325,5 @@ public class GeoIP {
|
||||
System.out.println(tests[i] + " : " + g.get(tests[i]));
|
||||
|
||||
}
|
||||
***/
|
||||
}
|
||||
|
@ -103,7 +103,8 @@ public class NTCPConnection implements FIFOBandwidthLimiter.CompleteListener {
|
||||
private long _nextInfoTime;
|
||||
|
||||
private static final int META_FREQUENCY = 10*60*1000;
|
||||
private static final int INFO_FREQUENCY = 6*60*60*1000;
|
||||
/** how often we send our routerinfo unsolicited */
|
||||
private static final int INFO_FREQUENCY = 90*60*1000;
|
||||
/**
|
||||
* Why this is 16K, and where it is documented, good question?
|
||||
* We claim we can do 32K datagrams so this is a problem.
|
||||
@ -200,7 +201,7 @@ public class NTCPConnection implements FIFOBandwidthLimiter.CompleteListener {
|
||||
_transport.inboundEstablished(this);
|
||||
_establishState = null;
|
||||
_nextMetaTime = System.currentTimeMillis() + _context.random().nextInt(META_FREQUENCY);
|
||||
_nextInfoTime = System.currentTimeMillis() + INFO_FREQUENCY + _context.random().nextInt(INFO_FREQUENCY);
|
||||
_nextInfoTime = System.currentTimeMillis() + (INFO_FREQUENCY / 2) + _context.random().nextInt(INFO_FREQUENCY);
|
||||
}
|
||||
public long getClockSkew() { return _clockSkew; }
|
||||
public long getUptime() {
|
||||
@ -370,7 +371,8 @@ public class NTCPConnection implements FIFOBandwidthLimiter.CompleteListener {
|
||||
_context.statManager().addRateData("ntcp.infoMessageEnqueued", 1, 0);
|
||||
send(infoMsg);
|
||||
|
||||
enqueueFloodfillMessage(target);
|
||||
// See comment below
|
||||
//enqueueFloodfillMessage(target);
|
||||
} else {
|
||||
if (_isInbound) {
|
||||
// ok, we shouldn't have enqueued it yet, as we havent received their info
|
||||
@ -380,12 +382,18 @@ public class NTCPConnection implements FIFOBandwidthLimiter.CompleteListener {
|
||||
}
|
||||
}
|
||||
|
||||
private static final int PEERS_TO_FLOOD = 3;
|
||||
//private static final int PEERS_TO_FLOOD = 3;
|
||||
|
||||
/**
|
||||
* to prevent people from losing track of the floodfill peers completely, lets periodically
|
||||
* send those we are connected to references to the floodfill peers that we know
|
||||
*
|
||||
* Do we really need this anymore??? Peers shouldn't lose track anymore, and if they do,
|
||||
* FloodOnlyLookupJob should recover.
|
||||
* The bandwidth isn't so much, but it is a lot of extra data at connection startup, which
|
||||
* hurts latency of new connections.
|
||||
*/
|
||||
/**********
|
||||
private void enqueueFloodfillMessage(RouterInfo target) {
|
||||
FloodfillNetworkDatabaseFacade fac = (FloodfillNetworkDatabaseFacade)_context.netDb();
|
||||
List peers = fac.getFloodfillPeers();
|
||||
@ -414,6 +422,7 @@ public class NTCPConnection implements FIFOBandwidthLimiter.CompleteListener {
|
||||
send(infoMsg);
|
||||
}
|
||||
}
|
||||
***********/
|
||||
|
||||
/**
|
||||
* @param clockSkew alice's clock minus bob's clock in seconds (may be negative, obviously, but |val| should
|
||||
@ -439,7 +448,7 @@ public class NTCPConnection implements FIFOBandwidthLimiter.CompleteListener {
|
||||
msgs = (_outbound.size() > 0);
|
||||
}
|
||||
_nextMetaTime = System.currentTimeMillis() + _context.random().nextInt(META_FREQUENCY);
|
||||
_nextInfoTime = System.currentTimeMillis() + INFO_FREQUENCY + _context.random().nextInt(INFO_FREQUENCY);
|
||||
_nextInfoTime = System.currentTimeMillis() + (INFO_FREQUENCY / 2) + _context.random().nextInt(INFO_FREQUENCY);
|
||||
if (msgs)
|
||||
_transport.getWriter().wantsWrite(this, "outbound established");
|
||||
}
|
||||
@ -465,11 +474,12 @@ public class NTCPConnection implements FIFOBandwidthLimiter.CompleteListener {
|
||||
*
|
||||
*/
|
||||
synchronized void prepareNextWrite() {
|
||||
if (FAST_LARGE)
|
||||
//if (FAST_LARGE)
|
||||
prepareNextWriteFast();
|
||||
else
|
||||
prepareNextWriteSmall();
|
||||
//else
|
||||
// prepareNextWriteSmall();
|
||||
}
|
||||
/********** nobody's tried this one in years
|
||||
private void prepareNextWriteSmall() {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("prepare next write w/ isInbound? " + _isInbound + " established? " + _established);
|
||||
@ -563,9 +573,10 @@ public class NTCPConnection implements FIFOBandwidthLimiter.CompleteListener {
|
||||
// the floodfill netDb servers, but they may...)
|
||||
if (_nextInfoTime <= System.currentTimeMillis()) {
|
||||
enqueueInfoMessage();
|
||||
_nextInfoTime = System.currentTimeMillis() + INFO_FREQUENCY + _context.random().nextInt(INFO_FREQUENCY);
|
||||
_nextInfoTime = System.currentTimeMillis() + (INFO_FREQUENCY / 2) + _context.random().nextInt(INFO_FREQUENCY);
|
||||
}
|
||||
}
|
||||
**********/
|
||||
|
||||
/**
|
||||
* prepare the next i2np message for transmission. this should be run from
|
||||
@ -647,7 +658,7 @@ public class NTCPConnection implements FIFOBandwidthLimiter.CompleteListener {
|
||||
if (_nextInfoTime <= System.currentTimeMillis()) {
|
||||
// perhaps this should check to see if we are bw throttled, etc?
|
||||
enqueueInfoMessage();
|
||||
_nextInfoTime = System.currentTimeMillis() + INFO_FREQUENCY + _context.random().nextInt(INFO_FREQUENCY);
|
||||
_nextInfoTime = System.currentTimeMillis() + (INFO_FREQUENCY / 2) + _context.random().nextInt(INFO_FREQUENCY);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -474,6 +474,8 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
_context.statManager().addRateData("udp.addressUpdated", 1, 0);
|
||||
if (!fixedPort)
|
||||
_context.router().setConfigSetting(PROP_EXTERNAL_PORT, ourPort+"");
|
||||
// queue a country code lookup of the new IP
|
||||
_context.commSystem().queueLookup(ourIP);
|
||||
// store these for laptop-mode (change ident on restart... or every time... when IP changes)
|
||||
_context.router().setConfigSetting(PROP_IP, _externalListenHost.getHostAddress());
|
||||
_context.router().setConfigSetting(PROP_IP_CHANGE, "" + _context.clock().now());
|
||||
|
Reference in New Issue
Block a user