Compare commits

...

24 Commits

Author SHA1 Message Date
0f60ac5acf 0.3.2.1 (backwards compatible blah blah blah) 2004-07-11 18:57:01 +00:00
c28f19fe8a less painful and/or redundant penalties for failures 2004-07-11 18:50:23 +00:00
mpc
09a6dbc755 FreeBSD port 2004-07-11 13:22:37 +00:00
3bc0e0fc8a added source and target declarations for the javac commands so we can build with the 1.5^W5.0 JDK
(also added deprecation, since, well, we can :)
2004-07-11 04:16:59 +00:00
eb0e187a54 throttle tunnel participation based on whether we've had to throttle our network connection > some number of times in the last 10-20 minutes (rather than a simple "are we throttled *right now*?") 2004-07-10 22:28:34 +00:00
a788d30f34 added support for new 'clientoptions' command which alters the properties passed when creating subsequent I2CP connections
e.g.: -e "clientoptions tunnels.depthInbound=0" -e "httpclient 6666"
this updates so many files because they all need a reference to an I2PTunnel object on construction so they query tunnel.getClientOptions() instead of System.getProperties
2004-07-10 16:59:49 +00:00
591dfc961e give the reliability more positive influence so it doesn't go negative so easily
update the peerProfile's CLI to make the resulting stats easier to read
2004-07-10 04:15:51 +00:00
809e12b034 logging 2004-07-10 04:13:42 +00:00
1669d174e1 use mihi's template engine to set a random timestamper password so people dont need to think about that stuff
don't use the dyndns anymore for seeding (use dev.i2p.net/i2pdb)
2004-07-10 02:36:27 +00:00
3cfd28de43 add a new unit test for repeated fast reconnections 2004-07-10 01:58:05 +00:00
4888207eca if a client reconnects, we always want to get a new leaseSet ASAP (even if the pool hadn't been marked as stopped yet)
logging
2004-07-10 01:46:57 +00:00
294cb96107 if the job's startAfter is changed, tell the jobQueue to go through the timed jobs again in case the new time changes the scheduling 2004-07-10 01:44:27 +00:00
b648fa2b70 send the stats page out in chunks (more mem efficient, blah blah blah) 2004-07-10 01:39:54 +00:00
ab99122211 render status HTML in pieces (continued) 2004-07-09 05:33:19 +00:00
dd014fee88 send the router console out bit by bit rather than building it all up and sending it (thereby reducing its memory footprint dramatically) 2004-07-09 05:29:02 +00:00
c81f864de3 reduce the throttle threshold from 5s lag to 2s lag 2004-07-09 05:22:29 +00:00
90fe7dceec include the expiration in the error message if its dropped 2004-07-09 05:20:26 +00:00
3a568096f2 new throttling code which rejects tunnel create requests, networkDb lookup requests, and even tells the I2NP components to stop reading from the network (it doesnt affect writing to the network)
the simple RouterThrottleImpl bases its decision entirely on how congested the jobQueue is - if there are jobs that have been waiting 5+ seconds, reject everything and stop reading from the network
(each i2npMessageReader randomly waits .5-1s when throttled before rechecking it)
minor adjustments in the stats published - removing a few useless ones and adding the router.throttleNetworkCause (which is the average ms lag in the jobQueue when an I2NP reader is throttled)
2004-07-09 03:56:22 +00:00
94e694fc61 reduce the job pipeline to send a message by fetching the bids and adding the message to the connection queue synchronously
these had been broken out into seperate jobs before to reduce thread and lock contention, but that isn't as serious an issue anymore (in these cases) and the non-contention-related delays of these mini-jobs are trivial
2004-07-09 03:48:12 +00:00
bdfa6e4af5 dont penalize send failures (beyond what we already do for comm errors)
keep a rate for tunnel rejection, rather than a simple 'last' occurrance, and penalize the reliability with it
2004-07-09 03:45:11 +00:00
8e64ffb4f6 keep the relay message size rate data for the 10 minute period (so we can throttle on logical periods) 2004-07-09 03:43:07 +00:00
6c162643cb expose stat for throttling (# tunnels we're currently participating in) 2004-07-09 03:41:27 +00:00
ff7742bca3 expose some stats useful for throttling (# ready & waiting jobs and the max lag of those jobs) 2004-07-09 03:39:38 +00:00
9685884279 deal with null peer (used by the SubmitMessageHistoryJob to bw limit the history)
current 0.3.2 throws an NPE which causes the submitMessageHistory functionality to fail, which isn't really a loss since i send that data to /dev/null at the moment ;)
(but you'll want to router.keepHistory=false and router.submitHistory=false)
this'll go into the next rev, whenever it comes out
(thanks ugha!)
2004-07-07 22:23:25 +00:00
74 changed files with 840 additions and 353 deletions

View File

@ -9,12 +9,12 @@
<target name="compile">
<mkdir dir="./build" />
<mkdir dir="./build/obj" />
<javac srcdir="./src" debug="true" destdir="./build/obj" includes="**/*.java" excludes="net/i2p/heartbeat/gui/**" classpath="../../../core/java/build/i2p.jar" />
<javac srcdir="./src" debug="true" target="1.1" source="1.3" deprecation="on" destdir="./build/obj" includes="**/*.java" excludes="net/i2p/heartbeat/gui/**" classpath="../../../core/java/build/i2p.jar" />
</target>
<target name="compileGUI">
<mkdir dir="./build" />
<mkdir dir="./build/obj" />
<javac debug="true" destdir="./build/obj">
<javac debug="true" target="1.1" source="1.3" deprecation="on" destdir="./build/obj">
<src path="src/" />
<classpath path="../../../core/java/build/i2p.jar" />
<classpath path="../../jfreechart/jfreechart-0.9.17/lib/jcommon-0.9.2.jar" />

View File

@ -11,7 +11,7 @@
<mkdir dir="./build/obj" />
<javac
srcdir="./src"
debug="true"
debug="true" target="1.1" source="1.3" deprecation="on"
destdir="./build/obj"
classpath="../../../core/java/build/i2p.jar:../../ministreaming/java/build/mstreaming.jar" />
</target>

View File

@ -11,7 +11,7 @@
<mkdir dir="./build/obj" />
<javac
srcdir="./src"
debug="true"
debug="true" target="1.1" source="1.3" deprecation="on"
destdir="./build/obj"
classpath="../../../core/java/build/i2p.jar:../../ministreaming/java/build/mstreaming.jar" />
</target>

View File

@ -46,6 +46,7 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;
@ -69,6 +70,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
private I2PAppContext _context;
private static long __tunnelId = 0;
private long _tunnelId;
private Properties _clientOptions;
public static final int PACKET_DELAY = 100;
@ -104,6 +106,9 @@ public class I2PTunnel implements Logging, EventDispatcher {
_tunnelId = ++__tunnelId;
_log = _context.logManager().getLog(I2PTunnel.class);
_event = new EventDispatcherImpl();
_clientOptions = new Properties();
_clientOptions.putAll(System.getProperties());
addConnectionEventListener(lsnr);
boolean gui = true;
boolean checkRunByE = true;
@ -167,6 +172,8 @@ public class I2PTunnel implements Logging, EventDispatcher {
}
}
public Properties getClientOptions() { return _clientOptions; }
private void addtask(I2PTunnelTask tsk) {
tsk.setTunnel(this);
if (tsk.isOpen()) {
@ -197,6 +204,8 @@ public class I2PTunnel implements Logging, EventDispatcher {
if ("help".equals(cmdname)) {
runHelp(l);
} else if ("clientoptions".equals(cmdname)) {
runClientOptions(args, l);
} else if ("server".equals(cmdname)) {
runServer(args, l);
} else if ("textserver".equals(cmdname)) {
@ -262,6 +271,29 @@ public class I2PTunnel implements Logging, EventDispatcher {
l.log("list");
l.log("run <commandfile>");
}
/**
* Configure the extra I2CP options to use in any subsequent I2CP sessions.
* Usage: "clientoptions[ key=value]*" .
*
* Sets the event "clientoptions_onResult" = "ok" after completion.
*
* @param args each args[i] is a key=value pair to add to the options
* @param l logger to receive events and output
*/
public void runClientOptions(String args[], Logging l) {
_clientOptions.clear();
if (args != null) {
for (int i = 0; i < args.length; i++) {
int index = args[i].indexOf('=');
if (index <= 0) continue;
String key = args[i].substring(0, index);
String val = args[i].substring(index+1);
_clientOptions.setProperty(key, val);
}
}
notifyEvent("clientoptions_onResult", "ok");
}
/**
* Run the server pointing at the host and port specified using the private i2p
@ -304,7 +336,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
notifyEvent("serverTaskId", new Integer(-1));
return;
}
I2PTunnelServer serv = new I2PTunnelServer(serverHost, portNum, privKeyFile, args[2], l, (EventDispatcher) this);
I2PTunnelServer serv = new I2PTunnelServer(serverHost, portNum, privKeyFile, args[2], l, (EventDispatcher) this, this);
serv.setReadTimeout(readTimeout);
serv.startRunning();
addtask(serv);
@ -350,7 +382,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
return;
}
I2PTunnelServer serv = new I2PTunnelServer(serverHost, portNum, args[2], l, (EventDispatcher) this);
I2PTunnelServer serv = new I2PTunnelServer(serverHost, portNum, args[2], l, (EventDispatcher) this, this);
serv.setReadTimeout(readTimeout);
serv.startRunning();
addtask(serv);
@ -386,7 +418,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
return;
}
I2PTunnelTask task;
task = new I2PTunnelClient(port, args[1], l, ownDest, (EventDispatcher) this);
task = new I2PTunnelClient(port, args[1], l, ownDest, (EventDispatcher) this, this);
addtask(task);
notifyEvent("clientTaskId", new Integer(task.getId()));
} else {
@ -423,7 +455,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
proxy = args[1];
}
I2PTunnelTask task;
task = new I2PTunnelHTTPClient(port, l, ownDest, proxy, (EventDispatcher) this);
task = new I2PTunnelHTTPClient(port, l, ownDest, proxy, (EventDispatcher) this, this);
addtask(task);
notifyEvent("httpclientTaskId", new Integer(task.getId()));
} else {
@ -460,7 +492,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
}
I2PTunnelTask task;
task = new I2PSOCKSTunnel(port, l, ownDest, (EventDispatcher) this);
task = new I2PSOCKSTunnel(port, l, ownDest, (EventDispatcher) this, this);
addtask(task);
notifyEvent("sockstunnelTaskId", new Integer(task.getId()));
} else {
@ -779,7 +811,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
if (allargs.length() != 0) {
I2PTunnelTask task;
// pings always use the main destination
task = new I2Ping(allargs, l, false, (EventDispatcher) this);
task = new I2Ping(allargs, l, false, (EventDispatcher) this, this);
addtask(task);
notifyEvent("pingTaskId", new Integer(task.getId()));
} else {

View File

@ -19,8 +19,8 @@ public class I2PTunnelClient extends I2PTunnelClientBase {
private static final long DEFAULT_READ_TIMEOUT = 5*60*1000; // -1
protected long readTimeout = DEFAULT_READ_TIMEOUT;
public I2PTunnelClient(int localPort, String destination, Logging l, boolean ownDest, EventDispatcher notifyThis) {
super(localPort, ownDest, l, notifyThis, "SynSender");
public I2PTunnelClient(int localPort, String destination, Logging l, boolean ownDest, EventDispatcher notifyThis, I2PTunnel tunnel) {
super(localPort, ownDest, l, notifyThis, "SynSender", tunnel);
if (waitEventValue("openBaseClientResult").equals("error")) {
notifyEvent("openClientResult", "error");

View File

@ -60,8 +60,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
// I2PTunnelClientBase(localPort, ownDest, l, (EventDispatcher)null);
//}
public I2PTunnelClientBase(int localPort, boolean ownDest, Logging l, EventDispatcher notifyThis, String handlerName) {
super(localPort + " (uninitialized)", notifyThis);
public I2PTunnelClientBase(int localPort, boolean ownDest, Logging l, EventDispatcher notifyThis, String handlerName, I2PTunnel tunnel) {
super(localPort + " (uninitialized)", notifyThis, tunnel);
_clientId = ++__clientId;
this.localPort = localPort;
this.l = l;
@ -103,16 +103,25 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
private static I2PSocketManager socketManager;
protected static synchronized I2PSocketManager getSocketManager() {
protected synchronized I2PSocketManager getSocketManager() {
return getSocketManager(getTunnel());
}
protected static synchronized I2PSocketManager getSocketManager(I2PTunnel tunnel) {
if (socketManager == null) {
socketManager = buildSocketManager();
socketManager = buildSocketManager(tunnel);
}
return socketManager;
}
protected static I2PSocketManager buildSocketManager() {
protected I2PSocketManager buildSocketManager() {
return buildSocketManager(getTunnel());
}
protected static I2PSocketManager buildSocketManager(I2PTunnel tunnel) {
Properties props = new Properties();
props.putAll(System.getProperties());
if (tunnel == null)
props.putAll(System.getProperties());
else
props.putAll(tunnel.getClientOptions());
I2PSocketManager sockManager = I2PSocketManagerFactory.createManager(I2PTunnel.host, Integer.parseInt(I2PTunnel.port), props);
sockManager.setName("Client");
return sockManager;

View File

@ -81,8 +81,8 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
/** used to assign unique IDs to the threads / clients. no logic or functionality */
private static volatile long __clientId = 0;
public I2PTunnelHTTPClient(int localPort, Logging l, boolean ownDest, String wwwProxy, EventDispatcher notifyThis) {
super(localPort, ownDest, l, notifyThis, "HTTPHandler " + (++__clientId));
public I2PTunnelHTTPClient(int localPort, Logging l, boolean ownDest, String wwwProxy, EventDispatcher notifyThis, I2PTunnel tunnel) {
super(localPort, ownDest, l, notifyThis, "HTTPHandler " + (++__clientId), tunnel);
if (waitEventValue("openBaseClientResult").equals("error")) {
notifyEvent("openHTTPClientResult", "error");
@ -127,7 +127,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
if (pos == -1) break;
method = line.substring(0, pos);
String request = line.substring(pos + 1);
if (request.startsWith("/") && System.getProperty("i2ptunnel.noproxy") != null) {
if (request.startsWith("/") && getTunnel().getClientOptions().getProperty("i2ptunnel.noproxy") != null) {
request = "http://i2p" + request;
}
pos = request.indexOf("//");

View File

@ -45,15 +45,15 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
/** default timeout to 3 minutes - override if desired */
private long readTimeout = DEFAULT_READ_TIMEOUT;
public I2PTunnelServer(InetAddress host, int port, String privData, Logging l, EventDispatcher notifyThis) {
super(host + ":" + port + " <- " + privData, notifyThis);
public I2PTunnelServer(InetAddress host, int port, String privData, Logging l, EventDispatcher notifyThis, I2PTunnel tunnel) {
super(host + ":" + port + " <- " + privData, notifyThis, tunnel);
ByteArrayInputStream bais = new ByteArrayInputStream(Base64.decode(privData));
init(host, port, bais, privData, l);
}
public I2PTunnelServer(InetAddress host, int port, File privkey, String privkeyname, Logging l,
EventDispatcher notifyThis) {
super(host + ":" + port + " <- " + privkeyname, notifyThis);
EventDispatcher notifyThis, I2PTunnel tunnel) {
super(host + ":" + port + " <- " + privkeyname, notifyThis, tunnel);
try {
init(host, port, new FileInputStream(privkey), privkeyname, l);
} catch (IOException ioe) {
@ -62,8 +62,8 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
}
}
public I2PTunnelServer(InetAddress host, int port, InputStream privData, String privkeyname, Logging l, EventDispatcher notifyThis) {
super(host + ":" + port + " <- " + privkeyname, notifyThis);
public I2PTunnelServer(InetAddress host, int port, InputStream privData, String privkeyname, Logging l, EventDispatcher notifyThis, I2PTunnel tunnel) {
super(host + ":" + port + " <- " + privkeyname, notifyThis, tunnel);
init(host, port, privData, privkeyname, l);
}
@ -73,7 +73,7 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
this.remotePort = port;
I2PClient client = I2PClientFactory.createClient();
Properties props = new Properties();
props.putAll(System.getProperties());
props.putAll(getTunnel().getClientOptions());
synchronized (slock) {
sockMgr = I2PSocketManagerFactory.createManager(privData, I2PTunnel.host, Integer.parseInt(I2PTunnel.port),
props);

View File

@ -26,16 +26,19 @@ public abstract class I2PTunnelTask implements EventDispatcher {
// I2PTunnelTask(name, (EventDispatcher)null);
//}
protected I2PTunnelTask(String name, EventDispatcher notifyThis) {
protected I2PTunnelTask(String name, EventDispatcher notifyThis, I2PTunnel tunnel) {
attachEventDispatcher(notifyThis);
this.name = name;
this.id = -1;
this.tunnel = tunnel;
}
/** for apps that use multiple I2PTunnel instances */
public void setTunnel(I2PTunnel pTunnel) {
tunnel = pTunnel;
}
public I2PTunnel getTunnel() { return tunnel; }
public int getId() {
return this.id;

View File

@ -47,15 +47,15 @@ public class I2Ping extends I2PTunnelTask implements Runnable {
// I2Ping(cmd, l, (EventDispatcher)null);
//}
public I2Ping(String cmd, Logging l, boolean ownDest, EventDispatcher notifyThis) {
super("I2Ping [" + cmd + "]", notifyThis);
public I2Ping(String cmd, Logging l, boolean ownDest, EventDispatcher notifyThis, I2PTunnel tunnel) {
super("I2Ping [" + cmd + "]", notifyThis, tunnel);
this.l = l;
command = cmd;
synchronized (slock) {
if (ownDest) {
sockMgr = I2PTunnelClient.buildSocketManager();
sockMgr = I2PTunnelClient.buildSocketManager(tunnel);
} else {
sockMgr = I2PTunnelClient.getSocketManager();
sockMgr = I2PTunnelClient.getSocketManager(tunnel);
}
}
Thread t = new I2PThread(this);

View File

@ -10,6 +10,7 @@ import java.net.Socket;
import net.i2p.client.streaming.I2PSocket;
import net.i2p.data.Destination;
import net.i2p.i2ptunnel.I2PTunnel;
import net.i2p.i2ptunnel.I2PTunnelClientBase;
import net.i2p.i2ptunnel.I2PTunnelRunner;
import net.i2p.i2ptunnel.Logging;
@ -26,8 +27,8 @@ public class I2PSOCKSTunnel extends I2PTunnelClientBase {
// I2PSOCKSTunnel(localPort, l, ownDest, (EventDispatcher)null);
//}
public I2PSOCKSTunnel(int localPort, Logging l, boolean ownDest, EventDispatcher notifyThis) {
super(localPort, ownDest, l, notifyThis, "SOCKSHandler");
public I2PSOCKSTunnel(int localPort, Logging l, boolean ownDest, EventDispatcher notifyThis, I2PTunnel tunnel) {
super(localPort, ownDest, l, notifyThis, "SOCKSHandler", tunnel);
if (waitEventValue("openBaseClientResult").equals("error")) {
notifyEvent("openSOCKSTunnelResult", "error");

View File

@ -8,7 +8,7 @@
<target name="compile">
<mkdir dir="./build" />
<mkdir dir="./build/obj" />
<javac srcdir="./src" debug="true" destdir="./build/obj" classpath="../../../core/java/build/i2p.jar" />
<javac srcdir="./src" debug="true" target="1.1" source="1.3" deprecation="on" destdir="./build/obj" classpath="../../../core/java/build/i2p.jar" />
</target>
<target name="jar" depends="compile">
<jar destfile="./build/mstreaming.jar" basedir="./build/obj" includes="**/*.class" />

View File

@ -9,13 +9,13 @@
<target name="compile">
<mkdir dir="./build" />
<mkdir dir="./build/obj" />
<javac srcdir="./src" debug="true" destdir="./build/obj" includes="net/**/*.java" excludes="net/i2p/netmonitor/gui/**" classpath="../../../core/java/build/i2p.jar" />
<javac srcdir="./src" debug="true" target="1.1" source="1.3" deprecation="on" destdir="./build/obj" includes="net/**/*.java" excludes="net/i2p/netmonitor/gui/**" classpath="../../../core/java/build/i2p.jar" />
</target>
<target name="compileGUI" depends="builddep">
<mkdir dir="./build" />
<mkdir dir="./build/obj" />
<javac debug="true" destdir="./build/obj">
<javac debug="true" target="1.1" source="1.3" deprecation="on" destdir="./build/obj">
<src path="src/" />
<classpath path="../../../core/java/build/i2p.jar" />
<classpath path="../../jfreechart/jfreechart-0.9.17/lib/jcommon-0.9.2.jar" />

View File

@ -8,7 +8,7 @@
<target name="compile">
<mkdir dir="./build" />
<mkdir dir="./build/obj" />
<javac srcdir="./src" debug="true" destdir="./build/obj" classpath="../../../core/java/build/i2p.jar:lib/javax.servlet.jar" />
<javac srcdir="./src" debug="true" target="1.1" source="1.3" deprecation="on" destdir="./build/obj" classpath="../../../core/java/build/i2p.jar:lib/javax.servlet.jar" />
</target>
<target name="jar" depends="compile">
<war destfile="./build/phttprelay.war" webxml="web.xml">

View File

@ -0,0 +1,63 @@
#
# This Makefile is compatible with GNU Make (gmake) and should work on FreeBSD
#
#
# Your operating system
#
OS = FREEBSD
#
# Directories
#
INCDIR = inc
LIBDIR = lib
OBJDIR = obj
SRCDIR = src
#
# Programs
#
AR = ar
CC = gcc
#
# Flags
#
CFLAGS = -g -O2 -pipe -std=c99 -Wall
CFLAGS += -DOS=$(OS)
CFLAGS += -I$(INCDIR)
#
# Object files
#
OBJS = $(OBJDIR)/sam.o
#
# Build rules
#
all: depend libsam
depend:
$(CC) $(CFLAGS) -MM $(SRCDIR)/*.c > .depend
$(OBJDIR)/%.o: $(SRCDIR)/%.c
$(CC) $(CFLAGS) -o $@ -c $<
libsam: $(OBJS)
$(AR) rcs $(LIBDIR)/libsam.a $(OBJS)
#
# Cleanup rules
#
clean:
-rm -f $(LIBDIR)/libsam.a $(OBJDIR)/* .depend
tidy: clean

View File

@ -1,4 +1,5 @@
v1.20
v1.20 2004-07-11
* Ported to FreeBSD (Makefile.freebsd)
* Full winsock compatibility - all Windows functions now return appropriate
error strings

View File

@ -34,7 +34,7 @@
/*
* Operating system
*/
#define FREEBSD 0 // FreeBSD (untested)
#define FREEBSD 0 // FreeBSD
#define MINGW 1 // Windows native (Mingw)
#define LINUX 2 // Linux
#define CYGWIN 3 // Cygwin
@ -83,9 +83,10 @@
#include <winsock.h>
#else
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/select.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/types.h>
#endif
#include <assert.h>
#include <errno.h>

View File

@ -189,7 +189,7 @@ samerr_t sam_dgram_send(const sam_pubkey_t dest, const void *data, size_t size)
#ifdef NO_Z_FORMAT
SAMLOG("Invalid data send size (%u bytes)", size);
#else
SAMLOG("Invalid data send size (%z bytes)", size);
SAMLOG("Invalid data send size (%dz bytes)", size);
#endif
return SAM_TOO_BIG;
}
@ -197,7 +197,7 @@ samerr_t sam_dgram_send(const sam_pubkey_t dest, const void *data, size_t size)
snprintf(cmd, sizeof cmd, "DATAGRAM SEND DESTINATION=%s SIZE=%u\n",
dest, size);
#else
snprintf(cmd, sizeof cmd, "DATAGRAM SEND DESTINATION=%s SIZE=%z\n",
snprintf(cmd, sizeof cmd, "DATAGRAM SEND DESTINATION=%s SIZE=%dz\n",
dest, size);
#endif
sam_write(cmd, strlen(cmd));
@ -957,7 +957,7 @@ samerr_t sam_stream_send(sam_sid_t stream_id, const void *data, size_t size)
SAMLOG("Invalid data send size (%u bytes) for stream %d",
size, stream_id);
#else
SAMLOG("Invalid data send size (%z bytes) for stream %d",
SAMLOG("Invalid data send size (%dz bytes) for stream %d",
size, stream_id);
#endif
return SAM_TOO_BIG;
@ -971,7 +971,7 @@ samerr_t sam_stream_send(sam_sid_t stream_id, const void *data, size_t size)
stream_id, size);
#endif
#else
snprintf(cmd, sizeof cmd, "STREAM SEND ID=%d SIZE=%z\n",
snprintf(cmd, sizeof cmd, "STREAM SEND ID=%d SIZE=%dz\n",
stream_id, size);
#endif
sam_write(cmd, strlen(cmd));

View File

@ -11,7 +11,7 @@
<mkdir dir="./build/obj" />
<javac
srcdir="./src"
debug="true"
debug="true" target="1.1" source="1.3" deprecation="on"
destdir="./build/obj"
classpath="../../../core/java/build/i2p.jar:../../ministreaming/java/build/mstreaming.jar" />
</target>

View File

@ -7,6 +7,7 @@ import java.io.OutputStream;
import java.net.Socket;
import net.i2p.util.Log;
import net.i2p.util.Clock;
public class TestCreateSessionRaw {
private static Log _log = new Log(TestCreateSessionRaw.class);
@ -15,6 +16,7 @@ public class TestCreateSessionRaw {
testTransient(samHost, samPort, conOptions);
testNewDest(samHost, samPort, conOptions);
testOldDest(samHost, samPort, conOptions);
testFast(samHost, samPort, conOptions);
}
private static void testTransient(String host, int port, String conOptions) {
@ -36,21 +38,34 @@ public class TestCreateSessionRaw {
_log.debug("\n\nTest of subsequent contact complete\n\n");
}
private static void testFast(String host, int port, String conOptions) {
String destName = "Alice" + Math.random();
long totalTime = 0;
for (int i = 0; i < 10; i++) {
long before = Clock.getInstance().now();
testDest(host, port, conOptions, destName);
long after = Clock.getInstance().now();
long difference = after-before;
_log.debug("Time to test destination: " + difference + " \n\n");
totalTime += difference;
}
_log.debug("\n\nTime to test fast reconnection: " + totalTime + " over 10 runs");
}
private static void testDest(String host, int port, String conOptions, String destName) {
_log.info("\n\nTesting creating a new destination (should come back with 'SESSION STATUS RESULT=OK DESTINATION=someName)\n\n\n");
//_log.info("\n\nTesting creating a new destination (should come back with 'SESSION STATUS RESULT=OK DESTINATION=someName)\n\n\n");
try {
Socket s = new Socket(host, port);
OutputStream out = s.getOutputStream();
out.write("HELLO VERSION MIN=1.0 MAX=1.0\n".getBytes());
BufferedReader reader = new BufferedReader(new InputStreamReader(s.getInputStream()));
String line = reader.readLine();
_log.debug("line read for valid version: " + line);
//_log.debug("line read for valid version: " + line);
String req = "SESSION CREATE STYLE=RAW DESTINATION=" + destName + " " + conOptions + "\n";
out.write(req.getBytes());
line = reader.readLine();
_log.info("Response to creating the session with destination " + destName + ": " + line);
_log.debug("The above should contain SESSION STATUS RESULT=OK\n\n\n");
try { Thread.sleep(5*1000); } catch (InterruptedException ie) {}
_log.debug("The above should contain SESSION STATUS RESULT=OK");
s.close();
} catch (Exception e) {
_log.error("Error testing for valid version", e);
@ -60,7 +75,7 @@ public class TestCreateSessionRaw {
public static void main(String args[]) {
// "i2cp.tcp.host=www.i2p.net i2cp.tcp.port=7765";
// "i2cp.tcp.host=localhost i2cp.tcp.port=7654 tunnels.inboundDepth=0";
String conOptions = "i2cp.tcp.host=dev.i2p.net i2cp.tcp.port=7002 tunnels.inboundDepth=0";
String conOptions = "i2cp.tcp.host=dev.i2p.net i2cp.tcp.port=7002 tunnels.depthInbound=0 tunnels.depthOutbound=0";
if (args.length > 0) {
conOptions = "";
for (int i = 0; i < args.length; i++)

View File

@ -8,7 +8,7 @@
<target name="compile">
<mkdir dir="./build" />
<mkdir dir="./build/obj" />
<javac srcdir="./src" debug="true" destdir="./build/obj" includes="**/*.java" classpath="../../../core/java/build/i2p.jar" />
<javac srcdir="./src" debug="true" target="1.1" source="1.3" deprecation="on" destdir="./build/obj" includes="**/*.java" classpath="../../../core/java/build/i2p.jar" />
</target>
<target name="jar" depends="compile">
<jar destfile="./build/timestamper.jar" basedir="./build/obj" includes="**/*.class">

View File

@ -8,7 +8,7 @@
<target name="compile">
<mkdir dir="./build" />
<mkdir dir="./build/obj" />
<javac srcdir="./src:./test" debug="true" destdir="./build/obj" />
<javac srcdir="./src:./test" debug="true" target="1.1" source="1.3" deprecation="on" destdir="./build/obj" />
</target>
<target name="jar" depends="compile">
<jar destfile="./build/i2p.jar" basedir="./build/obj" includes="**/*.class" />

View File

@ -14,8 +14,8 @@ package net.i2p;
*
*/
public class CoreVersion {
public final static String ID = "$Revision: 1.9 $ $Date: 2004/06/25 14:25:33 $";
public final static String VERSION = "0.3.2";
public final static String ID = "$Revision: 1.10 $ $Date: 2004/07/07 12:58:37 $";
public final static String VERSION = "0.3.2.1";
public static void main(String args[]) {
System.out.println("I2P Core version: " + VERSION);

View File

@ -15,7 +15,7 @@
<target name="compile">
<mkdir dir="./build" />
<mkdir dir="./build/obj" />
<javac srcdir="./src" debug="true" destdir="./build/obj" />
<javac srcdir="./src" debug="true" target="1.1" source="1.3" deprecation="on" destdir="./build/obj" />
</target>
<target name="jar" depends="installer, guiinstaller" />
<target name="fetchseeds" depends="compile">

View File

@ -79,7 +79,7 @@ public class FetchSeeds {
public static void main(String[] args) {
switch (args.length) {
case 1:
fetchSeeds(new File(args[0]), "http://i2p.dnsalias.net/i2pdb/");
fetchSeeds(new File(args[0]), "http://dev.i2p.net/i2pdb/");
return;
case 2:
fetchSeeds(new File(args[0]), args[1]);
@ -93,7 +93,7 @@ public class FetchSeeds {
System.out.println("Usage: FetchSeeds <outDir>");
System.out.println(" or FetchSeeds <outDir> <seedURL>");
System.out.println(" or FetchSeeds <outDir> <seedURL> <secondsBetweenFetch>");
System.out.println("The default seedURL is http://i2p.dnsalias.net/i2pdb/");
System.out.println("The default seedURL is http://dev.i2p.net/i2pdb/");
return;
}
}

View File

@ -325,6 +325,10 @@ public abstract class Install {
_i2cpPort = ((Integer)_answers.get("i2cpPort")).intValue();
_inBPS = ((Integer)_answers.get("inBPS")).intValue();
_outBPS = ((Integer)_answers.get("outBPS")).intValue();
long num = new java.util.Random().nextLong();
if (num < 0)
num = 0 - num;
_answers.put("timestamperPassword", new Long(num));
}
private void useTemplate(String templateName, File destFile) {

View File

@ -1,3 +1,3 @@
cd ##_scripts_installdir##
java -jar lib\fetchseeds.jar netDb
java -jar lib\fetchseeds.jar netDb http://dev.i2p.net/i2pdb/
pause

View File

@ -1,4 +1,4 @@
#!/bin/sh
cd ##_scripts_installdir##
java -jar lib/fetchseeds.jar netDb
java -jar lib/fetchseeds.jar netDb http://dev.i2p.net/i2pdb/
echo Router network database reseeded

View File

@ -125,13 +125,13 @@ tunnels.tunnelDuration=600000
clientApp.0.main=net.i2p.time.Timestamper
clientApp.0.name=Timestamper
clientApp.0.onBoot=true
clientApp.0.args=http://localhost:7655/setTime?putTheValueFromBelowHere pool.ntp.org pool.ntp.org pool.ntp.org
clientApp.0.args=http://localhost:7655/setTime?##timestamperPassword## pool.ntp.org pool.ntp.org pool.ntp.org
# The admin time passphrase, used to prevent unauthorized people from updating your
# routers time. The value should be included in the timestamper's args above,
# otherwise it wont honor timestamp updates. You shouldnt include any spaces or funky
# characters - just pick some random numbers.
adminTimePassphrase=pleaseSetSomeValueHere
adminTimePassphrase=##timestamperPassword##
# SAM bridge (a simplified socket based protocol for using I2P - listens on port 7656. see
# the specs at http://www.i2p.net/node/view/144 for more info)

View File

@ -8,7 +8,7 @@
<target name="compile">
<mkdir dir="./build" />
<mkdir dir="./build/obj" />
<javac srcdir="./src:./test" debug="true" destdir="./build/obj" classpath="../../core/java/build/i2p.jar" />
<javac srcdir="./src:./test" debug="true" target="1.1" source="1.3" deprecation="on" destdir="./build/obj" classpath="../../core/java/build/i2p.jar" />
</target>
<target name="jar" depends="compile">
<jar destfile="./build/router.jar" basedir="./build/obj" includes="**/*.class" />

View File

@ -114,6 +114,9 @@ public class I2NPMessageReader {
public void run() {
while (_stayAlive) {
while (_doRun) {
while (!_context.throttle().acceptNetworkMessage()) {
try { Thread.sleep(500 + _context.random().nextInt(512)); } catch (InterruptedException ie) {}
}
// do read
try {
I2NPMessage msg = _handler.readMessage(_stream);

View File

@ -8,6 +8,9 @@ package net.i2p.router;
*
*/
import java.io.IOException;
import java.io.OutputStream;
import net.i2p.data.Destination;
import net.i2p.data.Hash;
import net.i2p.data.LeaseSet;
@ -67,7 +70,7 @@ public abstract class ClientManagerFacade implements Service {
*
*/
public abstract SessionConfig getClientSessionConfig(Destination dest);
public String renderStatusHTML() { return ""; }
public void renderStatusHTML(OutputStream out) throws IOException { }
}
class DummyClientManagerFacade extends ClientManagerFacade {

View File

@ -8,6 +8,9 @@ package net.i2p.router;
*
*/
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashSet;
import java.util.Set;
@ -19,7 +22,7 @@ import java.util.Set;
public abstract class CommSystemFacade implements Service {
public abstract void processMessage(OutNetMessage msg);
public String renderStatusHTML() { return ""; }
public void renderStatusHTML(OutputStream out) throws IOException { }
/** Create the set of RouterAddress structures based on the router's config */
public Set createAddresses() { return new HashSet(); }

View File

@ -131,8 +131,10 @@ public class InNetMessagePool {
_log.info("Dropping unhandled delivery status message created " + timeSinceSent + "ms ago: " + msg);
_context.statManager().addRateData("inNetPool.droppedDeliveryStatusDelay", timeSinceSent, timeSinceSent);
} else {
if (_log.shouldLog(Log.ERROR))
_log.error("Message " + messageBody + " was not handled by a HandlerJobBuilder - DROPPING: "
if (_log.shouldLog(Log.WARN))
_log.warn("Message " + messageBody + " expiring on "
+ (messageBody != null ? (messageBody.getMessageExpiration()+"") : " [unknown]")
+ " was not handled by a HandlerJobBuilder - DROPPING: "
+ msg, new Exception("DROPPED MESSAGE"));
_context.statManager().addRateData("inNetPool.dropped", 1, 0);
}

View File

@ -8,6 +8,9 @@ package net.i2p.router;
*
*/
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
@ -186,6 +189,26 @@ public class JobQueue {
return;
}
public void timingUpdated() {
synchronized (_timedJobs) {
_timedJobs.notifyAll();
}
}
public int getReadyCount() {
synchronized (_readyJobs) {
return _readyJobs.size();
}
}
public long getMaxLag() {
synchronized (_readyJobs) {
if (_readyJobs.size() <= 0) return 0;
// first job is the one that has been waiting the longest
long startAfter = ((Job)_readyJobs.get(0)).getTiming().getStartAfter();
return _context.clock().now() - startAfter;
}
}
/**
* are we so overloaded that we should drop the given job?
* This is driven both by the numReady and waiting jobs, the type of job
@ -520,7 +543,7 @@ public class JobQueue {
// the remainder are utility methods for dumping status info
////
public String renderStatusHTML() {
public void renderStatusHTML(OutputStream out) throws IOException {
ArrayList readyJobs = null;
ArrayList timedJobs = null;
ArrayList activeJobs = new ArrayList(1);
@ -539,7 +562,8 @@ public class JobQueue {
}
}
}
StringBuffer buf = new StringBuffer(20*1024);
StringBuffer buf = new StringBuffer(32*1024);
buf.append("<h2>JobQueue</h2>");
buf.append("# runners: ");
synchronized (_queueRunners) {
@ -583,13 +607,12 @@ public class JobQueue {
buf.append(new Date(j.getTiming().getStartAfter())).append("</li>\n");
}
buf.append("</ol>\n");
buf.append(getJobStats());
return buf.toString();
getJobStats(buf);
out.write(buf.toString().getBytes());
}
/** render the HTML for the job stats */
private String getJobStats() {
StringBuffer buf = new StringBuffer(16*1024);
private void getJobStats(StringBuffer buf) {
buf.append("<table border=\"1\">\n");
buf.append("<tr><td><b>Job</b></td><td><b>Runs</b></td>");
buf.append("<td><b>Time</b></td><td><b><i>Avg</i></b></td><td><b><i>Max</i></b></td><td><b><i>Min</i></b></td>");
@ -658,6 +681,5 @@ public class JobQueue {
buf.append("</tr>\n");
buf.append("</table>\n");
return buf.toString();
}
}

View File

@ -33,7 +33,15 @@ public class JobTiming implements Clock.ClockUpdateListener {
*
*/
public long getStartAfter() { return _start; }
public void setStartAfter(long startTime) { _start = startTime; }
public void setStartAfter(long startTime) {
_start = startTime;
// sure, this current job object may not already be on the queue, so
// telling the queue of the update may be irrelevent...
// but...
// ...
// who cares? this helps in the case where it is on the queue
_context.jobQueue().timingUpdated();
}
/**
* # of milliseconds after the epoch the job actually started

View File

@ -8,6 +8,9 @@ package net.i2p.router;
*
*/
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@ -44,7 +47,6 @@ public abstract class NetworkDatabaseFacade implements Service {
public abstract void publish(LeaseSet localLeaseSet);
public abstract void unpublish(LeaseSet localLeaseSet);
public abstract void fail(Hash dbEntry);
public String renderStatusHTML() { return ""; }
}
@ -84,4 +86,6 @@ class DummyNetworkDatabaseFacade extends NetworkDatabaseFacade {
public void fail(Hash dbEntry) {}
public Set findNearestRouters(Hash key, int maxNumRouters, Set peersToIgnore) { return new HashSet(_routers.values()); }
public void renderStatusHTML(OutputStream out) throws IOException {}
}

View File

@ -8,6 +8,7 @@ package net.i2p.router;
*
*/
import java.io.OutputStream;
import java.util.List;
/**
@ -29,6 +30,6 @@ public interface PeerManagerFacade extends Service {
class DummyPeerManagerFacade implements PeerManagerFacade {
public void shutdown() {}
public void startup() {}
public String renderStatusHTML() { return ""; }
public void renderStatusHTML(OutputStream out) { }
public List selectPeers(PeerSelectionCriteria criteria) { return null; }
}

View File

@ -10,6 +10,7 @@ package net.i2p.router;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.text.DecimalFormat;
import java.util.Calendar;
import java.util.Date;
@ -220,34 +221,32 @@ public class Router {
_context.inNetMessagePool().registerHandlerJobBuilder(SourceRouteReplyMessage.MESSAGE_TYPE, new SourceRouteReplyMessageHandler(_context));
}
public String renderStatusHTML() {
StringBuffer buf = new StringBuffer();
buf.append("<html><head><title>I2P Router Console</title></head><body>\n");
buf.append("<h1>Router console</h1>\n");
buf.append("<i><a href=\"/routerConsole.html\">console</a> | <a href=\"/routerStats.html\">stats</a></i><br>\n");
buf.append("<form action=\"/routerConsole.html\">");
buf.append("<select name=\"go\" onChange='location.href=this.value'>");
buf.append("<option value=\"/routerConsole.html#bandwidth\">Bandwidth</option>\n");
buf.append("<option value=\"/routerConsole.html#clients\">Clients</option>\n");
buf.append("<option value=\"/routerConsole.html#transports\">Transports</option>\n");
buf.append("<option value=\"/routerConsole.html#profiles\">Peer Profiles</option>\n");
buf.append("<option value=\"/routerConsole.html#tunnels\">Tunnels</option>\n");
buf.append("<option value=\"/routerConsole.html#jobs\">Jobs</option>\n");
buf.append("<option value=\"/routerConsole.html#shitlist\">Shitlist</option>\n");
buf.append("<option value=\"/routerConsole.html#pending\">Pending messages</option>\n");
buf.append("<option value=\"/routerConsole.html#netdb\">Network Database</option>\n");
buf.append("<option value=\"/routerConsole.html#logs\">Log messages</option>\n");
buf.append("</select>");
buf.append("</form>");
buf.append("<form action=\"/shutdown\" method=\"GET\">");
buf.append("<b>Shut down the router:</b>");
buf.append("<input type=\"password\" name=\"password\" size=\"8\" />");
buf.append("<input type=\"submit\" value=\"shutdown!\" />");
buf.append("</form>");
buf.append("<hr />\n");
public void renderStatusHTML(OutputStream out) throws IOException {
out.write(("<html><head><title>I2P Router Console</title></head><body>\n" +
"<h1>Router console</h1>\n" +
"<i><a href=\"/routerConsole.html\">console</a> | <a href=\"/routerStats.html\">stats</a></i><br>\n" +
"<form action=\"/routerConsole.html\">" +
"<select name=\"go\" onChange='location.href=this.value'>" +
"<option value=\"/routerConsole.html#bandwidth\">Bandwidth</option>\n" +
"<option value=\"/routerConsole.html#clients\">Clients</option>\n" +
"<option value=\"/routerConsole.html#transports\">Transports</option>\n" +
"<option value=\"/routerConsole.html#profiles\">Peer Profiles</option>\n" +
"<option value=\"/routerConsole.html#tunnels\">Tunnels</option>\n" +
"<option value=\"/routerConsole.html#jobs\">Jobs</option>\n" +
"<option value=\"/routerConsole.html#shitlist\">Shitlist</option>\n" +
"<option value=\"/routerConsole.html#pending\">Pending messages</option>\n" +
"<option value=\"/routerConsole.html#netdb\">Network Database</option>\n" +
"<option value=\"/routerConsole.html#logs\">Log messages</option>\n" +
"</select>" +"</form>" +
"<form action=\"/shutdown\" method=\"GET\">" +
"<b>Shut down the router:</b>" +
"<input type=\"password\" name=\"password\" size=\"8\" />" +
"<input type=\"submit\" value=\"shutdown!\" />" +
"</form>" +
"<hr />\n").getBytes());
StringBuffer buf = new StringBuffer(32*1024);
if ( (_routerInfo != null) && (_routerInfo.getIdentity() != null) )
buf.append("<b>Router: </b> ").append(_routerInfo.getIdentity().getHash().toBase64()).append("<br />\n");
buf.append("<b>As of: </b> ").append(new Date(_context.clock().now())).append(" (uptime: ").append(DataHelper.formatDuration(getUptime())).append(") <br />\n");
@ -352,24 +351,43 @@ public class Router {
buf.append("trying to transfer data. Lifetime averages count how many elephants there are on the moon [like anyone reads this text]</i>");
buf.append("\n");
buf.append(_context.bandwidthLimiter().renderStatusHTML());
out.write(buf.toString().getBytes());
_context.bandwidthLimiter().renderStatusHTML(out);
buf.append("<hr /><a name=\"clients\"> </a>\n");
buf.append(_context.clientManager().renderStatusHTML());
buf.append("\n<hr /><a name=\"transports\"> </a>\n");
buf.append(_context.commSystem().renderStatusHTML());
buf.append("\n<hr /><a name=\"profiles\"> </a>\n");
buf.append(_context.peerManager().renderStatusHTML());
buf.append("\n<hr /><a name=\"tunnels\"> </a>\n");
buf.append(_context.tunnelManager().renderStatusHTML());
buf.append("\n<hr /><a name=\"jobs\"> </a>\n");
buf.append(_context.jobQueue().renderStatusHTML());
buf.append("\n<hr /><a name=\"shitlist\"> </a>\n");
buf.append(_context.shitlist().renderStatusHTML());
buf.append("\n<hr /><a name=\"pending\"> </a>\n");
buf.append(_context.messageRegistry().renderStatusHTML());
buf.append("\n<hr /><a name=\"netdb\"> </a>\n");
buf.append(_context.netDb().renderStatusHTML());
out.write("<hr /><a name=\"clients\"> </a>\n".getBytes());
_context.clientManager().renderStatusHTML(out);
out.write("\n<hr /><a name=\"transports\"> </a>\n".getBytes());
_context.commSystem().renderStatusHTML(out);
out.write("\n<hr /><a name=\"profiles\"> </a>\n".getBytes());
_context.peerManager().renderStatusHTML(out);
out.write("\n<hr /><a name=\"tunnels\"> </a>\n".getBytes());
_context.tunnelManager().renderStatusHTML(out);
out.write("\n<hr /><a name=\"jobs\"> </a>\n".getBytes());
_context.jobQueue().renderStatusHTML(out);
out.write("\n<hr /><a name=\"shitlist\"> </a>\n".getBytes());
_context.shitlist().renderStatusHTML(out);
out.write("\n<hr /><a name=\"pending\"> </a>\n".getBytes());
_context.messageRegistry().renderStatusHTML(out);
out.write("\n<hr /><a name=\"netdb\"> </a>\n".getBytes());
_context.netDb().renderStatusHTML(out);
buf.setLength(0);
buf.append("\n<hr /><a name=\"logs\"> </a>\n");
List msgs = _context.logManager().getBuffer().getMostRecentMessages();
buf.append("\n<h2>Most recent console messages:</h2><table border=\"1\">\n");
@ -380,7 +398,7 @@ public class Router {
}
buf.append("</table>");
buf.append("</body></html>\n");
return buf.toString();
out.write(buf.toString().getBytes());
}
public void shutdown() {

View File

@ -49,6 +49,7 @@ public class RouterContext extends I2PAppContext {
private Shitlist _shitlist;
private MessageValidator _messageValidator;
private MessageStateMonitor _messageStateMonitor;
private RouterThrottle _throttle;
private Calculator _isFailingCalc;
private Calculator _integrationCalc;
private Calculator _speedCalc;
@ -83,6 +84,7 @@ public class RouterContext extends I2PAppContext {
_statPublisher = new StatisticsManager(this);
_shitlist = new Shitlist(this);
_messageValidator = new MessageValidator(this);
_throttle = new RouterThrottleImpl(this);
_isFailingCalc = new IsFailingCalculator(this);
_integrationCalc = new IntegrationCalculator(this);
_speedCalc = new SpeedCalculator(this);
@ -188,6 +190,11 @@ public class RouterContext extends I2PAppContext {
* well as other criteria for "validity".
*/
public MessageValidator messageValidator() { return _messageValidator; }
/**
* Component to coordinate our accepting/rejecting of requests under load
*
*/
public RouterThrottle throttle() { return _throttle; }
/** how do we rank the failure of profiles? */
public Calculator isFailingCalculator() { return _isFailingCalc; }

View File

@ -0,0 +1,34 @@
package net.i2p.router;
import net.i2p.data.Hash;
import net.i2p.data.i2np.TunnelCreateMessage;
/**
* Gatekeeper for deciding whether to throttle the further processing
* of messages through the router. This is seperate from the bandwidth
* limiting which simply makes sure the bytes transferred dont exceed the
* bytes allowed (though the router throttle should take into account the
* current bandwidth usage and limits when determining whether to accept or
* reject certain activities, such as tunnels)
*
*/
public interface RouterThrottle {
/**
* Should we accept any more data from the network for any sort of message,
* taking into account our current load, or should we simply slow down?
*
*/
public boolean acceptNetworkMessage();
/**
* Should we accept the request to participate in the given tunnel,
* taking into account our current load and bandwidth usage commitments?
*
*/
public boolean acceptTunnelRequest(TunnelCreateMessage msg);
/**
* Should we accept the netDb lookup message, replying either with the
* value or some closer peers, or should we simply drop it due to overload?
*
*/
public boolean acceptNetDbLookupRequest(Hash key);
}

View File

@ -0,0 +1,95 @@
package net.i2p.router;
import net.i2p.data.Hash;
import net.i2p.data.i2np.TunnelCreateMessage;
import net.i2p.stat.Rate;
import net.i2p.util.Log;
/**
* Simple throttle that basically stops accepting messages or nontrivial
* requests if the jobQueue lag is too large.
*
*/
class RouterThrottleImpl implements RouterThrottle {
private RouterContext _context;
private Log _log;
/**
* arbitrary hard limit of 2 seconds - if its taking this long to get
* to a job, we're congested.
*
*/
private static int JOB_LAG_LIMIT = 2000;
/**
* Arbitrary hard limit - if we throttle our network connection this many
* times in the previous 10-20 minute period, don't accept requests to
* participate in tunnels.
*
*/
private static int THROTTLE_EVENT_LIMIT = 300;
public RouterThrottleImpl(RouterContext context) {
_context = context;
_log = context.logManager().getLog(RouterThrottleImpl.class);
_context.statManager().createRateStat("router.throttleNetworkCause", "How lagged the jobQueue was when an I2NP was throttled", "Throttle", new long[] { 60*1000, 10*60*1000, 60*60*1000, 24*60*60*1000 });
_context.statManager().createRateStat("router.throttleNetDbCause", "How lagged the jobQueue was when a networkDb request was throttled", "Throttle", new long[] { 60*1000, 10*60*1000, 60*60*1000, 24*60*60*1000 });
_context.statManager().createRateStat("router.throttleTunnelCause", "How lagged the jobQueue was when a tunnel request was throttled", "Throttle", new long[] { 60*1000, 10*60*1000, 60*60*1000, 24*60*60*1000 });
_context.statManager().createRateStat("tunnel.bytesAllocatedAtAccept", "How many bytes had been 'allocated' for participating tunnels when we accepted a request?", "Tunnels", new long[] { 10*60*1000, 60*60*1000, 24*60*60*1000 });
}
public boolean acceptNetworkMessage() {
long lag = _context.jobQueue().getMaxLag();
if (lag > JOB_LAG_LIMIT) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Throttling network reader, as the job lag is " + lag);
_context.statManager().addRateData("router.throttleNetworkCause", lag, lag);
return false;
} else {
return true;
}
}
public boolean acceptNetDbLookupRequest(Hash key) {
long lag = _context.jobQueue().getMaxLag();
if (lag > JOB_LAG_LIMIT) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Refusing netDb request, as the job lag is " + lag);
_context.statManager().addRateData("router.throttleNetDbCause", lag, lag);
return false;
} else {
return true;
}
}
public boolean acceptTunnelRequest(TunnelCreateMessage msg) {
long lag = _context.jobQueue().getMaxLag();
Rate throttleRate = _context.statManager().getRate("router.throttleNetworkCause").getRate(10*60*1000);
long throttleEvents = throttleRate.getCurrentEventCount() + throttleRate.getLastEventCount();
if (throttleEvents > THROTTLE_EVENT_LIMIT) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Refusing tunnel request with the job lag of " + lag
+ " since there have been " + throttleEvents
+ " throttle events in the last 15 minutes or so");
_context.statManager().addRateData("router.throttleTunnelCause", lag, lag);
return false;
}
// ok, we're not hosed, but can we handle the bandwidth requirements
// of another tunnel?
double msgsPerTunnel = _context.statManager().getRate("tunnel.participatingMessagesProcessed").getRate(10*60*1000).getAverageValue();
double bytesPerMsg = _context.statManager().getRate("tunnel.relayMessageSize").getRate(10*60*1000).getAverageValue();
double bytesPerTunnel = msgsPerTunnel * bytesPerMsg;
int numTunnels = _context.tunnelManager().getParticipatingCount();
double bytesAllocated = (numTunnels + 1) * bytesPerTunnel;
_context.statManager().addRateData("tunnel.bytesAllocatedAtAccept", (long)bytesAllocated, msg.getTunnelDurationSeconds()*1000);
// todo: um, throttle (include bw usage of the netDb, our own tunnels, the clients,
// and check to see that they are less than the bandwidth limits
if (_log.shouldLog(Log.DEBUG))
_log.debug("Accepting a new tunnel request (now allocating " + bytesAllocated + " bytes across " + numTunnels
+ " tunnels with lag of " + lag + " and " + throttleEvents + " throttle events)");
return true;
}
}

View File

@ -15,8 +15,8 @@ import net.i2p.CoreVersion;
*
*/
public class RouterVersion {
public final static String ID = "$Revision: 1.8 $ $Date: 2004/06/25 14:25:33 $";
public final static String VERSION = "0.3.2";
public final static String ID = "$Revision: 1.9 $ $Date: 2004/07/07 12:58:38 $";
public final static String VERSION = "0.3.2.1";
public static void main(String args[]) {
System.out.println("I2P Router version: " + VERSION);
System.out.println("Router ID: " + RouterVersion.ID);

View File

@ -8,6 +8,9 @@ package net.i2p.router;
*
*/
import java.io.IOException;
import java.io.OutputStream;
/**
* Define the manageable service interface for the subsystems in the I2P router
*
@ -28,5 +31,5 @@ public interface Service {
*/
public void shutdown();
public String renderStatusHTML();
public void renderStatusHTML(OutputStream out) throws IOException;
}

View File

@ -4,6 +4,7 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import net.i2p.crypto.PersistentSessionKeyManager;
import net.i2p.crypto.SessionKeyManager;
@ -89,7 +90,7 @@ public class SessionKeyPersistenceHelper implements Service {
}
}
public String renderStatusHTML() { return ""; }
public void renderStatusHTML(OutputStream out) { }
private class SessionKeyWriterJob extends JobImpl {
public SessionKeyWriterJob() {

View File

@ -8,6 +8,9 @@ package net.i2p.router;
*
*/
import java.io.IOException;
import java.io.OutputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
@ -79,8 +82,8 @@ public class Shitlist {
}
}
public String renderStatusHTML() {
StringBuffer buf = new StringBuffer();
public void renderStatusHTML(OutputStream out) throws IOException {
StringBuffer buf = new StringBuffer(1024);
buf.append("<h2>Shitlist</h2>");
Map shitlist = new HashMap();
synchronized (_shitlist) {
@ -99,6 +102,6 @@ public class Shitlist {
buf.append("<li><b>").append(key.toBase64()).append("</b> was shitlisted on ").append(shitDate).append("</li>\n");
}
buf.append("</ul>\n");
return buf.toString();
out.write(buf.toString().getBytes());
}
}

View File

@ -8,6 +8,9 @@ package net.i2p.router;
*
*/
import java.io.IOException;
import java.io.OutputStream;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.Locale;
@ -106,7 +109,7 @@ public class StatisticsManager implements Service {
includeRate("crypto.garlic.decryptFail", stats, new long[] { 60*60*1000, 24*60*60*1000 });
includeRate("tunnel.unknownTunnelTimeLeft", stats, new long[] { 60*60*1000, 24*60*60*1000 });
includeRate("jobQueue.readyJobs", stats, new long[] { 60*1000, 60*60*1000 });
includeRate("jobQueue.droppedJobs", stats, new long[] { 60*60*1000, 24*60*60*1000 });
//includeRate("jobQueue.droppedJobs", stats, new long[] { 60*60*1000, 24*60*60*1000 });
includeRate("inNetPool.dropped", stats, new long[] { 60*60*1000, 24*60*60*1000 });
includeRate("tunnel.participatingTunnels", stats, new long[] { 5*60*1000, 60*60*1000 });
includeRate("tunnel.testSuccessTime", stats, new long[] { 60*60*1000l, 24*60*60*1000l });
@ -114,6 +117,7 @@ public class StatisticsManager implements Service {
includeRate("tunnel.inboundMessagesProcessed", stats, new long[] { 10*60*1000, 60*60*1000 });
includeRate("tunnel.participatingMessagesProcessed", stats, new long[] { 10*60*1000, 60*60*1000 });
includeRate("tunnel.expiredAfterAcceptTime", stats, new long[] { 10*60*1000l, 60*60*1000l, 24*60*60*1000l });
includeRate("tunnel.bytesAllocatedAtAccept", stats, new long[] { 10*60*1000l, 60*60*1000l, 24*60*60*1000l });
includeRate("netDb.lookupsReceived", stats, new long[] { 5*60*1000, 60*60*1000 });
includeRate("netDb.lookupsHandled", stats, new long[] { 5*60*1000, 60*60*1000 });
includeRate("netDb.lookupsMatched", stats, new long[] { 5*60*1000, 60*60*1000 });
@ -121,16 +125,17 @@ public class StatisticsManager implements Service {
includeRate("netDb.successPeers", stats, new long[] { 60*60*1000 });
includeRate("netDb.failedPeers", stats, new long[] { 60*60*1000 });
includeRate("netDb.searchCount", stats, new long[] { 3*60*60*1000});
includeRate("inNetMessage.timeToDiscard", stats, new long[] { 5*60*1000, 10*60*1000, 60*60*1000 });
includeRate("outNetMessage.timeToDiscard", stats, new long[] { 5*60*1000, 10*60*1000, 60*60*1000 });
//includeRate("inNetMessage.timeToDiscard", stats, new long[] { 5*60*1000, 10*60*1000, 60*60*1000 });
//includeRate("outNetMessage.timeToDiscard", stats, new long[] { 5*60*1000, 10*60*1000, 60*60*1000 });
includeRate("router.throttleNetworkCause", stats, new long[] { 10*60*1000, 60*60*1000 });
includeRate("transport.receiveMessageSize", stats, new long[] { 5*60*1000, 60*60*1000 });
includeRate("transport.sendMessageSize", stats, new long[] { 5*60*1000, 60*60*1000 });
includeRate("transport.sendMessageSmall", stats, new long[] { 5*60*1000, 60*60*1000 });
includeRate("transport.sendMessageMedium", stats, new long[] { 5*60*1000, 60*60*1000 });
includeRate("transport.sendMessageLarge", stats, new long[] { 5*60*1000, 60*60*1000 });
includeRate("transport.receiveMessageSmall", stats, new long[] { 5*60*1000, 60*60*1000 });
includeRate("transport.receiveMessageMedium", stats, new long[] { 5*60*1000, 60*60*1000 });
includeRate("transport.receiveMessageLarge", stats, new long[] { 5*60*1000, 60*60*1000 });
//includeRate("transport.sendMessageSize", stats, new long[] { 5*60*1000, 60*60*1000 });
//includeRate("transport.sendMessageSmall", stats, new long[] { 5*60*1000, 60*60*1000 });
//includeRate("transport.sendMessageMedium", stats, new long[] { 5*60*1000, 60*60*1000 });
//includeRate("transport.sendMessageLarge", stats, new long[] { 5*60*1000, 60*60*1000 });
//includeRate("transport.receiveMessageSmall", stats, new long[] { 5*60*1000, 60*60*1000 });
//includeRate("transport.receiveMessageMedium", stats, new long[] { 5*60*1000, 60*60*1000 });
//includeRate("transport.receiveMessageLarge", stats, new long[] { 5*60*1000, 60*60*1000 });
includeRate("client.sendAckTime", stats, new long[] { 60*60*1000, 24*60*60*1000l }, true);
stats.setProperty("stat_uptime", DataHelper.formatDuration(_context.router().getUptime()));
stats.setProperty("stat__rateKey", "avg;maxAvg;pctLifetime;[sat;satLim;maxSat;maxSatLim;][num;lifetimeFreq;maxFreq]");
@ -257,5 +262,5 @@ public class StatisticsManager implements Service {
private final String num(double num) { synchronized (_fmt) { return _fmt.format(num); } }
private final String pct(double num) { synchronized (_pct) { return _pct.format(num); } }
public String renderStatusHTML() { return ""; }
public void renderStatusHTML(OutputStream out) { }
}

View File

@ -60,4 +60,7 @@ public interface TunnelManagerFacade extends Service {
*
*/
boolean isInUse(Hash peer);
/** how many tunnels are we participating in? */
public int getParticipatingCount();
}

View File

@ -1,5 +1,8 @@
package net.i2p.router.admin;
import java.io.IOException;
import java.io.OutputStream;
import net.i2p.router.RouterContext;
import net.i2p.router.Service;
import net.i2p.util.I2PThread;
@ -18,7 +21,7 @@ public class AdminManager implements Service {
_log = context.logManager().getLog(AdminManager.class);
}
public String renderStatusHTML() { return ""; }
public void renderStatusHTML(OutputStream out) { }
public void shutdown() {
if (_listener != null) {

View File

@ -47,7 +47,15 @@ class AdminRunner implements Runnable {
if (command.indexOf("favicon") >= 0) {
reply(out, "this is not a website");
} else if (command.indexOf("routerStats.html") >= 0) {
reply(out, _generator.generateStatsPage());
try {
out.write("HTTP/1.1 200 OK\nConnection: close\nCache-control: no-cache\nContent-type: text/html\n\n".getBytes());
_generator.generateStatsPage(out);
out.close();
} catch (IOException ioe) {
if (_log.shouldLog(Log.WARN))
_log.warn("Error writing out the admin reply");
throw ioe;
}
} else if (command.indexOf("/profile/") >= 0) {
replyText(out, getProfile(command));
} else if (command.indexOf("setTime") >= 0) {
@ -60,7 +68,15 @@ class AdminRunner implements Runnable {
} else if (command.indexOf("/shutdown") >= 0) {
reply(out, shutdown(command));
} else if (true || command.indexOf("routerConsole.html") > 0) {
reply(out, _context.router().renderStatusHTML());
try {
out.write("HTTP/1.1 200 OK\nConnection: close\nCache-control: no-cache\nContent-type: text/html\n\n".getBytes());
_context.router().renderStatusHTML(out);
out.close();
} catch (IOException ioe) {
if (_log.shouldLog(Log.WARN))
_log.warn("Error writing out the admin reply");
throw ioe;
}
}
}

View File

@ -29,183 +29,180 @@ public class StatsGenerator {
_log = context.logManager().getLog(StatsGenerator.class);
}
public String generateStatsPage() {
ByteArrayOutputStream baos = new ByteArrayOutputStream(32*1024);
try {
generateStatsPage(baos);
} catch (IOException ioe) {
_log.error("Error generating stats", ioe);
}
return new String(baos.toByteArray());
}
public void generateStatsPage(OutputStream out) throws IOException {
PrintWriter pw = new PrintWriter(out);
pw.println("<html><head><title>I2P Router Stats</title></head><body>");
pw.println("<h1>Router statistics</h1>");
pw.println("<i><a href=\"/routerConsole.html\">console</a> | <a href=\"/routerStats.html\">stats</a></i><hr />");
StringBuffer buf = new StringBuffer(16*1024);
buf.append("<html><head><title>I2P Router Stats</title></head><body>");
buf.append("<h1>Router statistics</h1>");
buf.append("<i><a href=\"/routerConsole.html\">console</a> | <a href=\"/routerStats.html\">stats</a></i><hr />");
buf.append("<form action=\"/routerStats.html\">");
buf.append("<select name=\"go\" onChange='location.href=this.value'>");
out.write(buf.toString().getBytes());
buf.setLength(0);
Map groups = _context.statManager().getStatsByGroup();
pw.println("<form action=\"/routerStats.html\">");
pw.println("<select name=\"go\" onChange='location.href=this.value'>");
for (Iterator iter = groups.keySet().iterator(); iter.hasNext(); ) {
String group = (String)iter.next();
Set stats = (Set)groups.get(group);
pw.print("<option value=\"/routerStats.html#");
pw.print(group);
pw.print("\">");
pw.print(group);
pw.println("</option>\n");
buf.append("<option value=\"/routerStats.html#").append(group).append("\">");
buf.append(group).append("</option>\n");
for (Iterator statIter = stats.iterator(); statIter.hasNext(); ) {
String stat = (String)statIter.next();
pw.print("<option value=\"/routerStats.html#");
pw.print(stat);
pw.print("\">...");
pw.print(stat);
pw.println("</option>\n");
buf.append("<option value=\"/routerStats.html#");
buf.append(stat);
buf.append("\">...");
buf.append(stat);
buf.append("</option>\n");
}
out.write(buf.toString().getBytes());
buf.setLength(0);
}
pw.println("</select>");
pw.println("</form>");
buf.append("</select>");
buf.append("</form>");
pw.print("Statistics gathered during this router's uptime (");
buf.append("Statistics gathered during this router's uptime (");
long uptime = _context.router().getUptime();
pw.print(DataHelper.formatDuration(uptime));
pw.println("). The data gathered is quantized over a 1 minute period, so should just be used as an estimate<p />");
buf.append(DataHelper.formatDuration(uptime));
buf.append("). The data gathered is quantized over a 1 minute period, so should just be used as an estimate<p />");
out.write(buf.toString().getBytes());
buf.setLength(0);
for (Iterator iter = groups.keySet().iterator(); iter.hasNext(); ) {
String group = (String)iter.next();
Set stats = (Set)groups.get(group);
pw.print("<h2><a name=\"");
pw.print(group);
pw.print("\">");
pw.print(group);
pw.println("</a></h2>");
pw.println("<ul>");
buf.append("<h2><a name=\"");
buf.append(group);
buf.append("\">");
buf.append(group);
buf.append("</a></h2>");
buf.append("<ul>");
out.write(buf.toString().getBytes());
buf.setLength(0);
for (Iterator statIter = stats.iterator(); statIter.hasNext(); ) {
String stat = (String)statIter.next();
pw.print("<li><b><a name=\"");
pw.print(stat);
pw.print("\">");
pw.print(stat);
pw.println("</a></b><br />");
buf.append("<li><b><a name=\"");
buf.append(stat);
buf.append("\">");
buf.append(stat);
buf.append("</a></b><br />");
if (_context.statManager().isFrequency(stat))
renderFrequency(stat, pw);
renderFrequency(stat, buf);
else
renderRate(stat, pw);
renderRate(stat, buf);
out.write(buf.toString().getBytes());
buf.setLength(0);
}
pw.println("</ul><hr />");
out.write("</ul><hr />".getBytes());
}
pw.println("</body></html>");
pw.flush();
out.write("</body></html>".getBytes());
}
private void renderFrequency(String name, PrintWriter pw) throws IOException {
private void renderFrequency(String name, StringBuffer buf) {
FrequencyStat freq = _context.statManager().getFrequency(name);
pw.print("<i>");
pw.print(freq.getDescription());
pw.println("</i><br />");
buf.append("<i>");
buf.append(freq.getDescription());
buf.append("</i><br />");
long periods[] = freq.getPeriods();
Arrays.sort(periods);
for (int i = 0; i < periods.length; i++) {
renderPeriod(pw, periods[i], "frequency");
renderPeriod(buf, periods[i], "frequency");
Frequency curFreq = freq.getFrequency(periods[i]);
pw.print(" <i>avg per period:</i> (");
pw.print(num(curFreq.getAverageEventsPerPeriod()));
pw.print(", max ");
pw.print(num(curFreq.getMaxAverageEventsPerPeriod()));
buf.append(" <i>avg per period:</i> (");
buf.append(num(curFreq.getAverageEventsPerPeriod()));
buf.append(", max ");
buf.append(num(curFreq.getMaxAverageEventsPerPeriod()));
if ( (curFreq.getMaxAverageEventsPerPeriod() > 0) && (curFreq.getAverageEventsPerPeriod() > 0) ) {
pw.print(", current is ");
pw.print(pct(curFreq.getAverageEventsPerPeriod()/curFreq.getMaxAverageEventsPerPeriod()));
pw.print(" of max");
buf.append(", current is ");
buf.append(pct(curFreq.getAverageEventsPerPeriod()/curFreq.getMaxAverageEventsPerPeriod()));
buf.append(" of max");
}
pw.print(")");
buf.append(")");
//buf.append(" <i>avg interval between updates:</i> (").append(num(curFreq.getAverageInterval())).append("ms, min ");
//buf.append(num(curFreq.getMinAverageInterval())).append("ms)");
pw.print(" <i>strict average per period:</i> ");
pw.print(num(curFreq.getStrictAverageEventsPerPeriod()));
pw.print(" events (averaged ");
pw.print(" using the lifetime of ");
pw.print(num(curFreq.getEventCount()));
pw.print(" events)");
pw.println("<br />");
buf.append(" <i>strict average per period:</i> ");
buf.append(num(curFreq.getStrictAverageEventsPerPeriod()));
buf.append(" events (averaged ");
buf.append(" using the lifetime of ");
buf.append(num(curFreq.getEventCount()));
buf.append(" events)");
buf.append("<br />");
}
pw.println("<br />");
buf.append("<br />");
}
private void renderRate(String name, PrintWriter pw) throws IOException {
private void renderRate(String name, StringBuffer buf) {
RateStat rate = _context.statManager().getRate(name);
pw.print("<i>");
pw.print(rate.getDescription());
pw.println("</i><br />");
buf.append("<i>");
buf.append(rate.getDescription());
buf.append("</i><br />");
long periods[] = rate.getPeriods();
Arrays.sort(periods);
pw.println("<ul>");
buf.append("<ul>");
for (int i = 0; i < periods.length; i++) {
pw.println("<li>");
renderPeriod(pw, periods[i], "rate");
buf.append("<li>");
renderPeriod(buf, periods[i], "rate");
Rate curRate = rate.getRate(periods[i]);
pw.print( "<i>avg value:</i> (");
pw.print(num(curRate.getAverageValue()));
pw.print(" peak ");
pw.print(num(curRate.getExtremeAverageValue()));
pw.print(", [");
pw.print(pct(curRate.getPercentageOfExtremeValue()));
pw.print(" of max");
pw.print(", and ");
pw.print(pct(curRate.getPercentageOfLifetimeValue()));
pw.print(" of lifetime average]");
buf.append( "<i>avg value:</i> (");
buf.append(num(curRate.getAverageValue()));
buf.append(" peak ");
buf.append(num(curRate.getExtremeAverageValue()));
buf.append(", [");
buf.append(pct(curRate.getPercentageOfExtremeValue()));
buf.append(" of max");
buf.append(", and ");
buf.append(pct(curRate.getPercentageOfLifetimeValue()));
buf.append(" of lifetime average]");
pw.print(")");
pw.print(" <i>highest total period value:</i> (");
pw.print(num(curRate.getExtremeTotalValue()));
pw.print(")");
buf.append(")");
buf.append(" <i>highest total period value:</i> (");
buf.append(num(curRate.getExtremeTotalValue()));
buf.append(")");
if (curRate.getLifetimeTotalEventTime() > 0) {
pw.print(" <i>saturation:</i> (");
pw.print(pct(curRate.getLastEventSaturation()));
pw.print(")");
pw.print(" <i>saturated limit:</i> (");
pw.print(num(curRate.getLastSaturationLimit()));
pw.print(")");
pw.print(" <i>peak saturation:</i> (");
pw.print(pct(curRate.getExtremeEventSaturation()));
pw.print(")");
pw.print(" <i>peak saturated limit:</i> (");
pw.print(num(curRate.getExtremeSaturationLimit()));
pw.print(")");
buf.append(" <i>saturation:</i> (");
buf.append(pct(curRate.getLastEventSaturation()));
buf.append(")");
buf.append(" <i>saturated limit:</i> (");
buf.append(num(curRate.getLastSaturationLimit()));
buf.append(")");
buf.append(" <i>peak saturation:</i> (");
buf.append(pct(curRate.getExtremeEventSaturation()));
buf.append(")");
buf.append(" <i>peak saturated limit:</i> (");
buf.append(num(curRate.getExtremeSaturationLimit()));
buf.append(")");
}
pw.print(" <i>events per period:</i> ");
pw.print(num(curRate.getLastEventCount()));
buf.append(" <i>events per period:</i> ");
buf.append(num(curRate.getLastEventCount()));
long numPeriods = curRate.getLifetimePeriods();
if (numPeriods > 0) {
double avgFrequency = curRate.getLifetimeEventCount() / (double)numPeriods;
double peakFrequency = curRate.getExtremeEventCount();
pw.print(" (lifetime average: ");
pw.print(num(avgFrequency));
pw.print(", peak average: ");
pw.print(num(curRate.getExtremeEventCount()));
pw.println(")");
buf.append(" (lifetime average: ");
buf.append(num(avgFrequency));
buf.append(", peak average: ");
buf.append(num(curRate.getExtremeEventCount()));
buf.append(")");
}
pw.print("</li>");
buf.append("</li>");
if (i + 1 == periods.length) {
// last one, so lets display the strict average
pw.print("<li><b>lifetime average value:</b> ");
pw.print(num(curRate.getLifetimeAverageValue()));
pw.print(" over ");
pw.print(num(curRate.getLifetimeEventCount()));
pw.println(" events<br /></li>");
buf.append("<li><b>lifetime average value:</b> ");
buf.append(num(curRate.getLifetimeAverageValue()));
buf.append(" over ");
buf.append(num(curRate.getLifetimeEventCount()));
buf.append(" events<br /></li>");
}
}
pw.print("</ul>");
pw.println("<br />");
buf.append("</ul>");
buf.append("<br />");
}
private static void renderPeriod(PrintWriter pw, long period, String name) throws IOException {
pw.print("<b>");
pw.print(DataHelper.formatDuration(period));
pw.print(" ");
pw.print(name);
pw.print(":</b> ");
private static void renderPeriod(StringBuffer buf, long period, String name) {
buf.append("<b>");
buf.append(DataHelper.formatDuration(period));
buf.append(" ");
buf.append(name);
buf.append(":</b> ");
}
private final static DecimalFormat _fmt = new DecimalFormat("###,##0.00");

View File

@ -8,6 +8,9 @@ package net.i2p.router.client;
*
*/
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@ -305,8 +308,8 @@ public class ClientManager {
}
}
public String renderStatusHTML() {
StringBuffer buf = new StringBuffer();
public void renderStatusHTML(OutputStream out) throws IOException {
StringBuffer buf = new StringBuffer(8*1024);
buf.append("<h2>Clients</h2><ul>");
Map runners = null;
synchronized (_runners) {
@ -325,7 +328,7 @@ public class ClientManager {
buf.append(runner.getLeaseSet()).append("</pre>\n");
}
buf.append("</ul>\n");
return buf.toString();
out.write(buf.toString().getBytes());
}
public void messageReceived(ClientMessage msg) {

View File

@ -8,6 +8,9 @@ package net.i2p.router.client;
*
*/
import java.io.IOException;
import java.io.OutputStream;
import net.i2p.data.Destination;
import net.i2p.data.Hash;
import net.i2p.data.LeaseSet;
@ -148,12 +151,8 @@ public class ClientManagerFacadeImpl extends ClientManagerFacade {
}
}
public String renderStatusHTML() {
public void renderStatusHTML(OutputStream out) throws IOException {
if (_manager != null)
return _manager.renderStatusHTML();
else {
_log.error("Null manager on renderStatusHTML!");
return null;
}
_manager.renderStatusHTML(out);
}
}

View File

@ -52,7 +52,7 @@ public class HandleTunnelMessageJob extends JobImpl {
_handler = new I2NPMessageHandler(ctx);
ctx.statManager().createRateStat("tunnel.unknownTunnelTimeLeft", "How much time is left on tunnel messages we receive that are for unknown tunnels?", "Tunnels", new long[] { 5*60*1000l, 60*60*1000l, 24*60*60*1000l });
ctx.statManager().createRateStat("tunnel.gatewayMessageSize", "How large are the messages we are forwarding on as an inbound gateway?", "Tunnels", new long[] { 60*1000l, 60*60*1000l, 24*60*60*1000l });
ctx.statManager().createRateStat("tunnel.relayMessageSize", "How large are the messages we are forwarding on as a participant in a tunnel?", "Tunnels", new long[] { 60*1000l, 60*60*1000l, 24*60*60*1000l });
ctx.statManager().createRateStat("tunnel.relayMessageSize", "How large are the messages we are forwarding on as a participant in a tunnel?", "Tunnels", new long[] { 60*1000l, 10*60*1000l, 60*60*1000l, 24*60*60*1000l });
ctx.statManager().createRateStat("tunnel.endpointMessageSize", "How large are the messages we are forwarding in as an outbound endpoint?", "Tunnels", new long[] { 60*1000l, 60*60*1000l, 24*60*60*1000l });
ctx.statManager().createRateStat("tunnel.expiredAfterAcceptTime", "How long after expiration do we finally start running an expired tunnel message?", "Tunnels", new long[] { 10*60*1000l, 60*60*1000l, 24*60*60*1000l });
_message = msg;

View File

@ -16,6 +16,7 @@ import net.i2p.data.i2np.SourceRouteBlock;
import net.i2p.router.HandlerJobBuilder;
import net.i2p.router.Job;
import net.i2p.router.RouterContext;
import net.i2p.util.Log;
/**
* Build a HandleDatabaseLookupMessageJob whenever a DatabaseLookupMessage arrives
@ -23,14 +24,24 @@ import net.i2p.router.RouterContext;
*/
public class DatabaseLookupMessageHandler implements HandlerJobBuilder {
private RouterContext _context;
private Log _log;
public DatabaseLookupMessageHandler(RouterContext context) {
_context = context;
_log = context.logManager().getLog(DatabaseLookupMessageHandler.class);
_context.statManager().createRateStat("netDb.lookupsReceived", "How many netDb lookups have we received?", "Network Database", new long[] { 5*60*1000l, 60*60*1000l, 24*60*60*1000l });
_context.statManager().createRateStat("netDb.lookupsDropped", "How many netDb lookups did we drop due to throttling?", "Network Database", new long[] { 5*60*1000l, 60*60*1000l, 24*60*60*1000l });
}
public Job createJob(I2NPMessage receivedMessage, RouterIdentity from, Hash fromHash, SourceRouteBlock replyBlock) {
_context.statManager().addRateData("netDb.lookupsReceived", 1, 0);
// ignore the reply block for the moment
return new HandleDatabaseLookupMessageJob(_context, (DatabaseLookupMessage)receivedMessage, from, fromHash);
if (_context.throttle().acceptNetDbLookupRequest(((DatabaseLookupMessage)receivedMessage).getSearchKey())) {
return new HandleDatabaseLookupMessageJob(_context, (DatabaseLookupMessage)receivedMessage, from, fromHash);
} else {
if (_log.shouldLog(Log.INFO))
_log.info("Dropping lookup request as throttled");
_context.statManager().addRateData("netDb.lookupsDropped", 1, 1);
return null;
}
}
}

View File

@ -11,6 +11,7 @@ package net.i2p.router.networkdb.kademlia;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
@ -605,16 +606,19 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
return routers;
}
public String renderStatusHTML() {
StringBuffer buf = new StringBuffer();
public void renderStatusHTML(OutputStream out) throws IOException {
StringBuffer buf = new StringBuffer(10*1024);
buf.append("<h2>Kademlia Network DB Contents</h2>\n");
if (!_initialized) {
buf.append("<i>Not initialized</i>\n");
return buf.toString();
out.write(buf.toString().getBytes());
return;
}
Set leases = getLeases();
buf.append("<h3>Leases</h3>\n");
buf.append("<table border=\"1\">\n");
out.write(buf.toString().getBytes());
buf.setLength(0);
for (Iterator iter = leases.iterator(); iter.hasNext(); ) {
LeaseSet ls = (LeaseSet)iter.next();
Hash key = ls.getDestination().calculateHash();
@ -625,6 +629,8 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
else
buf.append("<td valign=\"top\" align=\"left\"><b>Last sent successfully:</b> never</td></tr>");
buf.append("<tr><td valign=\"top\" align=\"left\" colspan=\"2\"><pre>\n").append(ls.toString()).append("</pre></td></tr>\n");
out.write(buf.toString().getBytes());
buf.setLength(0);
}
buf.append("</table>\n");
@ -632,6 +638,9 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
Set routers = getRouters();
buf.append("<h3>Routers</h3>\n");
buf.append("<table border=\"1\">\n");
out.write(buf.toString().getBytes());
buf.setLength(0);
for (Iterator iter = routers.iterator(); iter.hasNext(); ) {
RouterInfo ri = (RouterInfo)iter.next();
Hash key = ri.getIdentity().getHash();
@ -648,10 +657,10 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
buf.append("<td valign=\"top\" align=\"left\"><a href=\"/profile/").append(key.toBase64().substring(0, 32)).append("\">Profile</a></td></tr>");
}
buf.append("<tr><td valign=\"top\" align=\"left\" colspan=\"3\"><pre>\n").append(ri.toString()).append("</pre></td></tr>\n");
out.write(buf.toString().getBytes());
buf.setLength(0);
}
buf.append("</table>\n");
return buf.toString();
out.write("</table>\n".getBytes());
}
}

View File

@ -8,6 +8,9 @@ package net.i2p.router.peermanager;
*
*/
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
@ -124,5 +127,7 @@ class PeerManager {
return rv;
}
public String renderStatusHTML() { return _organizer.renderStatusHTML(); }
public void renderStatusHTML(OutputStream out) throws IOException {
_organizer.renderStatusHTML(out);
}
}

View File

@ -8,6 +8,9 @@ package net.i2p.router.peermanager;
*
*/
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
@ -51,5 +54,7 @@ public class PeerManagerFacadeImpl implements PeerManagerFacade {
return new ArrayList(_manager.selectPeers(criteria));
}
public String renderStatusHTML() { return _manager.renderStatusHTML(); }
public void renderStatusHTML(OutputStream out) throws IOException {
_manager.renderStatusHTML(out);
}
}

View File

@ -2,6 +2,8 @@ package net.i2p.router.peermanager;
import java.io.File;
import java.text.DecimalFormat;
import net.i2p.data.Hash;
import net.i2p.router.RouterContext;
import net.i2p.stat.RateStat;
@ -297,6 +299,8 @@ public class PeerProfile {
*/
public static void main(String args[]) {
RouterContext ctx = new RouterContext(new net.i2p.router.Router());
DecimalFormat fmt = new DecimalFormat("0,000.0");
fmt.setPositivePrefix("+");
ProfilePersistenceHelper helper = new ProfilePersistenceHelper(ctx);
try { Thread.sleep(5*1000); } catch (InterruptedException e) {}
StringBuffer buf = new StringBuffer(1024);
@ -308,9 +312,9 @@ public class PeerProfile {
}
//profile.coallesceStats();
buf.append("Peer " + profile.getPeer().toBase64()
+ ":\t Speed:\t" + profile.calculateSpeed()
+ " Reliability:\t" + profile.calculateReliability()
+ " Integration:\t" + profile.calculateIntegration()
+ ":\t Speed:\t" + fmt.format(profile.calculateSpeed())
+ " Reliability:\t" + fmt.format(profile.calculateReliability())
+ " Integration:\t" + fmt.format(profile.calculateIntegration())
+ " Active?\t" + profile.getIsActive()
+ " Failing?\t" + profile.calculateIsFailing()
+ '\n');

View File

@ -563,7 +563,7 @@ public class ProfileOrganizer {
_persistenceHelper.writeProfile(prof, out);
}
public String renderStatusHTML() {
public void renderStatusHTML(OutputStream out) throws IOException {
Set peers = selectAllPeers();
long hideBefore = _context.clock().now() - 6*60*60*1000;
@ -581,7 +581,7 @@ public class ProfileOrganizer {
int reliable = 0;
int integrated = 0;
int failing = 0;
StringBuffer buf = new StringBuffer(8*1024);
StringBuffer buf = new StringBuffer(16*1024);
buf.append("<h2>Peer Profiles</h2>\n");
buf.append("<table border=\"1\">");
buf.append("<tr>");
@ -660,7 +660,7 @@ public class ProfileOrganizer {
buf.append("<b>Speed:</b> ").append(num(_thresholdSpeedValue)).append(" (").append(fast).append(" fast peers)<br />");
buf.append("<b>Reliability:</b> ").append(num(_thresholdReliabilityValue)).append(" (").append(reliable).append(" reliable peers)<br />");
buf.append("<b>Integration:</b> ").append(num(_thresholdIntegrationValue)).append(" (").append(integrated).append(" well integrated peers)<br />");
return buf.toString();
out.write(buf.toString().getBytes());
}

View File

@ -23,34 +23,45 @@ public class ReliabilityCalculator extends Calculator {
return profile.getReliabilityBonus();
long val = 0;
val += profile.getSendSuccessSize().getRate(60*1000).getCurrentEventCount() * 5;
val += profile.getSendSuccessSize().getRate(60*1000).getLastEventCount() * 2;
val += profile.getSendSuccessSize().getRate(60*60*1000).getLastEventCount();
val += profile.getSendSuccessSize().getRate(60*60*1000).getCurrentEventCount();
val += profile.getSendSuccessSize().getRate(60*1000).getCurrentEventCount() * 20;
val += profile.getSendSuccessSize().getRate(60*1000).getLastEventCount() * 10;
val += profile.getSendSuccessSize().getRate(60*60*1000).getLastEventCount() * 1;
val += profile.getSendSuccessSize().getRate(60*60*1000).getCurrentEventCount() * 5;
val += profile.getTunnelCreateResponseTime().getRate(10*60*1000).getLastEventCount() * 5;
val += profile.getTunnelCreateResponseTime().getRate(60*60*1000).getCurrentEventCount();
val += profile.getTunnelCreateResponseTime().getRate(60*60*1000).getLastEventCount();
val -= profile.getSendFailureSize().getRate(60*1000).getLastEventCount() * 5;
val -= profile.getSendFailureSize().getRate(60*60*1000).getCurrentEventCount()*2;
val -= profile.getSendFailureSize().getRate(60*60*1000).getLastEventCount()*2;
//val -= profile.getSendFailureSize().getRate(60*1000).getLastEventCount() * 5;
//val -= profile.getSendFailureSize().getRate(60*60*1000).getCurrentEventCount()*2;
//val -= profile.getSendFailureSize().getRate(60*60*1000).getLastEventCount()*2;
val -= profile.getTunnelHistory().getRejectionRate().getRate(60*1000).getCurrentEventCount() * 10;
val -= profile.getTunnelHistory().getRejectionRate().getRate(60*1000).getLastEventCount() * 5;
val -= profile.getTunnelHistory().getRejectionRate().getRate(60*60*1000).getCurrentEventCount() * 1;
//val -= profile.getTunnelHistory().getRejectionRate().getRate(60*60*1000).getLastEventCount() * 1;
// penalize them heavily for dropping netDb requests
val -= profile.getDBHistory().getFailedLookupRate().getRate(60*1000).getCurrentEventCount() * 10;
val -= profile.getDBHistory().getFailedLookupRate().getRate(60*1000).getLastEventCount() * 5;
if (profile.getDBHistory().getFailedLookupRate().getRate(60*1000).getCurrentEventCount() > 0)
val -= 10;
if (profile.getDBHistory().getFailedLookupRate().getRate(60*1000).getLastEventCount() > 0)
val -= 5;
//val -= profile.getDBHistory().getFailedLookupRate().getRate(60*60*1000).getCurrentEventCount();
//val -= profile.getDBHistory().getFailedLookupRate().getRate(60*60*1000).getLastEventCount();
//val -= profile.getDBHistory().getFailedLookupRate().getRate(24*60*60*1000).getCurrentEventCount() * 50;
//val -= profile.getDBHistory().getFailedLookupRate().getRate(24*60*60*1000).getLastEventCount() * 20;
val -= profile.getCommError().getRate(60*1000).getCurrentEventCount() * 200;
val -= profile.getCommError().getRate(60*1000).getLastEventCount() * 200;
if (profile.getCommError().getRate(60*1000).getCurrentEventCount() > 0)
val -= 200;
if (profile.getCommError().getRate(60*1000).getLastEventCount() > 0)
val -= 200;
val -= profile.getCommError().getRate(60*60*1000).getCurrentEventCount() * 50;
val -= profile.getCommError().getRate(60*60*1000).getLastEventCount() * 50;
if (profile.getCommError().getRate(60*60*1000).getCurrentEventCount() > 0)
val -= 10;
if (profile.getCommError().getRate(60*60*1000).getLastEventCount() > 0)
val -= 10;
val -= profile.getCommError().getRate(24*60*60*1000).getCurrentEventCount() * 10;
val -= profile.getCommError().getRate(24*60*60*1000).getCurrentEventCount() * 1;
long now = _context.clock().now();
@ -65,10 +76,10 @@ public class ReliabilityCalculator extends Calculator {
val -= 100; // we got a rejection within the last minute
}
if ( (profile.getLastSendSuccessful() > 0) && (now - 24*60*60*1000 > profile.getLastSendSuccessful()) ) {
// we know they're real, but we havent sent them a message successfully in over a day.
val -= 1000;
}
//if ( (profile.getLastSendSuccessful() > 0) && (now - 24*60*60*1000 > profile.getLastSendSuccessful()) ) {
// // we know they're real, but we havent sent them a message successfully in over a day.
// val -= 1000;
//}
val += profile.getReliabilityBonus();
return val;

View File

@ -5,6 +5,8 @@ import java.io.OutputStream;
import java.util.Properties;
import net.i2p.router.RouterContext;
import net.i2p.stat.RateStat;
import net.i2p.util.Log;
/**
* Tunnel related history information
@ -12,21 +14,29 @@ import net.i2p.router.RouterContext;
*/
public class TunnelHistory {
private RouterContext _context;
private Log _log;
private volatile long _lifetimeAgreedTo;
private volatile long _lifetimeRejected;
private volatile long _lastAgreedTo;
private volatile long _lastRejected;
private volatile long _lifetimeFailed;
private volatile long _lastFailed;
private RateStat _rejectRate;
public TunnelHistory(RouterContext context) {
_context = context;
_log = context.logManager().getLog(TunnelHistory.class);
_lifetimeAgreedTo = 0;
_lifetimeFailed = 0;
_lifetimeRejected = 0;
_lastAgreedTo = 0;
_lastFailed = 0;
_lastRejected = 0;
createRates();
}
private void createRates() {
_rejectRate = new RateStat("tunnelHistory.rejectRate", "How often does this peer reject a tunnel request?", "tunnelHistory", new long[] { 60*1000l, 60*60*1000l, 24*60*60*1000l });
}
/** total tunnels the peer has agreed to participate in */
@ -48,6 +58,7 @@ public class TunnelHistory {
}
public void incrementRejected() {
_lifetimeRejected++;
_rejectRate.addData(1, 1);
_lastRejected = _context.clock().now();
}
public void incrementFailed() {
@ -62,6 +73,8 @@ public class TunnelHistory {
public void setLastRejected(long when) { _lastRejected = when; }
public void setLastFailed(long when) { _lastFailed = when; }
public RateStat getRejectionRate() { return _rejectRate; }
private final static String NL = System.getProperty("line.separator");
public void store(OutputStream out) throws IOException {
@ -77,6 +90,7 @@ public class TunnelHistory {
add(buf, "lifetimeFailed", _lifetimeFailed, "How many tunnels has the peer ever agreed to participate in that failed prematurely?");
add(buf, "lifetimeRejected", _lifetimeRejected, "How many tunnels has the peer ever refused to participate in?");
out.write(buf.toString().getBytes());
_rejectRate.store(out, "tunnelHistory.rejectRate");
}
private void add(StringBuffer buf, String name, long val, String description) {
@ -91,6 +105,14 @@ public class TunnelHistory {
_lifetimeAgreedTo = getLong(props, "tunnels.lifetimeAgreedTo");
_lifetimeFailed = getLong(props, "tunnels.lifetimeFailed");
_lifetimeRejected = getLong(props, "tunnels.lifetimeRejected");
try {
_rejectRate.load(props, "tunnelHistory.rejectRate", true);
_log.debug("Loading tunnelHistory.rejectRate");
} catch (IllegalArgumentException iae) {
_log.warn("TunnelHistory reject rate is corrupt, resetting", iae);
createRates();
}
}
private final static long getLong(Properties props, String key) {

View File

@ -32,7 +32,8 @@ public class BandwidthLimitedInputStream extends FilterInputStream {
super(source);
_context = context;
_peer = peer;
_peerSource = peer.getHash().toBase64();
if (peer != null)
_peerSource = peer.getHash().toBase64();
_pullFromOutbound = pullFromOutbound;
}

View File

@ -8,6 +8,9 @@ package net.i2p.router.transport;
*
*/
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;
@ -48,10 +51,13 @@ public class CommSystemFacadeImpl extends CommSystemFacade {
}
public void processMessage(OutNetMessage msg) {
_context.jobQueue().addJob(new GetBidsJob(_context, this, msg));
GetBidsJob j = new GetBidsJob(_context, this, msg);
j.runJob();
}
public String renderStatusHTML() { return _manager.renderStatusHTML(); }
public void renderStatusHTML(OutputStream out) throws IOException {
_manager.renderStatusHTML(out);
}
public Set createAddresses() {
Set addresses = new HashSet();

View File

@ -1,12 +1,15 @@
package net.i2p.router.transport;
import net.i2p.I2PAppContext;
import net.i2p.util.Log;
import net.i2p.util.I2PThread;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
import java.util.ArrayList;
import net.i2p.I2PAppContext;
import net.i2p.util.I2PThread;
import net.i2p.util.Log;
public class FIFOBandwidthLimiter {
private Log _log;
private I2PAppContext _context;
@ -244,7 +247,7 @@ public class FIFOBandwidthLimiter {
}
}
public String renderStatusHTML() {
public void renderStatusHTML(OutputStream out) throws IOException {
long now = _context.clock().now();
StringBuffer buf = new StringBuffer(4096);
buf.append("<br /><b>Pending bandwidth requests (with ");
@ -271,7 +274,7 @@ public class FIFOBandwidthLimiter {
}
}
buf.append("</ol></li></ul>\n");
return buf.toString();
out.write(buf.toString().getBytes());
}
private static long __requestId = 0;

View File

@ -8,6 +8,9 @@ package net.i2p.router.transport;
*
*/
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
@ -271,7 +274,7 @@ public class OutboundMessageRegistry {
}
}
public String renderStatusHTML() {
public void renderStatusHTML(OutputStream out) throws IOException {
StringBuffer buf = new StringBuffer(8192);
buf.append("<h2>Pending messages</h2>\n");
Map msgs = null;
@ -291,7 +294,7 @@ public class OutboundMessageRegistry {
buf.append("</li>\n");
}
buf.append("</ul>");
return buf.toString();
out.write(buf.toString().getBytes());
}
/**

View File

@ -8,6 +8,9 @@ package net.i2p.router.transport;
*
*/
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
@ -252,8 +255,8 @@ public class TransportManager implements TransportEventListener {
_log.debug("Added to in pool: "+ num);
}
public String renderStatusHTML() {
StringBuffer buf = new StringBuffer();
public void renderStatusHTML(OutputStream out) throws IOException {
StringBuffer buf = new StringBuffer(8*1024);
buf.append("<h2>Transport Manager</h2>\n");
buf.append("Listening on: <br /><pre>\n");
for (Iterator iter = _addresses.iterator(); iter.hasNext(); ) {
@ -269,6 +272,6 @@ public class TransportManager implements TransportEventListener {
buf.append("<li>").append(str).append("</li>\n");
}
buf.append("</ul>\n");
return buf.toString();
out.write(buf.toString().getBytes());
}
}

View File

@ -1,6 +1,8 @@
package net.i2p.router.transport;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@ -146,4 +148,6 @@ public class VMCommSystem extends CommSystemFacade {
public void startup() {
_commSystemFacades.put(_context.routerHash(), this);
}
public void renderStatusHTML(OutputStream out) {}
}

View File

@ -119,7 +119,9 @@ public class TCPTransport extends TransportImpl {
* and it should not block
*/
protected void outboundMessageReady() {
_context.jobQueue().addJob(new NextJob());
//_context.jobQueue().addJob(new NextJob());
NextJob j = new NextJob();
j.runJob();
}
private class NextJob extends JobImpl {

View File

@ -53,11 +53,14 @@ class ClientLeaseSetManagerJob extends JobImpl {
_lastCreated = -1;
}
public void forceRequestLease() { _forceRequestLease = true; }
public void forceRequestLease() {
_currentLeaseSet = null;
_forceRequestLease = true;
}
public String getName() { return "Manage Client Lease Set"; }
public void runJob() {
if (_pool.isStopped()) {
if ((!_forceRequestLease) && (_pool.isStopped()) ) {
if ( (_pool.getInactiveInboundTunnelIds().size() <= 0) &&
(_pool.getInboundTunnelIds().size() <= 0) ) {
if (_log.shouldLog(Log.INFO))

View File

@ -43,32 +43,43 @@ class ClientTunnelPool {
}
public void startPool() {
if (!_isStopped) {
if (_log.shouldLog(Log.WARN))
_log.warn("Pool " + _poolId +": Not starting the pool /again/ (its already running)");
return;
} else {
//if (!_isStopped) {
// if (_log.shouldLog(Log.ERROR))
// _log.error("Pool " + _poolId +": Not starting the pool /again/ (its already running)");
// return;
//} else {
if (_log.shouldLog(Log.INFO))
_log.info("Pool " + _poolId +": Starting up the pool ");
}
//}
_isStopped = false;
if (_mgrJob == null) {
_mgrJob = new ClientTunnelPoolManagerJob(_context, _pool, this);
_context.jobQueue().addJob(_mgrJob);
} else {
_mgrJob.getTiming().setStartAfter(_context.clock().now());
_context.jobQueue().addJob(_mgrJob);
}
if (_leaseMgrJob == null) {
_leaseMgrJob = new ClientLeaseSetManagerJob(_context, this);
_context.jobQueue().addJob(_leaseMgrJob);
} else {
// we just restarted, so make sure we ask for a new leaseSet ASAP
if (_log.shouldLog(Log.DEBUG))
_log.debug("restarting the client pool and requesting a new leaseSet");
_leaseMgrJob.forceRequestLease();
_leaseMgrJob.getTiming().setStartAfter(_context.clock().now());
_context.jobQueue().addJob(_leaseMgrJob);
}
if (_tunnelExpirationJob == null) {
_tunnelExpirationJob = new ClientTunnelPoolExpirationJob(_context, this, _pool);
_context.jobQueue().addJob(_tunnelExpirationJob);
}
} else {
_tunnelExpirationJob.getTiming().setStartAfter(_context.clock().now());
_context.jobQueue().addJob(_tunnelExpirationJob);
}
}
public void stopPool() { _isStopped = true; }
public boolean isStopped() { return _isStopped; }

View File

@ -39,6 +39,7 @@ public class HandleTunnelCreateMessageJob extends JobImpl {
RouterIdentity from, Hash fromHash, SourceRouteBlock replyBlock) {
super(ctx);
_log = ctx.logManager().getLog(HandleTunnelCreateMessageJob.class);
ctx.statManager().createRateStat("tunnel.rejectOverloaded", "How many tunnels did we deny due to throttling?", "Tunnels", new long[] { 5*60*1000l, 60*60*1000l, 24*60*60*1000l });
_message = receivedMessage;
_from = from;
_fromHash = fromHash;
@ -83,8 +84,13 @@ public class HandleTunnelCreateMessageJob extends JobImpl {
}
private boolean isOverloaded() {
// hmmm....
return false;
boolean shouldAccept = _context.throttle().acceptTunnelRequest(_message);
if (!shouldAccept) {
_context.statManager().addRateData("tunnel.rejectOverloaded", 1, 1);
if (_log.shouldLog(Log.INFO))
_log.info("Refusing tunnel request due to overload");
}
return !shouldAccept;
}
private class TestJob extends JobImpl {

View File

@ -1,5 +1,8 @@
package net.i2p.router.tunnelmanager;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
@ -127,8 +130,12 @@ public class PoolingTunnelManagerFacade implements TunnelManagerFacade {
public void createTunnels(Destination destination, ClientTunnelSettings clientSettings, long timeoutMs) {
ClientTunnelPool pool = _pool.getClientPool(destination);
if (pool != null) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("createTunnels for destination " + destination.calculateHash().toBase64() + " where the client pool exists");
pool.setClientSettings(clientSettings);
} else {
if (_log.shouldLog(Log.DEBUG))
_log.debug("createTunnels for destination " + destination.calculateHash().toBase64() + " where the client pool does NOT exist");
_pool.createClientPool(destination, clientSettings);
}
}
@ -202,14 +209,16 @@ public class PoolingTunnelManagerFacade implements TunnelManagerFacade {
return false;
}
public int getParticipatingCount() {
return _pool.getParticipatingTunnelCount();
}
/**
* Aint she pretty?
*
*/
public String renderStatusHTML() {
public void renderStatusHTML(OutputStream out) throws IOException {
if (_pool != null)
return _pool.renderStatusHTML();
else
return "<h2>Tunnel Manager not initialized</h2>\n";
_pool.renderStatusHTML(out);
}
}

View File

@ -1,5 +1,8 @@
package net.i2p.router.tunnelmanager;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
@ -621,32 +624,34 @@ class TunnelPool {
return settings;
}
public String renderStatusHTML() {
if (!_isLive) return "";
StringBuffer buf = new StringBuffer();
buf.append("<h2>Tunnel Pool</h2>\n");
renderTunnels(buf, "Free inbound tunnels", getFreeTunnels());
renderTunnels(buf, "Outbound tunnels", getOutboundTunnels());
renderTunnels(buf, "Participating tunnels", getParticipatingTunnels());
public void renderStatusHTML(OutputStream out) throws IOException {
if (!_isLive) return;
out.write("<h2>Tunnel Pool</h2>\n".getBytes());
StringBuffer buf = new StringBuffer(4096);
renderTunnels(out, buf, "Free inbound tunnels", getFreeTunnels());
renderTunnels(out, buf, "Outbound tunnels", getOutboundTunnels());
renderTunnels(out, buf, "Participating tunnels", getParticipatingTunnels());
for (Iterator iter = getClientPools().iterator(); iter.hasNext(); ) {
Destination dest = (Destination)iter.next();
ClientTunnelPool pool = getClientPool(dest);
renderTunnels(buf, "Inbound tunnels for " + dest.calculateHash() + " - (still connected? " + (!pool.isStopped()) + ")", pool.getInboundTunnelIds());
renderTunnels(out, buf, "Inbound tunnels for " + dest.calculateHash() + " - (still connected? " + (!pool.isStopped()) + ")", pool.getInboundTunnelIds());
}
return buf.toString();
}
private void renderTunnels(StringBuffer buf, String msg, Set tunnelIds) {
private void renderTunnels(OutputStream out, StringBuffer buf, String msg, Set tunnelIds) throws IOException {
buf.append("<b>").append(msg).append(":</b> <i>(").append(tunnelIds.size()).append(" tunnels)</i><ul>\n");
out.write(buf.toString().getBytes());
buf.setLength(0);
for (Iterator iter = tunnelIds.iterator(); iter.hasNext(); ) {
TunnelId id = (TunnelId)iter.next();
TunnelInfo tunnel = getTunnelInfo(id);
renderTunnel(buf, id, tunnel);
renderTunnel(out, buf, id, tunnel);
}
buf.append("</ul>\n");
out.write("</ul>\n".getBytes());
}
private final static void renderTunnel(StringBuffer buf, TunnelId id, TunnelInfo tunnel) {
private final static void renderTunnel(OutputStream out, StringBuffer buf, TunnelId id, TunnelInfo tunnel) throws IOException {
buf.setLength(0);
if (tunnel == null) {
buf.append("<li>Tunnel: ").append(id.getTunnelId()).append(" is not known</li>\n");
} else {
@ -675,6 +680,8 @@ class TunnelPool {
buf.append("\n</pre>");
}
out.write(buf.toString().getBytes());
buf.setLength(0);
}
private final static String getStyle(TunnelId id) {