Compare commits

...

115 Commits

Author SHA1 Message Date
78b7f228f5 * dropped httptunnel.jar and phttprelay.war from the dist (neither are used)
* automate the building of {lib,weblib,webapps}.tar.bz2 (even if i only run this one more time)
2004-08-20 19:58:04 +00:00
84e03f8b16 0.3.4.3, backwards compatible, to be released later today 2004-08-20 19:56:34 +00:00
288580aed7 be more accepting in what router references we receive (let them be up to 6h old before throwing a hissy fit) 2004-08-20 19:55:46 +00:00
de63bbcc86 adding clientApp parameter to pass the user's preferred browser into systray 2004-08-20 14:38:56 +00:00
80b8c284b4 * fixed a bug causing the systray to hang upon exit on Linux
* various nips and tucks all around
2004-08-20 14:36:03 +00:00
ffff6d701f added browser selection dialog 2004-08-20 12:56:40 +00:00
0b084ece08 * added ant build file
* systray is functional
2004-08-20 10:08:29 +00:00
28855d3fd1 * adding systray client to clients.config
* updating installer readme (the public domain 'license')
2004-08-20 03:11:08 +00:00
f7d356dc95 adding systray libs 2004-08-20 03:08:05 +00:00
104b332906 initial commit of systray code; not yet integrated 2004-08-20 03:07:27 +00:00
8b30852639 might as well link 'em to the netDb like the shitlist 2004-08-20 00:31:42 +00:00
bdaa14c257 formatting fix 2004-08-20 00:19:58 +00:00
0234fb62fb properly clean up the temp files (thanks oOo) 2004-08-19 23:46:56 +00:00
687ca781ab the DoS isn't CRIT and we log instances and publish the stat appropriately 2004-08-19 23:18:38 +00:00
3053c797e8 handle removal and addition (duh) 2004-08-19 22:02:28 +00:00
62d6709949 * include prepWEB as part of buildWEB (prepWEB checks to see if we've already downloaded it)
* include buildWEB as part of build (so everyone builds everything by default)
* have clean include pkgclean
* new i2ptunnel.config and clients.config for the pkg
2004-08-19 21:26:11 +00:00
410abaf92c handle the tunnels being instantiated prior to the CLI being inoked
(aka someone went to /i2ptunnel/ before the 2 minute delay passes)
2004-08-19 21:11:42 +00:00
5e07c478f5 a little tidying up 2004-08-19 20:27:35 +00:00
3eda53a97f ugly pages to display the old console and stats info, linked to off the top nav
also link to the i2ptunnel from the top nav (in a new window).
2004-08-19 20:26:19 +00:00
4e25382901 * load clientApp.* lines from clients.config by default, falling back on
reading the router's props only if that file doesn't exist.
* by default, only log CRIT messages to the screen (the rest are sent to
the log file).  this will be useful with the upcoming service controller
* refactor a common Properties helper to DataHelper.loadProps
2004-08-19 17:42:47 +00:00
fccb172e20 * Display both the hash and the full destination associated with each tunnel on
the /i2ptunnel/ page so they can easily be shared.
* By default, try to create any needed private key files (for server tunnels only)
* keep track of the I2PSession objects used by the I2PTunnel instances (only needed
for exposing the associated Destination)
2004-08-19 17:36:27 +00:00
5a761242f5 adding the wrapper binaries 2004-08-19 08:22:15 +00:00
aaaf1e14a5 removed the unnecessary launch parameter piping to /dev/null 2004-08-19 07:38:46 +00:00
3dcb9f6424 Added datagram_test.i2p 2004-08-19 05:59:27 +00:00
04621ff64a * service wrapper fully functioning under Linux and WinXP, should also be working for the other *nix platforms but this isn't tested yet
* renaming wrapper binaries to 'i2psvc' for *nix and 'I2Psvc.exe' for win32
2004-08-19 05:41:36 +00:00
5053808058 initial commit of service wrapper files
moving standalone-compiler.jar into the izpack subdir
2004-08-19 04:48:42 +00:00
9912c673bf * allow 2 failures in a tunnel before killing the tunnel. this is useful because
much of our tunnel failure detection code itself uses tunnels - send out tunnel 1
and get the reply through tunnel 2.  If it fails, which one "broke"?
* we now add a failure mark to both in all situations, including during tunnel
creation
* properly check the tunnel expiration 2-2.5 minutes prior to completion, rather
than the old 0.5-1.5 minutes.
2004-08-19 02:38:50 +00:00
4636f7be7b oops, we need to mark the peer we don't send to as failed (otherwise we wont send any more requests out, since there will be 'too many pending') 2004-08-18 20:44:57 +00:00
0ffc0a1959 Oops 2004-08-18 12:16:09 +00:00
e86032b129 Ver 0.9.1 2004-08-18 12:13:56 +00:00
87941a0975 Removed reference to stasher 2004-08-18 11:36:08 +00:00
3d6a40a683 don't do the netDb store of the peer's routerInfo until after we validate what they tell us (so we can shitlist them for the right reason) [thanks duck!] 2004-08-18 07:23:01 +00:00
9753470dcb handle a situation that would otherwise cause a search to block indefinitely rather than complete properly 2004-08-18 07:20:27 +00:00
a45e1b4781 made installer window resizable to compensate for some buggy *nix window managers 2004-08-18 04:47:09 +00:00
54f52d37ca * don't allow concurrent requests for the same key - add them to a list of deferred
requests which are notified on completion
* query peers who are sending us bad references, just don't follow their suggestions.
this is necessary since the peer may actually have the data (and other people may not be
getting shitty references from them)
2004-08-18 00:20:59 +00:00
6e295a7afb added the new GUI installer and associated build tasks 2004-08-17 20:43:11 +00:00
692cd7adae * reduced the period used to detect / avoid peers who send invalid data (60m instead of 120m)
* expose the reason for a dbStore rejection more cleanly
2004-08-17 20:37:47 +00:00
7794547d30 .cvsignore evidently didn't ignore itself 2004-08-17 19:40:24 +00:00
aum
35eaaee627 added -l flag for local-only put/get 2004-08-17 16:57:21 +00:00
aum
8029901ed7 fixed error (.i2pstasher) in help output 2004-08-17 10:09:56 +00:00
342c55043d accept w/ skew (duh) 2004-08-17 06:01:50 +00:00
3cf363667c added targets for .tar.bz2 package creation 2004-08-17 05:53:56 +00:00
2f8993995b enforce diversification of tunnel participants.
when picking peers to participate in a tunnel, we still select from the 'fast' tier,
except now we pick the ones that have least recently agreed to participate in a tunnel.
(they're already in the fast tier, so they're reliable [ish]).
the diversification has been pretty good so far, but i'm going to leave 'er running and monitor it overnight
2004-08-17 05:20:17 +00:00
8e9c541eba * new simple 'invalid reply rate' tracking the number of replies a peer sends that Suck.
(e.g. we can't find the referenced peer or the data they send back is corrupt/expired).
This is like the old invalidReplies, except its a rate that decays.
* if we receive more than 5 invalid replies from a peer in a 1-2 hour period,
stop verifying any subsequent replies, and also stop asking them for keys.
* cleaned up the store validation even further
2004-08-17 02:03:09 +00:00
7ed310ffd2 update ardvark.i2p (after checking ID) 2004-08-17 02:02:34 +00:00
bc1b020e95 put the timestamper in the background by default (so Base64 completes, thanks duck!) 2004-08-17 00:02:17 +00:00
5fdff16b1e removed shitlist ref 2004-08-16 22:38:10 +00:00
43e22a9028 javadoc fix (thanks oOo) 2004-08-16 22:17:47 +00:00
e102bf9eed lots of bitchin' oOo patches (woot, thanks oOo!), plus some cleanup
* apply oOo's patch for beautifying the new console w/ links to a shitlisted peer's netDb entry
* apply oOo's patch to clean up the peer shitlist count more aggressively
* apply oOo's patch to allow removing lines via /configadvanced.jsp
* apply oOo's patch to clean up the memory usage display
* apply oOo's patch to include log messages on /logs.jsp most recent first, rather than last
* get rid of the netDb key shitlist (its a bad idea, better solution coming soon)
2004-08-16 20:27:06 +00:00
aum
bf3ee5c158 added code.leo, to aid with editing the code via the
wonderful Leo structural literate editor
2004-08-16 16:19:32 +00:00
aum
2e99e3d9c5 added beginnings of splitfiles handling code
might not work yet for files > 28k
2004-08-16 16:18:41 +00:00
3d7029493a avoid a rare busy loop (thanks lucky) 2004-08-16 13:13:08 +00:00
a6ad2bbc5b added files.nickster.i2p 2004-08-16 04:25:48 +00:00
4dc17773c4 added brittanyworld.i2p 2004-08-15 23:06:52 +00:00
e5d66f46c6 deal with a race on close
more zealous bc synchronization
make sure we always close the streams explicitly
logging
2004-08-15 20:48:35 +00:00
d2fc24e792 deal with no proxy available
more carefully retrieve a proxy
logging (w/ unique requestId)
2004-08-15 20:44:14 +00:00
aum
ec52c81f46 Eliminated incorrect truncation of retrieved keys 2004-08-15 18:49:05 +00:00
aum
0eb0c4cc83 fixed getref bug 2004-08-15 18:33:37 +00:00
aum
b54e6bc933 *** empty log message *** 2004-08-15 17:58:57 +00:00
aum
83f891138d *** empty log message *** 2004-08-15 17:56:33 +00:00
aum
c621940b0f *** empty log message *** 2004-08-15 17:53:45 +00:00
aum
a27b0a0a1e *** empty log message *** 2004-08-15 17:45:01 +00:00
aum
23a52dbc9a first scripted commit 2004-08-15 16:57:02 +00:00
aum
f8a57c7885 Pulled another n bugs 2004-08-15 13:49:27 +00:00
a295d0ad1e cleanup the shitlist code
logging
2004-08-15 09:04:56 +00:00
190a2147cc Handle the netDb DoS problem at the root. The DoS was basically old peers telling us about expired
peers that we would crawl the entire netDb looking for (always failing, since there aren't any current
netDb entries for that peer that we would accept).
* keep a shitlist of keys we have recently searched for but were unable to find so we don't flood
* if our in-memory data store won't accept the data, its not helpful, so delete it on disk
* no need to do the preemptive refetching of a leaseSet, since we already garlic wrap it with payloads
* logging
2004-08-15 08:00:28 +00:00
49573b9e72 changed Windows-corrupted line endings back to UNIX 2004-08-15 07:17:13 +00:00
aum
e60b30ed44 Fixed n bugs, particularly relating to store 2004-08-15 07:02:36 +00:00
5c10ddf54c removing bogo.config, replaced bogobot.config 2004-08-15 05:17:12 +00:00
600ece819f config file implemented (thanks oOo)
NickServ capability (thanks oOo)
2004-08-15 05:14:49 +00:00
6bc7a3d8aa handle errors initializing, and deal with logFilePatterns that don't include a full path (e.g. log-#.txt instead of logs/log-#.txt) 2004-08-14 20:57:50 +00:00
aum
0af07e5352 *** empty log message *** 2004-08-14 18:11:42 +00:00
aum
8732f54c64 corrected invalid noderef aum.stasher 2004-08-14 17:51:50 +00:00
aum
437d5d76e9 added -f option for running stasher in foreground
reduced timeouts to 60secs
2004-08-14 17:43:46 +00:00
aum
7378be05d3 *** empty log message *** 2004-08-14 17:33:28 +00:00
aum
75febe4b75 Relocated from i2p/apps/sam/python
Stasher is a Kademlia-based distributed file store (aka 'DHT')
for I2P. Written in python, it can be accessed as:
 - low level python classes, or
 - via a client socket, with simple text-based protocol, or
 - via command-line client prog (called 'stasher', unsurprisingly)

Release status is pre-alpha

Developed by aum, August 2004
2004-08-14 17:23:07 +00:00
aum
f6d8d93a1b Removed all stasher-specifics, relocated them to
i2p/apps/stasher
2004-08-14 17:19:24 +00:00
aum
130310fddd Will suffice for doco for now 2004-08-14 13:07:04 +00:00
aum
8bd312046d First alpha release of stasher, a python-based Kademlia DHT implementation
specifically created for I2P.

New Files:
 - aum.stasher - a single noderef
 - stasher - wrapper script for starting/stopping/using stasher
 - stasher.py - similar wrapper script for 'doze users
 - src/bencode.py - requisite module
 - src/i2p/stasher.py - the stasher application classes - python module

Modified Files:
 - setup.py - added code to install stasher wrapper
 - src/i2p/__init__.py - added stasher to '__all__', allowing import
2004-08-14 12:58:12 +00:00
9cc96f45d0 * add a main() to TunnelControllerGroup which can be used as a clientApp.*
* new config property to have a tunnel start on load (default=true), so tunnels, er, start on load
* use i2ptunnel.config instead of i2ptunnel.cfg (for consistency)
* minor refactoring
2004-08-14 02:03:45 +00:00
c18fc1984d *cough* i knew there was a reason i left that test running... 2004-08-13 22:02:29 +00:00
3b651076d1 added stasher.i2p 2004-08-13 21:26:50 +00:00
352396bdc2 > Date: Fri, 13 Aug 2004 15:58:30 +1200 (NZST)
> Message-ID: <1776.202.37.75.101.1092369510.squirrel@202.37.75.101>
> From: adam@adambuckley.net
> To: jrandom@i2p.net
>
> [...]
>
> I hereby authorize my NtpClient.java and NtpMessage.java code to be
> redistributed under the BSD license for the purpose of integration with
> the I2P project, providing that I am credited as the original author of
> the code.
>
> [...]
w00t!  adam++
code migrated into core/java/src/net/i2p/time, integrated with Clock,
dropping that whole ugly pass-the-time-through-URL, and hence dropped
support for :7655/setTime.
New router.config properties to control the timestamper:
  time.sntpServerList=pool.ntp.org,pool.ntp.org,pool.ntp.org
  time.queryFrequencyMs=300000
  time.disabled=false
So, to disable, add time.disabled=true to your router.config.  It is
enabled by default.
Default router.config and startup scripts updated accordingly (since
timestamper.jar is now gone)
2004-08-13 21:15:22 +00:00
3c9b0273d4 only count locally generated lookup messages for detecting local DoS (duh) 2004-08-13 02:52:17 +00:00
5122f9989c track more info 2004-08-13 02:22:45 +00:00
8ebd22da96 hmm i thought i already committed this. well, anyway, cleaner stats wrt searching 2004-08-13 02:21:18 +00:00
c2d55013a6 0.3.4.2, backwards compatible, release pretty soon 2004-08-13 02:15:54 +00:00
25eda1378e * do DoS detection in constructor, so we get useful "why are we doing this"
stack traces (rather than "oh, we're doing it when... uh... writing to the socket")
* increase the throttle max, since we want to be able to send a few concurrent
2004-08-13 02:11:54 +00:00
dfac7bde9c * track searches more carefully
* detect situations where we may be inadvertantly flooding the netDb
and log them as CRIT with a stacktrace, as well as publish the count
of those events in the netDb
* detect potential netDb DoS situations by checking to see if we have
received more than 20 netDb lookups in 10 seconds, and if so,
probabalistically drop subsequent netDb messages (P=1-(10/numReceived)).
This is also published in the netDb.
2004-08-13 01:43:01 +00:00
348168d6c0 made the log less verbose for duck ;) 2004-08-13 01:27:55 +00:00
a1c772c8d8 changed quadn.i2p to library.i2p 2004-08-12 21:02:43 +00:00
f1ce1b5361 if we reach this point, bump up the expiration if necessary (otherwise the fast expire will occur with small clock skews) 2004-08-12 03:24:44 +00:00
ebdc7d70a1 shitlist appropriately (continued) 2004-08-12 03:23:48 +00:00
c5947c23bb include the shitlist summary 2004-08-12 03:22:27 +00:00
eeb1852d95 take note of the reason each peer is shitlisted and display that on the console (good idea oOo)
cleaned up the shitlisting process within the TCPTransport so that we don't shitlist twice (clobbering the detailed cause with a general "uh, couldn't contact 'em" cause)
2004-08-11 22:51:00 +00:00
2f28a635a9 integrated oOo's memory usage patch (the % shown is unfortunately % of peak, not % of max) [thanks oOo!]
cleaned up build script to make sure we always build fresh JSPs and xml [thanks oOo^2!]
2004-08-11 22:23:48 +00:00
d524c77560 *cough* (oops) 2004-08-11 08:23:56 +00:00
0025d94aa4 if the message has expired but hasn't exceeded the fudge factor, we still need to give it some time to be processed (we receive and validate it first, and if it reaches these jobs, we should let it continue)
logging
2004-08-11 07:10:37 +00:00
bb5ae2922d added freshcoffee.i2p 2004-08-11 07:00:23 +00:00
fbe9fe1ba8 new method for sanitizing content to be rendered on a web page (specifically, the routerInfo options can be hacked to contain evil html)
thanks for finding and suggesting the fix oOo!
2004-08-11 04:42:04 +00:00
mpc
007194d674 Check mallocs for NULL return 2004-08-11 04:39:17 +00:00
cdd74505d7 optional flag to allow using the standard base64 charset on decode/encode, rather than the (filename friendly) i2p charset 2004-08-11 00:59:11 +00:00
0aa023189d shitlist the old idents of peers who change idents
be sure to fire any onFail jobs if we aren't going to pass a message off (duh)
take clock skew into account when determining whether a message is expired (duh^2)
2004-08-11 00:57:36 +00:00
79aa10dfcb just a test 2004-08-10 21:22:45 +00:00
9ecfda0110 added basic HTTP authentication for accessing the router console (if a consolePassword is specified in the router.config)
unfortunately, this password setting is only read on router startup...
2004-08-10 19:51:11 +00:00
b89e26c460 cleaned up the validation of leaseSet/routerInfo elements being accepted so we validate only in one place (in the facade instead of both the facade and the dataStore)
don't accept entries created (too far) in the future
2004-08-10 16:55:54 +00:00
97e5952544 another oOo catch (not sure if this is ever run - it shouldn't be, but now it'll display the silly statement more clearly :) 2004-08-10 04:52:48 +00:00
8627328047 set the nextHopId whenever we know the nextHopInfo (duh) [thanks oOo!]
this should fix the deserialization errors from tunnels.dat
2004-08-10 04:11:58 +00:00
ec0c912c6f oOo's updates:
* properly describe expired leaseSets (e.g. "30s ago" instead of "in -30s")
* add a little table at the end of the netDb HTML summarizing the versions people claim to be running
2004-08-10 01:07:33 +00:00
mpc
953de3f1f2 Indentation 2004-08-09 10:56:14 +00:00
mpc
e1264de514 Magically fixed itself 2004-08-09 10:02:07 +00:00
5abd2b400c Updated wiki text sources 2004-08-09 10:01:04 +00:00
mpc
2c2a103676 Some more Makefile updates 2004-08-09 09:39:20 +00:00
44af799b66 reverting previous commit; realized it would hammer Mort Bay's servers 2004-08-08 23:07:07 +00:00
ec22ba3248 'dist' target broken, fixed by adding prepWEB as a depend before buildWEB 2004-08-08 22:42:56 +00:00
177 changed files with 16181 additions and 754 deletions

View File

@ -1,2 +0,0 @@
.classpath
.project

View File

@ -7,8 +7,13 @@
*/
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Properties;
import org.apache.log4j.DailyRollingFileAppender;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
@ -20,12 +25,10 @@ import org.jibble.pircbot.PircBot;
import org.jibble.pircbot.User;
/**
* TODO 0.4 Implement java.util.Properties for configuration.
* TODO 0.4 Add NickServ interface.
* TODO 0.5 Add multi-server capability.
*
* @author hypercubus
* @version 0.3.1
* @author hypercubus, oOo
* @version 0.4
*/
public class Bogobot extends PircBot {
@ -36,32 +39,116 @@ public class Bogobot extends PircBot {
private boolean _isIntentionalDisconnect = false;
private long _lastUserlistCommandTimestamp = 0;
private Logger _logger = Logger.getLogger(Bogobot.class);
/*
* The following will soon be moved to bogo.config and loaded via
* java.util.Properties when I get some time.
*/
private String _botPrimaryNick = "somebot";
private String _botSecondaryNick = "somebot_";
private String _botShutdownPassword = "take off eh";
private long _commandAntiFloodInterval = 60;
private String _ircChannel = "#i2p-chat";
private String _ircServer = "irc.duck.i2p";
private int _ircServerPort = 6668;
private boolean _isLoggerEnabled = true;
private boolean _isUserlistCommandEnabled = true;
private String _logFilePrefix = "irc.duck.i2p.i2p-chat";
private String _logFileRotationInterval = INTERVAL_DAILY;
private String _ownerPrimaryNick = "somenick";
private String _ownerSecondaryNick = "somenick_";
private String _userlistCommandTrigger = "!who";
public Bogobot() {
private int _currentAutoRoundTripTag = 0;
private long _lastAutoRoundTripSentTime = 0;
private Timer _tickTimer;
private String _configFile;
private String _botPrimaryNick;
private String _botSecondaryNick;
private String _botNickservPassword;
private String _botUsername;
private String _ownerPrimaryNick;
private String _ownerSecondaryNick;
private String _botShutdownPassword;
private String _ircChannel;
private String _ircServer;
private int _ircServerPort;
private boolean _isLoggerEnabled;
private String _loggedHostnamePattern;
private boolean _isUserlistCommandEnabled;
private String _logFilePrefix;
private String _logFileRotationInterval;
private long _commandAntiFloodInterval;
private String _userlistCommandTrigger;
private boolean _isRoundTripDelayEnabled;
private int _roundTripDelayPeriod;
class BogobotTickTask extends TimerTask {
private Bogobot _caller;
public BogobotTickTask(Bogobot caller) {
_caller = caller;
}
public void run() {
_caller.onTick();
}
}
private void loadConfigFile(String configFileName) {
_configFile = configFileName;
Properties config = new Properties();
FileInputStream fis = null;
try {
fis = new FileInputStream(configFileName);
config.load(fis);
} catch (IOException ioe) {
System.err.println("Error loading configuration file");
System.exit(2);
} finally {
if (fis != null) try {
fis.close();
} catch (IOException ioe) { // nop
}
}
_botPrimaryNick = config.getProperty("botPrimaryNick", "somebot");
_botSecondaryNick = config.getProperty("botSecondaryNick", "somebot_");
_botNickservPassword = config.getProperty("botNickservPassword", "");
_botUsername = config.getProperty("botUsername", "somebot");
_ownerPrimaryNick = config.getProperty("ownerPrimaryNick", "somenick");
_ownerSecondaryNick = config.getProperty("ownerSecondaryNick", "somenick_");
_botShutdownPassword = config.getProperty("botShutdownPassword", "take off eh");
_ircChannel = config.getProperty("ircChannel", "#i2p-chat");
_ircServer = config.getProperty("ircServer", "irc.duck.i2p");
_ircServerPort = Integer.parseInt(config.getProperty("ircServerPort", "6668"));
_isLoggerEnabled = Boolean.valueOf(config.getProperty("isLoggerEnabled", "true")).booleanValue();
_loggedHostnamePattern = config.getProperty("loggedHostnamePattern", "");
_logFilePrefix = config.getProperty("logFilePrefix", "irc.duck.i2p.i2p-chat");
_logFileRotationInterval = config.getProperty("logFileRotationInterval", INTERVAL_DAILY);
_isRoundTripDelayEnabled = Boolean.valueOf(config.getProperty("isRoundTripDelayEnabled", "false")).booleanValue();
_roundTripDelayPeriod = Integer.parseInt(config.getProperty("roundTripDelayPeriod", "300"));
_isUserlistCommandEnabled = Boolean.valueOf(config.getProperty("isUserlistCommandEnabled", "true")).booleanValue();
_userlistCommandTrigger = config.getProperty("userlistCommandTrigger", "!who");
_commandAntiFloodInterval = Long.parseLong(config.getProperty("commandAntiFloodInterval", "60"));
}
public Bogobot(String configFileName) {
loadConfigFile(configFileName);
this.setName(_botPrimaryNick);
this.setLogin(_botUsername);
_tickTimer = new Timer();
_tickTimer.scheduleAtFixedRate(new BogobotTickTask(this), 1000, 10 * 1000);
}
public static void main(String[] args) {
Bogobot bogobot = new Bogobot();
Bogobot bogobot;
if (args.length > 1) {
System.err.println("Too many arguments, the only allowed parameter is configuration file name");
System.exit(3);
}
if (args.length == 1) {
bogobot = new Bogobot(args[0]);
} else {
bogobot = new Bogobot("bogobot.config");
}
bogobot.setVerbose(true);
@ -71,6 +158,19 @@ public class Bogobot extends PircBot {
bogobot.connectToServer();
}
protected void onTick() {
// Tick about once every ten seconds
if (this.isConnected() && _isRoundTripDelayEnabled) {
if( ( (System.currentTimeMillis() - _lastAutoRoundTripSentTime) >= (_roundTripDelayPeriod * 1000) ) && (this.getOutgoingQueueSize() == 0) ) {
// Connected, sending queue is empty and last RoundTrip is more then 5 minutes old -> Send a new one
_currentAutoRoundTripTag ++;
_lastAutoRoundTripSentTime = System.currentTimeMillis();
sendNotice(this.getNick(),"ROUNDTRIP " + _currentAutoRoundTripTag);
}
}
}
protected void onDisconnect() {
if (_isIntentionalDisconnect)
@ -88,16 +188,20 @@ public class Bogobot extends PircBot {
}
protected void onJoin(String channel, String sender, String login, String hostname) {
if (sender.equals(this.getName())) {
if (_isLoggerEnabled)
if (_isLoggerEnabled) {
if (sender.equals(this.getName())) {
_logger.info(System.currentTimeMillis() + " joins *** " + _botPrimaryNick + " ***");
} else {
} else {
if (_isLoggerEnabled)
_logger.info(System.currentTimeMillis() + " joins " + sender);
String prependedHostname = "@" + hostname;
if (prependedHostname.endsWith(_loggedHostnamePattern)) {
_logger.info(System.currentTimeMillis() + " joins " + sender);
}
}
}
}
@ -121,8 +225,16 @@ public class Bogobot extends PircBot {
protected void onPart(String channel, String sender, String login, String hostname) {
if (_isLoggerEnabled)
_logger.info(System.currentTimeMillis() + " parts " + sender);
if (_isLoggerEnabled) {
if (sender.equals(this.getName())) {
_logger.info(System.currentTimeMillis() + " parts *** " + _botPrimaryNick + " ***");
} else {
String prependedHostname = "@" + hostname;
if (prependedHostname.endsWith(_loggedHostnamePattern)) {
_logger.info(System.currentTimeMillis() + " parts " + sender);
}
}
}
}
@ -142,9 +254,16 @@ public class Bogobot extends PircBot {
}
protected void onQuit(String sourceNick, String sourceLogin, String sourceHostname, String reason) {
String prependedHostname = "@" + sourceHostname;
if (_isLoggerEnabled)
_logger.info(System.currentTimeMillis() + " quits " + sourceNick + " " + reason);
if (sourceNick.equals(_botPrimaryNick))
changeNick(_botPrimaryNick);
if (_isLoggerEnabled) {
if (prependedHostname.endsWith(_loggedHostnamePattern)) {
_logger.info(System.currentTimeMillis() + " quits " + sourceNick + " " + reason);
}
}
}
@ -187,6 +306,20 @@ public class Bogobot extends PircBot {
joinChannel(_ircChannel);
}
protected void onNotice(String sourceNick, String sourceLogin, String sourceHostname, String target, String notice) {
if (sourceNick.equals("NickServ") && (notice.indexOf("/msg NickServ IDENTIFY") >= 0) && (_botNickservPassword != "")) {
sendRawLineViaQueue("NICKSERV IDENTIFY " + _botNickservPassword);
}
if (sourceNick.equals(getNick()) && notice.equals( "ROUNDTRIP " + _currentAutoRoundTripTag)) {
int delay = (int)((System.currentTimeMillis() - _lastAutoRoundTripSentTime) / 100);
// sendMessage(_ircChannel, "Round-trip delay = " + (delay / 10.0f) + " seconds");
if (_isLoggerEnabled)
_logger.info(System.currentTimeMillis() + " roundtrip " + delay);
}
}
private void initLogger() {
String logFilePath = "logs" + File.separator + _logFilePrefix;
@ -211,4 +344,5 @@ public class Bogobot extends PircBot {
System.exit(1);
}
}
}

View File

@ -17,7 +17,7 @@ import java.util.regex.Pattern;
/**
* @author hypercubus
* @version 0.3.1
* @version 0.4
*/
public class Bogoparser {

View File

@ -1,5 +1,5 @@
#####
# Bogobot user configuration (This file is not yet used.)
# Bogobot user configuration
#####
###
@ -9,6 +9,17 @@
botPrimaryNick=somebot
botSecondaryNick=somebot_
###
# The bot's password required by Nickserv service's identify command.
# You have to register the nickname yourself first, the bot will not.
#
botNickservPassword=
###
# The bot's username. Appears in the whois replies
#
botUsername=somebot
#####
# The bot owner's nick and backup nick. One of these must match the owner's
# currently-used nick or else remote shutdown will not be possible. You will
@ -36,6 +47,14 @@ ircServerPort=6668
#
isLoggerEnabled=true
###
# Restrict logging of joins and parts on the user hostname.
# Leave empty to log all of them
# Prepend with a @ for a perfect match
# Otherwise, specify the required end of the user hostname
#
loggedHostnamePattern=@free.duck.i2p
###
# The prefix to be used for the filenames of logs.
#
@ -47,6 +66,18 @@ logFilePrefix=irc.duck.i2p.i2p-chat
#
logFileRotationInterval=daily
###
# Set to "true" to enable the regular round-trip delay computation,
# else "false" (but don't use quotation marks).
#
isRoundTripDelayEnabled=false
###
# How often should the round-trip delay be recorded.
# (in seconds)
#
roundTripDelayPeriod=300
###
# Set to "true" to enable the userlist command, else "false" (but don't use
# quotation marks).

View File

@ -3,12 +3,12 @@
<!-- ********************************************************** -->
<!-- bogobot - A simple join/part stats logger bot for I2P IRC. -->
<!-- -->
<!-- build_eclipse.xml -->
<!-- build-eclipse.xml -->
<!-- 2004 The I2P Project -->
<!-- This code is public domain. -->
<!-- -->
<!-- author hypercubus -->
<!-- version 0.3.1 -->
<!-- author hypercubus, oOo -->
<!-- version 0.4 -->
<!-- ********************************************************** -->
<project basedir="." default="dist" name="Bogobot">
@ -27,7 +27,7 @@
Create the binary distribution archive -->
<target depends="init" description="Create the binary distribution archive" name="dist.bin">
<zip destfile="dist/Bogobot_${DSTAMP}.zip">
<zipfileset dir="${basedir}" includes="bogobot.bat Bogobot.class bogobot.sh Bogoparser.class LICENSE_log4j.txt LICENSE_pircbot.txt log4j-1.2.8.jar pircbot.jar" />
<zipfileset dir="${basedir}" includes="bogobot.bat bogobot.config Bogobot.class bogobot.sh Bogoparser.class LICENSE_log4j.txt LICENSE_pircbot.txt log4j-1.2.8.jar pircbot.jar" />
</zip>
</target>
@ -35,7 +35,7 @@
Create the source distribution archive -->
<target depends="init" description="Create the source distribution archive" name="dist.source">
<zip destfile="dist/Bogobot_source_${DSTAMP}.zip">
<zipfileset dir="${basedir}" includes="bogobot.bat Bogobot.java bogobot.sh Bogoparser.java build.xml build_eclipse.xml LICENSE_log4j.txt LICENSE_pircbot.txt log4j-1.2.8.jar pircbot.jar" />
<zipfileset dir="${basedir}" includes="bogobot.bat bogobot.config Bogobot.java bogobot.sh Bogoparser.java build.xml build_eclipse.xml LICENSE_log4j.txt LICENSE_pircbot.txt log4j-1.2.8.jar pircbot.jar" />
</zip>
</target>

View File

@ -7,8 +7,8 @@
<!-- 2004 The I2P Project -->
<!-- This code is public domain. -->
<!-- -->
<!-- author hypercubus -->
<!-- version 0.3.1 -->
<!-- author hypercubus, oOo -->
<!-- version 0.4 -->
<!-- ********************************************************** -->
<project basedir="." default="compile" name="Bogobot">
@ -26,14 +26,14 @@
<!-- compile:
Compile source code -->
<target depends="init" description="Compile source code" name="compile">
<javac classpath="${basedir}" source="1.4" srcdir="." />
<javac classpath="${basedir};log4j-1.2.8.jar;pircbot.jar" source="1.4" srcdir="." />
</target>
<!-- dist.bin:
Create the binary distribution archive -->
<target depends="init,compile" description="Create the binary distribution archive" name="dist.bin">
<zip destfile="dist/Bogobot_${DSTAMP}.zip">
<zipfileset dir="${basedir}" includes="bogobot.bat Bogobot.class bogobot.sh Bogoparser.class LICENSE_log4j.txt LICENSE_pircbot.txt log4j-1.2.8.jar pircbot.jar" />
<zipfileset dir="${basedir}" includes="bogobot.bat bogobot.config Bogobot.class Bogobot$BogobotTickTask.class bogobot.sh Bogoparser.class LICENSE_log4j.txt LICENSE_pircbot.txt log4j-1.2.8.jar pircbot.jar" />
</zip>
</target>
@ -41,7 +41,7 @@
Create the source distribution archive -->
<target depends="init" description="Create the source distribution archive" name="dist.source">
<zip destfile="dist/Bogobot_source_${DSTAMP}.zip">
<zipfileset dir="${basedir}" includes="bogobot.bat Bogobot.java bogobot.sh Bogoparser.java build.xml build_eclipse.xml LICENSE_log4j.txt LICENSE_pircbot.txt log4j-1.2.8.jar pircbot.jar" />
<zipfileset dir="${basedir}" includes="bogobot.bat bogobot.config Bogobot.java bogobot.sh Bogoparser.java build.xml build_eclipse.xml LICENSE_log4j.txt LICENSE_pircbot.txt log4j-1.2.8.jar pircbot.jar" />
</zip>
</target>

View File

@ -54,6 +54,7 @@ import net.i2p.I2PAppContext;
import net.i2p.I2PException;
import net.i2p.client.I2PClient;
import net.i2p.client.I2PClientFactory;
import net.i2p.client.I2PSession;
import net.i2p.client.naming.NamingService;
import net.i2p.data.Base64;
import net.i2p.data.DataFormatException;
@ -71,6 +72,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
private static long __tunnelId = 0;
private long _tunnelId;
private Properties _clientOptions;
private List _sessions;
public static final int PACKET_DELAY = 100;
@ -108,6 +110,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
_event = new EventDispatcherImpl();
_clientOptions = new Properties();
_clientOptions.putAll(System.getProperties());
_sessions = new ArrayList(1);
addConnectionEventListener(lsnr);
boolean gui = true;
@ -172,6 +175,24 @@ public class I2PTunnel implements Logging, EventDispatcher {
}
}
List getSessions() {
synchronized (_sessions) {
return new ArrayList(_sessions);
}
}
void addSession(I2PSession session) {
if (session == null) return;
synchronized (_sessions) {
_sessions.add(session);
}
}
void removeSession(I2PSession session) {
if (session == null) return;
synchronized (_sessions) {
_sessions.remove(session);
}
}
public Properties getClientOptions() { return _clientOptions; }
private void addtask(I2PTunnelTask tsk) {

View File

@ -86,6 +86,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
}
l.log("I2P session created");
getTunnel().addSession(sockMgr.getSession());
Thread t = new I2PThread(this);
t.setName("Client " + _clientId);
listenerReady = false;
@ -275,6 +277,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
}
return false;
}
getTunnel().removeSession(sockMgr.getSession());
l.log("Closing client " + toString());
try {
if (ss != null) ss.close();

View File

@ -82,6 +82,16 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
"the following Destination:<BR><BR>")
.getBytes();
private final static byte[] ERR_NO_OUTPROXY =
("HTTP/1.1 503 Service Unavailable\r\n"+
"Content-Type: text/html; charset=iso-8859-1\r\n"+
"Cache-control: no-cache\r\n"+
"\r\n"+
"<html><body><H1>I2P ERROR: No outproxy found</H1>"+
"Your request was for a site outside of I2P, but you have no "+
"HTTP outproxy configured. Please configure an outproxy in I2PTunnel")
.getBytes();
/** used to assign unique IDs to the threads / clients. no logic or functionality */
private static volatile long __clientId = 0;
@ -113,23 +123,33 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
notifyEvent("openHTTPClientResult", "ok");
}
private String getPrefix() { return "Client[" + _clientId + "]: "; }
private String getPrefix(long requestId) { return "Client[" + _clientId + "/" + requestId + "]: "; }
private String selectProxy() {
if (proxyList.size() <= 0) {
l.log("Proxy list is emtpy - no outproxy available");
return null;
synchronized (proxyList) {
int size = proxyList.size();
if (size <= 0) {
if (_log.shouldLog(Log.INFO))
_log.info("Proxy list is empty - no outproxy available");
l.log("Proxy list is emtpy - no outproxy available");
return null;
}
int index = I2PAppContext.getGlobalContext().random().nextInt(size);
if (index >= size) index = size - 1;
if (index < 0) return null;
String proxy = (String)proxyList.get(index);
return proxy;
}
int index = I2PAppContext.getGlobalContext().random().nextInt(proxyList.size());
return (String)proxyList.get(index);
}
private static long __requestId = 0;
protected void clientConnectionRun(Socket s) {
OutputStream out = null;
String targetRequest = null;
boolean usingWWWProxy = false;
String currentProxy = null;
InactivityTimeoutThread timeoutThread = null;
long requestId = ++__requestId;
try {
out = s.getOutputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream(), "ISO-8859-1"));
@ -137,7 +157,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
StringBuffer newRequest = new StringBuffer();
while ((line = br.readLine()) != null) {
if (_log.shouldLog(Log.DEBUG))
_log.debug(getPrefix() + "Line=[" + line + "]");
_log.debug(getPrefix(requestId) + "Line=[" + line + "]");
if (line.startsWith("Connection: ") ||
line.startsWith("Keep-Alive: ") ||
@ -146,7 +166,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
if (method == null) { // first line (GET /base64/realaddr)
if (_log.shouldLog(Log.DEBUG))
_log.debug(getPrefix() + "Method is null for [" + line + "]");
_log.debug(getPrefix(requestId) + "Method is null for [" + line + "]");
int pos = line.indexOf(" ");
if (pos == -1) break;
@ -179,11 +199,29 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
line = method + " " + request.substring(pos);
} else if (host.indexOf(".") != -1) {
// The request must be forwarded to a WWW proxy
if (_log.shouldLog(Log.DEBUG))
_log.debug("Before selecting outproxy for " + host);
currentProxy = selectProxy();
if (_log.shouldLog(Log.DEBUG))
_log.debug("After selecting outproxy for " + host + ": " + currentProxy);
if (currentProxy == null) {
if (_log.shouldLog(Log.WARN))
_log.warn(getPrefix(requestId) + "Host wants to be outproxied, but we dont have any!");
l.log("No HTTP outproxy found for the request.");
if (out != null) {
out.write(ERR_NO_OUTPROXY);
out.write("<p /><i>Generated on: ".getBytes());
out.write(new Date().toString().getBytes());
out.write("</i></body></html>\n".getBytes());
out.flush();
}
s.close();
return;
}
destination = currentProxy;
usingWWWProxy = true;
if (_log.shouldLog(Log.DEBUG))
_log.debug(getPrefix() + "Host doesnt end with .i2p and it contains a period [" + host + "]: wwwProxy!");
_log.debug(getPrefix(requestId) + "Host doesnt end with .i2p and it contains a period [" + host + "]: wwwProxy!");
} else {
request = request.substring(pos + 1);
pos = request.indexOf("/");
@ -193,27 +231,27 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
boolean isValid = usingWWWProxy || isSupportedAddress(host, protocol);
if (!isValid) {
if (_log.shouldLog(Log.INFO)) _log.info(getPrefix() + "notValid(" + host + ")");
if (_log.shouldLog(Log.INFO)) _log.info(getPrefix(requestId) + "notValid(" + host + ")");
method = null;
destination = null;
break;
} else if (!usingWWWProxy) {
if (_log.shouldLog(Log.INFO)) _log.info(getPrefix() + "host=getHostName(" + destination + ")");
if (_log.shouldLog(Log.INFO)) _log.info(getPrefix(requestId) + "host=getHostName(" + destination + ")");
host = getHostName(destination); // hide original host
}
if (_log.shouldLog(Log.DEBUG)) {
_log.debug(getPrefix() + "METHOD:" + method + ":");
_log.debug(getPrefix() + "PROTOC:" + protocol + ":");
_log.debug(getPrefix() + "HOST :" + host + ":");
_log.debug(getPrefix() + "DEST :" + destination + ":");
_log.debug(getPrefix(requestId) + "METHOD:" + method + ":");
_log.debug(getPrefix(requestId) + "PROTOC:" + protocol + ":");
_log.debug(getPrefix(requestId) + "HOST :" + host + ":");
_log.debug(getPrefix(requestId) + "DEST :" + destination + ":");
}
} else {
if (line.startsWith("Host: ") && !usingWWWProxy) {
line = "Host: " + host;
if (_log.shouldLog(Log.INFO))
_log.info(getPrefix() + "Setting host = " + host);
_log.info(getPrefix(requestId) + "Setting host = " + host);
}
}
@ -225,7 +263,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
}
}
if (_log.shouldLog(Log.DEBUG))
_log.debug(getPrefix() + "NewRequest header: [" + newRequest.toString() + "]");
_log.debug(getPrefix(requestId) + "NewRequest header: [" + newRequest.toString() + "]");
while (br.ready()) { // empty the buffer (POST requests)
int i = br.read();
@ -247,7 +285,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
}
if (_log.shouldLog(Log.DEBUG))
_log.debug(getPrefix() + "Destination: " + destination);
_log.debug(getPrefix(requestId) + "Destination: " + destination);
Destination dest = I2PTunnel.destFromName(destination);
if (dest == null) {
@ -262,25 +300,25 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
I2PSocket i2ps = createI2PSocket(dest);
byte[] data = newRequest.toString().getBytes("ISO-8859-1");
I2PTunnelRunner runner = new I2PTunnelRunner(s, i2ps, sockLock, data);
timeoutThread = new InactivityTimeoutThread(runner, out, targetRequest, usingWWWProxy, currentProxy, s);
timeoutThread = new InactivityTimeoutThread(runner, out, targetRequest, usingWWWProxy, currentProxy, s, requestId);
timeoutThread.start();
} catch (SocketException ex) {
if (timeoutThread != null) timeoutThread.disable();
_log.info(getPrefix() + "Error trying to connect", ex);
_log.info(getPrefix(requestId) + "Error trying to connect", ex);
l.log(ex.getMessage());
handleHTTPClientException(ex, out, targetRequest, usingWWWProxy, currentProxy);
handleHTTPClientException(ex, out, targetRequest, usingWWWProxy, currentProxy, requestId);
closeSocket(s);
} catch (IOException ex) {
if (timeoutThread != null) timeoutThread.disable();
_log.info(getPrefix() + "Error trying to connect", ex);
_log.info(getPrefix(requestId) + "Error trying to connect", ex);
l.log(ex.getMessage());
handleHTTPClientException(ex, out, targetRequest, usingWWWProxy, currentProxy);
handleHTTPClientException(ex, out, targetRequest, usingWWWProxy, currentProxy, requestId);
closeSocket(s);
} catch (I2PException ex) {
if (timeoutThread != null) timeoutThread.disable();
_log.info("getPrefix() + Error trying to connect", ex);
_log.info("getPrefix(requestId) + Error trying to connect", ex);
l.log(ex.getMessage());
handleHTTPClientException(ex, out, targetRequest, usingWWWProxy, currentProxy);
handleHTTPClientException(ex, out, targetRequest, usingWWWProxy, currentProxy, requestId);
closeSocket(s);
}
}
@ -289,18 +327,19 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
private static volatile long __timeoutId = 0;
private class InactivityTimeoutThread extends I2PThread {
private Socket s;
private I2PTunnelRunner _runner;
private OutputStream _out;
private String _targetRequest;
private boolean _useWWWProxy;
private String _currentProxy;
private long _requestId;
private boolean _disabled;
private Object _disableLock = new Object();
public InactivityTimeoutThread(I2PTunnelRunner runner, OutputStream out, String targetRequest,
boolean useWWWProxy, String currentProxy, Socket s) {
boolean useWWWProxy, String currentProxy, Socket s, long requestId) {
this.s = s;
_runner = runner;
_out = out;
@ -308,8 +347,9 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
_useWWWProxy = useWWWProxy;
_currentProxy = currentProxy;
_disabled = false;
_requestId = requestId;
long timeoutId = ++__timeoutId;
setName("InactivityThread " + getPrefix() + timeoutId);
setName("InactivityThread " + getPrefix(requestId) + timeoutId);
}
public void disable() {
@ -322,13 +362,13 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
public void run() {
while (!_disabled) {
if (_runner.isFinished()) {
if (_log.shouldLog(Log.INFO)) _log.info(getPrefix() + "HTTP client request completed prior to timeout");
if (_log.shouldLog(Log.INFO)) _log.info(getPrefix(_requestId) + "HTTP client request completed prior to timeout");
return;
}
if (_runner.getLastActivityOn() < Clock.getInstance().now() - INACTIVITY_TIMEOUT) {
if (_runner.getStartedOn() < Clock.getInstance().now() - INACTIVITY_TIMEOUT) {
if (_log.shouldLog(Log.WARN))
_log.warn(getPrefix() + "HTTP client request timed out (lastActivity: "
_log.warn(getPrefix(_requestId) + "HTTP client request timed out (lastActivity: "
+ new Date(_runner.getLastActivityOn()) + ", startedOn: "
+ new Date(_runner.getStartedOn()) + ")");
timeout();
@ -349,7 +389,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
}
private void timeout() {
_log.info(getPrefix() + "Inactivity timeout reached");
_log.info(getPrefix(_requestId) + "Inactivity timeout reached");
l.log("Inactivity timeout reached");
if (_out != null) {
try {
@ -359,16 +399,17 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
writeErrorMessage(ERR_TIMEOUT, _out, _targetRequest, _useWWWProxy, _currentProxy);
}
} catch (IOException ioe) {
_log.warn(getPrefix() + "Error writing out the 'timeout' message", ioe);
_log.warn(getPrefix(_requestId) + "Error writing out the 'timeout' message", ioe);
}
} else {
_log.warn(getPrefix() + "Client disconnected before we could say we timed out");
_log.warn(getPrefix(_requestId) + "Client disconnected before we could say we timed out");
}
closeSocket(s);
}
}
private final static String getHostName(String host) {
if (host == null) return null;
try {
Destination dest = I2PTunnel.destFromName(host);
if (dest == null) return "i2p";
@ -394,18 +435,18 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
}
private void handleHTTPClientException(Exception ex, OutputStream out, String targetRequest,
boolean usingWWWProxy, String wwwProxy) {
boolean usingWWWProxy, String wwwProxy, long requestId) {
if (_log.shouldLog(Log.WARN))
_log.warn("Error sending to " + wwwProxy + " (proxy? " + usingWWWProxy + ", request: " + targetRequest, ex);
_log.warn(getPrefix(requestId) + "Error sending to " + wwwProxy + " (proxy? " + usingWWWProxy + ", request: " + targetRequest, ex);
if (out != null) {
try {
writeErrorMessage(ERR_DESTINATION_UNKNOWN, out, targetRequest, usingWWWProxy, wwwProxy);
} catch (IOException ioe) {
_log.warn(getPrefix() + "Error writing out the 'destination was unknown' " + "message", ioe);
_log.warn(getPrefix(requestId) + "Error writing out the 'destination was unknown' " + "message", ioe);
}
} else {
_log.warn(getPrefix() + "Client disconnected before we could say that destination " + "was unknown", ex);
_log.warn(getPrefix(requestId) + "Client disconnected before we could say that destination " + "was unknown", ex);
}
}

View File

@ -80,6 +80,7 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
}
sockMgr.setName("Server");
getTunnel().addSession(sockMgr.getSession());
l.log("Ready!");
notifyEvent("openServerResult", "ok");
open = true;
@ -130,6 +131,7 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
l.log("Shutting down server " + toString());
try {
if (i2pss != null) i2pss.close();
getTunnel().removeSession(sockMgr.getSession());
sockMgr.getSession().destroySession();
} catch (I2PException ex) {
_log.error("Error destroying the session", ex);

View File

@ -64,6 +64,7 @@ public abstract class I2PTunnelTask implements EventDispatcher {
public void disconnected(I2PSession session) {
routerDisconnected();
getTunnel().removeSession(session);
}
public void errorOccurred(I2PSession session, String message, Throwable error) {

View File

@ -13,6 +13,7 @@ import net.i2p.I2PAppContext;
import net.i2p.I2PException;
import net.i2p.client.I2PClient;
import net.i2p.client.I2PClientFactory;
import net.i2p.client.I2PSession;
import net.i2p.data.Destination;
import net.i2p.util.Log;
@ -39,7 +40,7 @@ public class TunnelController implements Logging {
* @param prefix beginning of key values that are relevent to this tunnel
*/
public TunnelController(Properties config, String prefix) {
this(config, prefix, false);
this(config, prefix, true);
}
/**
*
@ -53,12 +54,20 @@ public class TunnelController implements Logging {
setConfig(config, prefix);
_messages = new ArrayList(4);
_running = false;
if (createKey)
if (createKey && ("server".equals(getType())) )
createPrivateKey();
if (getStartOnLoad())
startTunnel();
}
private void createPrivateKey() {
I2PClient client = I2PClientFactory.createClient();
String filename = getPrivKeyFile();
if ( (filename == null) || (filename.trim().length() <= 0) ) {
log("No filename specified for the private key");
return;
}
File keyFile = new File(getPrivKeyFile());
if (keyFile.exists()) {
log("Not overwriting existing private keys in " + keyFile.getAbsolutePath());
@ -241,6 +250,7 @@ public class TunnelController implements Logging {
public String getListenPort() { return _config.getProperty("listenPort"); }
public String getTargetDestination() { return _config.getProperty("targetDestination"); }
public String getProxyList() { return _config.getProperty("proxyList"); }
public boolean getStartOnLoad() { return "true".equalsIgnoreCase(_config.getProperty("startOnLoad", "true")); }
public boolean getIsRunning() { return _running; }
@ -309,6 +319,24 @@ public class TunnelController implements Logging {
String opts = getClientOptions();
if ( (opts != null) && (opts.length() > 0) )
buf.append("Network options: ").append(opts).append("<br />\n");
if (_running) {
List sessions = _tunnel.getSessions();
for (int i = 0; i < sessions.size(); i++) {
I2PSession session = (I2PSession)sessions.get(i);
Destination dest = session.getMyDestination();
if (dest != null) {
buf.append("Destination hash: ").append(dest.calculateHash().toBase64()).append("<br />\n");
buf.append("Full destination: ");
buf.append("<input type=\"text\" size=\"10\" onclick=\"this.select();\" ");
buf.append("value=\"").append(dest.toBase64()).append("\" />\n");
if ("server".equals(getType())) {
buf.append(" Give that out to people so they can view your service.");
buf.append(" If you are going to share it on irc, be sure to split it on two lines");
}
buf.append("<br />\n");
}
}
}
}
public void log(String s) {

View File

@ -24,13 +24,39 @@ import net.i2p.util.Log;
*/
public class TunnelControllerGroup {
private Log _log;
private List _controllers;
private static TunnelControllerGroup _instance = new TunnelControllerGroup();
public static TunnelControllerGroup getInstance() { return _instance; }
private static TunnelControllerGroup _instance;
static final String DEFAULT_CONFIG_FILE = "i2ptunnel.config";
private TunnelControllerGroup() {
private List _controllers;
private String _configFile = DEFAULT_CONFIG_FILE;
public static TunnelControllerGroup getInstance() {
synchronized (TunnelControllerGroup.class) {
if (_instance == null)
_instance = new TunnelControllerGroup(DEFAULT_CONFIG_FILE);
return _instance;
}
}
private TunnelControllerGroup(String configFile) {
_log = I2PAppContext.getGlobalContext().logManager().getLog(TunnelControllerGroup.class);
_controllers = new ArrayList();
_configFile = configFile;
loadControllers(_configFile);
}
public static void main(String args[]) {
if ( (args == null) || (args.length <= 0) ) {
_instance = getInstance();
} else if (args.length == 1) {
if (DEFAULT_CONFIG_FILE.equals(args[0]))
_instance = getInstance();
else
_instance = new TunnelControllerGroup(args[0]);
} else {
System.err.println("Usage: TunnelControllerGroup [filename]");
return;
}
}
/**
@ -58,6 +84,11 @@ public class TunnelControllerGroup {
_log.info(i + " controllers loaded from " + configFile);
}
public void reloadControllers() {
unloadControllers();
loadControllers(_configFile);
}
/**
* Stop and remove reference to all known tunnels (but dont delete any config
* file or do other silly things)
@ -158,11 +189,20 @@ public class TunnelControllerGroup {
return msgs;
}
/**
* Save the configuration of all known tunnels to the default config
* file
*
*/
public void saveConfig() {
saveConfig(_configFile);
}
/**
* Save the configuration of all known tunnels to the given file
*
*/
public void saveConfig(String configFile) {
_configFile = configFile;
File cfgFile = new File(configFile);
File parent = cfgFile.getParentFile();
if ( (parent != null) && (!parent.exists()) )
@ -246,4 +286,5 @@ public class TunnelControllerGroup {
* @return list of TunnelController objects
*/
public List getControllers() { return _controllers; }
}

View File

@ -281,6 +281,12 @@ class WebEditPageFormGenerator {
}
}
buf.append("\" /><br />\n");
buf.append("<b>Start automatically?</b> \n");
buf.append("<input type=\"checkbox\" name=\"startOnLoad\" value=\"true\" ");
if ( (controller != null) && (controller.getStartOnLoad()) )
buf.append(" checked=\"true\" />\n<br />\n");
else
buf.append(" />\n<br />\n");
}
/**

View File

@ -38,6 +38,7 @@ public class WebEditPageHelper {
private String _targetHost;
private String _targetPort;
private String _privKeyFile;
private boolean _startOnLoad;
private boolean _privKeyGenerate;
private boolean _removeConfirmed;
@ -156,6 +157,13 @@ public class WebEditPageHelper {
public void setRemoveConfirm(String moo) {
_removeConfirmed = true;
}
/**
* If called with any value, we want this tunnel to start whenever it is
* loaded (aka right now and whenever the router is started up)
*/
public void setStartOnLoad(String moo) {
_startOnLoad = true;
}
/**
* Process the form and display any resulting messages
@ -248,7 +256,7 @@ public class WebEditPageHelper {
return getMessages(doSave());
}
private List doSave() {
TunnelControllerGroup.getInstance().saveConfig(WebStatusPageHelper.CONFIG_FILE);
TunnelControllerGroup.getInstance().saveConfig();
return TunnelControllerGroup.getInstance().clearAllMessages();
}
@ -320,6 +328,8 @@ public class WebEditPageHelper {
}
}
config.setProperty("startOnLoad", _startOnLoad + "");
if (_tunnelCount != null)
config.setProperty("option.tunnels.numInbound", _tunnelCount);
if (_tunnelDepth != null)

View File

@ -17,20 +17,11 @@ public class WebStatusPageHelper {
private Log _log;
private String _action;
private int _controllerNum;
private static boolean _configLoaded = false;
static final String CONFIG_FILE = "i2ptunnel.cfg";
public WebStatusPageHelper() {
_action = null;
_controllerNum = -1;
_log = I2PAppContext.getGlobalContext().logManager().getLog(WebStatusPageHelper.class);
synchronized (WebStatusPageHelper.class) {
if (!_configLoaded) {
reloadConfig();
_configLoaded = true;
}
}
}
public void setAction(String action) {
@ -113,8 +104,7 @@ public class WebStatusPageHelper {
return getMessages(msgs);
}
private String reloadConfig() {
TunnelControllerGroup.getInstance().unloadControllers();
TunnelControllerGroup.getInstance().loadControllers(CONFIG_FILE);
TunnelControllerGroup.getInstance().reloadControllers();
return "Config reloaded";
}
private String start() {

View File

@ -346,7 +346,7 @@ class I2PSocketImpl implements I2PSocket {
}
boolean timedOut = false;
while (read.length == 0) {
while ( (read.length == 0) && (!inStreamClosed) ) {
synchronized (flagLock) {
if (closed) {
if (_log.shouldLog(Log.DEBUG))
@ -378,6 +378,9 @@ class I2PSocketImpl implements I2PSocket {
}
}
if (read.length > len) throw new RuntimeException("BUG");
if ( (inStreamClosed) && ( (read == null) || (read.length <= 0) ) )
return -1;
System.arraycopy(read, 0, b, off, read.length);
if (_log.shouldLog(Log.DEBUG)) {
@ -456,6 +459,8 @@ class I2PSocketImpl implements I2PSocket {
synchronized (I2PInputStream.this) {
I2PInputStream.this.notifyAll();
}
if (_log.shouldLog(Log.DEBUG))
_log.debug(getStreamPrefix() + "After insert " + len + " bytes into queue: " + hashCode());
}
public void notifyClosed() {
@ -471,6 +476,8 @@ class I2PSocketImpl implements I2PSocket {
inStreamClosed = true;
bc.notifyAll();
}
if (_log.shouldLog(Log.DEBUG))
_log.debug(getStreamPrefix() + "After close");
}
}
@ -518,10 +525,21 @@ class I2PSocketImpl implements I2PSocket {
*/
private boolean handleNextPacket(ByteCollector bc, byte buffer[])
throws IOException, I2PSessionException {
if (_log.shouldLog(Log.DEBUG))
_log.debug(getPrefix() + ":" + Thread.currentThread().getName() + "handleNextPacket");
int len = in.read(buffer);
int bcsize = bc.getCurrentSize();
int bcsize = 0;
synchronized (bc) {
bcsize = bc.getCurrentSize();
}
if (_log.shouldLog(Log.DEBUG))
_log.debug(getPrefix() + ":" + Thread.currentThread().getName() + "handleNextPacket len=" + len + " bcsize=" + bcsize);
if (len != -1) {
bc.append(buffer, len);
synchronized (bc) {
bc.append(buffer, len);
}
} else if (bcsize == 0) {
// nothing left in the buffer, and read(..) got EOF (-1).
// the bart the
@ -529,7 +547,7 @@ class I2PSocketImpl implements I2PSocket {
}
if ((bcsize < MAX_PACKET_SIZE) && (in.available() == 0)) {
if (_log.shouldLog(Log.DEBUG))
_log.debug(getPrefix() + "Runner Point d: " + hashCode());
_log.debug(getPrefix() + ":" + Thread.currentThread().getName() + "Runner Point d: " + hashCode());
try {
Thread.sleep(PACKET_DELAY);
@ -538,19 +556,22 @@ class I2PSocketImpl implements I2PSocket {
}
}
if ((bcsize >= MAX_PACKET_SIZE) || (in.available() == 0)) {
byte[] data = bc.startToByteArray(MAX_PACKET_SIZE);
byte data[] = null;
synchronized (bc) {
data = bc.startToByteArray(MAX_PACKET_SIZE);
}
if (data.length > 0) {
if (_log.shouldLog(Log.DEBUG))
_log.debug(getPrefix() + "Message size is: " + data.length);
_log.debug(getPrefix() + ":" + Thread.currentThread().getName() + "Message size is: " + data.length);
boolean sent = sendBlock(data);
if (!sent) {
if (_log.shouldLog(Log.WARN))
_log.warn(getPrefix() + "Error sending message to peer. Killing socket runner");
_log.warn(getPrefix() + ":" + Thread.currentThread().getName() + "Error sending message to peer. Killing socket runner");
errorOccurred();
return false;
} else {
if (_log.shouldLog(Log.DEBUG))
_log.debug(getPrefix() + "Message sent to peer");
_log.debug(getPrefix() + ":" + Thread.currentThread().getName() + "Message sent to peer");
}
}
}
@ -567,7 +588,14 @@ class I2PSocketImpl implements I2PSocket {
while (keepHandling) {
keepHandling = handleNextPacket(bc, buffer);
packetsHandled++;
if (_log.shouldLog(Log.DEBUG))
_log.debug(getPrefix() + ":" + Thread.currentThread().getName()
+ "Packets handled: " + packetsHandled);
}
if (_log.shouldLog(Log.INFO))
_log.info(getPrefix() + ":" + Thread.currentThread().getName()
+ "After handling packets, we're done. Packets handled: " + packetsHandled);
if ((bc.getCurrentSize() > 0) && (packetsHandled > 1)) {
if (_log.shouldLog(Log.WARN))
_log.warn(getPrefix() + "We lost some data queued up due to a network send error (input stream: "
@ -583,16 +611,20 @@ class I2PSocketImpl implements I2PSocket {
} // FIXME: Race here?
if (sc) {
if (_log.shouldLog(Log.INFO))
_log.info(getPrefix() + "Sending close packet: (we started? " + outgoing + ") after reading " + _bytesRead + " and writing " + _bytesWritten);
_log.info(getPrefix() + ":" + Thread.currentThread().getName()
+ "Sending close packet: (we started? " + outgoing
+ ") after reading " + _bytesRead + " and writing " + _bytesWritten);
byte[] packet = I2PSocketManager.makePacket(getMask(0x02), remoteID, new byte[0]);
boolean sent = manager.getSession().sendMessage(remote, packet);
if (!sent) {
if (_log.shouldLog(Log.WARN))
_log.warn(getPrefix() + "Error sending close packet to peer");
_log.warn(getPrefix() + ":" + Thread.currentThread().getName()
+ "Error sending close packet to peer");
errorOccurred();
}
}
manager.removeSocket(I2PSocketImpl.this);
internalClose();
} catch (InterruptedIOException ex) {
_log.error(getPrefix() + "BUG! read() operations should not timeout!", ex);
} catch (IOException ex) {

View File

@ -28,10 +28,13 @@
</target>
<target name="war" depends="precompilejsp">
<war destfile="build/routerconsole.war" webxml="../jsp/web-out.xml"
basedir="../jsp/" excludes="web.xml, *.java, *.jsp">
basedir="../jsp/" excludes="web.xml, *.java, *.jsp, web-fragment.xml">
</war>
</target>
<target name="precompilejsp">
<delete dir="../jsp/WEB-INF/" />
<delete file="../jsp/web-fragment.xml" />
<delete file="../jsp/web-out.xml" />
<mkdir dir="../jsp/WEB-INF/" />
<mkdir dir="../jsp/WEB-INF/classes" />
<!-- there are various jspc ant tasks, but they all seem a bit flakey -->
@ -60,6 +63,10 @@
<pathelement location="build/routerconsole.jar" />
</classpath>
</javac>
<delete>
<fileset dir="../jsp/WEB-INF/" includes="**/*.java" />
<fileset dir="../jsp/WEB-INF/" includes="**/*.jsp" />
</delete>
<copy file="../jsp/web.xml" tofile="../jsp/web-out.xml" />
<loadfile property="jspc.web.fragment" srcfile="../jsp/web-fragment.xml" />
<replace file="../jsp/web-out.xml">

View File

@ -4,6 +4,8 @@ import java.io.ByteArrayInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashSet;
import java.util.Iterator;
/**
* Handler to deal with form submissions from the advanced config form and act
@ -41,6 +43,7 @@ public class ConfigAdvancedHandler extends FormHandler {
*
*/
private void saveChanges() {
HashSet unsetKeys = new HashSet(_context.router().getConfigMap().keySet());
if (_config != null) {
BufferedReader reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(_config.getBytes())));
String line = null;
@ -52,12 +55,19 @@ public class ConfigAdvancedHandler extends FormHandler {
String key = line.substring(0, eq).trim();
String val = line.substring(eq + 1).trim();
_context.router().setConfigSetting(key, val);
unsetKeys.remove(key);
}
} catch (IOException ioe) {
addFormError("Error updating the configuration (IOERROR) - please see the error logs");
return;
}
Iterator cleaner = unsetKeys.iterator();
while (cleaner.hasNext()) {
String unsetKey = (String)cleaner.next();
_context.router().removeConfigSetting(unsetKey);
}
boolean saved = _context.router().saveConfig();
if (saved)
addFormNotice("Configuration saved successfully");

View File

@ -17,6 +17,7 @@ import java.util.List;
import java.util.Set;
import net.i2p.util.Log;
import net.i2p.time.Timestamper;
import net.i2p.router.RouterContext;
import net.i2p.router.ClientTunnelSettings;
@ -221,9 +222,9 @@ public class ConfigNetHandler extends FormHandler {
updateRates();
if (_timeSyncEnabled) {
System.setProperty("timestamper.enabled", "true");
_context.router().setConfigSetting(Timestamper.PROP_DISABLED, "false");
} else {
System.setProperty("timestamper.enabled", "false");
_context.router().setConfigSetting(Timestamper.PROP_DISABLED, "false");
}
boolean saved = _context.router().saveConfig();

View File

@ -6,6 +6,7 @@ import java.util.List;
import java.util.Iterator;
import java.util.TreeMap;
import net.i2p.time.Timestamper;
import net.i2p.util.Log;
import net.i2p.router.RouterContext;
@ -50,8 +51,8 @@ public class ConfigNetHelper {
}
public String getEnableTimeSyncChecked() {
String enabled = System.getProperty("timestamper.enabled");
if ( (enabled == null) || (!"true".equals(enabled)) )
String enabled = _context.getProperty(Timestamper.PROP_DISABLED, "true");
if ( (enabled == null) || (!"true".equalsIgnoreCase(enabled)) )
return "";
else
return " checked ";

View File

@ -29,8 +29,8 @@ public class LogsHelper {
StringBuffer buf = new StringBuffer(16*1024);
buf.append("<h2>Most recent console messages:</h2><ul>");
buf.append("<code>\n");
for (int i = 0; i < msgs.size(); i++) {
String msg = (String)msgs.get(i);
for (int i = msgs.size(); i > 0; i--) {
String msg = (String)msgs.get(i - 1);
buf.append("<li>");
buf.append(msg);
buf.append("</li>\n");

View File

@ -0,0 +1,48 @@
package net.i2p.router.web;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.List;
import net.i2p.router.RouterContext;
import net.i2p.router.admin.StatsGenerator;
public class OldConsoleHelper {
private RouterContext _context;
/**
* Configure this bean to query a particular router context
*
* @param contextId begging few characters of the routerHash, or null to pick
* the first one we come across.
*/
public void setContextId(String contextId) {
try {
_context = ContextHelper.getContext(contextId);
} catch (Throwable t) {
t.printStackTrace();
}
}
public OldConsoleHelper() {}
public String getConsole() {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream(128*1024);
_context.router().renderStatusHTML(baos);
return baos.toString();
} catch (IOException ioe) {
return "<b>Error rending the console</b>";
}
}
public String getStats() {
StatsGenerator gen = new StatsGenerator(_context);
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream(32*1024);
gen.generateStatsPage(baos);
return baos.toString();
} catch (IOException ioe) {
return "<b>Error rending the console</b>";
}
}
}

View File

@ -32,4 +32,14 @@ public class ProfilesHelper {
}
return new String(baos.toByteArray());
}
public String getShitlistSummary() {
ByteArrayOutputStream baos = new ByteArrayOutputStream(4*1024);
try {
_context.shitlist().renderStatusHTML(baos);
} catch (IOException ioe) {
ioe.printStackTrace();
}
return new String(baos.toByteArray());
}
}

View File

@ -1,13 +1,22 @@
package net.i2p.router.web;
import java.io.IOException;
import java.util.List;
import net.i2p.router.RouterContext;
import org.mortbay.jetty.Server;
import org.mortbay.jetty.servlet.WebApplicationContext;
import org.mortbay.http.handler.SecurityHandler;
import org.mortbay.http.HashUserRealm;
import org.mortbay.http.HttpRequest;
import org.mortbay.http.SecurityConstraint;
import org.mortbay.util.MultiException;
public class RouterConsoleRunner {
private Server _server;
private String _listenPort = "7657";
private String _listenHost = "0.0.0.0";
private String _listenHost = "127.0.0.1";
private String _webAppsDir = "./webapps/";
public RouterConsoleRunner(String args[]) {
@ -25,10 +34,15 @@ public class RouterConsoleRunner {
public void startConsole() {
_server = new Server();
WebApplicationContext contexts[] = null;
try {
_server.addListener(_listenHost + ':' + _listenPort);
_server.setRootWebApp("routerconsole");
_server.addWebApplications(_webAppsDir);
contexts = _server.addWebApplications(_webAppsDir);
if (contexts != null) {
for (int i = 0; i < contexts.length; i++)
initialize(contexts[i]);
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
@ -39,6 +53,41 @@ public class RouterConsoleRunner {
}
}
private void initialize(WebApplicationContext context) {
String password = getPassword();
if (password != null) {
HashUserRealm realm = new HashUserRealm();
realm.put("admin", password);
realm.addUserToRole("admin", "routerAdmin");
context.setRealm(realm);
context.addHandler(0, new SecurityHandler());
SecurityConstraint constraint = new SecurityConstraint("admin", "routerAdmin");
constraint.setAuthenticate(true);
context.addSecurityConstraint("/", constraint);
}
}
private String getPassword() {
List contexts = RouterContext.listContexts();
if (contexts != null) {
for (int i = 0; i < contexts.size(); i++) {
RouterContext ctx = (RouterContext)contexts.get(i);
String password = ctx.getProperty("consolePassword");
if (password != null) {
password = password.trim();
if (password.length() > 0) {
return password;
}
}
}
// no password in any context
return null;
} else {
// no contexts?!
return null;
}
}
public void stopConsole() {
try {
_server.stop();

View File

@ -64,6 +64,18 @@ public class SummaryHelper {
else
return DataHelper.formatDuration(router.getUptime());
}
/**
* Retrieve amount of used memory.
*
*/
public String getMemory() {
DecimalFormat integerFormatter = new DecimalFormat("###,###,##0");
long used = (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory())/1024;
long usedPc = 100 - ((Runtime.getRuntime().freeMemory() * 100) / Runtime.getRuntime().totalMemory());
return integerFormatter.format(used) + "KB (" + usedPc + "%)";
}
/**
* How many active peers the router has.

View File

@ -34,10 +34,8 @@
to <a href="http://www.whatismyip.com/">www.whatismyip.com</a>.</i>
<hr />
<b>Enable internal time synchronization?</b> <input type="checkbox" <jsp:getProperty name="nethelper" property="enableTimeSyncChecked" /> name="enabletimesync" /><br />
<i>If disabled, your machine <b>must</b> be NTP synchronized. This option only
takes effect for the current run - if your machine is always synchronized within
(a few seconds), you can update your configuration so that it doesn't start the
"Timestamper" app (which would make this option irrelevent)</i>
<i>If disabled, your machine <b>must</b> be NTP synchronized - your clock must always
be within a few seconds of "correct".</i>
<hr />
<b>Bandwidth limiter</b><br />
<b>Inbound rate</b>:

View File

@ -23,7 +23,7 @@
<i><jsp:getProperty name="formhandler" property="notices" /></i>
<form action="configadvanced.jsp" method="POST">
<textarea rows="20" cols="80" name="config"><jsp:getProperty name="advancedhelper" property="settings" /></textarea><br />
<textarea rows="20" cols="100" name="config"><jsp:getProperty name="advancedhelper" property="settings" /></textarea><br />
<input type="submit" name="shouldsave" value="Apply" /> <input type="reset" value="Cancel" /> <br />
<b>Force restart:</b> <input type="checkbox" name="restart" value="force" /> <i>(specify this
if the changes made above require the router to reset itself - e.g. you are updating TCP ports

View File

@ -8,11 +8,14 @@
[<a href="config.jsp">configuration</a> | <a href="help.jsp">help</a>]
</div>
<h3>
<h4>
<a href="profiles.jsp">Profiles</a> |
<a href="netdb.jsp">Network Database</a> |
<a href="logs.jsp">Logs</a>
<a href="logs.jsp">Logs</a> |
<a href="oldconsole.jsp">Old console</a> |
<a href="oldstats.jsp">Stats</a> |
<a href="i2ptunnel/" target="_blank">I2PTunnel</a>
<jsp:useBean class="net.i2p.router.web.NavHelper" id="navhelper" scope="request" />
<jsp:setProperty name="navhelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:getProperty name="navhelper" property="clientAppLinks" />
</h3>
</h4>

View File

@ -0,0 +1,21 @@
<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head>
<title>I2P Router Console - home</title>
<link rel="stylesheet" href="default.css" type="text/css" />
</head><body>
<%@include file="nav.jsp" %>
<%@include file="summary.jsp" %>
<jsp:useBean class="net.i2p.router.web.OldConsoleHelper" id="conhelper" scope="request" />
<jsp:setProperty name="conhelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<div class="main" id="main">
<jsp:getProperty name="conhelper" property="console" />
</div>
</body>
</html>

View File

@ -0,0 +1,21 @@
<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head>
<title>I2P Router Console - home</title>
<link rel="stylesheet" href="default.css" type="text/css" />
</head><body>
<%@include file="nav.jsp" %>
<%@include file="summary.jsp" %>
<jsp:useBean class="net.i2p.router.web.OldConsoleHelper" id="oldhelper" scope="request" />
<jsp:setProperty name="oldhelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<div class="main" id="main">
<jsp:getProperty name="oldhelper" property="stats" />
</div>
</body>
</html>

View File

@ -14,6 +14,9 @@
<jsp:useBean class="net.i2p.router.web.ProfilesHelper" id="profilesHelper" scope="request" />
<jsp:setProperty name="profilesHelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:getProperty name="profilesHelper" property="profileSummary" />
<hr />
<a name="shitlist"> </a>
<jsp:getProperty name="profilesHelper" property="shitlistSummary" />
</div>
</body>

View File

@ -7,6 +7,7 @@
<b>Ident:</b> <jsp:getProperty name="helper" property="ident" /><br />
<b>Version:</b> <jsp:getProperty name="helper" property="version" /><br />
<b>Uptime:</b> <jsp:getProperty name="helper" property="uptime" /><br />
<b>Memory:</b> <jsp:getProperty name="helper" property="memory" /><br />
<hr />
<u><b>Peers</b></u><br />

View File

@ -2,7 +2,6 @@
# This Makefile contains instructions common to all platforms
#
#
# Build rules
#
@ -23,4 +22,4 @@ libsam: $(OBJS)
#
clean:
-$(RM) -f $(LIBDIR)/libsam.a $(OBJDIR)/* .depend
-$(RM) -f $(LIBDIR)/libsam.a $(OBJDIR)/*.o .depend

View File

@ -1,34 +0,0 @@
#
# This Makefile is compatible with GNU Make
#
#
# Programs
#
CC = gcc
#
# Flags
#
CFLAGS = -g -O2 -pipe -std=c99 -Wall
CFLAGS += -I../inc -L../lib
LIBS = -lsam
#
# Build rules
#
all: warhammer-dgram
warhammer-dgram: warhammer-dgram.c
$(CC) $(CFLAGS) -o warhammer-dgram.o -c warhammer-dgram.c
$(CC) $(CFLAGS) -o warhammer-dgram warhammer-dgram.o $(LIBS)
#
# Cleanup rules
#
clean:
-rm -f *.o *.exe warhammer-dgram

View File

@ -0,0 +1,20 @@
#
# This Makefile contains instructions common to all platforms
#
#
# Build rules
#
all: clean warhammer-dgram
warhammer-dgram: warhammer-dgram.c
$(CC) $(CFLAGS) -o warhammer-dgram.o -c warhammer-dgram.c
$(CC) $(CFLAGS) -o warhammer-dgram warhammer-dgram.o $(LIBS)
#
# Cleanup rules
#
clean:
-$(RM) -f warhammer-dgram *.exe *.o

View File

@ -7,6 +7,7 @@
#
CC = C:\Dev-Cpp\bin\gcc
RM = C:\Dev-Cpp\bin\rm
#
# Flags
@ -18,18 +19,7 @@ CFLAGS += -I../inc -L../lib
LIBS = -lsam -lwsock32
#
# Build rules
# Include the make instructions common to all platforms
#
all: warhammer-dgram
warhammer-dgram:
$(CC) $(CFLAGS) -o warhammer-dgram.o -c warhammer-dgram.c
$(CC) $(CFLAGS) -o warhammer-dgram warhammer-dgram.o $(LIBS)
#
# Cleanup rules
#
clean:
-rm -f *.o *.exe warhammer-dgram
include Makefile.common

View File

@ -0,0 +1,24 @@
#
# This Makefile is compatible with GNU Make and should work on POSIX systems
#
#
# Programs
#
CC = gcc
RM = rm
#
# Flags
#
CFLAGS = -g -O2 -pipe -std=c99 -Wall
CFLAGS += -I../inc -L../lib
LIBS = -lsam
#
# Include the make instructions common to all platforms
#
include Makefile.common

View File

@ -1,5 +1,5 @@
#
# This Makefile is compatible with GNU Make
# This Makefile is compatible with GNU Make and should work on POSIX systems
#
#
@ -8,6 +8,7 @@
CC = gcc
INSTALL = install
RM = rm
#
# Flags
@ -21,7 +22,7 @@ LIBS = -lsam
# Build rules
#
all: i2p-ping
all: clean i2p-ping
i2p-ping: i2p-ping.c
$(CC) $(CFLAGS) -o i2p-ping.o -c i2p-ping.c
@ -35,4 +36,4 @@ install: i2p-ping
#
clean:
-rm -f *.o *.exe i2p-ping
-$(RM) -f i2p-ping *.o

View File

@ -42,8 +42,8 @@ extern "C" {
*/
/* The maximum length a SAM command can be */
#define SAM_CMD_LEN 128
/*The maximum size of a single datagram packet (-30 temporary bug fix for SAM)*/
#define SAM_DGRAM_PAYLOAD_MAX ((31 * 1024) - 30)
/* The maximum size of a single datagram packet */
#define SAM_DGRAM_PAYLOAD_MAX (31 * 1024)
/* The longest log message */
#define SAM_LOGMSG_LEN 256
/* The longest `name' arg for the naming lookup callback */

View File

@ -125,22 +125,22 @@ bool sam_close(sam_sess_t *session)
* for use.
*/
samerr_t sam_connect(sam_sess_t *session, const char *samhost, uint16_t samport,
const char *destname, sam_conn_t style, uint_t tunneldepth)
const char *destname, sam_conn_t style, uint_t tunneldepth)
{
assert(session != NULL);
samerr_t rc;
if (style == SAM_STREAM) {
if (sam_closeback == NULL || sam_connectback == NULL ||
sam_databack == NULL || sam_diedback == NULL ||
sam_logback == NULL || sam_namingback == NULL ||
sam_statusback == NULL) {
if (sam_closeback == NULL || sam_connectback == NULL
|| sam_databack == NULL || sam_diedback == NULL
|| sam_logback == NULL || sam_namingback == NULL
|| sam_statusback == NULL) {
SAMLOGS("Please set callback functions before connecting");
return SAM_CALLBACKS_UNSET;
}
} else if (style == SAM_DGRAM) {
if (sam_dgramback == NULL || sam_diedback == NULL ||
sam_logback == NULL || sam_namingback == NULL) {
if (sam_dgramback == NULL || sam_diedback == NULL
|| sam_logback == NULL || sam_namingback == NULL) {
SAMLOGS("Please set callback functions before connecting");
return SAM_CALLBACKS_UNSET;
}
@ -189,7 +189,7 @@ samerr_t sam_connect(sam_sess_t *session, const char *samhost, uint16_t samport,
* Returns: true on success, false on failure
*/
samerr_t sam_dgram_send(sam_sess_t *session, const sam_pubkey_t dest,
const void *data, size_t size)
const void *data, size_t size)
{
assert(session != NULL);
char cmd[SAM_PKCMD_LEN];
@ -316,6 +316,10 @@ static void sam_parse(sam_sess_t *session, char *s)
data is sent, the extra NUL character will
just be ignored by the client program,
because it is not added to the size */
if (data == NULL) {
SAMLOGS("Out of memory");
abort();
}
if (sam_read2(session, data, size) != -1) {
p = data + size;
*p = '\0'; /* see above NUL note */
@ -450,6 +454,10 @@ static void sam_parse(sam_sess_t *session, char *s)
data is sent, the extra NUL character will
just be ignored by the client program,
because it is not added to the size */
if (data == NULL) {
SAMLOGS("Out of memory");
abort();
}
if (sam_read2(session, data, size) != -1) {
p = data + size;
*p = '\0'; /* see above NUL note */
@ -667,7 +675,6 @@ static bool sam_readable(sam_sess_t *session)
sam_diedback(session);
return false;
}
/* it seems like there should be a better way to do this (i.e. not select)*/
FD_ZERO(&rset);
FD_SET(session->sock, &rset);
tv.tv_sec = 0;
@ -698,7 +705,7 @@ static bool sam_readable(sam_sess_t *session)
* Returns: true on success, false on error
*/
void sam_sendq_add(sam_sess_t *session, sam_sid_t stream_id,
sam_sendq_t **sendq, const void *data, size_t dsize)
sam_sendq_t **sendq, const void *data, size_t dsize)
{
assert(session != NULL);
assert(dsize >= 0);
@ -747,7 +754,15 @@ static sam_sendq_t *sam_sendq_create()
sam_sendq_t *sendq;
sendq = malloc(sizeof(sam_sendq_t));
if (sendq == NULL) {
SAMLOGS("Out of memory");
abort();
}
sendq->data = malloc(SAM_STREAM_PAYLOAD_MAX);
if (sendq->data == NULL) {
SAMLOGS("Out of memory");
abort();
}
/* ^^ a waste of memory perhaps, but more efficient than realloc'ing every
* time data is added the to queue */
sendq->size = 0;
@ -762,7 +777,7 @@ static sam_sendq_t *sam_sendq_create()
* sendq - the send queue
*/
void sam_sendq_flush(sam_sess_t *session, sam_sid_t stream_id,
sam_sendq_t **sendq)
sam_sendq_t **sendq)
{
assert(session != NULL);
sam_stream_send(session, stream_id, (*sendq)->data, (*sendq)->size);
@ -782,8 +797,13 @@ void sam_sendq_flush(sam_sess_t *session, sam_sid_t stream_id,
*/
sam_sess_t *sam_session_init(sam_sess_t *session)
{
if (session == NULL)
if (session == NULL) {
session = malloc(sizeof(sam_sess_t));
if (session == NULL) {
SAMLOGS("Out of memory");
abort();
}
}
session->connected = false;
session->prev_id = 0;
@ -957,10 +977,11 @@ retry:
}
a.s_addr = ((struct in_addr *)h->h_addr)->s_addr;
#ifdef NO_INET_NTOP
/* inet_ntoa() was very poorly designed! */
char *tmp;
tmp = inet_ntoa(a);
assert(tmp != NULL);
strlcpy(ipaddr, tmp, INET_ADDRSTRLEN); /* inet_ntoa() was very poorly designed */
strlcpy(ipaddr, tmp, INET_ADDRSTRLEN);
return true;
#else
if (inet_ntop(AF_INET, &a, ipaddr, INET_ADDRSTRLEN) != NULL) {
@ -1027,7 +1048,7 @@ sam_sid_t sam_stream_connect(sam_sess_t *session, const sam_pubkey_t dest)
* Returns: true on success, false on failure
*/
samerr_t sam_stream_send(sam_sess_t *session, sam_sid_t stream_id,
const void *data, size_t size)
const void *data, size_t size)
{
assert(session != NULL);
char cmd[SAM_CMD_LEN];
@ -1251,7 +1272,7 @@ const char *sam_winsock_strerror(int code)
return "This is a nonrecoverable error";
case WSANO_DATA:
return "Valid name, no data record of requested type";
/* None of this shit compiles under Mingw - who knows why...
/* None of this shit compiles under Mingw - who knows why...
case WSA_INVALID_HANDLE:
return "Specified event object handle is invalid";
case WSA_INVALID_PARAMETER:
@ -1269,8 +1290,7 @@ const char *sam_winsock_strerror(int code)
case WSAINVALIDPROVIDER:
return "Invalid service provider version number";
case WSAPROVIDERFAILEDINIT:
return "Unable to initialize a service provider";
*/
return "Unable to initialize a service provider"; */
case WSASYSCALLFAILURE:
return "System call failure";
default:

View File

@ -0,0 +1,49 @@
Title: User's Guide:i2p.BaseHTTPServer
Emulates Python BaseHTTPServer module using I2P sockets.
== Overview ==
The Python module is described at http://www.python.org/doc/current/lib/module-BaseHTTPServer.html
To get a server going, use:
<ul><pre>
>>> from i2p import BaseHTTPServer
>>> BaseHTTPServer.test().
</pre></ul>
Consult the documentation for function test() to change basic server settings, such as the session name.
A fully customizable example:
<ul><pre>
>>> from i2p import BaseHTTPServer
>>> session = "mytestxxx.i2p" # SAM session name
>>> class MyServer(BaseHTTPServer.HTTPServer): pass
>>> class MyRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): pass
>>> httpd = MyServer(session, MyRequestHandler)
>>> httpd.socket.dest
(Base64 Destination of server)
>>> httpd.serve_forever()
</pre></ul>
== Classes ==
class '''BaseHTTPRequestHandler'''
<ul><pre>
Same interface as Python class BaseHTTPServer.BaseHTTPRequestHandler.
</pre></ul>
class '''HTTPServer'''
<ul><pre>
Same interface as Python class BaseHTTPServer.HTTPServer.
</pre></ul>
== Functions ==
'''test'''(HandlerClass=BaseHTTPRequestHandler, ServerClass=HTTPServer, protocol='HTTP/1.0', session='mytestxxx.i2p')
<ul><pre>
Test the HTTP request handler class.
This runs an I2P TCP server under SAM session 'session'. If a single command
line argument is given, the argument is used instead as the SAM session name.
</pre></ul>

View File

@ -0,0 +1,48 @@
Title: User's Guide:i2p.CGIHTTPServer
Module <code>i2p.CGIHTTPServer</code> emulates the Python CGIHTTPServer module using I2P sockets.
== Overview ==
The Python module is described at http://www.python.org/doc/current/lib/module-CGIHTTPServer.html
To get a server going, use:
<ul><pre>
>>> from i2p import CGIHTTPServer
>>> CGIHTTPServer.test().
</pre></ul>
Consult the documentation for function test() to change basic server settings, such as the session name.
A fully customizable example:
<ul><pre>
>>> from i2p import BaseHTTPServer, CGIHTTPServer
>>> session = "mytestxxx.i2p" # SAM session name
>>> class MyServer(BaseHTTPServer.HTTPServer): pass
>>> class MyRequestHandler(CGIHTTPServer.CGIHTTPRequestHandler): pass
>>> httpd = MyServer(session, MyRequestHandler)
>>> httpd.socket.dest
(Base64 Destination of server)
>>> httpd.serve_forever()
</pre></ul>
== Classes ==
class '''CGIHTTPRequestHandler'''
<ul><pre>
Same interface as Python class CGIHTTPServer.CGIHTTPRequestHandler.
</pre></ul>
== Functions ==
'''test'''(HandlerClass=CGIHTTPRequestHandler,
ServerClass=i2p.BaseHTTPServer.HTTPServer,
session='mytestxxx.i2p')
<ul><pre>
Test the HTTP CGI request handler class.
This runs an I2P TCP server under SAM session 'session'. If a single
command line argument is given, the argument is used instead as the SAM session
name.
</pre></ul>

View File

@ -0,0 +1,45 @@
Title: User's Guide:i2p.SimpleHTTPServer
Emulates Python SimpleHTTPServer module using I2P sockets.
== Overview ==
The Python module is described at http://www.python.org/doc/current/lib/module-SimpleHTTPServer.html
To get a server going, use:
<ul><pre>
>>> from i2p import SimpleHTTPServer
>>> SimpleHTTPServer.test().
</pre></ul>
Consult the documentation for function test() to change basic server settings, such as the session name.
A fully customizable example:
<ul><pre>
>>> from i2p import BaseHTTPServer, SimpleHTTPServer
>>> session = "mytestxxx.i2p" # SAM session name
>>> class MyServer(BaseHTTPServer.HTTPServer): pass
>>> class MyRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): pass
>>> httpd = MyServer(session, MyRequestHandler)
>>> httpd.socket.dest
(Base64 Destination of server)
>>> httpd.serve_forever()
</pre></ul>
== Classes ==
class '''SimpleHTTPRequestHandler'''
<ul><pre>
Same interface as Python class SimpleHTTPServer.SimpleHTTPRequestHandler.
</pre></ul>
== Functions ==
'''test'''(HandlerClass=SimpleHTTPRequestHandler, ServerClass= i2p.BaseHTTPServer.HTTPServer, session='mytestxxx.i2p')
<ul><pre>
Test the HTTP simple request handler class.
This runs an I2P TCP server under SAM session 'session'. If a single command
line argument is given, the argument is used instead as the SAM session name.
</pre></ul>

View File

@ -0,0 +1,22 @@
Title: User's Guide:i2p.SocketServer
Emulates Python SocketServer module using I2P sockets.
The Python module is described at http://www.python.org/doc/current/lib/module-SocketServer.html
== Classes ==
<ul><pre>
BaseRequestHandler
BaseServer
DatagramRequestHandler
ForkingMixIn
ForkingTCPServer
ForkingUDPServer
StreamRequestHandler
TCPServer
ThreadingMixIn
ThreadingTCPServer
ThreadingUDPServer
UDPServer
</pre></ul>

View File

@ -19,8 +19,8 @@ Module <code>i2p.router</code> allows Python programs to control the I2P router.
Find the absolute path to a locally installed I2P router.
An I2P installation is located by looking in the
environment I2P, then in PATH, then in the dir argument
given to the function. It looks for startRouter.sh or
dir argument given to the function, then in the environment
I2P, then in PATH. It looks for startRouter.sh or
startRouter.bat. Raises ValueError if an I2P installation
could not be located.
</pre></ul>

View File

@ -0,0 +1,27 @@
Title: User's Guide:i2p.select
Module <code>i2p.select</code> emulates the Python module <code>select</code>.
With this module, a program can perform select and poll commands on traditional and I2P sockets.
'''poll'''()
<ul>
Returns a polling object. Works on SAM sockets and Python sockets.
See [http://www.python.org/doc/current/lib/module-select.html select.poll()] in the Python library for more information.
</ul>
'''select'''(readlist, writelist, errlist, timeout=None)
<ul>
Performs a select call. Works on SAM sockets and Python sockets.
See [http://www.python.org/doc/current/lib/module-select.html select.select()] in the Python library for more information.
</ul>
'''Polling flags'''
<ul><pre>
POLLIN = 1
POLLOUT = 4
POLLERR = 8
POLLHUP = 16
POLLNVAL = 32
POLLPRI = 1
</pre></ul>

View File

@ -0,0 +1,276 @@
Title: User's Guide:i2p.socket
Module <code>i2p.socket</code> allows Python programs to access the [[SAM proxy]]. It emulates the Python module <code>socket</code>.
With this module, a program can send stream data, datagrams, and raw packets across the I2P network.
== Sockets ==
class '''socket'''(session, type, samaddr='127.0.0.1:7656', **kwargs)
<ul><pre>
Create a new socket. Argument session should be a session
name -- if the name has not yet been used, an I2P
Destination will be created for it, otherwise, the
existing Destination will be re-used. An empty session
string causes a transient session to be created. Argument
type is one of SOCK_STREAM, SOCK_DGRAM, or SOCK_RAW.
I2P configuration keyword arguments:
- in_depth - depth of incoming tunnel (default 2)
- out_depth - depth of outgoing tunnel (default 2)
A single session may be shared by more than one socket, if
the sockets are the same type, and if the sockets are
created within the same Python process. The socket
objects are multithread-safe.
Examples:
>>> a = i2p.socket('Alice', i2p.SOCK_STREAM)
>>> b = i2p.socket('Bob', i2p.SOCK_DGRAM,
in_depth=2, out_depth=5)
The created object behaves identically to a socket from
module socket, with the following exceptions:
* I2P Destinations are used as address arguments [1].
* bind is a no-op: sockets are always bound.
* send* methods send all data and are non-blocking.
A given session name can only be open in a single Python
program at a time. If you need to overcome this
limitation, consider patching I2P.
[1]. Alternatively, a host name can be used as an address.
It will be resolved using hosts.txt.
</pre>
For details on how to use socket objects, see
http://www.python.org/doc/current/lib/socket-objects.html
See the examples directory for code examples.
</ul>
The class <code>socket</code> defines the following properties:
<ul>
dest - Local I2P Destination of socket
session - Session name
type - Socket type: SOCK_STREAM, SOCK_DGRAM, or SOCK_RAW.
</ul>
The class <code>socket</code> defines the following methods:
'''accept'''(self)
<ul><pre>
Accept an incoming connection. The socket must be type SOCK_STREAM, and
listen() must be called prior to this command. The return value is (conn,
remotedest), where conn is a new socket object made for the connection, and
remotedest is the remote Destination from which the connection was made.
Example:
>>> from i2p import socket
>>> s = socket.socket('Alice', socket.SOCK_STREAM)
>>> s.listen(10)
This prepares the server. Now accept an incoming connection:
>>> c, remotedest = s.accept()
>>> c.send('hello world!')
If accept() is called on a socket that is in non-blocking mode or has a
timeout, i2p.socket.BlockError or i2p.socket.Timeout may be raised. This
indicates that no incoming connection is currently available.
</pre></ul>
'''bind'''(self, address)
<ul><pre>
Does nothing. Provided for compatibility with the Python socket command
bind(), which binds a server to a port.
</pre></ul>
'''close'''(self)
<ul><pre>
Closes the socket. It is an error to call any method other than recv() or
recvfrom() on a closed socket. For streams, the receive methods return data
that was received prior to the closing of the socket. For datagram and raw
sockets, the receive methods cannot be used on a closed socket.
</pre></ul>
'''connect'''(self, address)
<ul><pre>
Connect to a remote dest, identified in local SAM bridge's hosts file as host
'address'.
For example:
>>> s.connect('duck.i2p')
Alternatively, you can use a full base64 Destination:
Example:
>>> s.connect('238797sdfh2k34kjh....AAAA')
If connect() is called on a socket that is in non-blocking mode or has a
timeout, i2p.socket.BlockError or i2p.socket.Timeout may be raised. This
indicates that the connection is still being initiated. Use i2p.select.select()
to determine when the connection is ready.
</pre></ul>
'''connect_ex'''(self, address)
<ul><pre>
Like connect(), but return any error that is raised. Returns None if no error
is raised.
</pre></ul>
'''getpeername'''(self)
<ul><pre>
Get the remote Destination associated with the socket. This is equivalent to
s.remotedest, and is provided for compatibility with the Python socket module.
</pre></ul>
'''getsockname'''(self)
<ul><pre>
Get the local Destination associated with the socket. This is equivalent to
s.dest, and is provided for compatibility with the Python socket module.
</pre></ul>
'''gettimeout'''(self)
<ul><pre>
Get the timeout value.
</pre></ul>
'''listen'''(self, backlog)
<ul><pre>
Listen for connections made to the socket. This method must be called before
accept(). The backlog argument specifies the maximum number of queued incoming
connections.
</pre></ul>
'''makefile'''(self, mode='r', bufsize=-1)
<ul><pre>
Return a file object for the socket. See socket.makefile() in the Python
documentation for more information.
</pre></ul>
'''recv'''(self, bufsize, flags=0)
<ul><pre>
Receive string data from the socket.
The maximum amount of data to be received is given by bufsize. If bufsize is
zero, this function returns an empty string immediately. If bufsize is nonzero,
this function blocks until at least one character is available for reading. If
the socket has been closed, an empty string is returned as an end of file
indicator.
If recv() is called on a socket that is in non-blocking mode or has a timeout,
i2p.socket.BlockError or i2p.socket.Timeout will be raised if data is not
available within the given timeframe.
For a datagram or raw socket, the first bufsize characters of the packet are
read, and the remainder of the packet is discarded. To read the entire packet,
use bufsize = -1.
For datagram and raw sockets, the packet may originate from any Destination.
Use recvfrom() with datagrams to determine the Destination from which the
packet was received.
The flags argument can be a bitwise OR of MSG_PEEK, MSG_WAITALL, and/or
MSG_DONTWAIT. MSG_PEEK indicates that any data read should not be removed from
the socket's incoming buffer. MSG_WAITALL indicates to wait for exactly bufsize
characters or an error. MSG_DONTWAIT indicates that the recv() command should
not block execution.
</pre></ul>
'''recvfrom'''(self, bufsize, flags=0)
<ul><pre>
Like recv(), but returns a tuple (data, remoteaddr), where data is the string
data received, and remoteaddr is the remote Destination.
</pre></ul>
'''send'''(self, string, flags=0)
<ul><pre>
Sends string data to a remote Destination.
For a stream, connect() must be called prior to send(). Once close() is called,
no further data can be sent, and the stream cannot be re-opened.
For datagram and raw sockets, connect() only specifies a Destination to which
packets are sent to. send() will then send a packet to the given Destination.
connect() can be used multiple times.
The send() command never blocks execution. The flags argument is ignored.
</pre></ul>
'''sendall'''(self, string, flags=0)
<ul><pre>
Identical to send().
</pre></ul>
'''sendto'''(self, string, flags, address)
<ul><pre>
Send a packet to the given Destination.
Only valid for datagram and raw sockets. The address argument should be either
a name from the hosts file, or a base64 Destination.
The sendto() command never blocks execution. The flags argument is ignored.
</pre></ul>
'''setblocking'''(self, flag)
<ul><pre>
Set blocking or non-blocking mode for the socket.
If flag is True, any method called on the socket will hang until the method has
completed. If flag is False, all methods will raise i2p.socket.BlockError() if
they cannot complete instantly.
s.setblocking(False) is equivalent to s.settimeout(0); s.setblocking(True) is
equivalent to s.settimeout(None).
</pre></ul>
'''settimeout'''(self, value)
<ul><pre>
Set a timeout for the socket.
The value argument should be a timeout value in seconds, or None. None is
equivalent to an infinite timeout.
A socket operation will raise a i2p.socket.Timeout if the operation cannot
complete within in the specified time limit.
</pre></ul>
== Functions ==
Functions defined in module <code>i2p.socket</code>:
'''resolve'''(host, samaddr='127.0.0.1:7656')
<ul>
Resolve I2P host name --> I2P Destination.
Returns the same string if host is already a Destination.
</ul>
== Errors ==
class '''Error'''(i2p.Error)
<ul><pre>
Base class for all SAM errors.
</pre></ul>
class '''BlockError'''(Error)
<ul><pre>
Socket call would have blocked.
</pre></ul>
class '''ClosedError'''(Error)
<ul><pre>
A command was used on a socket that closed gracefully.
</pre></ul>
class '''NetworkError'''(Error)
<ul><pre>
Network error occurred within I2P.
The error object is a 2-tuple: (errtag, errdesc).
errtag is a SAM error string,
errdesc is a human readable error description.
</pre></ul>
== Constants ==
'''Socket types'''
<ul><pre>
SOCK_STREAM = 1
SOCK_DGRAM = 2
SOCK_RAW = 3
</pre></ul>
'''Packet sizes'''
<ul><pre>
MAX_DGRAM = 31744 # Maximum size for datagram packet
MAX_RAW = 32768 # Maximum size for raw packet
</pre></ul>
'''Flags for recv()'''
<ul><pre>
MSG_DONTWAIT = 128 # Don't block
MSG_PEEK = 2 # Peek at incoming data
MSG_WAITALL = 64 # Wait for all data or error
</pre></ul>

View File

@ -0,0 +1,79 @@
Title: User's Guide:i2p.tunnel
Module <code>i2p.tunnel</code> allows data to be exchanged between traditional TCP sockets and I2P sockets.
== Tunnels ==
Tunnels allow stream sockets to be joined, so that connections to a listening socket are relayed to one or more sending sockets. This allows an ordinary web server to be exposed as an I2P Destination, or an I2P Destination to be bound as a local port, and so on.
class '''Tunnel'''(self, receive, make_send, nconnect=-1, timeout=60.0)
<ul><pre>
A Tunnel relays connections from a 'receive' socket to one
or more 'send' sockets. The receive socket must be bound
and listening. For each incoming connection, a new send
socket is created by calling make_send(). Data is then
exchanged between the created streams until one socket is
closed. nconnect is the maximum number of simultaneous
connections (-1 for infinite), and timeout is the time that
a single connection can last for (None allows a connection
to last forever).
Sockets must accept stream traffic and support the Python
socket interface. A separate daemonic thread is created to
manage the tunnel. For high performance, make_send() should
make a socket and connect in non-blocking mode (you should
catch and discard the i2p.socket.BlockError or socket.error due to
executing connect on a non-blocking socket).
Security Note:
A firewall is needed to maintain the end user's anonymity.
An attacker could keep a tunnel socket open by pinging it
regularly. The accepted sockets from 'receive' must prevent
this by closing down eventually.
Socket errors do not cause the Tunnel to shut down.
</pre></ul>
'''close'''()
<ul>
Close all connections made for this tunnel.
</ul>
=== Tunnel Server ===
class '''TunnelServer'''(session, port, samaddr='127.0.0.1:7656', nconnect=-1, timeout=None, **kwargs)
<ul><pre>
Tunnels incoming SAM streams --> localhost:port.
nconnect and timeout are the maximum number of connections
and maximum time per connection. All other arguments are
passed to i2p.socket.socket(). This call blocks until the
tunnel is ready.
</pre></ul>
'''TunnelServer''' properties:
<ul><pre>
dest - I2P Destination of server.
session - Session name for server.
</pre></ul>
=== Tunnel Client ===
class '''TunnelClient'''(session, port, dest, samaddr='127.0.0.1:7656', nconnect=-1, timeout=None, **kwargs)
<ul><pre>
Derived from Tunnel.
Tunnels localhost:port --> I2P Destination dest.
A session named 'session' is created locally, for purposes
of routing to 'dest'. nconnect and timeout are the maximum
number of connections and maximum time per connection. All
other arguments are passed to i2p.socket.socket(). This call
blocks until the tunnel is ready.
</pre></ul>
'''TunnelClient''' properties:
<ul><pre>
dest - Local Destination used for routing.
remotedest - Remote Destination.
session - Session name for local Destination.
</pre></ul>

View File

@ -2,15 +2,19 @@ Title: User's Guide:i2p
Package <code>i2p</code> is a container package for more specific modules.
It exports the following names:
<ul>
[[:User's Guide:i2p.sam|sam]]
[[:User's Guide:i2p.eep|eep]]
[[:User's Guide:i2p.router|router]]
[[:User's Guide:i2p#Error|Error]]
[[:User's Guide:i2p#RouterError|RouterError]]
</ul>
It contains the following modules:
<ul>
[[:User's Guide:i2p.BaseHTTPServer|i2p.BaseHTTPServer]] (Emulate Python BaseHTTPServer module)
[[:User's Guide:i2p.CGIHTTPServer|i2p.CGIHTTPServer]] (Emulate Python CGIHTTPServer module)
[[:User's Guide:i2p.eep|i2p.eep]] (Retrieve eepsites)
[[:User's Guide:i2p.router|i2p.router]] (Manage the I2P router)
[[:User's Guide:i2p.select|i2p.select]] (Emulate Python select module)
[[:User's Guide:i2p.SimpleHTTPServer|i2p.SimpleHTTPServer]] (Emulate Python SimpleHTTPServer module)
[[:User's Guide:i2p.socket|i2p.socket]] (Send and receive across the I2P network)
[[:User's Guide:i2p.SocketServer|i2p.SocketServer]] (Emulate Python SocketServer module)
[[:User's Guide:i2p.tunnel|i2p.tunnel]] (Exchange data between I2P and regular sockets)
</ul>
class '''Error'''(Exception):
<ul>
Base class for all I2P errors.

View File

@ -13,21 +13,29 @@ python setup.py install
Use:
<ul><pre>
>>> from i2p import sam
>>> s = sam.socket('Alice', sam.SOCK_STREAM)
>>> from i2p import socket
>>> s = socket.socket('Alice', socket.SOCK_STREAM)
>>> s.connect('duck.i2p')
>>> s.send('GET / HTTP/1.0\r\n\r\n')
>>> s.recv(1000)
(HTTP response from duck.i2p)
</pre></ul>
See the src/examples/ directory for more code examples.
== User's Guide ==
The following modules are available:
<ul>
[[:User's Guide:i2p|i2p]] (Container package)
[[:User's Guide:i2p.sam|i2p.sam]] (Send and receive across the I2P network)
[[:User's Guide:i2p.eep|i2p.eep]] (Retrieve eepsites)
[[:User's Guide:i2p.router|i2p.router]] (Manage the I2P router)
[[:User's Guide:i2p|i2p]] (Container package)
[[:User's Guide:i2p.BaseHTTPServer|i2p.BaseHTTPServer]] (Emulate Python BaseHTTPServer module)
[[:User's Guide:i2p.CGIHTTPServer|i2p.CGIHTTPServer]] (Emulate Python CGIHTTPServer module)
[[:User's Guide:i2p.eep|i2p.eep]] (Retrieve eepsites)
[[:User's Guide:i2p.router|i2p.router]] (Manage the I2P router)
[[:User's Guide:i2p.select|i2p.select]] (Emulate Python select module)
[[:User's Guide:i2p.SimpleHTTPServer|i2p.SimpleHTTPServer]] (Emulate Python SimpleHTTPServer module)
[[:User's Guide:i2p.socket|i2p.socket]] (Send and receive across the I2P network)
[[:User's Guide:i2p.SocketServer|i2p.SocketServer]] (Emulate Python SocketServer module)
[[:User's Guide:i2p.tunnel|i2p.tunnel]] (Exchange data between I2P and regular sockets)
</ul>

View File

@ -6,13 +6,17 @@ This directory houses the wiki text sources.
Feel free to move to any other documentation system, if
it is efficient and easy to maintain.
Ideally, one could patch pydoc to export only certain
names, in a certain order, like so:
Do not use the Monobook skin, as it is Copyrighted.
__pydoc__ = ['f', 'g'] # f() and g() documented in order
-------------------------------------------------------
This could proceed recursively for all namespaces.
The documentation made by epydoc is pretty nice.
Combine this with a second patch to make pydoc create
nice CSS, and this whole guide could be generated
directly from the sources.
Ideally, one could patch epydoc to use a more condensed
2-column format (where there are fewer pages, and it is
easier to read).
With a little work on the output, epydoc could then be
used solely for documenting this project.
Note that the docs produced by epydoc are huge.

View File

@ -1,7 +1,7 @@
#! /usr/bin/env python
from distutils.core import setup
import os
import os, sys
os.chdir('./src')

View File

@ -0,0 +1,77 @@
STASHER README
-----------------------
INSTALLING STASHER
Prerequisite:
Before you can install/run Stasher, you will first need to have installed
the I2P Python modules - available in cvs at i2p/apps/sam/python.
To install stasher, just make sure you've got the latest cvs, then type
python setup.py install
as root.
This installs the stasher engine, plus a wrapper client script called
'stasher', which setup.py will install into your execution path.
If you don't like the thought of becoming root, you could just put stasher.py
on your execution path, and/or create a symlink called 'stasher'.
Test your installation by typing 'stasher -h' - this should display
a help message.
------------------------
DOZE USERS PLEASE NOTE
You'll need to watch and see where the stasher.py
wrapper script gets installed. On my box, it ends up on d:\python23\scripts,
but on your box it'll likely go into c:\python23\scripts.
You may either update your system PATH environment variable to include your
python scripts directory, OR, you can copy stasher.py to anywhere that's
on your path.
In the explanations below, note that wherever I say to type 'stasher', you'll
need to type 'stasher.py' instead.
------------------------
WARNING
This is a very early pre-alpha test version of stasher.
It is only capable of storing or retrieving files of
less than 29k in size.
Also, files are totally insecure - anyone can overwrite any keys you
insert, and vice versa.
I'll be adding support for CHK-like and SSK-like keys in due course.
------------------------
USING STASHER
To see stasher's options, type:
stasher -h
This should dump out a verbose help message.
To start a stasher node, type:
stasher start
To shut down a stasher node, type:
stasher stop
To insert a file into stasher, type:
stasher put mykey myfile
Note, if you don't supply a filename, stasher can read
the file from standard input.
To retrieve a file from stasher, type:
stasher get mykey

View File

@ -0,0 +1 @@
qeu89U8BXS8~jlsGvr-wjMvSIcXpYZ6wX2iEmGFI2Lm9eMV-yZfoZcAAF1Ll8Ck3FvIkH3~N0OobuGjcVZTiZ5PC2~h-zGHVaBPbsnOdVjYEeCGUwxwlNW6cxZZ6SfWbjTxXrpbSjLYZtlnGTBm5cd2Qaj61~A4lcoI72kj-v9GNXD5zeCQ9PeqKJHRN5p29VR8lTh9eqoIIHlGnsllQeZieeFJEAdnydOTi1ERzm4Hftq0P47lWu2FYh3aMtxI7HLeklWrmnQ--rW0XJ~xndWl45e~DEDaIL0k2FfMEmWYPtF-8l-xBX9IwIx8uZ2tcsexxLvJCY8-RiI4wgBqSf1CxPTGJ4TYUIqTUcMv2Sku8WslAdrWSPJofHWmeAmTJdSgCe8ZwvgMLkNZVeGgEccwtCDJbe5AeyJaQDFOTLlgwhHu5ExbyUPZtNZ4nSg-~qiGnpFTdgonqEYoJF9LvSaAgSfhOS3kdtZ6kKqgMFFY8InpGgCBuc6A6c5hsfCVjAAAA

View File

@ -0,0 +1,10 @@
#! /usr/bin/env python
# wrapper script to run stasher node
# set this to the directory where you've installed stasher
stasherDir = "/path/to/my/stasher/dir"
import sys
sys.path.append(stasherDir)
import stasher
stasher.main()

View File

@ -0,0 +1,9 @@
# wrapper script to run stasher node
# set this to the directory where you've installed stasher
stasherDir = "/path/to/my/stasher/dir"
import sys
sys.path.append(stasherDir)
import stasher
stasher.main()

View File

@ -0,0 +1,46 @@
#! /usr/bin/env python
#@+leo-ver=4
#@+node:@file setup-stasher.py
#@@first
"""
This is the installation script for Stasher, a distributed
file storage framework for I2P.
"""
import sys, os
from distutils.core import setup
oldcwd = os.getcwd()
os.chdir("src")
if sys.platform == 'win32':
stasherScript = "..\\scripts\\stasher.py"
else:
stasherScript = "../scripts/stasher"
try:
import i2p
import i2p.socket
import i2p.select
except:
print "Sorry, but you don't seem to have the core I2P"
print "python library modules installed."
print "If you're installing from cvs, please go to"
print "i2p/apps/sam/python, become root, and type:"
print " python setup.py install"
print "Then, retry this installation."
sys.exit(1)
setup(name="Stasher",
version="0.0",
description="Kademlia-based P2P distributed file storage app for I2P",
author="aum",
author_email="aum_i2p@hotmail.com",
url="http://stasher.i2p",
py_modules = ['stasher', 'bencode'],
scripts = [stasherScript],
)
#@nonl
#@-node:@file setup-stasher.py
#@-leo

View File

@ -0,0 +1,254 @@
# Written by Petru Paler
# see LICENSE.txt for license information
from types import IntType, LongType, StringType, ListType, TupleType, DictType
import re
from cStringIO import StringIO
int_filter = re.compile('(0|-?[1-9][0-9]*)e')
def decode_int(x, f):
m = int_filter.match(x, f)
if m is None:
raise ValueError
return (long(m.group(1)), m.end())
string_filter = re.compile('(0|[1-9][0-9]*):')
def decode_string(x, f):
m = string_filter.match(x, f)
if m is None:
raise ValueError
l = int(m.group(1))
s = m.end()
return (x[s:s+l], s + l)
def decode_list(x, f):
r = []
while x[f] != 'e':
v, f = bdecode_rec(x, f)
r.append(v)
return (r, f + 1)
def decode_dict(x, f):
r = {}
lastkey = None
while x[f] != 'e':
k, f = decode_string(x, f)
if lastkey is not None and lastkey >= k:
raise ValueError
lastkey = k
v, f = bdecode_rec(x, f)
r[k] = v
return (r, f + 1)
def bdecode_rec(x, f):
t = x[f]
if t == 'i':
return decode_int(x, f + 1)
elif t == 'l':
return decode_list(x, f + 1)
elif t == 'd':
return decode_dict(x, f + 1)
else:
return decode_string(x, f)
def bdecode(x):
try:
r, l = bdecode_rec(x, 0)
except IndexError:
raise ValueError
if l != len(x):
raise ValueError
return r
def test_bdecode():
try:
bdecode('0:0:')
assert 0
except ValueError:
pass
try:
bdecode('ie')
assert 0
except ValueError:
pass
try:
bdecode('i341foo382e')
assert 0
except ValueError:
pass
assert bdecode('i4e') == 4L
assert bdecode('i0e') == 0L
assert bdecode('i123456789e') == 123456789L
assert bdecode('i-10e') == -10L
try:
bdecode('i-0e')
assert 0
except ValueError:
pass
try:
bdecode('i123')
assert 0
except ValueError:
pass
try:
bdecode('')
assert 0
except ValueError:
pass
try:
bdecode('i6easd')
assert 0
except ValueError:
pass
try:
bdecode('35208734823ljdahflajhdf')
assert 0
except ValueError:
pass
try:
bdecode('2:abfdjslhfld')
assert 0
except ValueError:
pass
assert bdecode('0:') == ''
assert bdecode('3:abc') == 'abc'
assert bdecode('10:1234567890') == '1234567890'
try:
bdecode('02:xy')
assert 0
except ValueError:
pass
try:
bdecode('l')
assert 0
except ValueError:
pass
assert bdecode('le') == []
try:
bdecode('leanfdldjfh')
assert 0
except ValueError:
pass
assert bdecode('l0:0:0:e') == ['', '', '']
try:
bdecode('relwjhrlewjh')
assert 0
except ValueError:
pass
assert bdecode('li1ei2ei3ee') == [1, 2, 3]
assert bdecode('l3:asd2:xye') == ['asd', 'xy']
assert bdecode('ll5:Alice3:Bobeli2ei3eee') == [['Alice', 'Bob'], [2, 3]]
try:
bdecode('d')
assert 0
except ValueError:
pass
try:
bdecode('defoobar')
assert 0
except ValueError:
pass
assert bdecode('de') == {}
assert bdecode('d3:agei25e4:eyes4:bluee') == {'age': 25, 'eyes': 'blue'}
assert bdecode('d8:spam.mp3d6:author5:Alice6:lengthi100000eee') == {'spam.mp3': {'author': 'Alice', 'length': 100000}}
try:
bdecode('d3:fooe')
assert 0
except ValueError:
pass
try:
bdecode('di1e0:e')
assert 0
except ValueError:
pass
try:
bdecode('d1:b0:1:a0:e')
assert 0
except ValueError:
pass
try:
bdecode('d1:a0:1:a0:e')
assert 0
except ValueError:
pass
try:
bdecode('i03e')
assert 0
except ValueError:
pass
try:
bdecode('l01:ae')
assert 0
except ValueError:
pass
try:
bdecode('9999:x')
assert 0
except ValueError:
pass
try:
bdecode('l0:')
assert 0
except ValueError:
pass
try:
bdecode('d0:0:')
assert 0
except ValueError:
pass
try:
bdecode('d0:')
assert 0
except ValueError:
pass
def bencode_rec(x, b):
t = type(x)
if t in (IntType, LongType):
b.write('i%de' % x)
elif t is StringType:
b.write('%d:%s' % (len(x), x))
elif t in (ListType, TupleType):
b.write('l')
for e in x:
bencode_rec(e, b)
b.write('e')
elif t is DictType:
b.write('d')
keylist = x.keys()
keylist.sort()
for k in keylist:
assert type(k) is StringType
bencode_rec(k, b)
bencode_rec(x[k], b)
b.write('e')
else:
assert 0
def bencode(x):
b = StringIO()
bencode_rec(x, b)
return b.getvalue()
def test_bencode():
assert bencode(4) == 'i4e'
assert bencode(0) == 'i0e'
assert bencode(-10) == 'i-10e'
assert bencode(12345678901234567890L) == 'i12345678901234567890e'
assert bencode('') == '0:'
assert bencode('abc') == '3:abc'
assert bencode('1234567890') == '10:1234567890'
assert bencode([]) == 'le'
assert bencode([1, 2, 3]) == 'li1ei2ei3ee'
assert bencode([['Alice', 'Bob'], [2, 3]]) == 'll5:Alice3:Bobeli2ei3eee'
assert bencode({}) == 'de'
assert bencode({'age': 25, 'eyes': 'blue'}) == 'd3:agei25e4:eyes4:bluee'
assert bencode({'spam.mp3': {'author': 'Alice', 'length': 100000}}) == 'd8:spam.mp3d6:author5:Alice6:lengthi100000eee'
try:
bencode({1: 'foo'})
assert 0
except AssertionError:
pass

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,341 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

View File

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<project basedir="." default="all" name="systray">
<target name="all" depends="clean, build" />
<target name="build" depends="jar" />
<target name="compile">
<mkdir dir="./build" />
<mkdir dir="./build/obj" />
<javac
srcdir="./src"
debug="true"
deprecation="on"
source="1.3"
target="1.3"
destdir="./build/obj"
includes="**/*.java"
classpath="./src/net/i2p/apps/systray/lib/systray4j.jar" />
</target>
<target name="jar" depends="compile">
<copy todir="./build/lib">
<fileset dir="./src/net/i2p/apps/systray/lib" includes="libsystray4j.so systray4j.dll systray4j.jar" />
</copy>
<copy todir="./build/icons">
<fileset dir="./src/net/i2p/apps/systray/icons" />
</copy>
<mkdir dir="./build/jar_temp" />
<copy todir="./build/jar_temp">
<fileset dir="./build/obj" includes="**/*.class" />
</copy>
<jar destfile="./build/lib/systray.jar" basedir="./build/jar_temp" includes="**/*">
<manifest>
<attribute name="Main-Class" value="net.i2p.apps.systray.SysTray" />
<attribute name="Class-Path" value="systray4j.jar" />
</manifest>
</jar>
<delete dir="./build/jar_temp" />
</target>
<target name="javadoc">
<mkdir dir="./build" />
<mkdir dir="./build/javadoc" />
<javadoc
sourcepath="./src"
classpath="./src:./src/net/i2p/apps/systray/systray4j.jar"
destdir="./build/javadoc"
packagenames="*"
use="true"
access="package"
splitindex="true" />
</target>
<target name="clean">
<delete dir="./build" />
</target>
</project>

View File

@ -0,0 +1,29 @@
/*
* I2P - An anonymous, secure, and fully-distributed communication network.
*
* BrowserChooser.java
* 2004 The I2P Project
* This code is public domain.
*/
package net.i2p.apps.systray;
import java.awt.FileDialog;
import java.awt.Frame;
/**
* A simple file chooser dialog.
*
* @author hypercubus
*/
public class BrowserChooser extends FileDialog {
public BrowserChooser(Frame owner, String windowTitle) {
super(owner, windowTitle);
initialize();
}
public void initialize(){
this.show();
}
}

View File

@ -0,0 +1,398 @@
/*
* I2P - An anonymous, secure, and fully-distributed communication network.
*
* ShellCommand.java
* 2004 The I2P Project
* This code is public domain.
*/
package net.i2p.apps.systray;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
/**
* Passes a command to the OS shell for execution and manages the output.
* <p>
* This class must be kept <code>gcj</code>-compatible.
*
* @author hypercubus
*/
public class ShellCommand {
private static final boolean CONSUME_OUTPUT = true;
private static final boolean NO_CONSUME_OUTPUT = false;
private static final boolean WAIT_FOR_EXIT_STATUS = true;
private static final boolean NO_WAIT_FOR_EXIT_STATUS = false;
private boolean _commandSuccessful;
private CommandThread _commandThread;
private InputStream _errorStream;
private InputStream _inputStream;
private OutputStream _outputStream;
private Process _process;
/**
* Executes a shell command in its own thread.
*
* @author hypercubus
*/
private class CommandThread extends Thread {
Object caller;
boolean consumeOutput;
String shellCommand;
CommandThread(Object caller, String shellCommand, boolean consumeOutput) {
super("CommandThread");
this.caller = caller;
this.shellCommand = shellCommand;
this.consumeOutput = consumeOutput;
}
public void run() {
_commandSuccessful = execute(shellCommand, consumeOutput, WAIT_FOR_EXIT_STATUS);
synchronized(caller) {
caller.notify(); // In case the caller is still in the wait() state.
}
return;
}
}
/**
* Consumes stream data. Instances of this class, when given the
* <code>STDOUT</code> and <code>STDERR</code> input streams of a
* <code>Runtime.exec()</code> process for example, will prevent blocking
* during a <code>Process.waitFor()</code> loop and thereby allow the
* process to exit properly. This class makes no attempt to preserve the
* consumed data.
*
* @author hypercubus
*/
private class StreamConsumer extends Thread {
private BufferedReader bufferedReader;
private InputStreamReader inputStreamReader;
public StreamConsumer(InputStream inputStream) {
super("StreamConsumer");
this.inputStreamReader = new InputStreamReader(inputStream);
this.bufferedReader = new BufferedReader(inputStreamReader);
}
public void run() {
String streamData;
try {
while ((streamData = bufferedReader.readLine()) != null) {
// Just like a Hoover.
}
} catch (IOException e) {
// Don't bother.
}
}
}
/**
* Reads data from a <code>java.io.InputStream</code> and writes it to
* <code>STDOUT</code>.
*
* @author hypercubus
*/
private class StreamReader extends Thread {
final int BUFFER_SIZE = 1024;
private BufferedReader bufferedReader;
private InputStreamReader inputStreamReader;
public StreamReader(InputStream inputStream) {
super("StreamReader");
this.inputStreamReader = new InputStreamReader(inputStream);
this.bufferedReader = new BufferedReader(inputStreamReader);
}
public void run() {
char[] buffer = new char[BUFFER_SIZE];
int bytesRead;
try {
while (true)
while ((bytesRead = bufferedReader.read(buffer, 0, BUFFER_SIZE)) != -1)
for (int i = 0; i < bytesRead; i++)
System.out.print(buffer[i]); // TODO Pipe this to the calling thread instead of STDOUT
} catch (IOException e) {
// Don't bother.
}
}
}
/**
* Reads data from <code>STDIN</code> and writes it to a
* <code>java.io.OutputStream</code>.
*
* @author hypercubus
*/
private class StreamWriter extends Thread {
private BufferedWriter bufferedWriter;
private BufferedReader in;
private OutputStreamWriter outputStreamWriter;
public StreamWriter(OutputStream outputStream) {
super("StreamWriter");
this.outputStreamWriter = new OutputStreamWriter(outputStream);
this.bufferedWriter = new BufferedWriter(outputStreamWriter);
}
public void run() {
String input;
in = new BufferedReader(new InputStreamReader(System.in));
try {
while (true) {
input = in.readLine() + "\r\n";
bufferedWriter.write(input, 0, input.length());
bufferedWriter.flush();
}
} catch (Exception e) {
try {
bufferedWriter.flush();
} catch (IOException e1) {
// Eat it.
}
}
}
}
/**
* Passes a command to the shell for execution and returns immediately
* without waiting for an exit status. All output produced by the
* executed command will go to <code>STDOUT</code> and <code>STDERR</code>
* as appropriate, and can be read via {@link #getOutputStream()} and
* {@link #getErrorStream()}, respectively. Input can be passed to the
* <code>STDIN</code> of the shell process via {@link #getInputStream()}.
*
* @param _shellCommand The command for the shell to execute.
*/
public void execute(String shellCommand) {
execute(shellCommand, NO_CONSUME_OUTPUT, NO_WAIT_FOR_EXIT_STATUS);
}
/**
* Passes a command to the shell for execution. This method blocks until
* all of the command's resulting shell processes have completed. All output
* produced by the executed command will go to <code>STDOUT</code> and
* <code>STDERR</code> as appropriate, and can be read via
* {@link #getOutputStream()} and {@link #getErrorStream()}, respectively.
* Input can be passed to the <code>STDIN</code> of the shell process via
* {@link #getInputStream()}.
*
* @param _shellCommand The command for the shell to execute.
* @return <code>true</code> if the spawned shell process
* returns an exit status of 0 (indicating success),
* else <code>false</code>.
*/
public boolean executeAndWait(String shellCommand) {
if (execute(shellCommand, NO_CONSUME_OUTPUT, WAIT_FOR_EXIT_STATUS))
return true;
return false;
}
/**
* Passes a command to the shell for execution. This method blocks until
* all of the command's resulting shell processes have completed, unless a
* specified number of seconds has elapsed first. All output produced by the
* executed command will go to <code>STDOUT</code> and <code>STDERR</code>
* as appropriate, and can be read via {@link #getOutputStream()} and
* {@link #getErrorStream()}, respectively. Input can be passed to the
* <code>STDIN</code> of the shell process via {@link #getInputStream()}.
*
* @param _shellCommand The command for the shell to execute.
* @param seconds The method will return <code>true</code> if this
* number of seconds elapses without the process
* returning an exit status. A value of <code>0</code>
* here disables waiting.
* @return <code>true</code> if the spawned shell process
* returns an exit status of 0 (indicating success),
* else <code>false</code>.
*/
public synchronized boolean executeAndWaitTimed(String shellCommand, int seconds) {
_commandThread = new CommandThread(Thread.currentThread(), shellCommand, NO_CONSUME_OUTPUT);
_commandThread.start();
try {
if (seconds > 0) {
wait(seconds * 1000);
return true;
}
} catch (InterruptedException e) {
// Wake up, time to die.
}
if (_commandSuccessful)
return true;
return false;
}
/**
* Passes a command to the shell for execution and returns immediately
* without waiting for an exit status. Any output produced by the executed
* command will not be displayed.
*
* @param _shellCommand The command for the shell to execute.
* @throws IOException
*/
public void executeSilent(String shellCommand) throws IOException {
Runtime.getRuntime().exec(shellCommand, null);
}
/**
* Passes a command to the shell for execution. This method blocks until
* all of the command's resulting shell processes have completed. Any output
* produced by the executed command will not be displayed.
*
* @param _shellCommand The command for the shell to execute.
* @return <code>true</code> if the spawned shell process
* returns an exit status of 0 (indicating success),
* else <code>false</code>.
*/
public boolean executeSilentAndWait(String shellCommand) {
if (execute(shellCommand, CONSUME_OUTPUT, WAIT_FOR_EXIT_STATUS))
return true;
return false;
}
/**
* Passes a command to the shell for execution. This method blocks until
* all of the command's resulting shell processes have completed unless a
* specified number of seconds has elapsed first. Any output produced by the
* executed command will not be displayed.
*
* @param _shellCommand The command for the shell to execute.
* @param seconds The method will return <code>true</code> if this
* number of seconds elapses without the process
* returning an exit status. A value of <code>0</code>
* here disables waiting.
* @return <code>true</code> if the spawned shell process
* returns an exit status of 0 (indicating success),
* else <code>false</code>.
*/
public synchronized boolean executeSilentAndWaitTimed(String shellCommand, int seconds) {
_commandThread = new CommandThread(Thread.currentThread(), shellCommand, CONSUME_OUTPUT);
_commandThread.start();
try {
if (seconds > 0) {
wait(seconds * 1000);
return true;
}
} catch (InterruptedException e) {
// Wake up, time to die.
}
if (_commandSuccessful)
return true;
return false;
}
public InputStream getErrorStream() {
return _errorStream;
}
public InputStream getInputStream() {
return _inputStream;
}
public OutputStream getOutputStream() {
return _outputStream;
}
private synchronized boolean execute(String shellCommand, boolean consumeOutput, boolean waitForExitStatus) {
StreamConsumer processStderrConsumer;
StreamConsumer processStdoutConsumer;
StreamReader processStderrReader;
StreamWriter processStdinWriter;
StreamReader processStdoutReader;
try {
_process = Runtime.getRuntime().exec(shellCommand, null);
if (consumeOutput) {
processStderrConsumer = new StreamConsumer(_process.getErrorStream());
processStderrConsumer.start();
processStdoutConsumer = new StreamConsumer(_process.getInputStream());
processStdoutConsumer.start();
} else {
/*
* Will the following stream readers allow _process to return
* just as if _process's streams had been consumed as above? If
* so, get rid of the stream consumers and just use the
* following for all cases.
*/
_errorStream = _process.getErrorStream();
_inputStream = _process.getInputStream();
_outputStream = _process.getOutputStream();
processStderrReader = new StreamReader(_errorStream);
processStderrReader.start();
processStdinWriter = new StreamWriter(_outputStream);
processStdinWriter.start();
processStdoutReader = new StreamReader(_inputStream);
processStdoutReader.start();
}
if (waitForExitStatus) {
try {
_process.waitFor();
} catch (Exception e) {
if (!consumeOutput) {
_errorStream.close();
_errorStream = null;
_inputStream.close();
_inputStream = null;
_outputStream.close();
_outputStream = null;
}
return false;
}
if (!consumeOutput) {
_errorStream.close();
_errorStream = null;
_inputStream.close();
_inputStream = null;
_outputStream.close();
_outputStream = null;
}
if (_process.exitValue() > 0)
return false;
}
} catch (Exception e) {
return false;
}
return true;
}
}

View File

@ -0,0 +1,109 @@
/*
* I2P - An anonymous, secure, and fully-distributed communication network.
*
* SysTray.java
* 2004 The I2P Project
* This code is public domain.
*/
package net.i2p.apps.systray;
import java.awt.Frame;
import snoozesoft.systray4j.SysTrayMenu;
import snoozesoft.systray4j.SysTrayMenuEvent;
import snoozesoft.systray4j.SysTrayMenuIcon;
import snoozesoft.systray4j.SysTrayMenuItem;
import snoozesoft.systray4j.SysTrayMenuListener;
/**
* A system tray control for launching the I2P router console.
*
* @author hypercubus
*
* TODO Add a menu entry and dialog to let the user specify the location of their preferred web browser.
*/
public class SysTray implements SysTrayMenuListener {
private static String _browserString;
private BrowserChooser _browserChooser;
private Frame _frame;
private SysTrayMenuItem _itemExit = new SysTrayMenuItem("Exit systray", "exit");
private SysTrayMenuItem _itemSelectBrowser = new SysTrayMenuItem("Select preferred browser...", "selectbrowser");
private SysTrayMenuIcon _sysTrayMenuIcon = new SysTrayMenuIcon("../icons/iggy");
private SysTrayMenu _sysTrayMenu = new SysTrayMenu(_sysTrayMenuIcon, "I2P Router Console");
public SysTray() {
_sysTrayMenuIcon.addSysTrayMenuListener(this);
createSysTrayMenu();
}
public static void main(String[] args) {
new SysTray();
if (args.length == 1)
_browserString = args[0];
while(true)
try {
Thread.sleep(2 * 1000);
} catch (InterruptedException e) {
// blah
}
}
public void iconLeftClicked(SysTrayMenuEvent e) {}
public void iconLeftDoubleClicked(SysTrayMenuEvent e) {
if (_browserString == null || _browserString.equals("browser default")) {
try {
new UrlLauncher().openUrl("http://localhost:7657");
} catch (Exception ex) {
setBrowser(promptForBrowser("Please select another browser"));
}
} else {
try {
new UrlLauncher().openUrl("http://localhost:7657", _browserString);
} catch (Exception ex) {
setBrowser(promptForBrowser("Please select another browser"));
}
}
}
public void menuItemSelected(SysTrayMenuEvent e) {
if (e.getActionCommand().equals("exit")) {
_browserChooser = null;
_frame = null;
_itemExit = null;
_itemSelectBrowser = null;
_sysTrayMenuIcon = null;
_sysTrayMenu = null;
_browserChooser = null;
_frame = null;
System.exit(0);
} else if (e.getActionCommand().equals("selectbrowser")) {
setBrowser(promptForBrowser("Select preferred browser"));
}
}
private void createSysTrayMenu() {
_itemSelectBrowser.addSysTrayMenuListener(this);
_itemExit.addSysTrayMenuListener(this);
_sysTrayMenu.addItem(_itemExit);
_sysTrayMenu.addSeparator();
_sysTrayMenu.addItem(_itemSelectBrowser);
}
private String promptForBrowser(String windowTitle) {
_frame = new Frame();
_browserChooser = new BrowserChooser(_frame, windowTitle);
return _browserChooser.getDirectory() + _browserChooser.getFile();
}
private void setBrowser(String browser) {
_browserString = browser;
// change "clientApp.3.args=browser" property in clients.config here.
// System.out.println("User chose browser: " + browser);
}
}

View File

@ -0,0 +1,90 @@
/*
* I2P - An anonymous, secure, and fully-distributed communication network.
*
* UrlLauncher.java
* 2004 The I2P Project
* This code is public domain.
*/
package net.i2p.apps.systray;
/**
* A quick and simple multi-platform URL launcher. It attempts to launch the
* default browser for the host platform first, then popular third-party
* browsers if that was not successful.
* <p>
* Handles Galeon, Internet Explorer, Konqueror, Links, Lynx, Mozilla, Mozilla
* Firefox, Netscape, Opera, and Safari.
*
* @author hypercubus
*/
public class UrlLauncher {
ShellCommand _shellCommand = new ShellCommand();
/**
* Discovers the operating system the installer is running under and tries
* to launch the given URL using the default browser for that platform; if
* unsuccessful, an attempt is made to launch the URL using the most common
* browsers.
*/
public boolean openUrl(String url) throws Exception {
String osName = System.getProperty("os.name");
if (osName.toLowerCase().indexOf("mac") > -1) {
if (osName.toLowerCase().startsWith("mac os x")) {
if (_shellCommand.executeSilentAndWaitTimed("safari " + url, 5))
return true;
} else {
return false;
}
if (_shellCommand.executeSilentAndWaitTimed("iexplore " + url, 5))
return true;
} else if (osName.startsWith("Windows")) {
if (_shellCommand.executeSilentAndWaitTimed("\"C:\\Program Files\\Internet Explorer\\iexplore.exe\" " + url, 5))
return true;
} else {
if (_shellCommand.executeSilentAndWaitTimed("konqueror " + url, 5))
return true;
if (_shellCommand.executeSilentAndWaitTimed("galeon " + url, 5))
return true;
}
if (_shellCommand.executeSilentAndWaitTimed("firefox " + url, 5))
return true;
if (_shellCommand.executeSilentAndWaitTimed("opera -newpage " + url, 5))
return true;
if (_shellCommand.executeSilentAndWaitTimed("mozilla " + url, 5))
return true;
if (_shellCommand.executeSilentAndWaitTimed("netscape " + url, 5))
return true;
if (_shellCommand.executeSilentAndWaitTimed("links " + url, 5))
return true;
if (_shellCommand.executeSilentAndWaitTimed("lynx " + url, 5))
return true;
return false;
}
public boolean openUrl(String url, String browser) throws Exception {
// System.out.println("Launching: '" + browser + " " + url + "'");
if (_shellCommand.executeSilentAndWaitTimed(browser + " " + url, 5))
return true;
return false;
}
}

View File

@ -0,0 +1 @@
java -cp systray4j.jar;. -Djava.library.path=. -jar systray.jar

View File

@ -0,0 +1 @@
java -cp systray4j.jar:. -Djava.library.path=. -jar systray.jar

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1,210 @@
/* XPM */
static char * iggy_24x24_xpm[] = {
"24 24 183 2",
" c None",
". c #717120",
"+ c #8A8A08",
"@ c #959500",
"# c #88880C",
"$ c #6A6A23",
"% c #555615",
"& c #C9C902",
"* c #FDFD00",
"= c #FFFF00",
"- c #FCFC00",
"; c #C0C001",
"> c #5A5A25",
", c #565610",
"' c #E6E600",
") c #E2E201",
"! c #5A5A1F",
"~ c #CACA03",
"{ c #C8C803",
"] c #747414",
"^ c #F9F900",
"/ c #C9C90D",
"( c #C9C90F",
"_ c #FAFA00",
": c #D5D50A",
"< c #A8A859",
"[ c #A6A63D",
"} c #EEEE01",
"| c #767616",
"1 c #ACAC0A",
"2 c #B2B22C",
"3 c #DADAD8",
"4 c #DDDDDC",
"5 c #B7B730",
"6 c #B0B080",
"7 c #FEFEFE",
"8 c #F6F6F6",
"9 c #B0B032",
"0 c #AEAE0A",
"a c #C9C900",
"b c #B2B275",
"c c #D1D1D1",
"d c #B9B97C",
"e c #9F9F81",
"f c #8C8C8C",
"g c #FCFCFC",
"h c #B1B13F",
"i c #D2D200",
"j c #CDCD00",
"k c #B2B22A",
"l c #DBDBDB",
"m c #575756",
"n c #B4B429",
"o c #BDBD11",
"p c #7C7C5E",
"q c #A7A76D",
"r c #E2E205",
"s c #D7D700",
"t c #B6B605",
"u c #C6C601",
"v c #C5C500",
"w c #BBBB05",
"x c #858510",
"y c #868611",
"z c #5C5C34",
"A c #E4E400",
"B c #E3E300",
"C c #48481D",
"D c #76770C",
"E c #F8F800",
"F c #F6F600",
"G c #747416",
"H c #514745",
"I c #746506",
"J c #EDED00",
"K c #735809",
"L c #592732",
"M c #6F2F3F",
"N c #960D2F",
"O c #CD0134",
"P c #DA0037",
"Q c #7F5F08",
"R c #E7E700",
"S c #C2BF01",
"T c #917A06",
"U c #901D1D",
"V c #EA003B",
"W c #FE0040",
"X c #CF1242",
"Y c #8B092A",
"Z c #F6003E",
"` c #FF0040",
" . c #E20039",
".. c #A49A03",
"+. c #FEFE00",
"@. c #7F4E0D",
"#. c #B0002C",
"$. c #C50032",
"%. c #EF003C",
"&. c #83233B",
"*. c #6C2839",
"=. c #FB003F",
"-. c #FC003F",
";. c #B2002D",
">. c #CA0033",
",. c #A40F25",
"'. c #E2E200",
"). c #EEEE00",
"!. c #940B23",
"~. c #F2003D",
"{. c #F7003E",
"]. c #88243D",
"^. c #732C3E",
"/. c #F5003E",
"(. c #7E0020",
"_. c #890022",
":. c #572C0C",
"<. c #A9A402",
"[. c #D80036",
"}. c #920025",
"|. c #682234",
"1. c #790B26",
"2. c #CD0034",
"3. c #ED003B",
"4. c #92102C",
"5. c #C39C76",
"6. c #A78861",
"7. c #4E1E17",
"8. c #F1003C",
"9. c #890023",
"0. c #CC0234",
"a. c #2A1E19",
"b. c #7E6D31",
"c. c #776C22",
"d. c #73041F",
"e. c #E50039",
"f. c #DE0038",
"g. c #BF0030",
"h. c #6F001C",
"i. c #A40029",
"j. c #6F192E",
"k. c #3A3B2D",
"l. c #969703",
"m. c #7C8218",
"n. c #687560",
"o. c #6C7360",
"p. c #372C28",
"q. c #6D7561",
"r. c #7B8E74",
"s. c #819D7E",
"t. c #7D9C7D",
"u. c #6F5C46",
"v. c #96775A",
"w. c #484445",
"x. c #809F80",
"y. c #BAE8BA",
"z. c #CCFFCC",
"A. c #6A8369",
"B. c #AAD5AA",
"C. c #B1DDB1",
"D. c #565441",
"E. c #584F46",
"F. c #546254",
"G. c #BDECBD",
"H. c #8CAE8C",
"I. c #95BA95",
"J. c #B9E7B9",
"K. c #525C52",
"L. c #5B6B5B",
"M. c #A3CCA3",
"N. c #B2DEB2",
"O. c #9BC29B",
"P. c #728E72",
"Q. c #A5CEA5",
"R. c #90B490",
"S. c #4E5D4E",
"T. c #121212",
"U. c #000000",
"V. c #030303",
"W. c #020202",
"X. c #161616",
"Y. c #282828",
"Z. c #3F3F3F",
" . + @ # $ ",
" % & * = = = - ; > ",
" , ' = = = = = = = ) ! ",
" ~ = = = = = = = = = { ",
" ] * ^ / ( _ = : < [ } * | ",
" 1 = 2 3 4 5 = 6 7 8 9 = 0 ",
" a = b 7 c d = e f g h = i ",
" j = k l m n = o p q r = s ",
" t = * u v = = = = = = = w ",
" x = = = = = = = = = = = y ",
" z A = = = = = = = = = B C ",
" D E = = = = = = = F G ",
" H I J = = = = = ' K L ",
" M N O P Q = R s S T U V W V X ",
" Y Z ` ` ...+.@.#.$.%.` ` ` ` ` &. ",
" *.=.-.;.>.,.'.).!.` ` ` ` ` ` ~.{.]. ",
" ^.-./.(._.:.s <.[.` ` ` ` ` ` }.~.|. ",
" 1.2.3.4.5.6.7.W ` ` ` ` ` 8.9.0. ",
" a.b.c.d. .e.f.[.2.g.h.i.j. ",
" k.l.m.n.o.p.q.r.s.t.u.v.w. ",
" x.y.z.z.A.B.z.z.C.D.E. ",
" F.G.z.z.H.I.z.z.J.K. ",
" L.M.N.O.P.Q.R.S. ",
" T.U.U.U.V.W.X.Y.Z. "};

View File

@ -1,41 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project basedir="." default="all" name="time">
<target name="all" depends="clean, build" />
<target name="build" depends="builddep, jar" />
<target name="builddep">
<ant dir="../../../core/java/" target="build" />
</target>
<target name="compile">
<mkdir dir="./build" />
<mkdir dir="./build/obj" />
<javac srcdir="./src" debug="true" source="1.3" target="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">
<manifest>
<attribute name="Main-Class" value="net.i2p.time.Timestamper" />
<attribute name="Class-Path" value="i2p.jar timestamper.jar" />
</manifest>
</jar>
</target>
<target name="javadoc">
<mkdir dir="./build" />
<mkdir dir="./build/javadoc" />
<javadoc
sourcepath="./src:../../../core/java/src:../../../core/java/test" destdir="./build/javadoc"
packagenames="*"
use="true"
access="package"
splitindex="true"
windowtitle="I2P timestamper" />
</target>
<target name="clean">
<delete dir="./build" />
</target>
<target name="cleandep" depends="clean">
<ant dir="../../../core/java/" target="cleandep" />
</target>
<target name="distclean" depends="clean">
<ant dir="../../../core/java/" target="distclean" />
</target>
</project>

View File

@ -1,122 +0,0 @@
package net.i2p.time;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import net.i2p.util.I2PThread;
import net.i2p.util.Log;
/**
* Periodically query a series of NTP servers and post the offset
* to a given URL. It tries the NTP servers in order, contacting them
* using UDP port 123, and sends the current date to the URL specified
* (specifically, URL+"&now=" + yyyyMMdd_HH:mm:ss.SSS in the UK locale).
* It does this every 5 minutes, forever.
*
* Usage: <pre>
* Timestamper URL ntpServer1[ ntpServer2]*
* </pre>
*/
public class Timestamper implements Runnable {
private static Log _log = new Log(Timestamper.class);
private static String _targetURL;
private static String _serverList[];
private int DELAY_MS = 5*60*1000;
public Timestamper() {}
public void startTimestamper() {
if (_log.shouldLog(Log.INFO))
_log.info("Starting timestamper pointing at " + _targetURL);
synchronized (Timestamper.class) {
String enabled = System.getProperty("timestamper.started");
if (enabled != null) {
_log.warn("Timestamper already running");
return;
} else {
System.setProperty("timestamper.started", "true");
System.setProperty("timestamper.enabled", "true");
}
}
I2PThread t = new I2PThread(this, "Timestamper");
t.setPriority(I2PThread.MIN_PRIORITY);
t.start();
}
public void run() {
if (_log.shouldLog(Log.INFO))
_log.info("Starting up timestamper");
try {
while (true) {
String enabled = System.getProperty("timestamper.enabled");
if ( (enabled == null) || (!"true".equals(enabled)) ) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Not stamping the time");
} else {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Querying servers " + _serverList);
try {
long now = NtpClient.currentTime(_serverList);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Stamp time");
stampTime(now);
} catch (IllegalArgumentException iae) {
_log.log(Log.CRIT, "Unable to reach any of the NTP servers - network disconnected?");
}
}
try { Thread.sleep(DELAY_MS); } catch (InterruptedException ie) {}
}
} catch (Throwable t) {
_log.log(Log.CRIT, "Timestamper died!", t);
}
}
/**
* Send an HTTP request to a given URL specifying the current time
*/
private void stampTime(long now) {
try {
String toRequest = _targetURL + "&now=" + getNow(now);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Stamping [" + toRequest + "]");
URL url = new URL(toRequest);
Object o = url.getContent();
// ignore the content
} catch (MalformedURLException mue) {
_log.error("Invalid URL", mue);
} catch (IOException ioe) {
_log.error("Error stamping the time", ioe);
}
}
private SimpleDateFormat _fmt = new SimpleDateFormat("yyyyMMdd_HH:mm:ss.SSS", Locale.UK);
private String getNow(long now) {
synchronized (_fmt) {
return _fmt.format(new Date(now));
}
}
public static void main(String args[]) {
if ( (args == null) || (args.length < 2) ) {
usage();
return;
//args = new String[] { "http://dev.i2p.net:80/somePath?pass=password", "ntp1.sth.netnod.se", "ntp2.sth.netnod.se" };
}
String servers[] = new String[args.length-1];
System.arraycopy(args, 1, servers, 0, servers.length);
_targetURL = args[0];
_serverList = servers;
Timestamper ts = new Timestamper();
ts.startTimestamper();
}
private static void usage() {
System.err.println("Usage: Timestamper URL ntpServer[ ntpServer]*");
_log.error("Usage: Timestamper URL ntpServer[ ntpServer]*");
}
}

112
build.xml
View File

@ -10,11 +10,61 @@
<echo message=" dist: distclean, then build and javadoc (including the web app and associated libs)" />
<echo message=" prepGUI: pull the LGPL and APL code for JFreeChart that we use in the GUIs" />
<echo message=" buildGUI: build the heartbeat and netmonitor GUIs (must have run prepGUI already)" />
<echo message=" prepWEB: pull down the Jetty libraries and whatever they depend on for the router console web application" />
<echo message=" buildWEB: build the router console web application (depends upon prepWEB)" />
<echo message=" buildWEB: build the router console web application" />
<echo message=" pkg: make the tarball and installer jar (depends upon preppkg)" />
<echo message=" pkgclean: delete the ./pkg-temp/ dir, tarball and installer jar" />
<echo message=" preppkg: gather built files for tarball and installer (depends upon prepWEB)" />
<echo message=" tarball: tar the built files and compress with bz2 (depends upon preppkg)" />
<echo message=" installer: build the GUI installer (depends upon preppkg)" />
</target>
<target name="dist" depends="distclean, build, buildWEB, javadoc" />
<target name="build" depends="builddep, jar" />
<target name="dist" depends="distclean, build, buildWEB, javadoc">
<delete dir="build/lib" />
<delete dir="build/webapps" />
<mkdir dir="build/lib" />
<copy file="core/java/build/i2p.jar" todir="build/lib" />
<copy file="router/java/build/router.jar" todir="build/lib" />
<copy file="apps/ministreaming/java/build/mstreaming.jar" todir="build/lib" />
<copy file="apps/i2ptunnel/java/build/i2ptunnel.jar" todir="build/lib" />
<copy file="apps/sam/java/build/sam.jar" todir="build/lib" />
<copy file="apps/heartbeat/java/build/heartbeat.jar" todir="build/lib" />
<copy file="apps/netmonitor/java/build/netmonitor.jar" todir="build/lib" />
<copy file="installer/java/build/fetchseeds.jar" todir="build/lib" />
<tar compression="bzip2" destfile="build/lib.tar.bz2">
<tarfileset dir="build" includes="lib/*" />
</tar>
<delete dir="build/lib" />
<delete dir="build/webapps" />
<mkdir dir="build/lib" />
<mkdir dir="build/webapps" />
<copy file="apps/i2ptunnel/java/build/i2ptunnel.war" todir="build/webapps" />
<copy file="apps/routerconsole/java/build/routerconsole.war" todir="build/webapps" />
<copy file="apps/routerconsole/java/build/routerconsole.jar" todir="build/lib" />
<tar compression="bzip2" destfile="build/webapps.tar.bz2">
<tarfileset dir="build" includes="lib/* webapps/*" />
</tar>
<delete dir="build/lib" />
<delete dir="build/webapps" />
<mkdir dir="build/lib" />
<copy file="apps/jetty/jettylib/org.mortbay.jetty.jar" todir="build/lib" />
<copy file="apps/jetty/jettylib/org.mortbay.jetty-jdk1.2.jar" todir="build/lib" />
<copy file="apps/jetty/jettylib/ant.jar" todir="build/lib" />
<copy file="apps/jetty/jettylib/jasper-compiler.jar" todir="build/lib" />
<copy file="apps/jetty/jettylib/jasper-runtime.jar" todir="build/lib" />
<copy file="apps/jetty/jettylib/jnet.jar" todir="build/lib" />
<copy file="apps/jetty/jettylib/xercesImpl.jar" todir="build/lib" />
<copy file="apps/jetty/jettylib/xml-apis.jar" todir="build/lib" />
<copy file="apps/jetty/jettylib/javax.servlet.jar" todir="build/lib" />
<tar compression="bzip2" destfile="build/weblib.tar.bz2">
<tarfileset dir="build" includes="lib/*" />
</tar>
</target>
<target name="build" depends="builddep, jar, buildWEB" />
<target name="buildclean" depends="distclean, build" />
<target name="builddep">
<!-- build *everything* here, but only once -->
@ -22,12 +72,9 @@
<ant dir="router/java/" target="jar" />
<ant dir="apps/ministreaming/java/" target="jar" />
<ant dir="apps/i2ptunnel/java/" target="jar" />
<ant dir="apps/httptunnel/java/" target="jar" />
<ant dir="apps/phttprelay/java/" target="jar" />
<ant dir="apps/sam/java/" target="jar" />
<ant dir="apps/heartbeat/java/" target="jar" />
<ant dir="apps/netmonitor/java/" target="jar" />
<ant dir="apps/time/java/" target="jar" />
<ant dir="apps/routerconsole/java/" target="jar" />
<ant dir="installer/java/" target="jar" />
</target>
@ -38,12 +85,9 @@
<copy file="apps/ministreaming/java/build/mstreaming.jar" todir="build/" />
<copy file="apps/i2ptunnel/java/build/i2ptunnel.jar" todir="build/" />
<copy file="apps/i2ptunnel/java/build/i2ptunnel.war" todir="build/" />
<copy file="apps/httptunnel/java/build/httptunnel.jar" todir="build/" />
<copy file="apps/phttprelay/java/build/phttprelay.war" todir="build/" />
<copy file="apps/sam/java/build/sam.jar" todir="build/" />
<copy file="apps/heartbeat/java/build/heartbeat.jar" todir="build/" />
<copy file="apps/netmonitor/java/build/netmonitor.jar" todir="build/" />
<copy file="apps/time/java/build/timestamper.jar" todir="build/" />
<copy file="installer/java/build/install.jar" todir="build/" />
<copy file="installer/java/build/guiinstall.jar" todir="build/" />
<copy file="installer/java/build/fetchseeds.jar" todir="build/" />
@ -60,7 +104,7 @@
splitindex="true"
windowtitle="I2P" />
</target>
<target name="clean">
<target name="clean" depends="pkgclean" >
<delete dir="./build" />
</target>
<target name="distclean" depends="clean">
@ -68,13 +112,10 @@
<ant dir="router/java/" target="distclean" />
<ant dir="apps/ministreaming/java/" target="distclean" />
<ant dir="apps/i2ptunnel/java/" target="distclean" />
<ant dir="apps/httptunnel/java/" target="distclean" />
<ant dir="apps/phttprelay/java/" target="distclean" />
<ant dir="apps/sam/java/" target="distclean" />
<ant dir="apps/heartbeat/java/" target="distclean" />
<ant dir="apps/netmonitor/java/" target="distclean" />
<ant dir="apps/routerconsole/java/" target="distclean" />
<ant dir="apps/time/java/" target="distclean" />
<ant dir="installer/java/" target="distclean" />
<delete>
<fileset dir="." includes="**/*.class" />
@ -118,7 +159,7 @@
<target name="prepWEB">
<ant dir="apps/jetty" target="fetchJettylib" />
</target>
<target name="buildWEB" >
<target name="buildWEB" depends="prepWEB" >
<available property="jettylib.available" file="apps/jetty/jettylib" />
<ant target="doBuildWEB" />
</target>
@ -140,4 +181,45 @@
<echo message="routerconsole.war file under your i2p install dir as webapps/routerconsole.war and will want " />
<echo message="to add the RouterConsoleRunner to the router's clientApp list (it must be in the router's JVM)" />
</target>
<target name="pkg" depends="tarball, installer" />
<target name="pkgclean">
<delete dir="pkg-temp" />
<delete>
<fileset dir="." includes="i2p.tar.bz2 install.jar" />
</delete>
</target>
<target name="preppkg" depends="build, buildWEB">
<copy file="build/ant.jar" todir="pkg-temp/lib/" />
<copy file="build/heartbeat.jar" todir="pkg-temp/lib/" />
<copy file="build/i2p.jar" todir="pkg-temp/lib/" />
<copy file="build/i2ptunnel.jar" todir="pkg-temp/lib/" />
<copy file="build/jasper-compiler.jar" todir="pkg-temp/lib/" />
<copy file="build/jasper-runtime.jar" todir="pkg-temp/lib/" />
<copy file="build/javax.servlet.jar" todir="pkg-temp/lib/" />
<copy file="build/jnet.jar" todir="pkg-temp/lib/" />
<copy file="build/mstreaming.jar" todir="pkg-temp/lib/" />
<copy file="build/netmonitor.jar" todir="pkg-temp/lib/" />
<copy file="build/org.mortbay.jetty-jdk1.2.jar" todir="pkg-temp/lib/" />
<copy file="build/org.mortbay.jetty.jar" todir="pkg-temp/lib/" />
<copy file="build/router.jar" todir="pkg-temp/lib/" />
<copy file="build/routerconsole.jar" todir="pkg-temp/lib/" />
<copy file="build/sam.jar" todir="pkg-temp/lib/" />
<copy file="build/xercesImpl.jar" todir="pkg-temp/lib/" />
<copy file="build/xml-apis.jar" todir="pkg-temp/lib/" />
<copy file="build/i2ptunnel.war" todir="pkg-temp/webapps/" />
<copy file="build/routerconsole.war" todir="pkg-temp/webapps/" />
<copy file="hosts.txt" todir="pkg-temp/" />
<copy file="installer/resources/i2ptunnel.config" todir="pkg-temp/" />
<copy file="installer/resources/clients.config" todir="pkg-temp/" />
<copy file="readme.txt" todir="pkg-temp/" />
</target>
<target name="tarball" depends="preppkg">
<tar compression="bzip2" destfile="i2p.tar.bz2">
<tarfileset dir="pkg-temp" includes="**/*" prefix="i2p" />
</tar>
</target>
<taskdef name="izpack" classpath="${basedir}/installer/lib/izpack/standalone-compiler.jar" classname="com.izforge.izpack.ant.IzPackTask" />
<target name="installer" depends="preppkg">
<izpack input="${basedir}/installer/install.xml" output="${basedir}/install.jar" installerType="standard" basedir="${basedir}" />
</target>
</project>

View File

@ -14,8 +14,8 @@ package net.i2p;
*
*/
public class CoreVersion {
public final static String ID = "$Revision: 1.15 $ $Date: 2004/07/29 16:37:19 $";
public final static String VERSION = "0.3.4.1";
public final static String ID = "$Revision: 1.17 $ $Date: 2004/08/12 21:15:54 $";
public final static String VERSION = "0.3.4.3";
public static void main(String args[]) {
System.out.println("I2P Core version: " + VERSION);

View File

@ -43,11 +43,14 @@ public class Base64 {
private final static Log _log = new Log(Base64.class);
public static String encode(byte[] source) {
return safeEncode(source);
return encode(source, false);
}
public static String encode(byte[] source, boolean useStandardAlphabet) {
return safeEncode(source, useStandardAlphabet);
}
public static byte[] decode(String s) {
return safeDecode(s);
return safeDecode(s, false);
}
/** Maximum line length (76) of Base64 output. */
@ -315,10 +318,14 @@ public class Base64 {
* Same as encodeBytes, except uses a filesystem / URL friendly set of characters,
* replacing / with ~, and + with -
*/
private static String safeEncode(byte[] source) {
private static String safeEncode(byte[] source, boolean useStandardAlphabet) {
String encoded = encodeBytes(source);
encoded = encoded.replace('/', '~');
encoded = encoded.replace('+', '-');
if (useStandardAlphabet) {
// noop
} else {
encoded = encoded.replace('/', '~');
encoded = encoded.replace('+', '-');
}
return encoded;
}
@ -326,9 +333,14 @@ public class Base64 {
* Same as decode, except from a filesystem / URL friendly set of characters,
* replacing / with ~, and + with -
*/
private static byte[] safeDecode(String source) {
String toDecode = source.replace('~', '/');
toDecode = toDecode.replace('-', '+');
private static byte[] safeDecode(String source, boolean useStandardAlphabet) {
String toDecode = null;
if (useStandardAlphabet) {
toDecode = source;
} else {
toDecode = source.replace('~', '/');
toDecode = toDecode.replace('-', '+');
}
return standardDecode(toDecode);
}

View File

@ -9,10 +9,15 @@ package net.i2p.data;
*
*/
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.util.ArrayList;
@ -129,6 +134,31 @@ public class DataHelper {
return buf.toString();
}
/**
* A more efficient Properties.load
*
*/
public static void loadProps(Properties props, File file) throws IOException {
BufferedReader in = null;
try {
in = new BufferedReader(new InputStreamReader(new FileInputStream(file)), 16*1024);
String line = null;
while ( (line = in.readLine()) != null) {
if (line.trim().length() <= 0) continue;
if (line.charAt(0) == '#') continue;
int split = line.indexOf('=');
if (split <= 0) continue;
String key = line.substring(0, split);
String val = line.substring(split+1);
if ( (key.length() > 0) && (val.length() > 0) )
props.setProperty(key, val);
}
} finally {
if (in != null) try { in.close(); } catch (IOException ioe) {}
}
}
/**
* Pretty print the collection
*
@ -528,6 +558,16 @@ public class DataHelper {
return (ms / (24 * 60 * 60 * 1000)) + "d";
}
}
/**
* Strip out any HTML (simply removing any less than / greater than symbols)
*/
public static String stripHTML(String orig) {
if (orig == null) return "";
String t1 = orig.replace('<', ' ');
String rv = t1.replace('>', ' ');
return rv;
}
/** compress the data and return a new GZIP compressed array */
public static byte[] compress(byte orig[]) {

View File

@ -1,5 +1,33 @@
package net.i2p.time;
/*
* Copyright (c) 2004, Adam Buckley
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Adam Buckley nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.DatagramPacket;
@ -17,20 +45,6 @@ import java.net.InetAddress;
* Note that on windows platforms, the curent time-of-day timestamp is limited
* to an resolution of 10ms and adversely affects the accuracy of the results.
*
*
* This code is copyright (c) Adam Buckley 2004
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version. A HTML version of the GNU General Public License can be
* seen at http://www.gnu.org/licenses/gpl.html
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* @author Adam Buckley
* (minor refactoring by jrandom)
*/

View File

@ -1,4 +1,33 @@
package net.i2p.time;
/*
* Copyright (c) 2004, Adam Buckley
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Adam Buckley nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
@ -34,21 +63,6 @@ import java.util.Date;
* socket.receive(packet);
* System.out.println(msg.toString());
*
*
* This code is copyright (c) Adam Buckley 2004
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version. A HTML version of the GNU General Public License can be
* seen at http://www.gnu.org/licenses/gpl.html
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*
* Comments for member variables are taken from RFC2030 by David Mills,
* University of Delaware.
*

View File

@ -0,0 +1,197 @@
package net.i2p.time;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import net.i2p.I2PAppContext;
import net.i2p.util.I2PThread;
import net.i2p.util.Log;
/**
* Periodically query a series of NTP servers and update any associated
* listeners. It tries the NTP servers in order, contacting them using
* SNTP (UDP port 123). By default, it does this every 5 minutes,
* forever.
*/
public class Timestamper implements Runnable {
private I2PAppContext _context;
private Log _log;
private List _servers;
private List _listeners;
private int _queryFrequency;
private boolean _disabled;
private boolean _daemon;
private static final int DEFAULT_QUERY_FREQUENCY = 5*60*1000;
private static final String DEFAULT_SERVER_LIST = "pool.ntp.org, pool.ntp.org";
private static final boolean DEFAULT_DISABLED = false;
public static final String PROP_QUERY_FREQUENCY = "time.queryFrequencyMs";
public static final String PROP_SERVER_LIST = "time.sntpServerList";
public static final String PROP_DISABLED = "time.disabled";
public Timestamper(I2PAppContext ctx) {
this(ctx, null, true);
}
public Timestamper(I2PAppContext ctx, UpdateListener lsnr) {
this(ctx, lsnr, true);
}
public Timestamper(I2PAppContext ctx, UpdateListener lsnr, boolean daemon) {
_context = ctx;
_daemon = daemon;
_servers = new ArrayList(1);
_listeners = new ArrayList(1);
if (lsnr != null)
_listeners.add(lsnr);
updateConfig();
startTimestamper();
}
public int getServerCount() {
synchronized (_servers) {
return _servers.size();
}
}
public String getServer(int index) {
synchronized (_servers) {
return (String)_servers.get(index);
}
}
public int getQueryFrequencyMs() { return _queryFrequency; }
public boolean getIsDisabled() { return _disabled; }
public void addListener(UpdateListener lsnr) {
synchronized (_listeners) {
_listeners.add(lsnr);
}
}
public void removeListener(UpdateListener lsnr) {
synchronized (_listeners) {
_listeners.remove(lsnr);
}
}
public int getListenerCount() {
synchronized (_listeners) {
return _listeners.size();
}
}
public UpdateListener getListener(int index) {
synchronized (_listeners) {
return (UpdateListener)_listeners.get(index);
}
}
private void startTimestamper() {
I2PThread t = new I2PThread(this, "Timestamper");
t.setPriority(I2PThread.MIN_PRIORITY);
t.setDaemon(_daemon);
t.start();
}
public void run() {
try { Thread.sleep(1000); } catch (InterruptedException ie) {}
_log = _context.logManager().getLog(Timestamper.class);
if (_log.shouldLog(Log.INFO))
_log.info("Starting timestamper");
if (_log.shouldLog(Log.INFO))
_log.info("Starting up timestamper");
try {
while (true) {
if (!_disabled) {
String serverList[] = null;
synchronized (_servers) {
serverList = new String[_servers.size()];
for (int i = 0; i < serverList.length; i++)
serverList[i] = (String)_servers.get(i);
}
if (_log.shouldLog(Log.DEBUG))
_log.debug("Querying servers " + _servers);
try {
long now = NtpClient.currentTime(serverList);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Stamp time");
stampTime(now);
} catch (IllegalArgumentException iae) {
_log.log(Log.CRIT, "Unable to reach any of the NTP servers - network disconnected?");
}
}
updateConfig();
try { Thread.sleep(_queryFrequency); } catch (InterruptedException ie) {}
}
} catch (Throwable t) {
_log.log(Log.CRIT, "Timestamper died!", t);
}
}
/**
* Send an HTTP request to a given URL specifying the current time
*/
private void stampTime(long now) {
synchronized (_listeners) {
for (int i = 0; i < _listeners.size(); i++) {
UpdateListener lsnr = (UpdateListener)_listeners.get(i);
lsnr.setNow(now);
}
}
}
/**
* Reload all the config elements from the appContext
*
*/
private void updateConfig() {
String serverList = _context.getProperty(PROP_SERVER_LIST);
if ( (serverList == null) || (serverList.trim().length() <= 0) )
serverList = DEFAULT_SERVER_LIST;
synchronized (_servers) {
_servers.clear();
StringTokenizer tok = new StringTokenizer(serverList, ",");
while (tok.hasMoreTokens()) {
String val = (String)tok.nextToken();
val = val.trim();
if (val.length() > 0)
_servers.add(val);
}
}
String freq = _context.getProperty(PROP_QUERY_FREQUENCY);
if ( (freq == null) || (freq.trim().length() <= 0) )
freq = DEFAULT_QUERY_FREQUENCY + "";
try {
int ms = Integer.parseInt(freq);
if (ms > 60*1000) {
_queryFrequency = ms;
} else {
if ( (_log != null) && (_log.shouldLog(Log.ERROR)) )
_log.error("Query frequency once every " + ms + "ms is too fast!");
_queryFrequency = DEFAULT_QUERY_FREQUENCY;
}
} catch (NumberFormatException nfe) {
if ( (_log != null) && (_log.shouldLog(Log.WARN)) )
_log.warn("Invalid query frequency [" + freq + "], falling back on " + DEFAULT_QUERY_FREQUENCY);
_queryFrequency = DEFAULT_QUERY_FREQUENCY;
}
String disabled = _context.getProperty(PROP_DISABLED);
if (disabled == null)
disabled = DEFAULT_DISABLED + "";
_disabled = Boolean.getBoolean(disabled);
}
/**
* Interface to receive update notifications for when we query the time
*
*/
public interface UpdateListener {
/**
* The time has been queried and we have a current value for 'now'
*
*/
public void setNow(long now);
}
}

View File

@ -5,6 +5,7 @@ import java.util.Iterator;
import java.util.Set;
import net.i2p.I2PAppContext;
import net.i2p.time.Timestamper;
/**
* Alternate location for determining the time which takes into account an offset.
@ -13,18 +14,23 @@ import net.i2p.I2PAppContext;
* (such as an NTP synchronized clock).
*
*/
public class Clock {
public class Clock implements Timestamper.UpdateListener {
private I2PAppContext _context;
private Timestamper _timestamper;
public Clock(I2PAppContext context) {
_context = context;
_offset = 0;
_alreadyChanged = false;
_listeners = new HashSet(64);
_timestamper = new Timestamper(context, this);
}
public static Clock getInstance() {
return I2PAppContext.getGlobalContext().clock();
}
public Timestamper getTimestamper() { return _timestamper; }
/** we fetch it on demand to avoid circular dependencies (logging uses the clock) */
private Log getLog() { return _context.logManager().getLog(Clock.class); }

View File

@ -59,7 +59,7 @@ public class LogManager {
public final static int DEFAULT_CONSOLEBUFFERSIZE = 20;
public final static String DEFAULT_ROTATIONLIMIT = "2";
public final static String DEFAULT_DEFAULTLEVEL = Log.STR_ERROR;
public final static String DEFAULT_ONSCREENLEVEL = Log.STR_ERROR;
public final static String DEFAULT_ONSCREENLEVEL = Log.STR_CRIT;
private I2PAppContext _context;
private Log _log;

View File

@ -46,10 +46,16 @@ class LogWriter implements Runnable {
public void run() {
_write = true;
rotateFile();
while (_write) {
flushRecords();
rereadConfig();
try {
rotateFile();
while (_write) {
flushRecords();
rereadConfig();
}
System.err.println("Done writing");
} catch (Exception e) {
System.err.println("Error writing the logs: " + e.getMessage());
e.printStackTrace();
}
}
@ -131,17 +137,19 @@ class LogWriter implements Runnable {
_currentFile = f;
_numBytesInCurrentFile = 0;
File parent = f.getParentFile();
if (!parent.exists()) {
boolean ok = parent.mkdirs();
if (!ok) {
System.err.println("Unable to create the parent directy: " + parent.getAbsolutePath());
if (parent != null) {
if (!parent.exists()) {
boolean ok = parent.mkdirs();
if (!ok) {
System.err.println("Unable to create the parent directy: " + parent.getAbsolutePath());
System.exit(0);
}
}
if (!parent.isDirectory()) {
System.err.println("wtf, we cannot put the logs in a subdirectory of a plain file! we want to stre the log as " + f.getAbsolutePath());
System.exit(0);
}
}
if (!parent.isDirectory()) {
System.err.println("wtf, we cannot put the logs in a subdirectory of a plain file! we want to stre the log as " + f.getAbsolutePath());
System.exit(0);
}
try {
_currentOut = new FileOutputStream(f);
} catch (IOException ioe) {

View File

@ -1,6 +1,13 @@
; TC's hosts.txt guaranteed freshness
; $Id: hosts.txt,v 1.22 2004/08/02 16:09:21 jrandom Exp $
; $Id: hosts.txt,v 1.30 2004/08/16 21:02:34 duck Exp $
; changelog:
; (1.56) added datagram_test.i2p
; (1.55) updated ardvark.i2p (after checking ID)
; (1.54) added files.nickster.i2p
; (1.53) added brittanyworld.i2p
; (1.52) added stasher.i2p
; (1.51) changed quadn.i2p to library.i2p
; (1.50) added freshcoffee.i2p
; (1.49) added ems.i2p
; (1.48) added ooo.i2p
; (1.47) added fproxy2.i2p
@ -10,7 +17,7 @@
; (1.43) added files.hypercubus.i2p
; (1.42) added www1.squid.i2p
; (1.41) added quadn.i2p
; (1.40) added nickster2.i2p and irc.nickster.i2p (pointing at iip)
; (1.40) added nickster2.i2p and irc.nickster.i2p (pointing at IIP)
; (1.39) added jdot.i2p
; (1.38) added forum.i2p
; (1.36) added ferret.i2p
@ -88,7 +95,7 @@ bt1.eco.i2p=SUHjD4QvbuY5VVTGTm49U8B~DtvTS2bwO1lREMNfJtZU6rxa4tgdqaIpUjRRrbZYLxZc
gernika.i2p=1D9ee5J04ZI7pvCwQ3hXQMpeMvbNw9cz3V2pioQ9LakwRQzfMEb9CVAeiFt-wE4HyTFWKeof5rz8F5vmIqFMaH~oMJSkCyNtwPfqiRAENeNeALHbY2plMPfqCfEFR4GkTqXnalAkJGqDjo55CokUfalEVTGMvNiv6i6dmNvwS8~0X56sXIaXgLKuGIK~UNOg9hT8A~uEGQWXwTKD3EDmECsJL40iYcT1UR9rffzuyxOvDhL12HbJ8bIlUGarzEscH-jolj5ShvZAbEyw-MnVzR9LiEqy7DaniKpPtC0oXRZuz7PpcQTqzN-zgQaLq8bHTx7NHIfTuA4P~hhz-STO4SjPot7h~Gbdglc193OmGlL5QwbfjXfdOIccBDh6~jtFaa28GxHrTMoi9GafjnllLfWpvynN1y5H7Jh7Uw3E7KDtBGVsDg9-btyvyQLP3kkqPfIAn7Oj6ePHr9u-TN9ZwDbWj~QBmXXutsE~lLu7aT7kv5Jx6PFmLEeWPib82UuGAAAA
www.aum.i2p=8x3TYbh9aq6EVo8rSuPWBVSrwD~yS1al6z0RZYvRaQFXL9hFUUJYJNL2n3oR3tBg7Zr00MjqntIuBMd20LUKasnklTp4hDlDCE0KfeftYh~bFGykMRf0yTYEWaMHYpIRBY-IJEvSVlgHe8E4AWLMv-b6VKCDZ0~0AdUrsHQ0Qb4NQ-igBPZfU6c~UU0tUVUl1Efsuz1CdAp5pw5RdPviFtPH4tMvUca2t54Rwa-6v6QCqFZ7S2awyhAa73Zb9YlcqT4hP1JHF0wR0rL-OEoJV0gG47Co4Zr903SNW6cgKDj3lW1tIpzcVMoH3BE22SMEVjYyEHgAORdoYwaj19CUg1slDGmvUCoq4dPsnCIrvV7N0LeoUkZekt2pvr~yCH47ENV3oQYpFVLcMLN82tzI0ZFz5IyBHWGr22vlDlT1C-QVhAYQKN92XubDXSEgrhWv5IHPB0h~EgZi-rDcsJG2zb6ZqjtKFHp4CnNvTUxE1cCJh0aR1MDzM~o0iSMiMqh0AAAA
madman2003.i2p=Uilou~5268x~UI5Cjg3XYKfBCeKVEMuD0g9Ea7~j2aNXbczbYXCdRQEetYMk0919Dyyj5Bfpiz5m4~xHMUoXs1aJedteFjvwwOHcXE1IuhORhILv8kKyW4zBYrK7LUnvn~xFsnl6~xaThgwxneXLGhKz5UOitIzDUJmxCAwfcARHgx9PIUuJ5LTninB3Luyev11TIqweOfe~X0dzVYSmemBgaw2T6dxCz7qz0mN5fJe18~qnTqJibKT~7teX~hQhRQolk38P3tLeBRq3wZGTRsJ6biGEydTbE-rqKrNvIMNYvUbhhRHEMdShAiUo4gPJwbyCRRScI~DbluYuy6iXXURnrCIEv2DKtfpHSS~JccPu25HKcpNBfCLzQye7L8hWgjAyaQoTi3idW2JJNEIBBBS4yfGk7wq9swlzBK2aanI-JzFcDrVDXd~fpN0JYN-phF3YJnKspJe2i83BW8J9b-y2JJVbTWBwU2mIEE~gXKggsCvqESfuKK5RhgFaS4dTAAAA
ardvark.i2p=lHNIrjt2OnxJG~p1ZVJ1UzdwoCNLSAGbXq81bSKFQsMNCXvVtYA8-uJPTk~F4uYyaiH7x9SGg5B5dK0RmLdacBNCpwPlCPPxEpHbWizUahUQMo8ifLsyOS02ev4Bxf~i50RHmjU1zPUDe6LNxlFmA60zehKAkSR~pp2SJdbs-3nyBhvG6SX5CUHY5r3g7PpcGvGDnPOuGGJtR0xIqi-~89TsKK74qS6JiKv4BzqbWUn9eZ3TrSaC1-LAjoIiowC6e2Ske9r2HEl3T4fJ3qmOTu6vZWLQCBkzprAVOFoTwou8MJU97n3l9~1UrgghU939jC~IrAye~VolxqCdbsSz~m4Ol9fWdGmAfs~l4ZNgA89Q0O9Z5ooCm5LBlR6SjtOLOO2tQJstSb0V7-XpOxafp-a4EmXMEzg6f9ttBZNDW86hxLUPUzT9O90~27ss6j9txgx7lmFrDL8EjoQIFis6MNZRhqK4O7elL55UltDQeSel2E11iogHa4oZs8S7BsReAAAA
ardvark.i2p=Bqd4fvbGq1WhOKQpkHAXML3r3aRdHbkwm~M59b6ROGH0mgTPwWHo~m7drA-ghxj2~N6pTdaQj757iduYHwmRcqXYQnFHSUIPkpDO9JBv41p7LEbHFD7eQetvcRTAbv~UFh8xR~zrMtWY-byY-Pzbe7tlOwxSN~HYgTDq7mpqZ~L8tOwCOfXTZPqVtHc2nasCPtEPHKLFjxs9ng35gs5LJz16wbNod12yq3Ykx0ZS9ttif8BnZIQMwQmV5Nb~VVaoFDYTomyPHvIVYRDYu4jIwCeTHKXdbmZMCtlWjW7sRn2ucwrxO05e06ApPgChb8UEiDku9c1wtMfAFTsaWdZ16oWBUiRB091mNuR0F9K8AgTBuVJwkisye6DffH8sGsu2WbYEK9E2dawqYIt0Bi~a2Vu-RtqXi0DkHLMHl9KWGfgIdTDHVpDsM-c7eSkyJST78aW4OXKTieEOFRZ1NXj0aevpGTTOIWLnuWaiiRNTP8b-OK3iAzczBzYhQsKo3hVzAAAA
nntp.baffled.i2p=FpTF-krVDnZvQrY3JPZ4A44P5ewaVMSppoNrfH60g~4O3AnU6Uz9V-izgw~Hrn9u10MexFZSYYDTznxCOc6MdSEME6X~hfWYP-g0zCt~OutUAyhyUiWV~g2PAD6u-SMAzxw8F9gesheQKU7drjplDXiTNMXqD9ILuAVaW4VABmci1k0mqSEOKPyZkRyJZJNbU6vx~ELytgQJqwK~LOqDiiG9~6-e3MpMJ0xHy2yUibd6xv3GRLMaJ9kWAruMM5otZdxJiOUOf7n7wWvSVDgmwUx6eEkS8bVlsPxD~HW7i~DNPa5Aa7QD0o46abx77YF2jaComxTzpFx6dwj-0AqTMRhVwtfPgiiXbzx6g28Eggyc93QFJ1wUX5Wgix3RjndsHE9bVOpxNjjDlRwpRP6ytu7zYDkyjJUXDiC-8SRIGDvcSQZi0Op7KsvrxgGt6hGeJyN4JhxE08vDHN~1S8DwqNzc5sQKkpmdJHywOBhzeeNucB3EcSvh6ZaJfJUywZ8FAAAA
www.baffled.i2p=XchfxmcxW-Ex4IJ9Udd8b3O4eKgjJJx0FKM6fUbqqqXUQmOOoXKhzKwlKYobN3JIOE5zYXuWoPiW13a6befjYhZ4x6lky5--GwZe9IgLsmBqwsqGRHRaCqGiDcsHLdIWUJFWmHz38U0GYW6ggcgODQgxs00Kc2u2zfhOfVbFb8ckjvPOFah5iyfh4UQn8uaOl7WOCQmg0U47vSd6glHRq50NdRryGJv722U9TZlnrara-5f7oQn2qm1ctwnnm3sUjRMsNCJbCwuvsVY04axL5VXggwrZ6nDaZOIQHvzoNVnQtbT82GQvcBEda4Jr~IX7gLYiDS7BGNbX1NsOWBTr8GwaozPzFnaA1HMHYH0n-m2Tf~8O~7oqWzlQSP4mqcPd4ePbaXdV1uNXAr4-kziO7J3ID4vhG-biS4fYAUZqEs2rwUgFU1jPocl~Aoi~8alcgWK98mN680ZrT6th~w1BC~rf1q8Zg3MkE5RwW5jRpkOpH5a7vU8Lp6x1xQlLx6YXAAAA
irc.baffled.i2p=AjR0lkZfdzmQqLofq5En-yeUYZ9XOugrcpqgA6giY1v880AnhB~xokcAdV76Sx~D3MLkXKjCYF-AMIrvfV8cRZ0XkY8FPFb-MnsnACGirQ4~WN6kEjQ18iEH-OStEeoATiEzCzhQlIaJkCLnRo~lAbsnmqMrV3tJIjdQOL~uxbZQB5rQl~50w01XWIzsjwo0ZqzPjsJ6715HMRp6hag0NYNgf8ZE7vFKkvRNubl60lI3LWduoA7BjwuqCvHP8QddYmmL1s-L0rjDB0JGxRJ7~YZlUA0BECTIxdv2Kv-QEwr2UmuSLFQiQ2jQ5U5z0tzwObaIcAX4aAaKY16mC~cQE5cltSS3ElnLrI0qhpIeTM6217uigbAO6iigYFK5sazru9YEt0jDk2gzxlTF6m5BAn70tnu5IAikzRe2NI8VnkRa7K473r~mS30CzwOHXuxlSEPQUK3AkkrQN1Nfw5dCBLTpIF6aMPqR5tracYPOEOlro76rzChnNu-QDZmOQGkxAAAA
@ -113,7 +120,7 @@ forum.i2p=XaZscxXGaXxuIkZDX87dfN0dcEG1xwSXktDbMX9YBOQ1LWbf0j6Kzde37j8dlPUhUK9kqV
jdot.i2p=yUqfBnnApqi3gcDlh8cafqd6T0Btw2yT8AA97Qtadu~wDbNd4znyrHnitrSCqGNk3KBAq~-Y5wxQ933NMQXyqgxQ-6U-2nNCS6EbH01dJfwCsoa1WayQR9k~LheSW7Vu6L12-STuNP~qhgaquSFOohpRuFEWwEzQ71zVcCpOYfAgkxD1zdIa8Dz-9ZcbPP5Nr4xCq08ls5CCROWyP0EKiB45GxPOfDTZmZxLGGcRly0NoU9uAB441GKJyPtuhrk-XhR~UhlH~BB9kaGfv09saQaEV~KsHOPU3u02O6uweE2EqzJ7oPrVM40L9OHsrrVKLZlUBwoReiwHxSjAZJlZfg4LkXGH~i7cczDaVQFOwBdj3MuzYuMhnnoIZu2I-Kg2J7aLM1vH1piO8-IH9mzItLOVUXS1gExAcflp9lmoXnGzojkn6~so6cL-iXHj7LY~~301o4-JnfqB65B4keZF4v2Fc4TKBnIERcAmx6adVOwjPXLL9nYBQNreoUFVxULsAAAA
irc.nickster.i2p=4xIbFi15l6BFLkKCPDEVcb23aQia4Ry1pQeC5C0RGzqy5IednmnDQqG5l8mDID8vL831rUmCrj~sC537iQiUXlkKFJvdiuI0HEL4c6a7NCYz3cPncc2Uz~gnlG1YOPv-CkxcXSHxxGrv0-HA281a87hrEc7uQ7hBLPybMl6-Z4k-qsyABDdaZwbqEJDWxJKWNfEWfhj2fHSuYB9c6CJgkPektLdMEIxIO4fWgRaIvyr0jt7ObBcB9QhvZAUnP5~iD9gnl~sxfSg~Zi7UW2sB0ewrb63KLZtRDXmnb-Gc3Cn-6oqvqt~YeNXW2OKiEMggkonLJR8RmdTsgMSwbHvXhyp0utqwgIIP7W0if0IIcDg7t38JzSo67uKs3m9aBf1kJWL~d31v6enPjIpgeLllJB6OaJVtKojn~Yi7Sje~5DJnLxiZVGf~Dn3a9IynFCQ6KXiPo-6418Wl2-vkrq0~cWjmlYMASR9AMILZMr1rOQUf748e92~oYwX2W5saRVnoAAAA
nickster2.i2p=aVMk7wdk-ebssXJmuthnwIy8IdAWLiNiftdNHVvqQCmbJUC1fSVuEkUPkAEW2Hdhzzv9M8t1-MH5Ip2UnTIe5XWjwLvfyg0skX4QouLWX~EZIMq6SrTpIBguYuG9pV5XKfVslwnYyYU-S-lL82S98YJDRWw4eGO~Alg2Sisp8x8iuvLrWwXX61hOcQp6e5OVM5Al3kHcVBFwIGfgIglXy6d7lPZHBRDj7W4jTKKj4OUOaJ84vdRtMZaVXbM~xHZJTZxRo99SmVQpxr4j2n0f4RfYDQxjz2eMPLfhl1IF4svBGbQ1d0PGQlTy0vftRqMjxrS4XoGdlYGyACpDE5eMjIgRhnAyAXbZ4OY7htXKvLgpM6VBQ0JjBwQITsI~MO1IUJXvc3yEg~rLnBtv01YNspiGyE8v0~Va6rps3KjEc6E-C4ZN6pNHBqtKajFPLz4kgrJ-E6P2bXoHMadbNIkEEM5vKSPTFAf~y1ElBH9RD5yaxOxGEzyS076vJ6phK~w2AAAA
quadn.i2p=v-nBRbrA06mVVTGjY7MLcc~DSqQGwCssyKDNoFxh5mb4rRKHLbRT3sRxDybNsribQw0iZfUA0~bxh~26uO0VEAFpoa5CSBoSRjWq7f56J9w~beZIcNcXutG0UNMsJngOr-5lwAwiK8YrYbNveiNB7-iOXoNCLXZEDWb4xZ8TbManX1WH8v0id-2vqW9g6opIxv3KvzHXAg7qANhRCf7O2Xrk8cVQIWo~hCs5~-6hcP7G6WolGEZN0peBZPT5hKX4v3pKmGX-5xMIuZx-qev0dnjmgb-0DXwX7suJsPpzKzaUDQP6sje0z35DU~ov-M0umeqVQNFCvaNwPXWs9Fw0zShlUXN8STXE2AutMTyACT~k734deL5GeO-~-kab8qeTHgmUsBryBMvDqxt0TYhgxyD~63OD2DzmrJHcdZNVVrJev~Z~FtZMuQ2xwsg5INpt5tu2F0noCeYl5ThxRbr3F7mmfx2X-oOw-gYYBhov1lzAckSXNDze~chGB0dmop~KAAAA
library.i2p=v-nBRbrA06mVVTGjY7MLcc~DSqQGwCssyKDNoFxh5mb4rRKHLbRT3sRxDybNsribQw0iZfUA0~bxh~26uO0VEAFpoa5CSBoSRjWq7f56J9w~beZIcNcXutG0UNMsJngOr-5lwAwiK8YrYbNveiNB7-iOXoNCLXZEDWb4xZ8TbManX1WH8v0id-2vqW9g6opIxv3KvzHXAg7qANhRCf7O2Xrk8cVQIWo~hCs5~-6hcP7G6WolGEZN0peBZPT5hKX4v3pKmGX-5xMIuZx-qev0dnjmgb-0DXwX7suJsPpzKzaUDQP6sje0z35DU~ov-M0umeqVQNFCvaNwPXWs9Fw0zShlUXN8STXE2AutMTyACT~k734deL5GeO-~-kab8qeTHgmUsBryBMvDqxt0TYhgxyD~63OD2DzmrJHcdZNVVrJev~Z~FtZMuQ2xwsg5INpt5tu2F0noCeYl5ThxRbr3F7mmfx2X-oOw-gYYBhov1lzAckSXNDze~chGB0dmop~KAAAA
www1.squid.i2p=xFjsznzFpBBjt8VtDaorQ8-lbr9sSAjW8BAHq-m-NtblMWVlTqqg41wgG0NNOkVwOZFGP-l4B9COtrXqxpu6Wsw13XO1AZqtA37p-etnPkyOwYVuwIqTWZkI79fowSm3Mg2Y-siKwH~NKf6zmslqOxqiXlQ6nhbBFa4NDRuVh2M55OtaqE8nOgZeO6lkMCfpn~t-qQCAh2vz-2LeXFM8ypy-V6nFz18UsI7ptSne9Df6MqWMm9JVlpNTRldrIsSNeGcLW8E-HbR9paV6-YDy3Z4o6dzchjxGJu-fkWbB5TIMNkkDfPuCCpXezgNGRDnJhZSZO~duyL67yhkrylRdYElIDV4FAOBrY~z2J7YkVGI3r5JekBioyfYv39MW99jMTtQCA7g5SNvOUV3iT~AxOQGXlfc65vJsoas6xZEXPaAN4jt4YacEtrq~ondD8LrJnkftz5LaZO16AvHxeMrtF1un-T9l44V~KunQ59hECxyCRAPM3xCGa-Up3Fq5iMrGAAAA
files.hypercubus.i2p=VaShB-eG8OljGqQ8lKRlwHeZbRipnlFSozkT-YN-X7bmZQZY6D-IDiauJmf3WDS8ZLto9ywPtBu48PCMf3wkqFUZSiLBiFbinkMVBsgJc8oEKDTFha57S2qPlkyEwGJX65GEu8oLVySCr~XHV46PVgN-5Kgvt5U3INNfQ9TO98rOFtip3kz3rjjws-vDTQgL0HwxQaHdMVM6T~lyeCdDlGU5kXf7zE2fGr9Io-gqsza4BxNYMs4-Byzt2JuEH7GgiaADyVVkmNgl7VWcxAQY7Ms64N7s3~xTnL7I~0VnBgpXhLsbLZqfb9OsTaPHZfH~pj6SLZ8tvmdW7ib02XZI9Dg3FeL2FIKy78uDRDK1diMTOGWmJ6lnL9JScxVynfmo~RY51ZtfmdypektQVcicKz87cremi11ur1MsnNmVINd09-uO-jsx1emuhwhkSsFwkOq4whgWw6rGyClQSAMWyh3q0vjBWGIvY06ck5QGcSqhqrxNb04Q8LLQgmt3qsdjAAAA
fproxy.i2p=0shTIrUEgGomAYPo0YFChct95PclUbX0XnLJPhHXGzy9g3JpWnhfWFyIXCl8xVkMSDHLwgQSpvt83nfEDJ08i1spYBVZ2X~eEr1RxcDtElMy0-awrA8h3Th19bC64L9RiOvb8ADuuznnEIxdUaRlf9BhGegeyewmU3FmA4vXA40aDmGtuyz7JPv2S3NVK-BoGiUcMlWZGryVYin7u9D6R5OyClGFLg3tq3gSue8kAHpZsjTHD44QTc0onOvIRPOmsOexIb8zXKI~ctApkKGaJA38yoCDMlBQKiCr9BXPOHr1B9lbMEda7Tq0y0poelknQaPvfWDxQkFZ-ACgwsrJ2xqdHcP-t2P9~UtWPJxrke5PK5pb5AwukeBhSmUTB-fajoBMRVfIiOqTr2wmC5h~~x-1977BRhyrRFJLQo6RD9jUf2sQ75hk3U4LfbZa7q618bYq4r6leAnhm1hl6TNW3a1d-ZeCnWwjwIc-Myd79tZNf0BEjoFetVm3e2M~mUh1AAAA
@ -122,4 +129,8 @@ thetower.i2p=O2eThCYji0ds8z9-kOxeJHCEz9Z7rgl~9RhsM3wrkm6bboT7y1MNBThWl3xTq-PFC8w
fproxy2.i2p=S~8V9eIaGwhbtdMMNx8w7YcyzNBhFx-GaaTOlZHqYEkQbZi3rn1k8CQxf49x6LbPWSDjdf17kWKMlW4ocx17ykfuaxJIfj4zt~s~oLc-2~B5DYYjmUMR7Gf2QmonWnHr~jMgRTqdKDU-peehUYOun~3A0N2u79Ud-Y9gl0~T~XV7ojIOrvyouTURaDzxwr2PQB~x~bQRiTuBDQV6QCG7tucw7EiU9RGIjrSNiGgz1FvDdMp7T7y-PbyzWMzETpQPe9k8Qzq74fImgLCTqXGOf~jzZh5UblKIQbliPfs4yk7mwdLuDZx0EriXImPY5I6w8scBsR3UvsbGMX39LLCQaIltRhkhc2UakPyh-grFRESssjIg9QJ5KCqUvAYw3GNp7xcyDXdQJ3y8mBa7-U8f6ZCR6kzhrlZ7NwUShtL-2Go9wly0KZvImDQua0~kqwod6ccU4DSeHxuf7ZimvUkvfxUYNMlm9sSTN-2oU9S5K-pMoFr0n~rK4jQZsqI7IkTLAAAA
ooo.i2p=FpCkYW5pwVz36sSHoBuRT4ZvGif9QC9oQUWfz-wu4zEnJ1ewlAvinPuw3YnXUKmgLFZ0UY3wB7wqd0eQYiW2ZV1bwVhXvsyGV5ZehzxGaFu05IspCJjyaMIe90z5fyda4KgzyBwHKqwjGX57SMyn2cZhXbCKF6aNuipWxYOnL65uATDbw3jShEtL9v9299ohhGA3EcrYk3u86FgLmsOdi2GZruxy2RzioA-VKhaZl4RSJs6dFHPUYWgeLF3gT7Ciy-HbMZdDuiLTEX7mUlO0UZwnzT8mjUDeeYfyWtv9arwv-rAMeXxAVUYm7X2dDHN8TvmQCZ~LiQrnGmGReSIDKVT4u59xZX2Qg0GZf0fA5LRSW1zHLrlZWDJfNeESW57RlOkA9DDDOxwSVSw8LUQN-hPsoz~AgwA-vDklNWULqvp4lLifEJUlr5ZmnWrviLr6W6cHhdJBl89VzMThoknb5UibIvwTnu~tfA0rkyILXX07hdaoXF~prptuOhMtEcV2AAAA
ems.i2p=G4ZdYgTUkGsJ4VJTgPqTcJGeUp0ZWlf8~GIQO1VuIj8Lc3gTDdnC7c1RoG4XAQlbKkpN7xZMKKCBUgyuptyeVsEQ-4Q4Pjf7LSxx0ntvm9DVff3Put5opd-txTiG7C8-2fi8eqva~gaEocj4GfTm5grCnWm0oNMAe1tqC1WMXuKO2ciDbZ0JeS05vTeBFTxJ2OAeVfNNYWNY-hBUvyaBtUKIWq8GaVW1Sa3ZQTEjsAsMmABRnfgt8tureBvp1e2xmAVfShtbJVLM4FfYYcNQfW1XSBa3vSnQ-~jFqyx-XR18meieGrra7SqC~8HDy6S1tkLKVKUZYFe6xF6rVa1e~Uox5HAX40dTDOWIGLv6CeEgtgyc~i33IkAs~hVWKUs~NLAB~u20Y09pBppu0ZhUgsoSMAPXoDh-VOQRn~QMSXgXVP-5W~qShhdDNa8wJVEnOEqWLnK6ikIFrkEFVg9CHbb4-q7ZdMZ5gu~V612xCQpxI~0iSqVjkADOdo3ZDHtxAAAA
freshcoffee.i2p=bljvyRLSf2lCPJYJ49iGJ7RxTppQfJHh0UviwxeFUwfznUYZ3nnVZhqDKtfKLSt82klW5bJ0QjN5Qhh6h-~tzDpZoQS16lHjwrxz5LHMqZr5AwugKEU8QKM4akB7931YWgrsLVWIJkdRoCEbLFGDcBGbNMkrI10RCz7kh4Rvc95kPOMGZrX562DQbooKoGSlo3rooV-aE5L0hFLyvx4yuxDf96wWjWQ9yjh0ltm3W3MiEsmDrC24FADoKPKPimDnddfIUjeXVWnsn5mjs6OOj1HKI0zxpK0dGqEp7PgsXsdot3e5HozwX9BKk0ZOF-OAcjnm3GHwwAo9vtav2QibjIPUtE~JaZ63Y546gf24KFzdl0gyhusfuvEo5btl2~-xyivVVO5RYHyBLO7D7QCYhnKSrPd9nOcVwZndNqObrX2EKjAHJIRyyh2KnG2N7YcYbnnjxJn8gIiPgX8bMfzFvg5dBo8kmZe684IZmpq5LPv~CmC9R8gNaKrPbiSgU8D0AAAA
stasher.i2p=WsfNc~1sP-eCU5XRoPoyYFwJZ-BrrN29rs89fYAs2kFIyCbsKYeA9rYbD3O1sFCD~kLUC1DELoTwQlHas7JkDkEPXO1plDjzKm8l1iTsPyQmeEVW2Uy6LXOibT6FsdIfoh59G4yfCsEZ~dsxtZZR2ICDb3sRKC8Vx9lZOz72AfBATYQ0S2oQd2iVAjIb0wC0HaVw1XOqhKCmMjWtQhT0qxtkx7ky9ZG1ZAhKeCX4SkCy5YvGeUuCWgPpFLR6D3Hn074Qmtg8g1nAFhlsZ2NiY2OSwNtVM3f2lL6~l4O~xi5oOV7OAtQr5tKywa0SC53hJAAk2VI6HwiexTEwswnaSYwlyW47pO-onpc3sguCmbBWHbxJDzCE5eoi8iFGOH~Awl~ieI6vkvPnGtjvXM4t0jDe3FnrbYCZeSqToKOgIYz0f8iVVbSsh7UVdSepN5tIL~ljIoZIiG6VH37H1ju4loRiADr2wyWWlI94YvZB8rmgUHTPuE9YCijVwmXQNky5AAAA
brittanyworld.i2p=tJaK0vA6NNBjyGTjGqHr4k9005aiRToLxP~LIA-WXrjRaWgglh6s8CuE8o60i6i~isELPMAZJGSdPNAP~d2OVEOVu9yXom8xpQyX~xc8gVOhTXi3PvjlCDcG09mFfzPm3XJFJR00EkBcfa2ssaXqOX3vXiR-aGdObmCBngNHeh0sgUJTnfOKFUXRN1leXdWj9ADBPk2iCEvLM7Rrt-vFdr0slrIY0ILzBBK65fZenZtf5QQwskyBeLljpUBbTo21tCSUs89U6yXheYiakR3cQgTDbr9MrcRv8bWiNCKRnoVb5HVrPFZZDk5zCvpMK-zV7YmoO0qYK2AWgnGGZ2PI4ycL7sAHZ~QJixw~7UYtslrisMHKbWAvZfRf4MwFhbKH9RVb2ft2vtSXOz5h7lXtVpPv-xeqoJlclBSLYNt5Ji1iZuFOJFEnjUc3WhSFDph2Tz72PkyU-qXoydrv~JQK7kY5GpjDZ2whqrHjk4ceyQs4jTRfpwbkt~qrQ7AzKnpkAAAA
files.nickster.i2p=C-A1MrwV~WC3ld5mDKW57EpaFmIUv5LQThPL~OAOE63Psej8GhH-m61P3yII0NxVJrkKcTa3CZfnPkQCVXkTD2gv2qpZuiX3j4vGJFuQYByKwzuTJ7Ucff9XeO9A~kaXFg9JwMmkzHJZ37X~tKIr-EfHA23mMmUrvmsemAkCOxTHPab33WEkQgBPfTfL9BOSaEzG362OerU7O2QBWjDHrAoMBztHOx4s61pSKMDky71o2fTi4TgoVcOL1oRzprsf5BV9BiY5TRtY7uvYp7-93uct0EAVu686IrM~RzqGuHhSm9TGtEFC6UyMMcn6dxD7q6srI-kR807umEUO8ILNCF79pVZWmA0sBN16wyq-~LtX45dun0UFKDiYyJXcrdN9wyRkro3oZImjW0bLxP5YhMw1C8HhTBSWhDmuJVucZByWqM~Es9pSVql1NX0EU96iqFtWHOEbw9XoT~eBhnqYdQ-PnB79wFWaFFxq-0X89FqxEvl79R7Nqjb46BEkzjoQAAAA
datagram_test.i2p=8iJSGzSY8BOFcGohooX94PWiRB3VZYPmLfSBorLTzVC3tmviLcEngN8e8U9kuVTxiQ7Za6HMESzzgnZvKOmL2jD~yon5zNGDShICJv134bX7odSzqbFG5xwpfwRJ8jQvUEnS0bg3BCfK9vmVnqpixd~8qnGThr5KzQxXfI72NcQYlbszp2BOLhGjxDFh5fQpy6Vm8d1R4GF4RGGTaKXANQ9I49LND10xYNE9BayxrUQrkzCDMMI1JXyoR2N~WwuoFK3RzKSrSTMcGbZpZgLZjo47jSqD9ssJPcD94hAllTtk5iTajLhXhoSCFSzpyrAxuRxhHEl8OKIxaNA5DqZMLo7KqfrwSkyRvUyqeFXnzz8DZq8YXu9GeXzkzPhnQdFEiOSV6ypJndv7rVJ1ccarDLdbxEBFZgl4LUux-Aemt4FfuNOvnKzr3OdOX4eT8TvO0kQKwA4NLs0noqiHMzDSUijNGtHv0npvMgT9dO~UIxLHV~sYqIl4t58bSTqJWRATAAAA

View File

@ -0,0 +1,351 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

View File

@ -0,0 +1,41 @@
Copyright (c) 1999, 2004 Tanuki Software
Permission is hereby granted, free of charge, to any person
obtaining a copy of the Java Service Wrapper and associated
documentation files (the "Software"), to deal in the Software
without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sub-license,
and/or sell copies of the Software, and to permit persons to
whom the Software is furnished to do so, subject to the
following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
Portions of the Software have been derived from source code
developed by Silver Egg Technology under the following license:
Copyright (c) 2001 Silver Egg Technology
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sub-license, and/or
sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

44
installer/install.xml Normal file
View File

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="iso-8859-1" standalone="yes" ?>
<installation version="1.0">
<info>
<appname>I2P</appname>
<appversion>0.4.0</appversion>
<authors>
<author name="The I2P Project" email="support@i2p.net"/>
</authors>
<url>http://www.i2p.net</url>
</info>
<guiprefs width="580" height="356" resizable="yes">
<laf name="liquid">
<os family="unix"/>
</laf>
</guiprefs>
<locale>
<langpack iso3="eng"/>
</locale>
<resources>
<res id="Installer.image" src="installer/resources/i2plogo.png" />
<res id="InfoPanel.info" src="installer/resources/readme.license.txt"/>
</resources>
<panels>
<panel classname="HelloPanel"/>
<panel classname="InfoPanel"/>
<panel classname="TargetPanel"/>
<panel classname="InstallPanel"/>
<panel classname="FinishPanel"/>
</panels>
<packs>
<pack name="Base" required="yes">
<description>Base installation files</description>
<fileset dir="pkg-temp" includes="**/*" targetdir="$INSTALL_PATH"/>
</pack>
</packs>
</installation>

View File

@ -10,7 +10,6 @@
<ant dir="../../apps/sam/java/" target="build" />
<ant dir="../../apps/netmonitor/java/" target="build" />
<ant dir="../../apps/heartbeat/java/" target="build" />
<ant dir="../../apps/time/java/" target="build" />
</target>
<target name="compile">
<mkdir dir="./build" />
@ -40,7 +39,6 @@
<fileset file="../../apps/sam/java/build/sam.jar" />
<fileset file="../../apps/heartbeat/java/build/heartbeat.jar" />
<fileset file="../../apps/netmonitor/java/build/netmonitor.jar" />
<fileset file="../../apps/time/java/build/timestamper.jar" />
<fileset file="../doc/COPYING" />
<fileset file="../../readme.txt" />
<fileset file="../../hosts.txt" />
@ -64,7 +62,6 @@
<fileset file="../../apps/sam/java/build/sam.jar" />
<fileset file="../../apps/heartbeat/java/build/heartbeat.jar" />
<fileset file="../../apps/netmonitor/java/build/netmonitor.jar" />
<fileset file="../../apps/time/java/build/timestamper.jar" />
<fileset file="../doc/COPYING" />
<fileset file="../../readme.txt" />
<fileset file="../../hosts.txt" />
@ -86,7 +83,6 @@
<ant dir="../../apps/sam/java/" target="cleandep" />
<ant dir="../../apps/heartbeat/java" target="cleandep" />
<ant dir="../../apps/netmonitor/java" target="cleandep" />
<ant dir="../../apps/time/java" target="cleandep" />
</target>
<target name="distclean" depends="clean">
<ant dir="../../core/java/" target="distclean" />
@ -96,6 +92,5 @@
<ant dir="../../apps/sam/java/" target="distclean" />
<ant dir="../../apps/heartbeat/java" target="distclean" />
<ant dir="../../apps/netmonitor/java" target="distclean" />
<ant dir="../../apps/time/java" target="distclean" />
</target>
</project>

View File

@ -325,10 +325,6 @@ 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

@ -222,8 +222,17 @@ statGroup.10.detail.3.name=db store sent (hour)
statGroup.10.detail.3.option=stat_netDb.storeSent.60m
statGroup.10.detail.3.field=3
statGroup.10.detail.4.name=failed db lookups (hour)
statGroup.10.detail.3.option=stat_netDb.failedPeers.60m
statGroup.10.detail.3.field=3
statGroup.10.detail.4.option=stat_netDb.failedPeers.60m
statGroup.10.detail.4.field=3
statGroup.10.detail.5.name=lookups sent (5m)
statGroup.10.detail.5.option=stat_netDb.searchMessageCount.5m
statGroup.10.detail.5.field=0
statGroup.10.detail.6.name=lookups sent (10m)
statGroup.10.detail.6.option=stat_netDb.searchMessageCount.10m
statGroup.10.detail.6.field=0
statGroup.10.detail.7.name=lookups sent (60m)
statGroup.10.detail.7.option=stat_netDb.searchMessageCount.60m
statGroup.10.detail.7.field=0
#
statGroup.11.name=bandwidth
statGroup.11.detail.0.name=send rate (5 minutes)

View File

@ -0,0 +1,22 @@
tunnel.0.description=HTTP proxy for browsing eepsites and the web
tunnel.0.i2cpHost=localhost
tunnel.0.i2cpPort=7654
tunnel.0.interface=127.0.0.1
tunnel.0.listenPort=4444
tunnel.0.name=eepProxy
tunnel.0.option.tunnels.depthInbound=2
tunnel.0.option.tunnels.numInbound=2
tunnel.0.proxyList=squid.i2p
tunnel.0.startOnLoad=true
tunnel.0.type=httpclient
tunnel.1.description=IRC proxy to access the anonymous irc net
tunnel.1.i2cpHost=localhost
tunnel.1.i2cpPort=7654
tunnel.1.interface=127.0.0.1
tunnel.1.listenPort=6668
tunnel.1.name=ircProxy
tunnel.1.option.tunnels.depthInbound=2
tunnel.1.option.tunnels.numInbound=2
tunnel.1.startOnLoad=true
tunnel.1.targetDestination=irc.duck.i2p
tunnel.1.type=client

View File

@ -115,5 +115,3 @@ libs.0012.name=harvester.config
libs.0012.islib=false
libs.0013.name=heartbeat.config
libs.0013.islib=false
libs.0014.name=timestamper.jar
libs.0014.islib=true

View File

@ -109,13 +109,7 @@ tunnels.tunnelDuration=600000
# http://localhost:7655/shutdown?password=thisIsASecret)
#router.shutdownPassword=thisIsASecret
#
# the remaining lines describe how you can get your router to fire up client
# applications it is up and running, all within the router's JVM. Uncomment the
# ones you want (revising the numbers and ports accordingly)
# Keep the router's clock in sync by querying one of the specified NTP servers once
# a minute (uses UDP port 123)
# Comma delimited list of SNTP servers to query. pool.ntp.org is a DNS trick to
# This defaults to the DNS round-robin ntp pool - see http://www.pool.ntp.org/
# Please change the NTP server specified to include ones closer to you - see
# http://www.eecis.udel.edu/~mills/ntp/clock2a.html for a list (you can specify as
@ -126,50 +120,56 @@ tunnels.tunnelDuration=600000
# BR: ntp1.pucpr.br
# BE: ntp2.belbone.be
# AU: ntp.saard.net
clientApp.0.main=net.i2p.time.Timestamper
clientApp.0.name=Timestamper
clientApp.0.onBoot=true
clientApp.0.args=http://localhost:7655/setTime?##timestamperPassword## pool.ntp.org pool.ntp.org pool.ntp.org
time.sntpServerList=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=##timestamperPassword##
# Query an SNTP server every 5 minutes
# time.queryFrequencyMs=300000
# If you really really know that your computer's clock is ALWAYS correct, set this property
# time.disabled=true
#
# the remaining lines describe how you can get your router to fire up client
# applications it is up and running, all within the router's JVM. Uncomment the
# ones you want (revising the numbers and ports accordingly)
# 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)
clientApp.1.main=net.i2p.sam.SAMBridge
clientApp.1.name=SAMBridge
clientApp.1.args=sam.keys 0.0.0.0 7656 i2cp.tcp.host=localhost i2cp.tcp.port=##_router_i2cp_port##
clientApp.0.main=net.i2p.sam.SAMBridge
clientApp.0.name=SAMBridge
clientApp.0.args=sam.keys 0.0.0.0 7656 i2cp.tcp.host=localhost i2cp.tcp.port=##_router_i2cp_port##
# The eepProxy (HTTP proxy that lets you browse both eepsites and the normal web via squid.i2p) and
# the ircProxy (which connects to the anonymously hosted ircd at irc.duck.i2p)
clientApp.2.main=net.i2p.i2ptunnel.I2PTunnel
clientApp.2.name=Tunnels
clientApp.2.args=-nocli -e "config localhost ##_router_i2cp_port##" -e "httpclient 4444" -e "client 6668 irc.duck.i2p"
clientApp.1.main=net.i2p.i2ptunnel.I2PTunnel
clientApp.1.name=Tunnels
clientApp.1.args=-nocli -e "config localhost ##_router_i2cp_port##" -e "httpclient 4444" -e "client 6668 irc.duck.i2p"
# note: if you want the proxies to be reachable from other machines, add:
# -e "listen_on 0.0.0.0"
# before the -e "httpclient 4444". otherwise, both of these proxies will only listen for connections on 127.0.0.1
# The following three lines replace the clientApp.1.* lines above, for use with the new router console.
# It loads up all of the tunnels (2 minutes later, giving the router time to boot), and starts any defined with
# startOnLoad. It can be further controlled at http://localhost:7657/i2ptunnel/
#
#clientApp.1.main=net.i2p.i2ptunnel.TunnelControllerGroup
#clientApp.1.name=Tunnels
#clientApp.1.args=i2ptunnel.config
# New router console webapp, driven by Jetty
# to use, you must mkdir ./webapps/ and place the routerconsole.war file in there,
# and add jetty-all.jar and routerconsole.jar in the router's classpath in the startRouter
# script
# (don't bother trying to figure this out prior to the 0.4 release)
#clientApp.3.main=net.i2p.router.web.RouterConsoleRunner
#clientApp.3.name=webConsole
#clientApp.3.args=7657 127.0.0.1 ./webapps/
#clientApp.2.main=net.i2p.router.web.RouterConsoleRunner
#clientApp.2.name=webConsole
#clientApp.2.args=7657 127.0.0.1 ./webapps/
#clientApp.2.onBoot=true
# Network monitor (harvests data from the network database and stores it under
# monitorData/, and with the netviewer GUI you can browse through its results)
#clientApp.4.main=net.i2p.netmonitor.NetMonitor
#clientApp.4.name=NetMonitor
#clientApp.4.args=
# Heartbeat engine (ueber-simple ping/pong system, configured in heartbeat.config. By itself
# it just writes out stat data where its told to, but there's a seperate HeartbeatMonitor
# GUI to let you visualize things)
#clientApp.5.main=net.i2p.heartbeat.Heartbeat
#clientApp.5.name=Heartbeat
#clientApp.5.args=heartbeat.config
# To require simple HTTP authentication for accessing any of the pages underneath the web console
# (including any other webapps deployed), uncomment the following line and set the password
# accordingly (the username is 'admin'). If the following is commented out, or is blank, then
# no password will be required, and anyone will be able to access your router console (and change
# settings, etc). This is only used for the new jetty console (started in clientApp.3.* above)
#
#consolePassword=fooBarBaz

View File

@ -4,4 +4,4 @@ cd ##_scripts_installdir##
REM the -XX args are workarounds for bugs in java 1.4.2's garbage collector
java -cp lib\i2p.jar;lib\router.jar;lib\mstreaming.jar;lib\heartbeat.jar;lib\i2ptunnel.jar;lib\netmonitor.jar;lib\sam.jar;lib\timestamper.jar -Djava.library.path=. -DloggerFilenameOverride=logs\log-router-#.txt -XX:NewSize=4M -XX:MaxNewSize=8M -XX:PermSize=8M -XX:MaxPermSize=32M net.i2p.router.Router
java -cp lib\i2p.jar;lib\router.jar;lib\mstreaming.jar;lib\heartbeat.jar;lib\i2ptunnel.jar;lib\netmonitor.jar;lib\sam.jar -Djava.library.path=. -DloggerFilenameOverride=logs\log-router-#.txt -XX:NewSize=4M -XX:MaxNewSize=8M -XX:PermSize=8M -XX:MaxPermSize=32M net.i2p.router.Router

View File

@ -2,7 +2,7 @@
cd ##_scripts_installdir##
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
# the -XX args are workarounds for bugs in java 1.4.2's garbage collector
nohup nice java -cp lib/i2p.jar:lib/router.jar:lib/mstreaming.jar:lib/heartbeat.jar:lib/i2ptunnel.jar:lib/netmonitor.jar:lib/sam.jar:lib/timestamper.jar -Djava.library.path=. -DloggerFilenameOverride=logs/log-router-#.txt -XX:NewSize=4M -XX:MaxNewSize=8M -XX:PermSize=8M -XX:MaxPermSize=32M net.i2p.router.Router --quiet > /dev/null &
nohup nice java -cp lib/i2p.jar:lib/router.jar:lib/mstreaming.jar:lib/heartbeat.jar:lib/i2ptunnel.jar:lib/netmonitor.jar:lib/sam.jar -Djava.library.path=. -DloggerFilenameOverride=logs/log-router-#.txt -XX:NewSize=4M -XX:MaxNewSize=8M -XX:PermSize=8M -XX:MaxPermSize=32M net.i2p.router.Router --quiet > /dev/null &
# Save the pid just in case we ever want to stop the router
echo $! > router.pid
echo I2P Router started

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More