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)
interval=1620
#
# UDP connection lifetime in seconds
# minimum 60 (1 minute), maximum 21600 (6 hours)
lifetime=1200
#
showfoooter=true
#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<PID> _pidCache;
private final Integer _interval;
private final int _udpLifetime;
/**
* @param interval in seconds
* @param udpInterval in seconds
*/
public Torrents(int interval) {
public Torrents(int interval, int udpLifetime) {
super();
_hashCache = new SDSCache<InfoHash>(InfoHash.class, InfoHash.LENGTH, CACHE_SIZE);
_pidCache = new SDSCache<PID>(PID.class, PID.LENGTH, CACHE_SIZE);
_interval = Integer.valueOf(interval);
_udpLifetime = udpLifetime;
}
public int countPeers() {
@ -60,6 +63,14 @@ public class Torrents extends ConcurrentHashMap<InfoHash, Peers> {
return _interval;
}
/**
* @return in seconds
* @since 0.20.0
*/
public int getUDPLifetime() {
return _udpLifetime;
}
/**
* 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_STARTED = 2;
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) {
@ -77,6 +77,7 @@ public class UDPHandler implements I2PSessionMuxedListener {
_zzzot = zzzot;
_diss = new I2PDatagramDissector();
_connectCache = new ConcurrentHashMap<Long, DestAndTime>();
CLEAN_TIME = (zzzot.getTorrents().getUDPLifetime() + 60) * 1000;
_cleaner = new Cleaner();
}
@ -94,6 +95,7 @@ public class UDPHandler implements I2PSessionMuxedListener {
continue;
}
I2PSession session = sessions.get(0);
// TODO switch to Datagram2
session.addMuxedSessionListener(UDPHandler.this, I2PSession.PROTO_DATAGRAM, PORT);
session.addMuxedSessionListener(UDPHandler.this, I2PSession.PROTO_DATAGRAM_RAW, PORT);
_cleaner.schedule(CLEAN_TIME);
@ -119,6 +121,7 @@ public class UDPHandler implements I2PSessionMuxedListener {
try {
// receive message
byte[] msg = session.receiveMessage(id);
// TODO switch to Datagram2
if (proto == I2PSession.PROTO_DATAGRAM) {
// load datagram into it
_diss.loadI2PDatagram(msg);
@ -170,7 +173,12 @@ public class UDPHandler implements I2PSessionMuxedListener {
}
handleConnect(session, from, fromPort, data);
} 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) {
if (_log.shouldWarn())
_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) {
int transID = (int) DataHelper.fromLong(data, 12, 4);
long connID = _context.random().nextLong();
byte[] resp = new byte[16];
byte[] resp = new byte[18];
DataHelper.toLong(resp, 4, 4, transID);
DataHelper.toLong8(resp, 8, connID);
// Addition to BEP 15
DataHelper.toLong(resp, 16, 2, _zzzot.getTorrents().getUDPLifetime());
try {
session.sendMessage(from, resp, I2PSession.PROTO_DATAGRAM_RAW, PORT, fromPort);
if (_log.shouldDebug())
@ -203,22 +213,20 @@ public class UDPHandler implements I2PSessionMuxedListener {
/**
* @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;
if (sz < 96) {
if (_log.shouldWarn())
_log.warn("dropping short announce length " + sz);
return;
}
if (from == null) {
DestAndTime dat = _connectCache.get(Long.valueOf(connID));
if (dat == null) {
if (_log.shouldWarn())
_log.warn("no connID found " + connID);
return;
}
from = dat.dest;
}
Destination from = dat.dest;
// parse packet
int transID = (int) DataHelper.fromLong(data, 12, 4);

View File

@ -35,11 +35,15 @@ class ZzzOT {
private final long EXPIRE_TIME;
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 DEST_CACHE_CLEAN_TIME = 3*60*60*1000;
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 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) {
String intv = p.getProperty(PROP_INTERVAL);
@ -53,7 +57,18 @@ class ZzzOT {
interval = MAX_INTERVAL;
} 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);
_cleaner = new Cleaner(ctx);
}

View File

@ -21,6 +21,10 @@
<b>Torrents:</b> <%=torrents.size()%><br>
<b>Peers:</b> <%=torrents.countPeers()%><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>
<%
/*