Test: LocalClientManager fixes/improvements

- Fix NPEs caused by netdb changes
- Fix drop option
- Add rate limiter option to LocalClientManager
This commit is contained in:
zzz
2026-05-29 14:57:14 -04:00
parent 2de2741e4d
commit f512374280
4 changed files with 43 additions and 6 deletions
@@ -369,7 +369,10 @@ public class RouterContext extends I2PAppContext {
*/
public SegmentedNetworkDatabaseFacade netDbSegmentor() { return _netDb; }
public NetworkDatabaseFacade netDb() { return _netDb.mainNetDB(); }
/**
* @return may be null if called very early or in some unit tests
*/
public NetworkDatabaseFacade netDb() { return _netDb != null ? _netDb.mainNetDB() : null; }
/**
* Get the client netDb for the given id.
@@ -675,7 +675,8 @@ class ClientConnectionRunner {
}
}
}
if (isPrimary && _floodfillNetworkDatabaseFacade == null) {
// router() null for some unit tests
if (isPrimary && _floodfillNetworkDatabaseFacade == null && _context.router() != null) {
if (_log.shouldDebug())
_log.debug("Initializing subDb for client" + destHash);
_floodfillNetworkDatabaseFacade = new FloodfillNetworkDatabaseFacade(_context, destHash);
@@ -40,6 +40,7 @@ import net.i2p.data.i2cp.SetDateMessage;
import net.i2p.internal.I2CPMessageQueue;
import net.i2p.router.ClientManagerFacade;
import net.i2p.router.ClientMessage;
import net.i2p.router.CommSystemFacade;
import net.i2p.router.Job;
import net.i2p.router.JobImpl;
import net.i2p.router.RouterContext;
@@ -433,7 +434,8 @@ class ClientManager {
* @since 0.9.12
*/
private SessionId locked_getNextSessionId() {
if (_ctx.commSystem().isDummy())
CommSystemFacade csf = _ctx.commSystem();
if (csf != null && csf.isDummy()) // unit tests if null
return null;
int max = Math.max(1, Math.min(2048, _ctx.getProperty(PROP_MAX_SESSIONS, DEFAULT_MAX_SESSIONS)));
if (_runnerSessionIds.size() >= max) {
@@ -8,6 +8,8 @@ package net.i2p.router.client;
*
*/
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import gnu.getopt.Getopt;
@@ -19,6 +21,7 @@ import net.i2p.data.i2cp.MessageStatusMessage;
import net.i2p.router.RouterContext;
import net.i2p.util.I2PThread;
import net.i2p.util.SimpleTimer2;
import net.i2p.util.SyntheticREDQueue;
/**
* For testing clients without a full router.
@@ -30,7 +33,9 @@ import net.i2p.util.SimpleTimer2;
* @since 0.9.8
*/
class LocalClientManager extends ClientManager {
private static int dropX1000 = 0, jitter = 0, latency = 0;
private static int dropX1000 = 0, jitter = 0, latency = 0, ratelimit = 0;
private final Map<Destination, SyntheticREDQueue> limiters = new HashMap<Destination, SyntheticREDQueue>();
/**
* @param context stub, may be constructed with new RouterContext(null),
@@ -66,6 +71,23 @@ class LocalClientManager extends ClientManager {
System.out.println("Message " + msgId + " DROPPED randomly");
// pretend success
sender.updateMessageDeliveryStatus(fromDest, msgId, messageNonce, MessageStatusMessage.STATUS_SEND_GUARANTEED_SUCCESS);
return;
}
}
if (ratelimit > 0) {
SyntheticREDQueue srq;
synchronized(limiters) {
srq = limiters.get(fromDest);
if (srq == null) {
srq = new SyntheticREDQueue(_ctx, ratelimit * 1024);
limiters.put(fromDest, srq);
}
if (!srq.offer(payload.getSize(), 1)) {
System.out.println("Message " + msgId + " length " + payload.getSize() + " DROPPED by " + srq);
// pretend success
sender.updateMessageDeliveryStatus(fromDest, msgId, messageNonce, MessageStatusMessage.STATUS_SEND_GUARANTEED_SUCCESS);
return;
}
}
}
if (latency > 0 || jitter > 0) {
@@ -115,8 +137,9 @@ class LocalClientManager extends ClientManager {
public static void main(String args[]) {
int dropX1000 = 0, jitter = 0, latency = 0;
int port = ClientManagerFacadeImpl.DEFAULT_PORT;
int rate = 0;
boolean error = false;
Getopt g = new Getopt("LocalClientManager", args, "d:j:l:p:");
Getopt g = new Getopt("LocalClientManager", args, "d:j:l:p:r:");
try {
int c;
while ((c = g.getopt()) != -1) {
@@ -146,6 +169,12 @@ class LocalClientManager extends ClientManager {
error = true;
break;
case 'r':
rate = Integer.parseInt(g.getOptarg());
if (rate < 0)
error = true;
break;
default:
error = true;
}
@@ -167,6 +196,7 @@ class LocalClientManager extends ClientManager {
mgr.dropX1000 = dropX1000;
mgr.jitter = jitter;
mgr.latency = latency;
mgr.ratelimit = rate;
mgr.start();
System.out.println("Listening on port " + port);
try { Thread.sleep(60*60*1000); } catch (InterruptedException ie) {}
@@ -178,6 +208,7 @@ class LocalClientManager extends ClientManager {
" [-d droppercent] // 0.0 - 99.99999 (default 0)\n" +
" [-j jitter] // (integer ms for 1 std. deviation, default 0)\n" +
" [-l latency] // (integer ms, default 0)\n" +
" [-p port] // (I2CP port, default 7654)");
" [-p port] // (I2CP port, default 7654)\n" +
" [-r ratelimit] // (rate limit in KBps, default none)");
}
}