forked from I2P_Developers/i2p.i2p
Handle 429 responses
Some checks failed
Java CI / build (push) Has been cancelled
Java CI / javadoc-latest (push) Has been cancelled
Java CI / build-java7 (push) Has been cancelled
Java with IzPack Snapshot Setup / setup (push) Has been cancelled
Sync Primary Repository to GitHub Mirror / sync (push) Has been cancelled
Some checks failed
Java CI / build (push) Has been cancelled
Java CI / javadoc-latest (push) Has been cancelled
Java CI / build-java7 (push) Has been cancelled
Java with IzPack Snapshot Setup / setup (push) Has been cancelled
Sync Primary Repository to GitHub Mirror / sync (push) Has been cancelled
untested
This commit is contained in:
@ -19,6 +19,7 @@ import java.util.List;
|
|||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
import net.i2p.CoreVersion;
|
import net.i2p.CoreVersion;
|
||||||
@ -57,6 +58,7 @@ class RemoteSearch {
|
|||||||
private static final AtomicInteger _lastSent = new AtomicInteger();
|
private static final AtomicInteger _lastSent = new AtomicInteger();
|
||||||
private static final AtomicInteger _lastRcvd = new AtomicInteger();
|
private static final AtomicInteger _lastRcvd = new AtomicInteger();
|
||||||
private static final AtomicReference<String> _currentSearch = new AtomicReference<String>();
|
private static final AtomicReference<String> _currentSearch = new AtomicReference<String>();
|
||||||
|
private static final AtomicLong _bannedUntil = new AtomicLong();
|
||||||
// positive/negative cache, Result.result may be null
|
// positive/negative cache, Result.result may be null
|
||||||
private static final Map<String, Result> _cache = new LHMCache<String, Result>(16);
|
private static final Map<String, Result> _cache = new LHMCache<String, Result>(16);
|
||||||
//private static final List<Thread> _waiting = new ArrayList<Thread>(16);
|
//private static final List<Thread> _waiting = new ArrayList<Thread>(16);
|
||||||
@ -175,6 +177,19 @@ class RemoteSearch {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
long currentBan = _bannedUntil.get();
|
||||||
|
if (currentBan > 0) {
|
||||||
|
long now = _ctx.clock().now();
|
||||||
|
if (currentBan > now) {
|
||||||
|
long retry = currentBan - now;
|
||||||
|
if (retry <= 10*60*1000)
|
||||||
|
return _t("Rate limited for {0}", DataHelper.formatDuration(retry));
|
||||||
|
else
|
||||||
|
return _t("Rate limited until {0}", DataHelper.formatTime(currentBan));
|
||||||
|
}
|
||||||
|
_bannedUntil.compareAndSet(currentBan, 0);
|
||||||
|
}
|
||||||
|
|
||||||
// if a new search comes in within 650 ms, interrupt the old one
|
// if a new search comes in within 650 ms, interrupt the old one
|
||||||
if (isXHR) {
|
if (isXHR) {
|
||||||
Thread us = Thread.currentThread();
|
Thread us = Thread.currentThread();
|
||||||
@ -239,7 +254,11 @@ class RemoteSearch {
|
|||||||
code = -1;
|
code = -1;
|
||||||
if (code > 0) {
|
if (code > 0) {
|
||||||
buf.append(code);
|
buf.append(code);
|
||||||
String text = get.getStatusText();
|
String text;
|
||||||
|
if (code == 429)
|
||||||
|
text = process429(out);
|
||||||
|
else
|
||||||
|
text = get.getStatusText();
|
||||||
if (text != null)
|
if (text != null)
|
||||||
buf.append(' ').append(DataHelper.escapeHTML(text));
|
buf.append(' ').append(DataHelper.escapeHTML(text));
|
||||||
} else {
|
} else {
|
||||||
@ -304,6 +323,27 @@ class RemoteSearch {
|
|||||||
return buf.toString();
|
return buf.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String process429(ByteArrayStream out) {
|
||||||
|
try {
|
||||||
|
Reader in = new InputStreamReader(out.asInputStream(), "UTF-8");
|
||||||
|
JsonObject map = (JsonObject) Jsoner.deserialize(in);
|
||||||
|
long retry = map.getIntegerOrDefault(RETRY) * 1000L;
|
||||||
|
long until = _ctx.clock().now() + retry;
|
||||||
|
long currentBan = _bannedUntil.get();
|
||||||
|
while (until > currentBan && !_bannedUntil.compareAndSet(currentBan, until)) {
|
||||||
|
currentBan = _bannedUntil.get();
|
||||||
|
}
|
||||||
|
if (retry <= 10*60*1000)
|
||||||
|
return _t("Rate limited for {0}", DataHelper.formatDuration(retry));
|
||||||
|
else
|
||||||
|
return _t("Rate limited until {0}", DataHelper.formatTime(until));
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (_log.shouldWarn())
|
||||||
|
_log.warn("json error input=\"" + DataHelper.getUTF8(out.toByteArray()), e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// keys with defaults
|
// keys with defaults
|
||||||
private static final JsonKey ADDED = Jsoner.mintJsonKey("added", "");
|
private static final JsonKey ADDED = Jsoner.mintJsonKey("added", "");
|
||||||
private static final JsonKey ALIVE = Jsoner.mintJsonKey("is_alive", Integer.valueOf(0));
|
private static final JsonKey ALIVE = Jsoner.mintJsonKey("is_alive", Integer.valueOf(0));
|
||||||
@ -319,6 +359,7 @@ class RemoteSearch {
|
|||||||
private static final JsonKey LINK = Jsoner.mintJsonKey("download_link", "");
|
private static final JsonKey LINK = Jsoner.mintJsonKey("download_link", "");
|
||||||
private static final JsonKey NAME = Jsoner.mintJsonKey("name", "");
|
private static final JsonKey NAME = Jsoner.mintJsonKey("name", "");
|
||||||
private static final JsonKey OWNER = Jsoner.mintJsonKey("owner", "");
|
private static final JsonKey OWNER = Jsoner.mintJsonKey("owner", "");
|
||||||
|
private static final JsonKey RETRY = Jsoner.mintJsonKey("retry_after", Integer.valueOf(60));
|
||||||
private static final JsonKey SEEDS = Jsoner.mintJsonKey("seeders", Integer.valueOf(0));
|
private static final JsonKey SEEDS = Jsoner.mintJsonKey("seeders", Integer.valueOf(0));
|
||||||
private static final JsonKey SIZE = Jsoner.mintJsonKey("size", Long.valueOf(0));
|
private static final JsonKey SIZE = Jsoner.mintJsonKey("size", Long.valueOf(0));
|
||||||
private static final JsonKey TORRENTS = Jsoner.mintJsonKey("torrents", null);
|
private static final JsonKey TORRENTS = Jsoner.mintJsonKey("torrents", null);
|
||||||
|
Reference in New Issue
Block a user