I2P Address: [http://git.idk.i2p]

Skip to content
Snippets Groups Projects
Commit e01c443f authored by zzz's avatar zzz
Browse files

Test: Add random delay and drop options to LocalClientManager

Return failure codes from LCM to client (ticket #1939)
parent 2d8f0c29
No related branches found
No related tags found
No related merge requests found
...@@ -223,7 +223,11 @@ ...@@ -223,7 +223,11 @@
<!-- warning - The junit.test target below doesn't actually include i2ptest.jar in the classpath, <!-- warning - The junit.test target below doesn't actually include i2ptest.jar in the classpath,
only the build/obj directory. only the build/obj directory.
--> -->
<jar destfile="./build/i2ptest.jar" basedir="./build/obj" includes="**/*.class **/test.data **/baseDblPrecmp **/basePrecmp" /> <jar destfile="./build/i2ptest.jar" basedir="./build/obj" >
<fileset dir="./build/obj" includes="**/*.class **/test.data **/baseDblPrecmp **/basePrecmp" />
<!-- the getopt translation files -->
<fileset dir="src" includes="${translation.includes}" />
</jar>
</target> </target>
<!-- preparation of code coverage tool of choice --> <!-- preparation of code coverage tool of choice -->
<target name="prepareClover" depends="compile" if="with.clover"> <target name="prepareClover" depends="compile" if="with.clover">
......
...@@ -8,12 +8,15 @@ package net.i2p.router.client; ...@@ -8,12 +8,15 @@ package net.i2p.router.client;
* *
*/ */
import gnu.getopt.Getopt;
import net.i2p.data.Destination; import net.i2p.data.Destination;
import net.i2p.data.Payload; import net.i2p.data.Payload;
import net.i2p.data.i2cp.MessageId; import net.i2p.data.i2cp.MessageId;
import net.i2p.data.i2cp.MessageStatusMessage; import net.i2p.data.i2cp.MessageStatusMessage;
import net.i2p.router.RouterContext; import net.i2p.router.RouterContext;
import net.i2p.util.I2PThread; import net.i2p.util.I2PThread;
import net.i2p.util.SimpleTimer2;
/** /**
* For testing clients without a full router. * For testing clients without a full router.
...@@ -25,6 +28,7 @@ import net.i2p.util.I2PThread; ...@@ -25,6 +28,7 @@ import net.i2p.util.I2PThread;
* @since 0.9.8 * @since 0.9.8
*/ */
class LocalClientManager extends ClientManager { class LocalClientManager extends ClientManager {
private static int dropX1000 = 0, jitter = 0, latency = 0;
/** /**
* @param context stub, may be constructed with new RouterContext(null), * @param context stub, may be constructed with new RouterContext(null),
...@@ -45,7 +49,7 @@ class LocalClientManager extends ClientManager { ...@@ -45,7 +49,7 @@ class LocalClientManager extends ClientManager {
/** /**
* Local only * Local only
* TODO: add simulated delay and random drops to test streaming. * TODO: we could have per-destination delay/drop parameters in the client options
* *
* @param flags ignored for local * @param flags ignored for local
*/ */
...@@ -56,9 +60,31 @@ class LocalClientManager extends ClientManager { ...@@ -56,9 +60,31 @@ class LocalClientManager extends ClientManager {
ClientConnectionRunner sender = getRunner(fromDest); ClientConnectionRunner sender = getRunner(fromDest);
ClientConnectionRunner runner = getRunner(toDest); ClientConnectionRunner runner = getRunner(toDest);
if (runner != null) { if (runner != null) {
runner.receiveMessage(toDest, fromDest, payload); if (dropX1000 > 0) {
if (sender != null) if (100 * 1000 * _ctx.random().nextFloat() < dropX1000) {
sender.updateMessageDeliveryStatus(fromDest, msgId, messageNonce, MessageStatusMessage.STATUS_SEND_SUCCESS_LOCAL); System.out.println("Message " + msgId + " DROPPED randomly");
if (sender != null) {
// pretend success
sender.updateMessageDeliveryStatus(fromDest, msgId, messageNonce, MessageStatusMessage.STATUS_SEND_GUARANTEED_SUCCESS);
}
}
}
if (latency > 0 || jitter > 0) {
int delay = latency;
if (jitter > 0)
delay += (int) (jitter * _ctx.random().nextGaussian());
if (delay > 0) {
System.out.println("Message " + msgId + " DELAYED " + delay + " ms");
DelayedSend ds = new DelayedSend(_ctx, sender, runner, fromDest, toDest, payload, msgId, messageNonce);
ds.schedule(delay);
return;
}
}
boolean ok = runner.receiveMessage(toDest, fromDest, payload);
if (sender != null) {
int rc = ok ? MessageStatusMessage.STATUS_SEND_SUCCESS_LOCAL : MessageStatusMessage.STATUS_SEND_FAILURE_LOCAL;
sender.updateMessageDeliveryStatus(fromDest, msgId, messageNonce, rc);
}
} else { } else {
// remote. ignore. // remote. ignore.
System.out.println("Message " + msgId + " is targeting a REMOTE destination - DROPPED"); System.out.println("Message " + msgId + " is targeting a REMOTE destination - DROPPED");
...@@ -67,13 +93,87 @@ class LocalClientManager extends ClientManager { ...@@ -67,13 +93,87 @@ class LocalClientManager extends ClientManager {
} }
} }
private static class DelayedSend extends SimpleTimer2.TimedEvent {
private final ClientConnectionRunner s, r;
private final Destination fd, td;
private final Payload pl;
private final MessageId id;
private final long nonce;
public DelayedSend(RouterContext ctx, ClientConnectionRunner sender, ClientConnectionRunner runner,
Destination fromDest, Destination toDest, Payload payload,
MessageId msgId, long messageNonce) {
super(ctx.simpleTimer2());
s = sender; r = runner; fd = fromDest;
td = toDest; pl = payload;
id = msgId; nonce = messageNonce;
}
public void timeReached() {
boolean ok = r.receiveMessage(td, fd, pl);
if (s != null) {
int rc = ok ? MessageStatusMessage.STATUS_SEND_SUCCESS_LOCAL : MessageStatusMessage.STATUS_SEND_FAILURE_LOCAL;
s.updateMessageDeliveryStatus(fd, id, nonce, rc);
}
}
}
public static void main(String args[]) { public static void main(String args[]) {
int dropX1000 = 0, jitter = 0, latency = 0;
boolean error = false;
Getopt g = new Getopt("router", args, "d:j:l:");
try {
int c;
while ((c = g.getopt()) != -1) {
switch (c) {
case 'd':
dropX1000 = (int) (1000 * Double.parseDouble(g.getOptarg()));
if (dropX1000 < 0 || dropX1000 >= 100 * 1000)
error = true;
break;
case 'j':
jitter = Integer.parseInt(g.getOptarg());
if (jitter < 0)
error = true;
break;
case 'l':
latency = Integer.parseInt(g.getOptarg());
if (latency < 0)
error = true;
break;
default:
error = true;
}
}
} catch (RuntimeException e) {
e.printStackTrace();
error = true;
}
if (error || args.length - g.getOptind() > 0) {
usage();
System.exit(1);
}
RouterContext ctx = new RouterContext(null); RouterContext ctx = new RouterContext(null);
int port = ClientManagerFacadeImpl.DEFAULT_PORT; int port = ClientManagerFacadeImpl.DEFAULT_PORT;
ClientManager mgr = new LocalClientManager(ctx, port); LocalClientManager mgr = new LocalClientManager(ctx, port);
mgr.dropX1000 = dropX1000;
mgr.jitter = jitter;
mgr.latency = latency;
mgr.start(); mgr.start();
System.out.println("Listening on port " + port); System.out.println("Listening on port " + port);
try { Thread.sleep(60*60*1000); } catch (InterruptedException ie) {} try { Thread.sleep(60*60*1000); } catch (InterruptedException ie) {}
System.out.println("Done listening on port " + port); System.out.println("Done listening on port " + port);
} }
private static void usage() {
System.err.println("usage: LocalClientManager\n" +
" [-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)");
}
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment