forked from I2P_Developers/i2p.i2p
Compare commits
115 Commits
i2p_0_3_4_
...
i2p_0_3_4_
Author | SHA1 | Date | |
---|---|---|---|
78b7f228f5 | |||
84e03f8b16 | |||
288580aed7 | |||
de63bbcc86 | |||
80b8c284b4 | |||
ffff6d701f | |||
0b084ece08 | |||
28855d3fd1 | |||
f7d356dc95 | |||
104b332906 | |||
8b30852639 | |||
bdaa14c257 | |||
0234fb62fb | |||
687ca781ab | |||
3053c797e8 | |||
62d6709949 | |||
410abaf92c | |||
5e07c478f5 | |||
3eda53a97f | |||
4e25382901 | |||
fccb172e20 | |||
5a761242f5 | |||
aaaf1e14a5 | |||
3dcb9f6424 | |||
04621ff64a | |||
5053808058 | |||
9912c673bf | |||
4636f7be7b | |||
0ffc0a1959 | |||
e86032b129 | |||
87941a0975 | |||
3d6a40a683 | |||
9753470dcb | |||
a45e1b4781 | |||
54f52d37ca | |||
6e295a7afb | |||
692cd7adae | |||
7794547d30 | |||
35eaaee627 | |||
8029901ed7 | |||
342c55043d | |||
3cf363667c | |||
2f8993995b | |||
8e9c541eba | |||
7ed310ffd2 | |||
bc1b020e95 | |||
5fdff16b1e | |||
43e22a9028 | |||
e102bf9eed | |||
bf3ee5c158 | |||
2e99e3d9c5 | |||
3d7029493a | |||
a6ad2bbc5b | |||
4dc17773c4 | |||
e5d66f46c6 | |||
d2fc24e792 | |||
ec52c81f46 | |||
0eb0c4cc83 | |||
b54e6bc933 | |||
83f891138d | |||
c621940b0f | |||
a27b0a0a1e | |||
23a52dbc9a | |||
f8a57c7885 | |||
a295d0ad1e | |||
190a2147cc | |||
49573b9e72 | |||
e60b30ed44 | |||
5c10ddf54c | |||
600ece819f | |||
6bc7a3d8aa | |||
0af07e5352 | |||
8732f54c64 | |||
437d5d76e9 | |||
7378be05d3 | |||
75febe4b75 | |||
f6d8d93a1b | |||
130310fddd | |||
8bd312046d | |||
9cc96f45d0 | |||
c18fc1984d | |||
3b651076d1 | |||
352396bdc2 | |||
3c9b0273d4 | |||
5122f9989c | |||
8ebd22da96 | |||
c2d55013a6 | |||
25eda1378e | |||
dfac7bde9c | |||
348168d6c0 | |||
a1c772c8d8 | |||
f1ce1b5361 | |||
ebdc7d70a1 | |||
c5947c23bb | |||
eeb1852d95 | |||
2f28a635a9 | |||
d524c77560 | |||
0025d94aa4 | |||
bb5ae2922d | |||
fbe9fe1ba8 | |||
007194d674 | |||
cdd74505d7 | |||
0aa023189d | |||
79aa10dfcb | |||
9ecfda0110 | |||
b89e26c460 | |||
97e5952544 | |||
8627328047 | |||
ec0c912c6f | |||
953de3f1f2 | |||
e1264de514 | |||
5abd2b400c | |||
2c2a103676 | |||
44af799b66 | |||
ec22ba3248 |
@ -1,2 +0,0 @@
|
||||
.classpath
|
||||
.project
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author hypercubus
|
||||
* @version 0.3.1
|
||||
* @version 0.4
|
||||
*/
|
||||
public class Bogoparser {
|
||||
|
||||
|
@ -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).
|
@ -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>
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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; }
|
||||
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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)
|
||||
|
@ -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() {
|
||||
|
@ -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) {
|
||||
|
@ -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">
|
||||
|
@ -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");
|
||||
|
@ -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();
|
||||
|
@ -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 ";
|
||||
|
@ -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");
|
||||
|
@ -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>";
|
||||
}
|
||||
}
|
||||
}
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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.
|
||||
|
@ -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>:
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
21
apps/routerconsole/jsp/oldconsole.jsp
Normal file
21
apps/routerconsole/jsp/oldconsole.jsp
Normal 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>
|
21
apps/routerconsole/jsp/oldstats.jsp
Normal file
21
apps/routerconsole/jsp/oldstats.jsp
Normal 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>
|
@ -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>
|
||||
|
@ -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 />
|
||||
|
@ -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
|
||||
|
@ -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
|
20
apps/sam/c/examples/Makefile.common
Normal file
20
apps/sam/c/examples/Makefile.common
Normal 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
|
@ -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
|
||||
|
24
apps/sam/c/examples/Makefile.posix
Normal file
24
apps/sam/c/examples/Makefile.posix
Normal 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
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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:
|
||||
|
49
apps/sam/python/doc/guide/wiki/i2p.BaseHTTPServer.txt
Normal file
49
apps/sam/python/doc/guide/wiki/i2p.BaseHTTPServer.txt
Normal 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>
|
48
apps/sam/python/doc/guide/wiki/i2p.CGIHTTPServer.txt
Normal file
48
apps/sam/python/doc/guide/wiki/i2p.CGIHTTPServer.txt
Normal 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>
|
45
apps/sam/python/doc/guide/wiki/i2p.SimpleHTTPServer.txt
Normal file
45
apps/sam/python/doc/guide/wiki/i2p.SimpleHTTPServer.txt
Normal 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>
|
22
apps/sam/python/doc/guide/wiki/i2p.SocketServer.txt
Normal file
22
apps/sam/python/doc/guide/wiki/i2p.SocketServer.txt
Normal 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>
|
@ -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>
|
||||
|
27
apps/sam/python/doc/guide/wiki/i2p.select.txt
Normal file
27
apps/sam/python/doc/guide/wiki/i2p.select.txt
Normal 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>
|
276
apps/sam/python/doc/guide/wiki/i2p.socket.txt
Normal file
276
apps/sam/python/doc/guide/wiki/i2p.socket.txt
Normal 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>
|
79
apps/sam/python/doc/guide/wiki/i2p.tunnel.txt
Normal file
79
apps/sam/python/doc/guide/wiki/i2p.tunnel.txt
Normal 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>
|
@ -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.
|
||||
|
@ -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>
|
||||
|
@ -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.
|
||||
|
@ -1,7 +1,7 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
from distutils.core import setup
|
||||
import os
|
||||
import os, sys
|
||||
|
||||
os.chdir('./src')
|
||||
|
||||
|
77
apps/stasher/python/README.txt
Normal file
77
apps/stasher/python/README.txt
Normal 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
|
||||
|
1
apps/stasher/python/noderefs/aum.stasher
Normal file
1
apps/stasher/python/noderefs/aum.stasher
Normal file
@ -0,0 +1 @@
|
||||
qeu89U8BXS8~jlsGvr-wjMvSIcXpYZ6wX2iEmGFI2Lm9eMV-yZfoZcAAF1Ll8Ck3FvIkH3~N0OobuGjcVZTiZ5PC2~h-zGHVaBPbsnOdVjYEeCGUwxwlNW6cxZZ6SfWbjTxXrpbSjLYZtlnGTBm5cd2Qaj61~A4lcoI72kj-v9GNXD5zeCQ9PeqKJHRN5p29VR8lTh9eqoIIHlGnsllQeZieeFJEAdnydOTi1ERzm4Hftq0P47lWu2FYh3aMtxI7HLeklWrmnQ--rW0XJ~xndWl45e~DEDaIL0k2FfMEmWYPtF-8l-xBX9IwIx8uZ2tcsexxLvJCY8-RiI4wgBqSf1CxPTGJ4TYUIqTUcMv2Sku8WslAdrWSPJofHWmeAmTJdSgCe8ZwvgMLkNZVeGgEccwtCDJbe5AeyJaQDFOTLlgwhHu5ExbyUPZtNZ4nSg-~qiGnpFTdgonqEYoJF9LvSaAgSfhOS3kdtZ6kKqgMFFY8InpGgCBuc6A6c5hsfCVjAAAA
|
10
apps/stasher/python/scripts/stasher
Normal file
10
apps/stasher/python/scripts/stasher
Normal 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()
|
9
apps/stasher/python/scripts/stasher.py
Normal file
9
apps/stasher/python/scripts/stasher.py
Normal 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()
|
46
apps/stasher/python/setup.py
Normal file
46
apps/stasher/python/setup.py
Normal 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
|
254
apps/stasher/python/src/bencode.py
Normal file
254
apps/stasher/python/src/bencode.py
Normal 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
|
||||
|
6339
apps/stasher/python/src/code.leo
Normal file
6339
apps/stasher/python/src/code.leo
Normal file
File diff suppressed because it is too large
Load Diff
4416
apps/stasher/python/src/stasher.py
Normal file
4416
apps/stasher/python/src/stasher.py
Normal file
File diff suppressed because it is too large
Load Diff
341
apps/systray/doc/LICENSE.systray4j.txt
Normal file
341
apps/systray/doc/LICENSE.systray4j.txt
Normal 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.
|
||||
|
52
apps/systray/java/build.xml
Normal file
52
apps/systray/java/build.xml
Normal 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>
|
@ -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();
|
||||
}
|
||||
}
|
398
apps/systray/java/src/net/i2p/apps/systray/ShellCommand.java
Normal file
398
apps/systray/java/src/net/i2p/apps/systray/ShellCommand.java
Normal 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;
|
||||
}
|
||||
}
|
109
apps/systray/java/src/net/i2p/apps/systray/SysTray.java
Normal file
109
apps/systray/java/src/net/i2p/apps/systray/SysTray.java
Normal 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);
|
||||
}
|
||||
}
|
90
apps/systray/java/src/net/i2p/apps/systray/UrlLauncher.java
Normal file
90
apps/systray/java/src/net/i2p/apps/systray/UrlLauncher.java
Normal 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;
|
||||
}
|
||||
}
|
@ -0,0 +1 @@
|
||||
java -cp systray4j.jar;. -Djava.library.path=. -jar systray.jar
|
1
apps/systray/java/src/net/i2p/apps/systray/i2psystray.sh
Normal file
1
apps/systray/java/src/net/i2p/apps/systray/i2psystray.sh
Normal file
@ -0,0 +1 @@
|
||||
java -cp systray4j.jar:. -Djava.library.path=. -jar systray.jar
|
BIN
apps/systray/java/src/net/i2p/apps/systray/icons/iggy.ico
Normal file
BIN
apps/systray/java/src/net/i2p/apps/systray/icons/iggy.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
210
apps/systray/java/src/net/i2p/apps/systray/icons/iggy.xpm
Normal file
210
apps/systray/java/src/net/i2p/apps/systray/icons/iggy.xpm
Normal 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. "};
|
BIN
apps/systray/java/src/net/i2p/apps/systray/lib/libsystray4j.so
Normal file
BIN
apps/systray/java/src/net/i2p/apps/systray/lib/libsystray4j.so
Normal file
Binary file not shown.
BIN
apps/systray/java/src/net/i2p/apps/systray/lib/systray4j.dll
Normal file
BIN
apps/systray/java/src/net/i2p/apps/systray/lib/systray4j.dll
Normal file
Binary file not shown.
BIN
apps/systray/java/src/net/i2p/apps/systray/lib/systray4j.jar
Normal file
BIN
apps/systray/java/src/net/i2p/apps/systray/lib/systray4j.jar
Normal file
Binary file not shown.
@ -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>
|
@ -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
112
build.xml
@ -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>
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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[]) {
|
||||
|
@ -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)
|
||||
*/
|
@ -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.
|
||||
*
|
197
core/java/src/net/i2p/time/Timestamper.java
Normal file
197
core/java/src/net/i2p/time/Timestamper.java
Normal 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);
|
||||
}
|
||||
}
|
@ -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); }
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
21
hosts.txt
21
hosts.txt
@ -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
|
||||
|
351
installer/doc/LICENSE.izpack.txt
Normal file
351
installer/doc/LICENSE.izpack.txt
Normal 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.
|
||||
|
41
installer/doc/LICENSE.wrapper.txt
Normal file
41
installer/doc/LICENSE.wrapper.txt
Normal 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
44
installer/install.xml
Normal 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>
|
@ -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>
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
|
22
installer/java/src/i2ptunnel.config
Normal file
22
installer/java/src/i2ptunnel.config
Normal 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
|
@ -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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
BIN
installer/lib/izpack/standalone-compiler.jar
Normal file
BIN
installer/lib/izpack/standalone-compiler.jar
Normal file
Binary file not shown.
BIN
installer/lib/wrapper/aix/i2psvc
Normal file
BIN
installer/lib/wrapper/aix/i2psvc
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user