diff --git a/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java b/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java index 6cef36f67b1cfd93109396b8525cca36eb736026..0433ffcbb28e3259fdbc679589f2f64d4f822d0a 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java +++ b/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java @@ -1,5 +1,6 @@ package org.klomp.snark; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.util.ArrayList; @@ -393,6 +394,46 @@ public class I2PSnarkUtil { } } + /** + * Fetch to memory + * @param retries if < 0, set timeout to a few seconds + * @param initialSize buffer size + * @param maxSize fails if greater + * @return null on error + * @since 0.9.4 + */ + public byte[] get(String url, boolean rewrite, int retries, int initialSize, int maxSize) { + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Fetching [" + url + "] to memory"); + String fetchURL = url; + if (rewrite) + fetchURL = rewriteAnnounce(url); + int timeout; + if (retries < 0) { + if (!connected()) + return null; + timeout = EEPGET_CONNECT_TIMEOUT_SHORT; + retries = 0; + } else { + timeout = EEPGET_CONNECT_TIMEOUT; + if (!connected()) { + if (!connect()) + return null; + } + } + ByteArrayOutputStream out = new ByteArrayOutputStream(initialSize); + EepGet get = new I2PSocketEepGet(_context, _manager, retries, -1, maxSize, null, out, fetchURL); + if (get.fetch(timeout)) { + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Fetch successful [" + url + "]: size=" + out.size()); + return out.toByteArray(); + } else { + if (_log.shouldLog(Log.WARN)) + _log.warn("Fetch failed [" + url + "]"); + return null; + } + } + public I2PServerSocket getServerSocket() { I2PSocketManager mgr = _manager; if (mgr != null) @@ -523,6 +564,15 @@ public class I2PSnarkUtil { return Collections.EMPTY_LIST; return _openTrackers; } + + /** + * List of open trackers to use as backups even if disabled + * @return non-null + * @since 0.9.4 + */ + public List<String> getBackupTrackers() { + return _openTrackers; + } public void setUseOpenTrackers(boolean yes) { _shouldUseOT = yes; diff --git a/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java b/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java index dccfddbcd3513201e5c9fb6df89ede8b43c0c40b..6a821f2ba7a1c511739ec87a2ca5a65ee851049b 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java +++ b/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java @@ -20,6 +20,7 @@ package org.klomp.snark; +import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; @@ -43,6 +44,7 @@ import net.i2p.util.I2PAppThread; import net.i2p.util.Log; import net.i2p.util.SimpleTimer2; +import org.klomp.snark.bencode.InvalidBEncodingException; import org.klomp.snark.dht.DHT; /** @@ -70,6 +72,8 @@ public class TrackerClient implements Runnable { private static final String COMPLETED_EVENT = "completed"; private static final String STOPPED_EVENT = "stopped"; private static final String NOT_REGISTERED = "torrent not registered"; //bytemonsoon + /** this is our equivalent to router.utorrent.com for bootstrap */ + private static final String DEFAULT_BACKUP_TRACKER = "http://tracker.welterde.i2p/a"; private final static int SLEEP = 5; // 5 minutes. private final static int DELAY_MIN = 2000; // 2 secs. @@ -78,7 +82,7 @@ public class TrackerClient implements Runnable { private final static int INITIAL_SLEEP = 90*1000; private final static int MAX_CONSEC_FAILS = 5; // slow down after this private final static int LONG_SLEEP = 30*60*1000; // sleep a while after lots of fails - private final static long MIN_TRACKER_ANNOUNCE_INTERVAL = 10*60*1000; + private final static long MIN_TRACKER_ANNOUNCE_INTERVAL = 15*60*1000; private final static long MIN_DHT_ANNOUNCE_INTERVAL = 10*60*1000; private final I2PSnarkUtil _util; @@ -106,6 +110,7 @@ public class TrackerClient implements Runnable { private volatile boolean _fastUnannounce; private long lastDHTAnnounce; private final List<Tracker> trackers; + private final List<Tracker> backupTrackers; /** * Call start() to start it. @@ -131,6 +136,7 @@ public class TrackerClient implements Runnable { this.infoHash = urlencode(snark.getInfoHash()); this.peerID = urlencode(snark.getID()); this.trackers = new ArrayList(2); + this.backupTrackers = new ArrayList(2); } public synchronized void start() { @@ -233,7 +239,7 @@ public class TrackerClient implements Runnable { if (!_initialized) { _initialized = true; // FIXME only when starting everybody at once, not for a single torrent - long delay = I2PAppContext.getGlobalContext().random().nextInt(30*1000); + long delay = _util.getContext().random().nextInt(30*1000); try { Thread.sleep(delay); } catch (InterruptedException ie) {} @@ -267,18 +273,20 @@ public class TrackerClient implements Runnable { if (primary != null) { if (isValidAnnounce(primary)) { trackers.add(new Tracker(primary, true)); - _log.debug("Announce: [" + primary + "] infoHash: " + infoHash); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Announce: [" + primary + "] infoHash: " + infoHash); } else { - _log.warn("Skipping invalid or non-i2p announce: " + primary); + if (_log.shouldLog(Log.WARN)) + _log.warn("Skipping invalid or non-i2p announce: " + primary); } } else { _log.warn("No primary announce"); primary = ""; } - List tlist = _util.getOpenTrackers(); - if (tlist != null && (meta == null || !meta.isPrivate())) { + if (meta == null || !meta.isPrivate()) { + List<String> tlist = _util.getOpenTrackers(); for (int i = 0; i < tlist.size(); i++) { - String url = (String)tlist.get(i); + String url = tlist.get(i); if (!isValidAnnounce(url)) { _log.error("Bad announce URL: [" + url + "]"); continue; @@ -301,9 +309,37 @@ public class TrackerClient implements Runnable { continue; // opentrackers are primary if we don't have primary trackers.add(new Tracker(url, primary.equals(""))); - _log.debug("Additional announce: [" + url + "] for infoHash: " + infoHash); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Additional announce: [" + url + "] for infoHash: " + infoHash); } } + + // backup trackers if DHT needs bootstrapping + if (trackers.isEmpty() && (meta == null || !meta.isPrivate())) { + List<String> tlist = _util.getBackupTrackers(); + for (int i = 0; i < tlist.size(); i++) { + String url = tlist.get(i); + if (!isValidAnnounce(url)) { + _log.error("Bad announce URL: [" + url + "]"); + continue; + } + int slash = url.indexOf('/', 7); + if (slash <= 7) { + _log.error("Bad announce URL: [" + url + "]"); + continue; + } + String dest = _util.lookup(url.substring(7, slash)); + if (dest == null) { + _log.error("Announce host unknown: [" + url.substring(7, slash) + "]"); + continue; + } + backupTrackers.add(new Tracker(url, false)); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Backup announce: [" + url + "] for infoHash: " + infoHash); + } + if (backupTrackers.isEmpty()) + backupTrackers.add(new Tracker(DEFAULT_BACKUP_TRACKER, false)); + } this.completed = coordinator.getLeft() == 0; } @@ -315,7 +351,7 @@ public class TrackerClient implements Runnable { private void loop() { try { - Random r = I2PAppContext.getGlobalContext().random(); + // normally this will only go once, then call queueLoop() and return while(!stop) { if (!verifyConnected()) { @@ -325,9 +361,71 @@ public class TrackerClient implements Runnable { // Local DHT tracker announce DHT dht = _util.getDHT(); - if (dht != null) + if (dht != null && (meta == null || !meta.isPrivate())) dht.announce(snark.getInfoHash()); + int maxSeenPeers = 0; + if (!trackers.isEmpty()) + maxSeenPeers = getPeersFromTrackers(trackers); + int p = getPeersFromPEX(); + if (p > maxSeenPeers) + maxSeenPeers = p; + p = getPeersFromDHT(); + if (p > maxSeenPeers) + maxSeenPeers = p; + // backup if DHT needs bootstrapping + if (trackers.isEmpty() && !backupTrackers.isEmpty() && dht != null && dht.size() < 16) { + p = getPeersFromTrackers(backupTrackers); + if (p > maxSeenPeers) + maxSeenPeers = p; + } + + // we could try and total the unique peers but that's too hard for now + snark.setTrackerSeenPeers(maxSeenPeers); + + if (stop) + return; + + try { + // Sleep some minutes... + // Sleep the minimum interval for all the trackers, but 60s minimum + int delay; + Random r = _util.getContext().random(); + int random = r.nextInt(120*1000); + if (completed && runStarted) + delay = 3*SLEEP*60*1000 + random; + else if (snark.getTrackerProblems() != null && ++consecutiveFails < MAX_CONSEC_FAILS) + delay = INITIAL_SLEEP; + else if ((!runStarted) && _runCount < MAX_CONSEC_FAILS) + delay = INITIAL_SLEEP; + else + // sleep a while, when we wake up we will contact only the trackers whose intervals have passed + delay = SLEEP*60*1000 + random; + + if (delay > 20*1000) { + // put ourselves on SimpleTimer2 + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Requeueing in " + DataHelper.formatDuration(delay) + ": " + Thread.currentThread().getName()); + queueLoop(delay); + return; + } else if (delay > 0) { + Thread.sleep(delay); + } + } catch(InterruptedException interrupt) {} + } // *** end of while loop + } // try + catch (Throwable t) + { + _log.error("TrackerClient: " + t, t); + if (t instanceof OutOfMemoryError) + throw (OutOfMemoryError)t; + } + } + + /** + * @return max peers seen + */ + private int getPeersFromTrackers(List<Tracker> trckrs) { long uploaded = coordinator.getUploaded(); long downloaded = coordinator.getDownloaded(); long left = coordinator.getLeft(); // -1 in magnet mode @@ -341,10 +439,10 @@ public class TrackerClient implements Runnable { } else event = NO_EVENT; - + // *** loop once for each tracker int maxSeenPeers = 0; - for (Tracker tr : trackers) { + for (Tracker tr : trckrs) { if ((!stop) && (!tr.stop) && (completed || coordinator.needOutboundPeers() || !tr.started) && (event.equals(COMPLETED_EVENT) || System.currentTimeMillis() > tr.lastRequestTime + tr.interval)) @@ -372,7 +470,7 @@ public class TrackerClient implements Runnable { snark.setTrackerSeenPeers(tr.seenPeers); // pass everybody over to our tracker - dht = _util.getDHT(); + DHT dht = _util.getDHT(); if (dht != null) { for (Peer peer : peers) { dht.announce(snark.getInfoHash(), peer.getPeerID().getDestHash()); @@ -383,6 +481,7 @@ public class TrackerClient implements Runnable { // we only want to talk to new people if we need things // from them (duh) List<Peer> ordered = new ArrayList(peers); + Random r = _util.getContext().random(); Collections.shuffle(ordered, r); Iterator<Peer> it = ordered.iterator(); while ((!stop) && it.hasNext() && coordinator.needOutboundPeers()) { @@ -409,13 +508,13 @@ public class TrackerClient implements Runnable { snark.setTrackerProblems(tr.trackerProblems); if (tr.trackerProblems.toLowerCase(Locale.US).startsWith(NOT_REGISTERED)) { // Give a guy some time to register it if using opentrackers too - if (trackers.size() == 1) { - stop = true; - snark.stopTorrent(); - } else { // hopefully each on the opentrackers list is really open + //if (trckrs.size() == 1) { + // stop = true; + // snark.stopTorrent(); + //} else { // hopefully each on the opentrackers list is really open if (tr.registerFails++ > MAX_REGISTER_FAILS) tr.stop = true; - } + // } if (++tr.consecutiveFails == MAX_CONSEC_FAILS) { tr.seenPeers = 0; @@ -432,7 +531,15 @@ public class TrackerClient implements Runnable { maxSeenPeers = tr.seenPeers; } // *** end of trackers loop here + return maxSeenPeers; + } + + /** + * @return max peers seen + */ + private int getPeersFromPEX() { // Get peers from PEX + int rv = 0; if (coordinator.needOutboundPeers() && (meta == null || !meta.isPrivate()) && !stop) { Set<PeerID> pids = coordinator.getPEXPeers(); if (!pids.isEmpty()) { @@ -442,6 +549,7 @@ public class TrackerClient implements Runnable { for (PeerID pID : pids) { peers.add(new Peer(pID, snark.getID(), snark.getInfoHash(), snark.getMetaInfo())); } + Random r = _util.getContext().random(); Collections.shuffle(peers, r); Iterator<Peer> it = peers.iterator(); while ((!stop) && it.hasNext() && coordinator.needOutboundPeers()) { @@ -451,19 +559,27 @@ public class TrackerClient implements Runnable { try { Thread.sleep(delay); } catch (InterruptedException ie) {} } } + rv = pids.size(); } } else { if (_log.shouldLog(Log.INFO)) _log.info("Not getting PEX peers"); } + return rv; + } + /** + * @return max peers seen + */ + private int getPeersFromDHT() { // Get peers from DHT // FIXME this needs to be in its own thread - dht = _util.getDHT(); + int rv = 0; + DHT dht = _util.getDHT(); if (dht != null && (meta == null || !meta.isPrivate()) && (!stop) && _util.getContext().clock().now() > lastDHTAnnounce + MIN_DHT_ANNOUNCE_INTERVAL) { int numwant; - if (event.equals(STOPPED_EVENT) || !coordinator.needOutboundPeers()) + if (!coordinator.needOutboundPeers()) numwant = 1; else numwant = _util.getMaxConnections(); @@ -471,6 +587,7 @@ public class TrackerClient implements Runnable { if (!hashes.isEmpty()) { runStarted = true; lastDHTAnnounce = _util.getContext().clock().now(); + rv = hashes.size(); } if (_log.shouldLog(Log.INFO)) _log.info("Got " + hashes + " from DHT"); @@ -487,9 +604,12 @@ public class TrackerClient implements Runnable { if ((!stop) && !hashes.isEmpty()) { List<Peer> peers = new ArrayList(hashes.size()); for (Hash h : hashes) { - PeerID pID = new PeerID(h.getData(), _util); - peers.add(new Peer(pID, snark.getID(), snark.getInfoHash(), snark.getMetaInfo())); + try { + PeerID pID = new PeerID(h.getData(), _util); + peers.add(new Peer(pID, snark.getID(), snark.getInfoHash(), snark.getMetaInfo())); + } catch (InvalidBEncodingException ibe) {} } + Random r = _util.getContext().random(); Collections.shuffle(peers, r); Iterator<Peer> it = peers.iterator(); while ((!stop) && it.hasNext() && coordinator.needOutboundPeers()) { @@ -504,49 +624,10 @@ public class TrackerClient implements Runnable { if (_log.shouldLog(Log.INFO)) _log.info("Not getting DHT peers"); } - - - // we could try and total the unique peers but that's too hard for now - snark.setTrackerSeenPeers(maxSeenPeers); - - if (stop) - return; - - try { - // Sleep some minutes... - // Sleep the minimum interval for all the trackers, but 60s minimum - int delay; - int random = r.nextInt(120*1000); - if (completed && runStarted) - delay = 3*SLEEP*60*1000 + random; - else if (snark.getTrackerProblems() != null && ++consecutiveFails < MAX_CONSEC_FAILS) - delay = INITIAL_SLEEP; - else if ((!runStarted) && _runCount < MAX_CONSEC_FAILS) - delay = INITIAL_SLEEP; - else - // sleep a while, when we wake up we will contact only the trackers whose intervals have passed - delay = SLEEP*60*1000 + random; - - if (delay > 20*1000) { - // put ourselves on SimpleTimer2 - if (_log.shouldLog(Log.DEBUG)) - _log.debug("Requeueing in " + DataHelper.formatDuration(delay) + ": " + Thread.currentThread().getName()); - queueLoop(delay); - return; - } else if (delay > 0) { - Thread.sleep(delay); - } - } catch(InterruptedException interrupt) {} - } // *** end of while loop - } // try - catch (Throwable t) - { - _log.error("TrackerClient: " + t, t); - if (t instanceof OutOfMemoryError) - throw (OutOfMemoryError)t; - } + return rv; } + /** * Creates a thread for each tracker in parallel if tunnel is still open * @since 0.9.1 @@ -630,7 +711,8 @@ public class TrackerClient implements Runnable { if (! event.equals(NO_EVENT)) buf.append("&event=").append(event); buf.append("&numwant="); - if (left == 0 || event.equals(STOPPED_EVENT) || !coordinator.needOutboundPeers()) + boolean small = left == 0 || event.equals(STOPPED_EVENT) || !coordinator.needOutboundPeers(); + if (small) buf.append('0'); else buf.append(_util.getMaxConnections()); @@ -641,14 +723,12 @@ public class TrackerClient implements Runnable { tr.lastRequestTime = System.currentTimeMillis(); // Don't wait for a response to stopped when shutting down boolean fast = _fastUnannounce && event.equals(STOPPED_EVENT); - File fetched = _util.get(s, true, fast ? -1 : 0); + byte[] fetched = _util.get(s, true, fast ? -1 : 0, small ? 128 : 1024, small ? 1024 : 8*1024); if (fetched == null) { throw new IOException("Error fetching " + s); } - InputStream in = null; - try { - in = new FileInputStream(fetched); + InputStream in = new ByteArrayInputStream(fetched); TrackerInfo info = new TrackerInfo(in, snark.getID(), snark.getInfoHash(), snark.getMetaInfo(), _util); @@ -661,10 +741,6 @@ public class TrackerClient implements Runnable { tr.interval = Math.max(MIN_TRACKER_ANNOUNCE_INTERVAL, info.getInterval() * 1000l); return info; - } finally { - if (in != null) try { in.close(); } catch (IOException ioe) {} - fetched.delete(); - } } /** diff --git a/apps/i2psnark/java/src/org/klomp/snark/dht/KRPC.java b/apps/i2psnark/java/src/org/klomp/snark/dht/KRPC.java index 55521a7876f081fdaf00937c1ef801aa4643c969..b94c5f555fb5ff933ce5efca54c2a1e75be388f0 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/dht/KRPC.java +++ b/apps/i2psnark/java/src/org/klomp/snark/dht/KRPC.java @@ -143,6 +143,7 @@ public class KRPC implements I2PSessionMuxedListener, DHT { /** how long since generated do we delete - BEP 5 says 10 minutes */ private static final long MAX_TOKEN_AGE = 10*60*1000; private static final long MAX_INBOUND_TOKEN_AGE = MAX_TOKEN_AGE - 2*60*1000; + private static final int MAX_OUTBOUND_TOKENS = 5000; /** how long since sent do we wait for a reply */ private static final long MAX_MSGID_AGE = 2*60*1000; /** how long since sent do we wait for a reply */ @@ -1208,7 +1209,8 @@ public class KRPC implements I2PSessionMuxedListener, DHT { /** * Handle and respond to the query. - * We have no node info here, it came on response port, we have to get it from the token + * We have no node info here, it came on response port, we have to get it from the token. + * So we can't verify that it came from the same peer, as BEP 5 specifies. */ private void receiveAnnouncePeer(MsgID msgID, InfoHash ih, byte[] tok) throws InvalidBEncodingException { Token token = new Token(tok); @@ -1216,8 +1218,8 @@ public class KRPC implements I2PSessionMuxedListener, DHT { if (nInfo == null) { if (_log.shouldLog(Log.WARN)) _log.warn("Unknown token in announce_peer: " + token); - if (_log.shouldLog(Log.INFO)) - _log.info("Current known tokens: " + _outgoingTokens.keySet()); + //if (_log.shouldLog(Log.INFO)) + // _log.info("Current known tokens: " + _outgoingTokens.keySet()); return; } if (_log.shouldLog(Log.INFO)) @@ -1282,8 +1284,9 @@ public class KRPC implements I2PSessionMuxedListener, DHT { * @throws NPE, IllegalArgumentException, and others too */ private List<NodeInfo> receiveNodes(NodeInfo nInfo, byte[] ids) throws InvalidBEncodingException { - List<NodeInfo> rv = new ArrayList(ids.length / NodeInfo.LENGTH); - for (int off = 0; off < ids.length; off += NodeInfo.LENGTH) { + int max = Math.min(K, ids.length / NodeInfo.LENGTH); + List<NodeInfo> rv = new ArrayList(max); + for (int off = 0; off < ids.length && rv.size() < max; off += NodeInfo.LENGTH) { NodeInfo nInf = new NodeInfo(ids, off); if (_blacklist.contains(nInf.getNID())) { if (_log.shouldLog(Log.INFO)) @@ -1305,12 +1308,15 @@ public class KRPC implements I2PSessionMuxedListener, DHT { private List<Hash> receivePeers(NodeInfo nInfo, List<BEValue> peers) throws InvalidBEncodingException { if (_log.shouldLog(Log.INFO)) _log.info("Rcvd peers from: " + nInfo); - List<Hash> rv = new ArrayList(peers.size()); + int max = Math.min(MAX_WANT, peers.size()); + List<Hash> rv = new ArrayList(max); for (BEValue bev : peers) { byte[] b = bev.getBytes(); //Hash h = new Hash(b); Hash h = Hash.create(b); rv.add(h); + if (rv.size() >= max) + break; } if (_log.shouldLog(Log.INFO)) _log.info("Rcvd peers from: " + nInfo + ": " + DataHelper.toString(rv)); @@ -1535,20 +1541,28 @@ public class KRPC implements I2PSessionMuxedListener, DHT { _blacklist.size() + " in blacklist, " + _outgoingTokens.size() + " sent Tokens, " + _incomingTokens.size() + " rcvd Tokens"); + int cnt = 0; + long expire = now - MAX_TOKEN_AGE; for (Iterator<Token> iter = _outgoingTokens.keySet().iterator(); iter.hasNext(); ) { Token tok = iter.next(); - if (tok.lastSeen() < now - MAX_TOKEN_AGE) + // just delete at random if we have too many + // TODO reduce the expire time and iterate again? + if (tok.lastSeen() < expire || cnt >= MAX_OUTBOUND_TOKENS) iter.remove(); + else + cnt++; } + expire = now - MAX_INBOUND_TOKEN_AGE; for (Iterator<Token> iter = _incomingTokens.values().iterator(); iter.hasNext(); ) { Token tok = iter.next(); - if (tok.lastSeen() < now - MAX_INBOUND_TOKEN_AGE) + if (tok.lastSeen() < expire) iter.remove(); } + expire = now - BLACKLIST_CLEAN_TIME; for (Iterator<NID> iter = _blacklist.iterator(); iter.hasNext(); ) { NID nid = iter.next(); // lastSeen() is actually when-added - if (now > nid.lastSeen() + BLACKLIST_CLEAN_TIME) + if (nid.lastSeen() < expire) iter.remove(); } // TODO sent queries? diff --git a/apps/routerconsole/java/src/net/i2p/router/update/UnsignedUpdateRunner.java b/apps/routerconsole/java/src/net/i2p/router/update/UnsignedUpdateRunner.java index eb797b9a1bf1e9a3779efe0d308eeb21e02b5e90..e010714c12ff6d80394f5635a4a9d51f3e770811 100644 --- a/apps/routerconsole/java/src/net/i2p/router/update/UnsignedUpdateRunner.java +++ b/apps/routerconsole/java/src/net/i2p/router/update/UnsignedUpdateRunner.java @@ -53,6 +53,8 @@ class UnsignedUpdateRunner extends UpdateRunner { } catch (Throwable t) { _log.error("Error updating", t); } + if (!this.done) + _mgr.notifyTaskFailed(this, "", null); } /** eepget listener callback Overrides */ diff --git a/apps/routerconsole/java/src/net/i2p/router/web/CSSHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/CSSHelper.java index 785af69a3e3f980b395ddfe364d6312120eee32a..3d92f6d2ab390e00b382b88963b3f06aea21294d 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/CSSHelper.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/CSSHelper.java @@ -3,6 +3,8 @@ package net.i2p.router.web; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import net.i2p.util.RandomSource; + /** * Copied and modded from I2PTunnel IndexBean (GPL) * @author zzz @@ -11,8 +13,6 @@ public class CSSHelper extends HelperBase { private static final Map<String, Boolean> _UACache = new ConcurrentHashMap(); - public CSSHelper() {} - public static final String PROP_UNIVERSAL_THEMING = "routerconsole.universal.theme"; public static final String PROP_THEME_NAME = "routerconsole.theme"; public static final String DEFAULT_THEME = "light"; @@ -24,6 +24,16 @@ public class CSSHelper extends HelperBase { public static final String PROP_DISABLE_REFRESH = "routerconsole.summaryDisableRefresh"; private static final String PROP_XFRAME = "routerconsole.disableXFrame"; + private static final String _consoleNonce = Long.toString(RandomSource.getInstance().nextLong()); + + /** + * formerly stored in System.getProperty("router.consoleNonce") + * @since 0.9.4 + */ + public static String getNonce() { + return _consoleNonce; + } + public String getTheme(String userAgent) { String url = BASE_THEME_PATH; if (userAgent != null && userAgent.contains("MSIE")) { diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigRestartBean.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigRestartBean.java index 204bda9f829a961dd9f30e40ec205689e9d197bb..836d07ea368d428d868c895d93900e041615eea9 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigRestartBean.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigRestartBean.java @@ -3,6 +3,7 @@ package net.i2p.router.web; import net.i2p.data.DataHelper; import net.i2p.router.Router; import net.i2p.router.RouterContext; +import net.i2p.util.RandomSource; /** * simple helper to control restarts/shutdowns in the left hand nav @@ -12,20 +13,18 @@ public class ConfigRestartBean { /** all these are tagged below so no need to _x them here. * order is: form value, form class, display text. */ - static final String[] SET1 = {"shutdownImmediate", "stop", "Shutdown immediately", "cancelShutdown", "cancel", "Cancel shutdown"}; - static final String[] SET2 = {"restartImmediate", "reload", "Restart immediately", "cancelShutdown", "cancel", "Cancel restart"}; - static final String[] SET3 = {"restart", "reload", "Restart", "shutdown", "stop", "Shutdown"}; - static final String[] SET4 = {"shutdown", "stop", "Shutdown"}; + private static final String[] SET1 = {"shutdownImmediate", "stop", "Shutdown immediately", "cancelShutdown", "cancel", "Cancel shutdown"}; + private static final String[] SET2 = {"restartImmediate", "reload", "Restart immediately", "cancelShutdown", "cancel", "Cancel restart"}; + private static final String[] SET3 = {"restart", "reload", "Restart", "shutdown", "stop", "Shutdown"}; + private static final String[] SET4 = {"shutdown", "stop", "Shutdown"}; + private static final String _systemNonce = Long.toString(RandomSource.getInstance().nextLong()); + + /** formerly System.getProperty("console.nonce") */ public static String getNonce() { - RouterContext ctx = ContextHelper.getContext(null); - String nonce = System.getProperty("console.nonce"); - if (nonce == null) { - nonce = ""+ctx.random().nextLong(); - System.setProperty("console.nonce", nonce); - } - return nonce; + return _systemNonce; } + public static String renderStatus(String urlBase, String action, String nonce) { RouterContext ctx = ContextHelper.getContext(null); String systemNonce = getNonce(); diff --git a/apps/routerconsole/java/src/net/i2p/router/web/FormHandler.java b/apps/routerconsole/java/src/net/i2p/router/web/FormHandler.java index ba5856632a851e85f49bb391cfb14ff79ff4eb37..ebd1adc07ec26f0300f7f842109509f6df829228 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/FormHandler.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/FormHandler.java @@ -194,8 +194,8 @@ public class FormHandler { return; } - String sharedNonce = System.getProperty("router.consoleNonce"); - if ( (sharedNonce != null) && (sharedNonce.equals(_nonce) ) ) { + String sharedNonce = CSSHelper.getNonce(); + if (sharedNonce.equals(_nonce)) { return; } diff --git a/apps/routerconsole/java/src/net/i2p/router/web/NewsHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/NewsHelper.java index 5e5fcecfe4e8b55e67351bdbd89041afcda7842d..162290e9472e3dfb63f73b32df3020a951ea09cd 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/NewsHelper.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/NewsHelper.java @@ -212,7 +212,7 @@ public class NewsHelper extends ContentHelper { ctx)); } buf.append("</i>"); - String consoleNonce = System.getProperty("router.consoleNonce"); + String consoleNonce = CSSHelper.getNonce(); if (lastUpdated > 0 && consoleNonce != null) { if (shouldShowNews(ctx)) { buf.append(" <a href=\"/?news=0&consoleNonce=").append(consoleNonce).append("\">") diff --git a/apps/routerconsole/java/src/net/i2p/router/web/SummaryBarRenderer.java b/apps/routerconsole/java/src/net/i2p/router/web/SummaryBarRenderer.java index 61bed45480e46c53949aaaf57ac326e9ee9b738b..496c41cab0839b981dec4b0f79ca8f58c7cf20d1 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/SummaryBarRenderer.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/SummaryBarRenderer.java @@ -606,7 +606,7 @@ public class SummaryBarRenderer { NewsHelper newshelper = _helper.getNewsHelper(); if (newshelper == null || newshelper.shouldShowNews()) return ""; StringBuilder buf = new StringBuilder(512); - String consoleNonce = System.getProperty("router.consoleNonce"); + String consoleNonce = CSSHelper.getNonce(); if (consoleNonce != null) { // Set up title and pre-headings stuff. buf.append("<h3><a href=\"/configupdate\">") diff --git a/apps/routerconsole/java/src/net/i2p/router/web/SummaryHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/SummaryHelper.java index 2bd763606f9cd33f70dc8b4b2494f7ba985281bc..3015f23e94c7e2f7730aed9d02063daa7ef484af 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/SummaryHelper.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/SummaryHelper.java @@ -809,7 +809,13 @@ public class SummaryHelper extends HelperBase { private String _requestURI; public void setRequestURI(String s) { _requestURI = s; } - public String getRequestURI() { return _requestURI; } + + /** + * @return non-null; "/home" if (strangely) not set by jsp + */ + public String getRequestURI() { + return _requestURI != null ? _requestURI : "/home"; + } public String getConfigTable() { String[] allSections = SummaryBarRenderer.ALL_SECTIONS; diff --git a/apps/routerconsole/jsp/configui.jsp b/apps/routerconsole/jsp/configui.jsp index f1555a8920d1b99430144430c2030555ca810054..b19c0103caa81f49233d6f312fb26a5f3da12019 100644 --- a/apps/routerconsole/jsp/configui.jsp +++ b/apps/routerconsole/jsp/configui.jsp @@ -31,15 +31,7 @@ input.default { <%@include file="formhandler.jsi" %> <div class="configure"><div class="topshimten"><h3><%=uihelper._("Router Console Theme")%></h3></div> <form action="" method="POST"> -<% - /** lang setting is done in css.jsi, not in ConfigUIHandler */ - String consoleNonce = System.getProperty("router.consoleNonce"); - if (consoleNonce == null) { - consoleNonce = Long.toString(new java.util.Random().nextLong()); - System.setProperty("router.consoleNonce", consoleNonce); - } -%> - <input type="hidden" name="consoleNonce" value="<%=consoleNonce%>" > + <input type="hidden" name="consoleNonce" value="<%=intl.getNonce()%>" > <input type="hidden" name="nonce" value="<%=pageNonce%>" > <input type="hidden" name="action" value="blah" > <% diff --git a/apps/routerconsole/jsp/console.jsp b/apps/routerconsole/jsp/console.jsp index b70c4170eab4835353d2e850d6024a1177851ca5..883c83c56e452be29bde7341b0b3e0f00104dd10 100644 --- a/apps/routerconsole/jsp/console.jsp +++ b/apps/routerconsole/jsp/console.jsp @@ -10,11 +10,7 @@ <%@include file="summaryajax.jsi" %> </head><body onload="initAjax()"> <% - String consoleNonce = System.getProperty("router.consoleNonce"); - if (consoleNonce == null) { - consoleNonce = Long.toString(new java.util.Random().nextLong()); - System.setProperty("router.consoleNonce", consoleNonce); - } + String consoleNonce = intl.getNonce(); %> <%@include file="summary.jsi" %> diff --git a/apps/routerconsole/jsp/css.jsi b/apps/routerconsole/jsp/css.jsi index 437bf015ea495121592992faafa2b31e1c01ef31..21dc7eecc25905aaa32ee4ffa33140540b602c1a 100644 --- a/apps/routerconsole/jsp/css.jsi +++ b/apps/routerconsole/jsp/css.jsi @@ -34,7 +34,7 @@ response.setHeader("X-Frame-Options", "SAMEORIGIN"); String conNonceParam = request.getParameter("consoleNonce"); - if (conNonceParam != null && conNonceParam.equals(System.getProperty("router.consoleNonce"))) { + if (intl.getNonce().equals(conNonceParam)) { intl.setLang(request.getParameter("lang")); intl.setNews(request.getParameter("news")); } diff --git a/apps/routerconsole/jsp/home.jsp b/apps/routerconsole/jsp/home.jsp index 0971ac868402d110e290ba90e222b4b754659174..4423bed83cc05fb44ee9f332f0fc34e8bbfb36c2 100644 --- a/apps/routerconsole/jsp/home.jsp +++ b/apps/routerconsole/jsp/home.jsp @@ -8,11 +8,7 @@ <%@include file="summaryajax.jsi" %> </head><body onload="initAjax()"> <% - String consoleNonce = System.getProperty("router.consoleNonce"); - if (consoleNonce == null) { - consoleNonce = Long.toString(new java.util.Random().nextLong()); - System.setProperty("router.consoleNonce", consoleNonce); - } + String consoleNonce = intl.getNonce(); %> <jsp:useBean class="net.i2p.router.web.NewsHelper" id="newshelper" scope="request" /> <jsp:setProperty name="newshelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" /> diff --git a/history.txt b/history.txt index 634e385b05e7324bc1d4e181ca79020dd69b8f9f..783e80d9252ed522b26bc818bfe8d66ba3f4d663 100644 --- a/history.txt +++ b/history.txt @@ -1,6 +1,20 @@ +2012-11-05 zzz + * Console: + - Fix NPE after restart (ticket #763) + - Move more nonces out of system properties + * i2psnark: + - More DHT limits + - Announce to backup trackers if DHT is empty + - Use PEX and DHT info in torrent peer count + - Don't use temp files for announces + * PeerManager: Don't reorganize as often if it takes too long (ticket #765) + * RequestLeaseSetJob: Only disconnect client after multiple dropped + lease set requests; reduce timeout, other cleanups + * Unsigned Update: Fix notification on failure + 2012-11-02 kytv -* German, Portuguese, and Swedish translation updates from Transifex -* Refreshed English po files to push to TX. + * German, Portuguese, and Swedish translation updates from Transifex + * Refreshed English po files to push to TX. 2012-11-02 zzz * configstats: Fix group sorting, translate groups diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index f6e6df3a5c0d10fbf1efc2f7069c342c2fe16f4e..4e28a2c8d2676ff98ee569a93ae883ef407d9461 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -18,7 +18,7 @@ public class RouterVersion { /** deprecated */ public final static String ID = "Monotone"; public final static String VERSION = CoreVersion.VERSION; - public final static long BUILD = 4; + public final static long BUILD = 5; /** for example "-test" */ public final static String EXTRA = ""; diff --git a/router/java/src/net/i2p/router/client/ClientConnectionRunner.java b/router/java/src/net/i2p/router/client/ClientConnectionRunner.java index cfe23fa9863cb2f74b81df72314d5e0f97f1fca3..36b3689062e4c3f6e95aa2c84caacf8896ece5a8 100644 --- a/router/java/src/net/i2p/router/client/ClientConnectionRunner.java +++ b/router/java/src/net/i2p/router/client/ClientConnectionRunner.java @@ -71,6 +71,7 @@ class ClientConnectionRunner { private final Map<MessageId, Payload> _messages; /** lease set request state, or null if there is no request pending on at the moment */ private LeaseRequestState _leaseRequest; + private int _consecutiveLeaseRequestFails; /** currently allocated leaseSet, or null if none is allocated */ private LeaseSet _currentLeaseSet; /** set of messageIds created but not yet ACCEPTED */ @@ -100,6 +101,7 @@ class ClientConnectionRunner { // e.g. on local access private static final int MAX_MESSAGE_ID = 0x4000000; + private static final int MAX_LEASE_FAILS = 5; private static final int BUF_SIZE = 32*1024; /** @since 0.9.2 */ @@ -191,12 +193,17 @@ class ClientConnectionRunner { /** data for the current leaseRequest, or null if there is no active leaseSet request */ LeaseRequestState getLeaseRequest() { return _leaseRequest; } - void setLeaseRequest(LeaseRequestState req) { + /** @param req non-null */ + public void failLeaseRequest(LeaseRequestState req) { + boolean disconnect = false; synchronized (this) { - if ( (_leaseRequest != null) && (req != _leaseRequest) ) - _log.error("Changing leaseRequest from " + _leaseRequest + " to " + req); - _leaseRequest = req; + if (_leaseRequest == req) { + _leaseRequest = null; + disconnect = ++_consecutiveLeaseRequestFails > MAX_LEASE_FAILS; + } } + if (disconnect) + disconnectClient("Too many leaseset request fails"); } /** already closed? */ @@ -287,6 +294,7 @@ class ClientConnectionRunner { if (_log.shouldLog(Log.DEBUG)) _log.debug("LeaseSet created fully: " + state + " / " + ls); _leaseRequest = null; + _consecutiveLeaseRequestFails = 0; } } if ( (state != null) && (state.getOnGranted() != null) ) @@ -351,9 +359,8 @@ class ClientConnectionRunner { _acceptedPending.add(id); if (_log.shouldLog(Log.DEBUG)) - _log.debug("** Receiving message [" + id.getMessageId() + "] with payload of size [" - + payload.getSize() + "]" + " for session [" + _sessionId.getSessionId() - + "]"); + _log.debug("** Receiving message " + id.getMessageId() + " with payload of size " + + payload.getSize() + " for session " + _sessionId.getSessionId()); //long beforeDistribute = _context.clock().now(); // the following blocks as described above SessionConfig cfg = _config; @@ -380,7 +387,7 @@ class ClientConnectionRunner { if (sid == null) return; if (_log.shouldLog(Log.DEBUG)) _log.debug("Acking message send [accepted]" + id + " / " + nonce + " for sessionId " - + sid, new Exception("sendAccepted")); + + sid); MessageStatusMessage status = new MessageStatusMessage(); status.setMessageId(id.getMessageId()); status.setSessionId(sid.getSessionId()); @@ -486,10 +493,11 @@ class ClientConnectionRunner { return; // already requesting } else { _leaseRequest = state = new LeaseRequestState(onCreateJob, onFailedJob, _context.clock().now() + expirationTime, set); - _log.debug("Not already requesting, continue to request " + set); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("New request: " + state); } } - _context.jobQueue().addJob(new RequestLeaseSetJob(_context, this, set, _context.clock().now() + expirationTime, onCreateJob, onFailedJob, state)); + _context.jobQueue().addJob(new RequestLeaseSetJob(_context, this, state)); } private class Rerequest implements SimpleTimer.TimedEvent { @@ -646,8 +654,8 @@ class ClientConnectionRunner { if (!alreadyAccepted(_messageId)) { _log.warn("Almost send an update for message " + _messageId + " to " + MessageStatusMessage.getStatusString(msg.getStatus()) - + " for session [" + _sessionId.getSessionId() - + "] before they knew the messageId! delaying .5s"); + + " for session " + _sessionId.getSessionId() + + " before they knew the messageId! delaying .5s"); _lastTried = _context.clock().now(); requeue(REQUEUE_DELAY); return; @@ -680,15 +688,14 @@ class ClientConnectionRunner { if (_log.shouldLog(Log.DEBUG)) _log.info("Updating message status for message " + _messageId + " to " + MessageStatusMessage.getStatusString(msg.getStatus()) - + " for session [" + _sessionId.getSessionId() - + "] (with nonce=2), retrying after [" - + (_context.clock().now() - _lastTried) - + "]"); + + " for session " + _sessionId.getSessionId() + + " (with nonce=2), retrying after " + + (_context.clock().now() - _lastTried)); } else { if (_log.shouldLog(Log.DEBUG)) _log.debug("Updating message status for message " + _messageId + " to " + MessageStatusMessage.getStatusString(msg.getStatus()) - + " for session [" + _sessionId.getSessionId() + "] (with nonce=2)"); + + " for session " + _sessionId.getSessionId() + " (with nonce=2)"); } try { diff --git a/router/java/src/net/i2p/router/client/ClientManager.java b/router/java/src/net/i2p/router/client/ClientManager.java index c1816bfd0287ad95d58f3b64e86a813e1844d764..1a07da10e069a9152684ca031af1e9cf661098b2 100644 --- a/router/java/src/net/i2p/router/client/ClientManager.java +++ b/router/java/src/net/i2p/router/client/ClientManager.java @@ -62,6 +62,8 @@ class ClientManager { private static final int INTERNAL_QUEUE_SIZE = 256; + private static final long REQUEST_LEASESET_TIMEOUT = 60*1000; + public ClientManager(RouterContext context, int port) { _ctx = context; _log = context.logManager().getLog(ClientManager.class); @@ -275,6 +277,8 @@ class ClientManager { * within the timeout specified, queue up the onFailedJob. This call does not * block. * + * UNUSED, the call below without jobs is always used. + * * @param dest Destination from which the LeaseSet's authorization should be requested * @param set LeaseSet with requested leases - this object must be updated to contain the * signed version (as well as any changed/added/removed Leases) @@ -290,12 +294,10 @@ class ClientManager { + dest.calculateHash().toBase64() + ". disconnected?"); _ctx.jobQueue().addJob(onFailedJob); } else { - runner.requestLeaseSet(set, _ctx.clock().now() + timeout, onCreateJob, onFailedJob); + runner.requestLeaseSet(set, timeout, onCreateJob, onFailedJob); } } - private static final int REQUEST_LEASESET_TIMEOUT = 120*1000; - public void requestLeaseSet(Hash dest, LeaseSet ls) { ClientConnectionRunner runner = getRunner(dest); if (runner != null) { diff --git a/router/java/src/net/i2p/router/client/ClientManagerFacadeImpl.java b/router/java/src/net/i2p/router/client/ClientManagerFacadeImpl.java index e422e99177965f23120316e3c0c7df10dcf947dc..ff40c211599a149e63015d99faa2bc52421a7694 100644 --- a/router/java/src/net/i2p/router/client/ClientManagerFacadeImpl.java +++ b/router/java/src/net/i2p/router/client/ClientManagerFacadeImpl.java @@ -110,6 +110,8 @@ public class ClientManagerFacadeImpl extends ClientManagerFacade implements Inte * within the timeout specified, queue up the onFailedJob. This call does not * block. * + * UNUSED, the call below without jobs is always used. + * * @param dest Destination from which the LeaseSet's authorization should be requested * @param set LeaseSet with requested leases - this object must be updated to contain the * signed version (as well as any changed/added/removed Leases) diff --git a/router/java/src/net/i2p/router/client/LeaseRequestState.java b/router/java/src/net/i2p/router/client/LeaseRequestState.java index 50f4003ca1c9a36d93ce8dbbe5990fee2af0ee73..67968df3b945df7c0bbb0de84569d160b5a12d30 100644 --- a/router/java/src/net/i2p/router/client/LeaseRequestState.java +++ b/router/java/src/net/i2p/router/client/LeaseRequestState.java @@ -28,6 +28,9 @@ class LeaseRequestState { private final long _expiration; private boolean _successful; + /** + * @param expiration absolute time + */ public LeaseRequestState(Job onGranted, Job onFailed, long expiration, LeaseSet requested) { _onGranted = onGranted; _onFailed = onFailed; diff --git a/router/java/src/net/i2p/router/client/RequestLeaseSetJob.java b/router/java/src/net/i2p/router/client/RequestLeaseSetJob.java index 1abb54c887c262b153e052995023ec400e85cc31..72147c060c8a59bb1cba0349214b010dc0ffddc7 100644 --- a/router/java/src/net/i2p/router/client/RequestLeaseSetJob.java +++ b/router/java/src/net/i2p/router/client/RequestLeaseSetJob.java @@ -31,7 +31,7 @@ class RequestLeaseSetJob extends JobImpl { private final ClientConnectionRunner _runner; private final LeaseRequestState _requestState; - public RequestLeaseSetJob(RouterContext ctx, ClientConnectionRunner runner, LeaseSet set, long expiration, Job onCreate, Job onFail, LeaseRequestState state) { + public RequestLeaseSetJob(RouterContext ctx, ClientConnectionRunner runner, LeaseRequestState state) { super(ctx); _log = ctx.logManager().getLog(RequestLeaseSetJob.class); _runner = runner; @@ -42,6 +42,7 @@ class RequestLeaseSetJob extends JobImpl { } public String getName() { return "Request Lease Set"; } + public void runJob() { if (_runner.isDead()) return; @@ -59,21 +60,23 @@ class RequestLeaseSetJob extends JobImpl { msg.setSessionId(_runner.getSessionId()); for (int i = 0; i < _requestState.getRequested().getLeaseCount(); i++) { - msg.addEndpoint(_requestState.getRequested().getLease(i).getGateway(), _requestState.getRequested().getLease(i).getTunnelId()); + msg.addEndpoint(_requestState.getRequested().getLease(i).getGateway(), + _requestState.getRequested().getLease(i).getTunnelId()); } try { //_runner.setLeaseRequest(state); _runner.doSend(msg); - getContext().jobQueue().addJob(new CheckLeaseRequestStatus(getContext(), _requestState)); - return; + getContext().jobQueue().addJob(new CheckLeaseRequestStatus()); } catch (I2CPMessageException ime) { getContext().statManager().addRateData("client.requestLeaseSetDropped", 1, 0); _log.error("Error sending I2CP message requesting the lease set", ime); _requestState.setIsSuccessful(false); - _runner.setLeaseRequest(null); - _runner.disconnectClient("I2CP error requesting leaseSet"); - return; + if (_requestState.getOnFailed() != null) + RequestLeaseSetJob.this.getContext().jobQueue().addJob(_requestState.getOnFailed()); + _runner.failLeaseRequest(_requestState); + // Don't disconnect, the tunnel will retry + //_runner.disconnectClient("I2CP error requesting leaseSet"); } } @@ -84,14 +87,12 @@ class RequestLeaseSetJob extends JobImpl { * */ private class CheckLeaseRequestStatus extends JobImpl { - private final LeaseRequestState _req; private final long _start; - public CheckLeaseRequestStatus(RouterContext enclosingContext, LeaseRequestState state) { - super(enclosingContext); - _req = state; + public CheckLeaseRequestStatus() { + super(RequestLeaseSetJob.this.getContext()); _start = System.currentTimeMillis(); - getTiming().setStartAfter(state.getExpiration()); + getTiming().setStartAfter(_requestState.getExpiration()); } public void runJob() { @@ -100,20 +101,22 @@ class RequestLeaseSetJob extends JobImpl { _log.debug("Already dead, dont try to expire the leaseSet lookup"); return; } - if (_req.getIsSuccessful()) { + if (_requestState.getIsSuccessful()) { // we didn't fail - RequestLeaseSetJob.CheckLeaseRequestStatus.this.getContext().statManager().addRateData("client.requestLeaseSetSuccess", 1, 0); + CheckLeaseRequestStatus.this.getContext().statManager().addRateData("client.requestLeaseSetSuccess", 1); return; } else { - RequestLeaseSetJob.CheckLeaseRequestStatus.this.getContext().statManager().addRateData("client.requestLeaseSetTimeout", 1, 0); + CheckLeaseRequestStatus.this.getContext().statManager().addRateData("client.requestLeaseSetTimeout", 1); if (_log.shouldLog(Log.ERROR)) { long waited = System.currentTimeMillis() - _start; - _log.error("Failed to receive a leaseSet in the time allotted (" + waited + "): " + _req + " for " + _log.error("Failed to receive a leaseSet in the time allotted (" + waited + "): " + _requestState + " for " + _runner.getConfig().getDestination().calculateHash().toBase64()); } - _runner.disconnectClient("Took too long to request leaseSet"); - if (_req.getOnFailed() != null) - RequestLeaseSetJob.this.getContext().jobQueue().addJob(_req.getOnFailed()); + if (_requestState.getOnFailed() != null) + RequestLeaseSetJob.this.getContext().jobQueue().addJob(_requestState.getOnFailed()); + _runner.failLeaseRequest(_requestState); + // Don't disconnect, the tunnel will retry + //_runner.disconnectClient("Took too long to request leaseSet"); } } public String getName() { return "Check LeaseRequest Status"; } diff --git a/router/java/src/net/i2p/router/peermanager/PeerManager.java b/router/java/src/net/i2p/router/peermanager/PeerManager.java index 1cc82a46e5b257c4342c0cb20011bac08899cb85..bf3564298aac90d497023ba0c62a9cd35879e7a6 100644 --- a/router/java/src/net/i2p/router/peermanager/PeerManager.java +++ b/router/java/src/net/i2p/router/peermanager/PeerManager.java @@ -89,14 +89,16 @@ class PeerManager { super(_context.simpleTimer2(), REORGANIZE_TIME); } public void timeReached() { + long start = System.currentTimeMillis(); try { _organizer.reorganize(true); } catch (Throwable t) { _log.log(Log.CRIT, "Error evaluating profiles", t); } + long orgtime = System.currentTimeMillis() - start; long uptime = _context.router().getUptime(); long delay; - if (uptime > 2*60*60*1000) + if (orgtime > 1000 || uptime > 2*60*60*1000) delay = REORGANIZE_TIME_LONG; else if (uptime > 10*60*1000) delay = REORGANIZE_TIME_MEDIUM;