Updates for proposal 160 changes (WIP)

- Remove fast mode support
- Add configurable lifetime

TODO: Switch to Datagram2
This commit is contained in:
zzz
2025-04-25 11:14:13 -04:00
parent 20245a3e8e
commit 8ff2c93b0a
5 changed files with 56 additions and 14 deletions

View File

@ -5,6 +5,10 @@
# minimum 900 (15 minutes), maximum 21600 (6 hours) # minimum 900 (15 minutes), maximum 21600 (6 hours)
interval=1620 interval=1620
# #
# UDP connection lifetime in seconds
# minimum 60 (1 minute), maximum 21600 (6 hours)
lifetime=1200
#
showfoooter=true showfoooter=true
#footerText=your html text here #footerText=your html text here
# #

View File

@ -33,15 +33,18 @@ public class Torrents extends ConcurrentHashMap<InfoHash, Peers> {
private final SDSCache<InfoHash> _hashCache; private final SDSCache<InfoHash> _hashCache;
private final SDSCache<PID> _pidCache; private final SDSCache<PID> _pidCache;
private final Integer _interval; private final Integer _interval;
private final int _udpLifetime;
/** /**
* @param interval in seconds * @param interval in seconds
* @param udpInterval in seconds
*/ */
public Torrents(int interval) { public Torrents(int interval, int udpLifetime) {
super(); super();
_hashCache = new SDSCache<InfoHash>(InfoHash.class, InfoHash.LENGTH, CACHE_SIZE); _hashCache = new SDSCache<InfoHash>(InfoHash.class, InfoHash.LENGTH, CACHE_SIZE);
_pidCache = new SDSCache<PID>(PID.class, PID.LENGTH, CACHE_SIZE); _pidCache = new SDSCache<PID>(PID.class, PID.LENGTH, CACHE_SIZE);
_interval = Integer.valueOf(interval); _interval = Integer.valueOf(interval);
_udpLifetime = udpLifetime;
} }
public int countPeers() { public int countPeers() {
@ -60,6 +63,14 @@ public class Torrents extends ConcurrentHashMap<InfoHash, Peers> {
return _interval; return _interval;
} }
/**
* @return in seconds
* @since 0.20.0
*/
public int getUDPLifetime() {
return _udpLifetime;
}
/** /**
* Pull from cache or return new * Pull from cache or return new
* *

View File

@ -67,7 +67,7 @@ public class UDPHandler implements I2PSessionMuxedListener {
private static final int EVENT_COMPLETED = 1; private static final int EVENT_COMPLETED = 1;
private static final int EVENT_STARTED = 2; private static final int EVENT_STARTED = 2;
private static final int EVENT_STOPPED = 3; private static final int EVENT_STOPPED = 3;
private static final long CLEAN_TIME = 2*60*1000; private final long CLEAN_TIME;
public UDPHandler(I2PAppContext ctx, I2PTunnel tunnel, ZzzOT zzzot) { public UDPHandler(I2PAppContext ctx, I2PTunnel tunnel, ZzzOT zzzot) {
@ -77,6 +77,7 @@ public class UDPHandler implements I2PSessionMuxedListener {
_zzzot = zzzot; _zzzot = zzzot;
_diss = new I2PDatagramDissector(); _diss = new I2PDatagramDissector();
_connectCache = new ConcurrentHashMap<Long, DestAndTime>(); _connectCache = new ConcurrentHashMap<Long, DestAndTime>();
CLEAN_TIME = (zzzot.getTorrents().getUDPLifetime() + 60) * 1000;
_cleaner = new Cleaner(); _cleaner = new Cleaner();
} }
@ -94,6 +95,7 @@ public class UDPHandler implements I2PSessionMuxedListener {
continue; continue;
} }
I2PSession session = sessions.get(0); I2PSession session = sessions.get(0);
// TODO switch to Datagram2
session.addMuxedSessionListener(UDPHandler.this, I2PSession.PROTO_DATAGRAM, PORT); session.addMuxedSessionListener(UDPHandler.this, I2PSession.PROTO_DATAGRAM, PORT);
session.addMuxedSessionListener(UDPHandler.this, I2PSession.PROTO_DATAGRAM_RAW, PORT); session.addMuxedSessionListener(UDPHandler.this, I2PSession.PROTO_DATAGRAM_RAW, PORT);
_cleaner.schedule(CLEAN_TIME); _cleaner.schedule(CLEAN_TIME);
@ -119,6 +121,7 @@ public class UDPHandler implements I2PSessionMuxedListener {
try { try {
// receive message // receive message
byte[] msg = session.receiveMessage(id); byte[] msg = session.receiveMessage(id);
// TODO switch to Datagram2
if (proto == I2PSession.PROTO_DATAGRAM) { if (proto == I2PSession.PROTO_DATAGRAM) {
// load datagram into it // load datagram into it
_diss.loadI2PDatagram(msg); _diss.loadI2PDatagram(msg);
@ -170,7 +173,12 @@ public class UDPHandler implements I2PSessionMuxedListener {
} }
handleConnect(session, from, fromPort, data); handleConnect(session, from, fromPort, data);
} else if (action == ACTION_ANNOUNCE) { } else if (action == ACTION_ANNOUNCE) {
handleAnnounce(session, connID, from, fromPort, data); if (from != null) {
if (_log.shouldWarn())
_log.warn("dropping repliable announce");
return;
}
handleAnnounce(session, connID, fromPort, data);
} else if (action == ACTION_SCRAPE) { } else if (action == ACTION_SCRAPE) {
if (_log.shouldWarn()) if (_log.shouldWarn())
_log.warn("got unsupported scrape"); _log.warn("got unsupported scrape");
@ -186,9 +194,11 @@ public class UDPHandler implements I2PSessionMuxedListener {
private void handleConnect(I2PSession session, Destination from, int fromPort, byte[] data) { private void handleConnect(I2PSession session, Destination from, int fromPort, byte[] data) {
int transID = (int) DataHelper.fromLong(data, 12, 4); int transID = (int) DataHelper.fromLong(data, 12, 4);
long connID = _context.random().nextLong(); long connID = _context.random().nextLong();
byte[] resp = new byte[16]; byte[] resp = new byte[18];
DataHelper.toLong(resp, 4, 4, transID); DataHelper.toLong(resp, 4, 4, transID);
DataHelper.toLong8(resp, 8, connID); DataHelper.toLong8(resp, 8, connID);
// Addition to BEP 15
DataHelper.toLong(resp, 16, 2, _zzzot.getTorrents().getUDPLifetime());
try { try {
session.sendMessage(from, resp, I2PSession.PROTO_DATAGRAM_RAW, PORT, fromPort); session.sendMessage(from, resp, I2PSession.PROTO_DATAGRAM_RAW, PORT, fromPort);
if (_log.shouldDebug()) if (_log.shouldDebug())
@ -203,22 +213,20 @@ public class UDPHandler implements I2PSessionMuxedListener {
/** /**
* @param from may be null * @param from may be null
*/ */
private void handleAnnounce(I2PSession session, long connID, Destination from, int fromPort, byte[] data) { private void handleAnnounce(I2PSession session, long connID, int fromPort, byte[] data) {
int sz = data.length; int sz = data.length;
if (sz < 96) { if (sz < 96) {
if (_log.shouldWarn()) if (_log.shouldWarn())
_log.warn("dropping short announce length " + sz); _log.warn("dropping short announce length " + sz);
return; return;
} }
if (from == null) { DestAndTime dat = _connectCache.get(Long.valueOf(connID));
DestAndTime dat = _connectCache.get(Long.valueOf(connID)); if (dat == null) {
if (dat == null) { if (_log.shouldWarn())
if (_log.shouldWarn()) _log.warn("no connID found " + connID);
_log.warn("no connID found " + connID); return;
return;
}
from = dat.dest;
} }
Destination from = dat.dest;
// parse packet // parse packet
int transID = (int) DataHelper.fromLong(data, 12, 4); int transID = (int) DataHelper.fromLong(data, 12, 4);

View File

@ -35,11 +35,15 @@ class ZzzOT {
private final long EXPIRE_TIME; private final long EXPIRE_TIME;
private static final String PROP_INTERVAL = "interval"; private static final String PROP_INTERVAL = "interval";
private static final String PROP_UDP_LIFETIME = "lifetime";
private static final long CLEAN_TIME = 4*60*1000; private static final long CLEAN_TIME = 4*60*1000;
private static final long DEST_CACHE_CLEAN_TIME = 3*60*60*1000; private static final long DEST_CACHE_CLEAN_TIME = 3*60*60*1000;
private static final int DEFAULT_INTERVAL = 27*60; private static final int DEFAULT_INTERVAL = 27*60;
private static final int DEFAULT_UDP_LIFETIME = 20*60;
private static final int MIN_INTERVAL = 15*60; private static final int MIN_INTERVAL = 15*60;
private static final int MAX_INTERVAL = 6*60*60; private static final int MAX_INTERVAL = 6*60*60;
private static final int MIN_UDP_LIFETIME = 60;
private static final int MAX_UDP_LIFETIME = 6*60*60;
ZzzOT(I2PAppContext ctx, Properties p) { ZzzOT(I2PAppContext ctx, Properties p) {
String intv = p.getProperty(PROP_INTERVAL); String intv = p.getProperty(PROP_INTERVAL);
@ -53,7 +57,18 @@ class ZzzOT {
interval = MAX_INTERVAL; interval = MAX_INTERVAL;
} catch (NumberFormatException nfe) {} } catch (NumberFormatException nfe) {}
} }
_torrents = new Torrents(interval); intv = p.getProperty(PROP_UDP_LIFETIME);
int lifetime = DEFAULT_UDP_LIFETIME;
if (intv != null) {
try {
lifetime = Integer.parseInt(intv);
if (lifetime < MIN_UDP_LIFETIME)
interval = MIN_UDP_LIFETIME;
else if (interval > MAX_UDP_LIFETIME)
interval = MAX_UDP_LIFETIME;
} catch (NumberFormatException nfe) {}
}
_torrents = new Torrents(interval, lifetime);
EXPIRE_TIME = 1000 * (interval + interval / 2); EXPIRE_TIME = 1000 * (interval + interval / 2);
_cleaner = new Cleaner(ctx); _cleaner = new Cleaner(ctx);
} }

View File

@ -21,6 +21,10 @@
<b>Torrents:</b> <%=torrents.size()%><br> <b>Torrents:</b> <%=torrents.size()%><br>
<b>Peers:</b> <%=torrents.countPeers()%><br> <b>Peers:</b> <%=torrents.countPeers()%><br>
<b>Announce Interval:</b> <%=torrents.getInterval() / 60%> minutes<br> <b>Announce Interval:</b> <%=torrents.getInterval() / 60%> minutes<br>
<!--
<b>UDP Announce Support:</b> yes<br>
<b>UDP Connection Lifetime:</b> <%=torrents.getUDPLifetime() / 60%> minutes<br>
-->
</p> </p>
<% <%
/* /*