Compare commits

...

31 Commits

Author SHA1 Message Date
jrandom
1c66543938 0.6.1.29 released 2007-08-24 00:33:28 +00:00
zzz
53ab3c472e 2007-08-13 zzz
* readme.html - Add inproxy.tino.i2p, replace search.i2p with eepsites.i2p,
      tweak the eepsite and troubleshooting sections
2007-08-13 19:42:59 +00:00
zzz
a4b221fa71 2007-08-11 zzz
* Add stats for individual tunnel rates (nice when graphed)
    * i2psnark: Fix outbound tunnel nickname
2007-08-11 20:48:14 +00:00
complication
e3e1d0842d 2007-08-05 Complication
* Update the sharing calculator on config.jsp
      and explain the trade-off even more thoroughly.
2007-08-06 03:35:42 +00:00
complication
99b5bf9609 2007-08-04 Complication
* Lower the threshold between the K and L bandwidth class,
      so that K is now < 12 KB/s, instead of <= 16 KB/s.
      Hopefully this lets people with 128 kbit/s (16 KB/s) upload lines
      participate in routing, if they keep the default share percentage.
2007-08-05 03:25:30 +00:00
zzz
da10fe0df7 (zzz) ask for bandwidth 2007-07-19 18:05:44 +00:00
zzz
9fd5ba7b2d 2007-07-16 zzz
* i2psnark: Add tooltip info for choked/uninterested
2007-07-16 21:15:51 +00:00
zzz
05b5df9d76 2007-07-16 zzz
* Make selection of graphed data configurable via configstats.jsp,
      remove most of the default graphs to save some memory
2007-07-16 20:47:57 +00:00
zzz
5c1dc79767 2007-07-15 zzz
* Add current values to graph legends
    * Fix up previous Rate fix to check for divide by zero
2007-07-15 18:34:33 +00:00
complication
4acd2996c5 2007-07-14 Complication
* Take the post-download routerInfo size check back out of ReseedHandler,
      since it wasn't helpful, and a lower limit caused false warnings.
    * Give EepGet ability to enforce a min/max HTTP response size.
    * Enforce a maximum response size of 8 MB when ReseedHandler
      downloads into a ByteArrayOutputStream.
    * Refactor ReseedHandler/ReseedRunner from static to ordinary classes,
      change invocation from RouterConsoleRunner accordingly.
    * Add an EepGet status listener to ReseedHandler to log causes of reseed failure,
      provide status reports to indicate the progress of reseeding.
    * Enable icon for default eepsite, and the index page
      of the router console (more later).
2007-07-15 00:56:18 +00:00
zzz
16fa6a89bc 2007-07-14 zzz
* Clean up graphs.jsp - set K=1024 where appropriate,
      output image sizes in html, catch ooms, other minor tweaks
    * Fix current event count truncation which fixes graphs with low
      60-sec event counts displaying high values
      (bw.* and router.* graphs for example were 1.5x too high)
      Affects all "events per period" (non-lifetime) counts.
2007-07-14 18:44:11 +00:00
zzz
2a72e8574b 2007-07-09 zzz
* i2psnark: give a better error message for a non-i2p torrent
2007-07-10 01:20:37 +00:00
zzz
d4a1bcf28f 2007-07-07 zzz
* Add auto-detect IP/Port to NTCP. When enabled on config.jsp,
      SSU will notify/restart NTCP when the external address changes.
      Now you can enable inbound TCP without a static IP or dyndns service.
2007-07-07 20:03:50 +00:00
zzz
409b71def5 2007-07-04 zzz
* Display calculated share bandwidth and remove load testing
      on config.jsp
2007-07-04 22:58:48 +00:00
zzz
2dc5fbda02 2007-07-01 zzz
* Replace broken option i2np.udp.alwaysPreferred with
      i2np.udp.preferred and adjust UDP bids; possible settings are
      "false" (default), "true", and "always".
      Default setting results in same behavior as before
      (NTCP is preferred unless it isn't established and UDP is established).
      Use to compare NTCP and UDP transports.
2007-07-01 22:07:52 +00:00
jrandom
71aaf03d09 2007-06-27 jrandom
* fix for a streaming lib bug that could leave a thread waiting
      indefinitely (thanks Complication!)
2007-06-28 01:51:16 +00:00
complication
30c99e630b 2007-06-16 Complication
* First pass on EepGet and ReseedHandler improvements,
      please avoid use on routers which matter!
    * Give EepGet ability of downloading into an OutputStream,
      such as the ByteArrayOutputStream of ReseedHandler.
    * Detect failure to reseed better, report it persistently
      and more verbosely, provide a link to logs
      and suggest manual reseed.
2007-06-16 23:15:49 +00:00
complication
445b39171a 2007-05-06 Complication
* spelling correction to history.txt
2007-05-06 20:02:04 +00:00
complication
571c2d6047 2007-05-06 Complication
* Fix the build.xml file, so the preppkg build target won't try copying files
      which became deprecated with the old Syndie (thank for alerting, itsu!)
2007-05-06 19:52:39 +00:00
zzz
42ff763933 (zzz) 4-10 2007-04-11 06:01:35 +00:00
zzz
727edc3ff9 (zzz) add 204 log link 2007-04-08 04:18:18 +00:00
zzz
82a4758a0a (zzz) 3-27 and 4-3 2007-04-05 06:11:21 +00:00
zzz
915914ebb3 2007-03-31 zzz
* Add trevorreznik jump server to the http proxy error page
    * Add anonymity to the trackers supporting details links in i2psnark
2007-03-31 21:50:51 +00:00
zzz
c438b56378 (zzz) 3-20 2007-03-25 22:58:18 +00:00
zzz
307ccfb1b4 2007-03-24 zzz
* Remove Syndie from build targets and navbar
2007-03-24 07:57:37 +00:00
zzz
34e23259b4 2007-03-22 zzz
* i2psnark tracker handling tweaks:
    -   Add link to tracker details page (Postman only for now, requires bytemonsoon patch)
    -   Add Base URL to tracker list configuration
    -   Web page links built from tracker list Base URLs
    -   Only build and sort tracker list once
    -   Add anonymityWeb tracker to default list
    -   Add tooltip info for TrackerErrs
    -   Stop torrent if not registered with tracker
    -   Mark temp files as delete on exit
2007-03-22 05:21:25 +00:00
zzz
036802d66a 2007-03-18 zzz
* i2psnark: Cleanup some handling of saved partial pieces
    * i2psnark: Put bit counting in Bitfield.java for efficiency
    * i2psnark: Save torrent completion state in i2psnark.config
2007-03-18 21:57:01 +00:00
zzz
6a7dbc8e3a (zzz) i2psnark: Save torrent completion status in i2psnark.config 2007-03-18 21:43:41 +00:00
zzz
cf4a9ffc27 (zzz) i2psnark: Put bit counting in Bitfield.java for efficiency 2007-03-18 21:28:28 +00:00
zzz
6ef4adf318 (zzz) i2psnark: Remove saved partial when halted, don't save partial when halted 2007-03-18 21:25:18 +00:00
zzz
f84c9bf3b1 (zzz) .28 news 2007-03-18 02:17:16 +00:00
46 changed files with 1135 additions and 359 deletions

View File

@@ -32,6 +32,7 @@ public class BitField
private final byte[] bitfield;
private final int size;
private int count;
/**
* Creates a new BitField that represents <code>size</code> unset bits.
@@ -41,6 +42,7 @@ public class BitField
this.size = size;
int arraysize = ((size-1)/8)+1;
bitfield = new byte[arraysize];
this.count = 0;
}
/**
@@ -60,6 +62,11 @@ public class BitField
// XXX - More correct would be to check that unused bits are
// cleared or clear them explicitly ourselves.
System.arraycopy(bitfield, 0, this.bitfield, 0, arraysize);
this.count = 0;
for (int i = 0; i < size; i++)
if (get(i))
this.count++;
}
/**
@@ -95,7 +102,10 @@ public class BitField
throw new IndexOutOfBoundsException(Integer.toString(bit));
int index = bit/8;
int mask = 128 >> (bit % 8);
bitfield[index] |= mask;
if ((bitfield[index] & mask) == 0) {
count++;
bitfield[index] |= mask;
}
}
/**
@@ -114,6 +124,22 @@ public class BitField
return (bitfield[index] & mask) != 0;
}
/**
* Return the number of set bits.
*/
public int count()
{
return count;
}
/**
* Return true if all bits are set.
*/
public boolean complete()
{
return count >= size;
}
public String toString()
{
// Not very efficient
@@ -129,4 +155,5 @@ public class BitField
return sb.toString();
}
}

View File

@@ -101,6 +101,8 @@ public class I2PSnarkUtil {
}
if (opts.getProperty("inbound.nickname") == null)
opts.setProperty("inbound.nickname", "I2PSnark");
if (opts.getProperty("outbound.nickname") == null)
opts.setProperty("outbound.nickname", "I2PSnark");
if (opts.getProperty("i2p.streaming.inactivityTimeout") == null)
opts.setProperty("i2p.streaming.inactivityTimeout", "90000");
if (opts.getProperty("i2p.streaming.inactivityAction") == null)

View File

@@ -54,8 +54,8 @@ public class Peer implements Comparable
private boolean deregister = true;
private static long __id;
private long _id;
final static long CHECK_PERIOD = 40*1000; // 40 seconds
final static int RATE_DEPTH = 6; // make following arrays RATE_DEPTH long
final static long CHECK_PERIOD = PeerCoordinator.CHECK_PERIOD; // 40 seconds
final static int RATE_DEPTH = PeerCoordinator.RATE_DEPTH; // make following arrays RATE_DEPTH long
private long uploaded_old[] = {-1,-1,-1,-1,-1,-1};
private long downloaded_old[] = {-1,-1,-1,-1,-1,-1};
@@ -493,33 +493,24 @@ public class Peer implements Comparable
/**
* Return how much the peer has
* Quite inefficient - a byte lookup table or counter in Bitfield would be much better
*/
public int completed()
{
PeerState s = state;
if (s == null || s.bitfield == null)
return 0;
int count = 0;
for (int i = 0; i < s.bitfield.size(); i++)
if (s.bitfield.get(i))
count++;
return count;
return s.bitfield.count();
}
/**
* Return if a peer is a seeder
* Quite inefficient - a byte lookup table or counter in Bitfield would be much better
*/
public boolean isCompleted()
{
PeerState s = state;
if (s == null || s.bitfield == null)
return false;
for (int i = 0; i < s.bitfield.size(); i++)
if (!s.bitfield.get(i))
return false;
return true;
return s.bitfield.complete();
}
/**

View File

@@ -237,6 +237,8 @@ public class PeerCoordinator implements PeerListener
peer.disconnect();
removePeerFromPieces(peer);
}
// delete any saved orphan partial piece
savedRequest = null;
}
public void connected(Peer peer)
@@ -263,6 +265,7 @@ public class PeerCoordinator implements PeerListener
{
if (_log.shouldLog(Log.WARN))
_log.warn("Already connected to: " + peer + ": " + old + ", inactive for " + old.getInactiveTime());
// toDisconnect = peer to get out of synchronized(peers)
peer.disconnect(false); // Don't deregister this connection/peer.
}
else
@@ -357,7 +360,6 @@ public class PeerCoordinator implements PeerListener
while (it.hasNext())
{
Peer peer = (Peer)it.next();
boolean remove = false;
if (peer.isChoking() && peer.isInterested())
{
count++;
@@ -691,6 +693,8 @@ public class PeerCoordinator implements PeerListener
private long savedRequestTime = 0;
public void savePeerPartial(PeerState state)
{
if (halted)
return;
Request req = state.getPartialRequest();
if (req == null)
return;
@@ -791,7 +795,7 @@ public class PeerCoordinator implements PeerListener
*/
public void markUnrequested(Peer peer)
{
if (peer.state == null)
if (halted || peer.state == null)
return;
int[] arr = peer.state.getRequestedPieces();
for (int i = 0; arr[i] >= 0; i++)

View File

@@ -468,6 +468,8 @@ public class Snark
pc.halt();
Storage st = storage;
if (st != null) {
if (storage.changed)
SnarkManager.instance().saveTorrentStatus(storage.getMetaInfo(), storage.getBitField());
try {
storage.close();
} catch (IOException ioe) {

View File

@@ -3,6 +3,7 @@ package org.klomp.snark;
import java.io.*;
import java.util.*;
import net.i2p.I2PAppContext;
import net.i2p.data.Base64;
import net.i2p.data.DataHelper;
import net.i2p.util.I2PThread;
import net.i2p.util.Log;
@@ -30,6 +31,8 @@ public class SnarkManager implements Snark.CompleteListener {
public static final String PROP_EEP_PORT = "i2psnark.eepPort";
public static final String PROP_UPLOADERS_TOTAL = "i2psnark.uploaders.total";
public static final String PROP_DIR = "i2psnark.dir";
public static final String PROP_META_PREFIX = "i2psnark.zmeta.";
public static final String PROP_META_BITFIELD_SUFFIX = ".bitfield";
public static final String PROP_AUTO_START = "i2snark.autoStart";
public static final String DEFAULT_AUTO_START = "false";
@@ -271,7 +274,9 @@ public class SnarkManager implements Snark.CompleteListener {
public void saveConfig() {
try {
DataHelper.storeProps(_config, new File(_configFile));
synchronized (_configFile) {
DataHelper.storeProps(_config, new File(_configFile));
}
} catch (IOException ioe) {
addMessage("Unable to save the config to '" + _configFile + "'");
}
@@ -361,7 +366,97 @@ public class SnarkManager implements Snark.CompleteListener {
}
}
/**
* Get the timestamp for a torrent from the config file
*/
public long getSavedTorrentTime(MetaInfo metainfo) {
byte[] ih = metainfo.getInfoHash();
String infohash = Base64.encode(ih);
infohash = infohash.replace('=', '$');
String time = _config.getProperty(PROP_META_PREFIX + infohash + PROP_META_BITFIELD_SUFFIX);
if (time == null)
return 0;
int comma = time.indexOf(',');
if (comma <= 0)
return 0;
time = time.substring(0, comma);
try { return Long.parseLong(time); } catch (NumberFormatException nfe) {}
return 0;
}
/**
* Get the saved bitfield for a torrent from the config file.
* Convert "." to a full bitfield.
*/
public BitField getSavedTorrentBitField(MetaInfo metainfo) {
byte[] ih = metainfo.getInfoHash();
String infohash = Base64.encode(ih);
infohash = infohash.replace('=', '$');
String bf = _config.getProperty(PROP_META_PREFIX + infohash + PROP_META_BITFIELD_SUFFIX);
if (bf == null)
return null;
int comma = bf.indexOf(',');
if (comma <= 0)
return null;
bf = bf.substring(comma + 1).trim();
int len = metainfo.getPieces();
if (bf.equals(".")) {
BitField bitfield = new BitField(len);
for (int i = 0; i < len; i++)
bitfield.set(i);
return bitfield;
}
byte[] bitfield = Base64.decode(bf);
if (bitfield == null)
return null;
if (bitfield.length * 8 < len)
return null;
return new BitField(bitfield, len);
}
/**
* Save the completion status of a torrent and the current time in the config file
* in the form "i2psnark.zmeta.$base64infohash=$time,$base64bitfield".
* The config file property key is appended with the Base64 of the infohash,
* with the '=' changed to '$' since a key can't contain '='.
* The time is a standard long converted to string.
* The status is either a bitfield converted to Base64 or "." for a completed
* torrent to save space in the config file and in memory.
*/
public void saveTorrentStatus(MetaInfo metainfo, BitField bitfield) {
byte[] ih = metainfo.getInfoHash();
String infohash = Base64.encode(ih);
infohash = infohash.replace('=', '$');
String now = "" + System.currentTimeMillis();
String bfs;
if (bitfield.complete()) {
bfs = ".";
} else {
byte[] bf = bitfield.getFieldBytes();
bfs = Base64.encode(bf);
}
_config.setProperty(PROP_META_PREFIX + infohash + PROP_META_BITFIELD_SUFFIX, now + "," + bfs);
saveConfig();
}
/**
* Remove the status of a torrent from the config file.
* This may help the config file from growing too big.
*/
public void removeTorrentStatus(MetaInfo metainfo) {
byte[] ih = metainfo.getInfoHash();
String infohash = Base64.encode(ih);
infohash = infohash.replace('=', '$');
_config.remove(PROP_META_PREFIX + infohash + PROP_META_BITFIELD_SUFFIX);
saveConfig();
}
private String locked_validateTorrent(MetaInfo info) throws IOException {
String announce = info.getAnnounce();
// basic validation of url
if ((!announce.startsWith("http://")) ||
(announce.indexOf(".i2p/") < 0))
return "Non-i2p tracker in " + info.getName() + ", deleting it";
List files = info.getFiles();
if ( (files != null) && (files.size() > MAX_FILES_PER_TORRENT) ) {
return "Too many files in " + info.getName() + " (" + files.size() + "), deleting it";
@@ -426,6 +521,8 @@ public class SnarkManager implements Snark.CompleteListener {
if (torrent != null) {
File torrentFile = new File(filename);
torrentFile.delete();
if (torrent.storage != null)
removeTorrentStatus(torrent.storage.getMetaInfo());
addMessage("Torrent removed: '" + torrentFile.getName() + "'");
}
}
@@ -496,25 +593,29 @@ public class SnarkManager implements Snark.CompleteListener {
}
private static final String DEFAULT_TRACKERS[] = {
"Postman's tracker", "http://YRgrgTLGnbTq2aZOZDJQ~o6Uk5k6TK-OZtx0St9pb0G-5EGYURZioxqYG8AQt~LgyyI~NCj6aYWpPO-150RcEvsfgXLR~CxkkZcVpgt6pns8SRc3Bi-QSAkXpJtloapRGcQfzTtwllokbdC-aMGpeDOjYLd8b5V9Im8wdCHYy7LRFxhEtGb~RL55DA8aYOgEXcTpr6RPPywbV~Qf3q5UK55el6Kex-6VCxreUnPEe4hmTAbqZNR7Fm0hpCiHKGoToRcygafpFqDw5frLXToYiqs9d4liyVB-BcOb0ihORbo0nS3CLmAwZGvdAP8BZ7cIYE3Z9IU9D1G8JCMxWarfKX1pix~6pIA-sp1gKlL1HhYhPMxwyxvuSqx34o3BqU7vdTYwWiLpGM~zU1~j9rHL7x60pVuYaXcFQDR4-QVy26b6Pt6BlAZoFmHhPcAuWfu-SFhjyZYsqzmEmHeYdAwa~HojSbofg0TMUgESRXMw6YThK1KXWeeJVeztGTz25sL8AAAA.i2p/announce.php"
, "eBook Tracker", "http://E71FRom6PZNEqTN2Lr8P-sr23b7HJVC32KoGnVQjaX6zJiXwhJy2HsXob36Qmj81TYFZdewFZa9mSJ533UZgGyQkXo2ahctg82JKYZfDe5uDxAn1E9YPjxZCWJaFJh0S~UwSs~9AZ7UcauSJIoNtpxrtbmRNVFLqnkEDdLZi26TeucfOmiFmIWnVblLniWv3tG1boE9Abd-6j3FmYVrRucYuepAILYt6katmVNOk6sXmno1Eynrp~~MBuFq0Ko6~jsc2E2CRVYXDhGHEMdt-j6JUz5D7S2RIVzDRqQyAZLKJ7OdQDmI31przzmne1vOqqqLC~1xUumZVIvF~yOeJUGNjJ1Vx0J8i2BQIusn1pQJ6UCB~ZtZZLQtEb8EPVCfpeRi2ri1M5CyOuxN0V5ekmPHrYIBNevuTCRC26NP7ZS5VDgx1~NaC3A-CzJAE6f1QXi0wMI9aywNG5KGzOPifcsih8eyGyytvgLtrZtV7ykzYpPCS-rDfITncpn5hliPUAAAA.i2p/pub/bt/announce.php"
, "Gaytorrents Tracker", "http://uxPWHbK1OIj9HxquaXuhMiIvi21iK0~ZiG9d8G0840ZXIg0r6CbiV71xlsqmdnU6wm0T2LySriM0doW2gUigo-5BNkUquHwOjLROiETnB3ZR0Ml4IGa6QBPn1aAq2d9~g1r1nVjLE~pcFnXB~cNNS7kIhX1d6nLgYVZf0C2cZopEow2iWVUggGGnAA9mHjE86zLEnTvAyhbAMTqDQJhEuLa0ZYSORqzJDMkQt90MV4YMjX1ICY6RfUSFmxEqu0yWTrkHsTtRw48l~dz9wpIgc0a0T9C~eeWvmBFTqlJPtQZwntpNeH~jF7nlYzB58olgV2HHFYpVYD87DYNzTnmNWxCJ5AfDorm6AIUCV2qaE7tZtI1h6fbmGpGlPyW~Kw5GXrRfJwNvr6ajwAVi~bPVnrBwDZezHkfW4slOO8FACPR28EQvaTu9nwhAbqESxV2hCTq6vQSGjuxHeOuzBOEvRWkLKOHWTC09t2DbJ94FSqETmZopTB1ukEmaxRWbKSIaAAAA.i2p/announce.php"
, "NickyB Tracker", "http://9On6d3cZ27JjwYCtyJJbowe054d5tFnfMjv4PHsYs-EQn4Y4mk2zRixatvuAyXz2MmRfXG-NAUfhKr0KCxRNZbvHmlckYfT-WBzwwpiMAl0wDFY~Pl8cqXuhfikSG5WrqdPfDNNIBuuznS0dqaczf~OyVaoEOpvuP3qV6wKqbSSLpjOwwAaQPHjlRtNIW8-EtUZp-I0LT45HSoowp~6b7zYmpIyoATvIP~sT0g0MTrczWhbVTUZnEkZeLhOR0Duw1-IRXI2KHPbA24wLO9LdpKKUXed05RTz0QklW5ROgR6TYv7aXFufX8kC0-DaKvQ5JKG~h8lcoHvm1RCzNqVE-2aiZnO2xH08H-iCWoLNJE-Td2kT-Tsc~3QdQcnEUcL5BF-VT~QYRld2--9r0gfGl-yDrJZrlrihHGr5J7ImahelNn9PpkVp6eIyABRmJHf2iicrk3CtjeG1j9OgTSwaNmEpUpn4aN7Kx0zNLdH7z6uTgCGD9Kmh1MFYrsoNlTp4AAAA.i2p/bittorrent/announce.php"
, "Orion's tracker", "http://gKik1lMlRmuroXVGTZ~7v4Vez3L3ZSpddrGZBrxVriosCQf7iHu6CIk8t15BKsj~P0JJpxrofeuxtm7SCUAJEr0AIYSYw8XOmp35UfcRPQWyb1LsxUkMT4WqxAT3s1ClIICWlBu5An~q-Mm0VFlrYLIPBWlUFnfPR7jZ9uP5ZMSzTKSMYUWao3ejiykr~mtEmyls6g-ZbgKZawa9II4zjOy-hdxHgP-eXMDseFsrym4Gpxvy~3Fv9TuiSqhpgm~UeTo5YBfxn6~TahKtE~~sdCiSydqmKBhxAQ7uT9lda7xt96SS09OYMsIWxLeQUWhns-C~FjJPp1D~IuTrUpAFcVEGVL-BRMmdWbfOJEcWPZ~CBCQSO~VkuN1ebvIOr9JBerFMZSxZtFl8JwcrjCIBxeKPBmfh~xYh16BJm1BBBmN1fp2DKmZ2jBNkAmnUbjQOqWvUcehrykWk5lZbE7bjJMDFH48v3SXwRuDBiHZmSbsTY6zhGY~GkMQHNGxPMMSIAAAA.i2p/bt/announce.php"
"Postman", "http://YRgrgTLGnbTq2aZOZDJQ~o6Uk5k6TK-OZtx0St9pb0G-5EGYURZioxqYG8AQt~LgyyI~NCj6aYWpPO-150RcEvsfgXLR~CxkkZcVpgt6pns8SRc3Bi-QSAkXpJtloapRGcQfzTtwllokbdC-aMGpeDOjYLd8b5V9Im8wdCHYy7LRFxhEtGb~RL55DA8aYOgEXcTpr6RPPywbV~Qf3q5UK55el6Kex-6VCxreUnPEe4hmTAbqZNR7Fm0hpCiHKGoToRcygafpFqDw5frLXToYiqs9d4liyVB-BcOb0ihORbo0nS3CLmAwZGvdAP8BZ7cIYE3Z9IU9D1G8JCMxWarfKX1pix~6pIA-sp1gKlL1HhYhPMxwyxvuSqx34o3BqU7vdTYwWiLpGM~zU1~j9rHL7x60pVuYaXcFQDR4-QVy26b6Pt6BlAZoFmHhPcAuWfu-SFhjyZYsqzmEmHeYdAwa~HojSbofg0TMUgESRXMw6YThK1KXWeeJVeztGTz25sL8AAAA.i2p/announce.php=http://tracker.postman.i2p/"
, "eBook", "http://E71FRom6PZNEqTN2Lr8P-sr23b7HJVC32KoGnVQjaX6zJiXwhJy2HsXob36Qmj81TYFZdewFZa9mSJ533UZgGyQkXo2ahctg82JKYZfDe5uDxAn1E9YPjxZCWJaFJh0S~UwSs~9AZ7UcauSJIoNtpxrtbmRNVFLqnkEDdLZi26TeucfOmiFmIWnVblLniWv3tG1boE9Abd-6j3FmYVrRucYuepAILYt6katmVNOk6sXmno1Eynrp~~MBuFq0Ko6~jsc2E2CRVYXDhGHEMdt-j6JUz5D7S2RIVzDRqQyAZLKJ7OdQDmI31przzmne1vOqqqLC~1xUumZVIvF~yOeJUGNjJ1Vx0J8i2BQIusn1pQJ6UCB~ZtZZLQtEb8EPVCfpeRi2ri1M5CyOuxN0V5ekmPHrYIBNevuTCRC26NP7ZS5VDgx1~NaC3A-CzJAE6f1QXi0wMI9aywNG5KGzOPifcsih8eyGyytvgLtrZtV7ykzYpPCS-rDfITncpn5hliPUAAAA.i2p/pub/bt/announce.php=http://de-ebook-archiv.i2p/pub/bt/"
, "Gaytorrents", "http://uxPWHbK1OIj9HxquaXuhMiIvi21iK0~ZiG9d8G0840ZXIg0r6CbiV71xlsqmdnU6wm0T2LySriM0doW2gUigo-5BNkUquHwOjLROiETnB3ZR0Ml4IGa6QBPn1aAq2d9~g1r1nVjLE~pcFnXB~cNNS7kIhX1d6nLgYVZf0C2cZopEow2iWVUggGGnAA9mHjE86zLEnTvAyhbAMTqDQJhEuLa0ZYSORqzJDMkQt90MV4YMjX1ICY6RfUSFmxEqu0yWTrkHsTtRw48l~dz9wpIgc0a0T9C~eeWvmBFTqlJPtQZwntpNeH~jF7nlYzB58olgV2HHFYpVYD87DYNzTnmNWxCJ5AfDorm6AIUCV2qaE7tZtI1h6fbmGpGlPyW~Kw5GXrRfJwNvr6ajwAVi~bPVnrBwDZezHkfW4slOO8FACPR28EQvaTu9nwhAbqESxV2hCTq6vQSGjuxHeOuzBOEvRWkLKOHWTC09t2DbJ94FSqETmZopTB1ukEmaxRWbKSIaAAAA.i2p/announce.php=http://gaytorrents.i2p/"
, "NickyB", "http://9On6d3cZ27JjwYCtyJJbowe054d5tFnfMjv4PHsYs-EQn4Y4mk2zRixatvuAyXz2MmRfXG-NAUfhKr0KCxRNZbvHmlckYfT-WBzwwpiMAl0wDFY~Pl8cqXuhfikSG5WrqdPfDNNIBuuznS0dqaczf~OyVaoEOpvuP3qV6wKqbSSLpjOwwAaQPHjlRtNIW8-EtUZp-I0LT45HSoowp~6b7zYmpIyoATvIP~sT0g0MTrczWhbVTUZnEkZeLhOR0Duw1-IRXI2KHPbA24wLO9LdpKKUXed05RTz0QklW5ROgR6TYv7aXFufX8kC0-DaKvQ5JKG~h8lcoHvm1RCzNqVE-2aiZnO2xH08H-iCWoLNJE-Td2kT-Tsc~3QdQcnEUcL5BF-VT~QYRld2--9r0gfGl-yDrJZrlrihHGr5J7ImahelNn9PpkVp6eIyABRmJHf2iicrk3CtjeG1j9OgTSwaNmEpUpn4aN7Kx0zNLdH7z6uTgCGD9Kmh1MFYrsoNlTp4AAAA.i2p/bittorrent/announce.php=http://nickyb.i2p/bittorrent/"
, "Orion", "http://gKik1lMlRmuroXVGTZ~7v4Vez3L3ZSpddrGZBrxVriosCQf7iHu6CIk8t15BKsj~P0JJpxrofeuxtm7SCUAJEr0AIYSYw8XOmp35UfcRPQWyb1LsxUkMT4WqxAT3s1ClIICWlBu5An~q-Mm0VFlrYLIPBWlUFnfPR7jZ9uP5ZMSzTKSMYUWao3ejiykr~mtEmyls6g-ZbgKZawa9II4zjOy-hdxHgP-eXMDseFsrym4Gpxvy~3Fv9TuiSqhpgm~UeTo5YBfxn6~TahKtE~~sdCiSydqmKBhxAQ7uT9lda7xt96SS09OYMsIWxLeQUWhns-C~FjJPp1D~IuTrUpAFcVEGVL-BRMmdWbfOJEcWPZ~CBCQSO~VkuN1ebvIOr9JBerFMZSxZtFl8JwcrjCIBxeKPBmfh~xYh16BJm1BBBmN1fp2DKmZ2jBNkAmnUbjQOqWvUcehrykWk5lZbE7bjJMDFH48v3SXwRuDBiHZmSbsTY6zhGY~GkMQHNGxPMMSIAAAA.i2p/bt/announce.php=http://orion.i2p/bt/"
, "anonymity", "http://8EoJZIKrWgGuDrxA3nRJs1jsPfiGwmFWL91hBrf0HA7oKhEvAna4Ocx47VLUR9retVEYBAyWFK-eZTPcvhnz9XffBEiJQQ~kFSCqb1fV6IfPiV3HySqi9U5Caf6~hC46fRd~vYnxmaBLICT3N160cxBETqH3v2rdxdJpvYt8q4nMk9LUeVXq7zqCTFLLG5ig1uKgNzBGe58iNcsvTEYlnbYcE930ABmrzj8G1qQSgSwJ6wx3tUQNl1z~4wSOUMan~raZQD60lRK70GISjoX0-D0Po9WmPveN3ES3g72TIET3zc3WPdK2~lgmKGIs8GgNLES1cXTolvbPhdZK1gxddRMbJl6Y6IPFyQ9o4-6Rt3Lp-RMRWZ2TG7j2OMcNSiOmATUhKEFBDfv-~SODDyopGBmfeLw16F4NnYednvn4qP10dyMHcUASU6Zag4mfc2-WivrOqeWhD16fVAh8MoDpIIT~0r9XmwdaVFyLcjbXObabJczxCAW3fodQUnvuSkwzAAAA.i2p/anonymityTracker/announce.php=http://anonymityweb.i2p/anonymityTracker/"
// , "The freak's tracker", "http://mHKva9x24E5Ygfey2llR1KyQHv5f8hhMpDMwJDg1U-hABpJ2NrQJd6azirdfaR0OKt4jDlmP2o4Qx0H598~AteyD~RJU~xcWYdcOE0dmJ2e9Y8-HY51ie0B1yD9FtIV72ZI-V3TzFDcs6nkdX9b81DwrAwwFzx0EfNvK1GLVWl59Ow85muoRTBA1q8SsZImxdyZ-TApTVlMYIQbdI4iQRwU9OmmtefrCe~ZOf4UBS9-KvNIqUL0XeBSqm0OU1jq-D10Ykg6KfqvuPnBYT1BYHFDQJXW5DdPKwcaQE4MtAdSGmj1epDoaEBUa9btQlFsM2l9Cyn1hzxqNWXELmx8dRlomQLlV4b586dRzW~fLlOPIGC13ntPXogvYvHVyEyptXkv890jC7DZNHyxZd5cyrKC36r9huKvhQAmNABT2Y~pOGwVrb~RpPwT0tBuPZ3lHYhBFYmD8y~AOhhNHKMLzea1rfwTvovBMByDdFps54gMN1mX4MbCGT4w70vIopS9yAAAA.i2p/bytemonsoon/announce.php"
};
/** comma delimited list of name=announceURL for the trackers to be displayed */
/** comma delimited list of name=announceURL=baseURL for the trackers to be displayed */
public static final String PROP_TRACKERS = "i2psnark.trackers";
/** unordered map of announceURL to name */
private static Map trackerMap = null;
/** sorted map of name to announceURL=baseURL */
public Map getTrackers() {
HashMap rv = new HashMap();
if (trackerMap != null) // only do this once, can't be updated while running
return trackerMap;
Map rv = new TreeMap();
String trackers = _config.getProperty(PROP_TRACKERS);
if ( (trackers == null) || (trackers.trim().length() <= 0) )
trackers = _context.getProperty(PROP_TRACKERS);
if ( (trackers == null) || (trackers.trim().length() <= 0) ) {
for (int i = 0; i < DEFAULT_TRACKERS.length; i += 2)
rv.put(DEFAULT_TRACKERS[i+1], DEFAULT_TRACKERS[i]);
rv.put(DEFAULT_TRACKERS[i], DEFAULT_TRACKERS[i+1]);
} else {
StringTokenizer tok = new StringTokenizer(trackers, ",");
while (tok.hasMoreTokens()) {
@@ -525,11 +626,12 @@ public class SnarkManager implements Snark.CompleteListener {
String name = pair.substring(0, split).trim();
String url = pair.substring(split+1).trim();
if ( (name.length() > 0) && (url.length() > 0) )
rv.put(url, name);
rv.put(name, url);
}
}
return rv;
trackerMap = rv;
return trackerMap;
}
private static class TorrentFilenameFilter implements FilenameFilter {

View File

@@ -45,6 +45,7 @@ public class Storage
// XXX - Not always set correctly
int piece_size;
int pieces;
boolean changed;
/** The default piece size. */
private static int MIN_PIECE_SIZE = 256*1024;
@@ -285,6 +286,10 @@ public class Storage
public void check(String rootDir) throws IOException
{
File base = new File(rootDir, filterName(metainfo.getName()));
// look for saved bitfield and timestamp in the config file
long savedTime = SnarkManager.instance().getSavedTorrentTime(metainfo);
BitField savedBitField = SnarkManager.instance().getSavedTorrentBitField(metainfo);
boolean useSavedBitField = savedTime > 0 && savedBitField != null;
List files = metainfo.getFiles();
if (files == null)
@@ -298,6 +303,11 @@ public class Storage
rafs = new RandomAccessFile[1];
names = new String[1];
lengths[0] = metainfo.getTotalLength();
if (useSavedBitField) {
long lm = base.lastModified();
if (lm <= 0 || lm > savedTime)
useSavedBitField = false;
}
if (base.exists() && !base.canWrite()) // hope we can get away with this, if we are only seeding...
rafs[0] = new RandomAccessFile(base, "r");
else
@@ -322,6 +332,11 @@ public class Storage
File f = createFileFromNames(base, (List)files.get(i));
lengths[i] = ((Long)ls.get(i)).longValue();
total += lengths[i];
if (useSavedBitField) {
long lm = base.lastModified();
if (lm <= 0 || lm > savedTime)
useSavedBitField = false;
}
if (f.exists() && !f.canWrite()) // see above re: only seeding
rafs[i] = new RandomAccessFile(f, "r");
else
@@ -335,7 +350,14 @@ public class Storage
throw new IOException("File lengths do not add up "
+ total + " != " + metalength);
}
checkCreateFiles();
if (useSavedBitField) {
bitfield = savedBitField;
needed = metainfo.getPieces() - bitfield.count();
Snark.debug("Found saved state and files unchanged, skipping check", Snark.NOTICE);
} else {
checkCreateFiles();
SnarkManager.instance().saveTorrentStatus(metainfo, bitfield);
}
}
/**
@@ -354,7 +376,7 @@ public class Storage
if (!base.exists())
throw new IOException("Could not reopen file " + base);
if (!base.canWrite()) // hope we can get away with this, if we are only seeding...
if (complete() || !base.canWrite()) // hope we can get away with this, if we are only seeding...
rafs[0] = new RandomAccessFile(base, "r");
else
rafs[0] = new RandomAccessFile(base, "rw");
@@ -372,7 +394,7 @@ public class Storage
File f = getFileFromNames(base, (List)files.get(i));
if (!f.exists())
throw new IOException("Could not reopen file " + f);
if (!f.canWrite()) // see above re: only seeding
if (complete() || !f.canWrite()) // see above re: only seeding
rafs[i] = new RandomAccessFile(f, "r");
else
rafs[i] = new RandomAccessFile(f, "rw");
@@ -517,6 +539,7 @@ public class Storage
// gobble gobble
}
}
changed = false;
}
/**
@@ -604,6 +627,7 @@ public class Storage
}
}
changed = true;
if (complete) {
// listener.storageCompleted(this);
// do we also need to close all of the files and reopen
@@ -623,6 +647,8 @@ public class Storage
listener.setWantedPieces(this);
Snark.debug("WARNING: Not really done, missing " + needed
+ " pieces", Snark.WARNING);
} else {
SnarkManager.instance().saveTorrentStatus(metainfo, bitfield);
}
}

View File

@@ -41,6 +41,7 @@ public class TrackerClient extends I2PThread
private static final String STARTED_EVENT = "started";
private static final String COMPLETED_EVENT = "completed";
private static final String STOPPED_EVENT = "stopped";
private static final String NOT_REGISTERED = "torrent not registered"; //bytemonsoon
private final static int SLEEP = 5; // 5 minutes.
private final static int DELAY_MIN = 2000; // 2 secs.
@@ -151,6 +152,10 @@ public class TrackerClient extends I2PThread
("WARNING: Could not contact tracker at '"
+ announce + "': " + ioe, Snark.WARNING);
coordinator.trackerProblems = ioe.getMessage();
if (coordinator.trackerProblems.toLowerCase().startsWith(NOT_REGISTERED)) {
stop = true;
coordinator.snark.stopTorrent();
}
}
if (stop)
@@ -254,6 +259,10 @@ public class TrackerClient extends I2PThread
("WARNING: Could not contact tracker at '"
+ announce + "': " + ioe, Snark.WARNING);
coordinator.trackerProblems = ioe.getMessage();
if (coordinator.trackerProblems.toLowerCase().startsWith(NOT_REGISTERED)) {
stop = true;
coordinator.snark.stopTorrent();
}
}
}
}
@@ -298,6 +307,7 @@ public class TrackerClient extends I2PThread
if (fetched == null) {
throw new IOException("Error fetching " + s);
}
fetched.deleteOnExit();
InputStream in = null;
try {
@@ -325,7 +335,7 @@ public class TrackerClient extends I2PThread
* Very lazy byte[] to URL encoder. Just encodes everything, even
* "normal" chars.
*/
static String urlencode(byte[] bs)
public static String urlencode(byte[] bs)
{
StringBuffer sb = new StringBuffer(bs.length*3);
for (int i = 0; i < bs.length; i++)

View File

@@ -67,14 +67,23 @@ public class I2PSnarkServlet extends HttpServlet {
out.write("<tr><td width=\"20%\" class=\"snarkTitle\" valign=\"top\" align=\"left\">");
out.write("I2PSnark<br />\n");
out.write("<table border=\"0\" width=\"100%\">\n");
out.write("<tr><td><a href=\"" + req.getRequestURI() + peerString + "\" class=\"snarkRefresh\">Refresh</a><br />\n");
out.write("<td><a href=\"http://forum.i2p/viewforum.php?f=21\" class=\"snarkRefresh\">Forum</a><br />\n");
out.write("<tr><td><a href=\"http://de-ebook-archiv.i2p/pub/bt/\" class=\"snarkRefresh\">eBook</a><br />\n");
out.write("<td><a href=\"http://gaytorrents.i2p/\" class=\"snarkRefresh\">GayTorrents</a><br />\n");
out.write("<tr><td><a href=\"http://nickyb.i2p/bittorrent/\" class=\"snarkRefresh\">NickyB</a><br />\n");
out.write("<td><a href=\"http://orion.i2p/bt/\" class=\"snarkRefresh\">Orion</a><br />\n");
out.write("<tr><td><a href=\"http://tracker.postman.i2p/\" class=\"snarkRefresh\">Postman</a><br />\n");
out.write("<td>&nbsp;\n");
out.write("<tr><td><a href=\"" + req.getRequestURI() + peerString + "\" class=\"snarkRefresh\">Refresh</a>\n");
out.write("<td><a href=\"http://forum.i2p/viewforum.php?f=21\" class=\"snarkRefresh\">Forum</a>\n");
int count = 0;
Map trackers = _manager.getTrackers();
for (Iterator iter = trackers.keySet().iterator(); iter.hasNext(); ) {
String name = (String)iter.next();
String baseURL = (String)trackers.get(name);
int e = baseURL.indexOf('=');
if (e < 0)
continue;
baseURL = baseURL.substring(e + 1);
if (count++ % 2 == 0)
out.write("<tr>");
out.write("<td><a href=\"" + baseURL + "\" class=\"snarkRefresh\">" + name + "</a>\n");
}
if (count % 2 == 1)
out.write("<td>&nbsp;\n");
out.write("</table>\n");
out.write("</td><td width=\"80%\" class=\"snarkMessages\" valign=\"top\" align=\"left\"><pre>");
List msgs = _manager.getMessages();
@@ -335,7 +344,7 @@ public class I2PSnarkServlet extends HttpServlet {
}
private static final int MAX_DISPLAYED_FILENAME_LENGTH = 60;
private static final int MAX_DISPLAYED_ERROR_LENGTH = 30;
private static final int MAX_DISPLAYED_ERROR_LENGTH = 40;
private void displaySnark(PrintWriter out, Snark snark, String uri, int row, long stats[], boolean showPeers) throws IOException {
String filename = snark.torrent;
File f = new File(filename);
@@ -388,15 +397,15 @@ public class I2PSnarkServlet extends HttpServlet {
String statusString = "Unknown";
if (err != null) {
if (isRunning && curPeers > 0 && !showPeers)
statusString = "TrackerErr (" +
statusString = "<a title=\"" + err + "\">TrackerErr</a> (" +
curPeers + "/" + knownPeers +
" <a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">peers</a>)";
else if (isRunning)
statusString = "TrackerErr (" + curPeers + "/" + knownPeers + " peers)";
statusString = "<a title=\"" + err + "\">TrackerErr (" + curPeers + "/" + knownPeers + " peers)";
else {
if (err.length() > MAX_DISPLAYED_ERROR_LENGTH)
err = err.substring(0, MAX_DISPLAYED_ERROR_LENGTH) + "...";
statusString = "TrackerErr (" + err + ")";
statusString = "TrackerErr<br />(" + err + ")";
}
} else if (remaining <= 0) {
if (isRunning && curPeers > 0 && !showPeers)
@@ -438,6 +447,25 @@ public class I2PSnarkServlet extends HttpServlet {
out.write(filename);
if (remaining == 0)
out.write("</a>");
// temporarily hardcoded for postman and anonymity, requires bytemonsoon patch for lookup by info_hash
String announce = snark.meta.getAnnounce();
if (announce.startsWith("http://YRgrgTLG") || announce.startsWith("http://8EoJZIKr")) {
Map trackers = _manager.getTrackers();
for (Iterator iter = trackers.keySet().iterator(); iter.hasNext(); ) {
String name = (String)iter.next();
String baseURL = (String)trackers.get(name);
if (!baseURL.startsWith(announce))
continue;
int e = baseURL.indexOf('=');
if (e < 0)
continue;
baseURL = baseURL.substring(e + 1);
out.write("&nbsp;&nbsp;&nbsp;(<a href=\"" + baseURL + "details.php?dllist=1&filelist=1&info_hash=");
out.write(TrackerClient.urlencode(snark.meta.getInfoHash()));
out.write("\" title=\"" + name + " Tracker\">Details</a>)");
break;
}
}
out.write("</td>\n\t");
out.write("<td valign=\"top\" align=\"right\" class=\"snarkTorrentETA " + rowClass + "\">");
@@ -500,7 +528,7 @@ public class I2PSnarkServlet extends HttpServlet {
client = "Azureus";
else
client = "Unknown";
out.write("<font size=-1>" + client + "</font> <tt>" + peer.toString().substring(5, 9) + "</tt>");
out.write("<font size=-1>" + client + "</font>&nbsp;&nbsp;<tt>" + peer.toString().substring(5, 9) + "</tt>");
out.write("</td>\n\t");
out.write("<td class=\"snarkTorrentStatus " + rowClass + "\">");
out.write("</td>\n\t");
@@ -519,20 +547,32 @@ public class I2PSnarkServlet extends HttpServlet {
out.write("</td>\n\t");
out.write("<td valign=\"top\" align=\"right\" class=\"snarkTorrentStatus " + rowClass + "\">");
if (remaining > 0) {
if (peer.isInteresting() && !peer.isChoked())
if (peer.isInteresting() && !peer.isChoked()) {
out.write("<font color=#008000>");
else
out.write("<font color=#a00000>");
out.write("<font size=-1>" + formatSize(peer.getDownloadRate()) + "ps</font></font>");
out.write("<font size=-1>" + formatSize(peer.getDownloadRate()) + "ps</font></font>");
} else {
out.write("<font color=#a00000><font size=-1><a title=\"");
if (!peer.isInteresting())
out.write("Uninteresting\">");
else
out.write("Choked\">");
out.write(formatSize(peer.getDownloadRate()) + "ps</a></font></font>");
}
}
out.write("</td>\n\t");
out.write("<td valign=\"top\" align=\"right\" class=\"snarkTorrentStatus " + rowClass + "\">");
if (pct != 100.0) {
if (peer.isInterested() && !peer.isChoking())
if (peer.isInterested() && !peer.isChoking()) {
out.write("<font color=#008000>");
else
out.write("<font color=#a00000>");
out.write("<font size=-1>" + formatSize(peer.getUploadRate()) + "ps</font></font>");
out.write("<font size=-1>" + formatSize(peer.getUploadRate()) + "ps</font></font>");
} else {
out.write("<font color=#a00000><font size=-1><a title=\"");
if (!peer.isInterested())
out.write("Uninterested\">");
else
out.write("Choking\">");
out.write(formatSize(peer.getUploadRate()) + "ps</a></font></font>");
}
}
out.write("</td>\n\t");
out.write("<td class=\"snarkTorrentStatus " + rowClass + "\">");
@@ -578,12 +618,14 @@ public class I2PSnarkServlet extends HttpServlet {
+ "<input type=\"text\" name=\"baseFile\" size=\"20\" value=\"" + baseFile
+ "\" title=\"File to seed (must be within the specified path)\" /><br />\n");
out.write("Tracker: <select name=\"announceURL\"><option value=\"\">Select a tracker</option>\n");
Map trackers = sort(_manager.getTrackers());
Map trackers = _manager.getTrackers();
for (Iterator iter = trackers.keySet().iterator(); iter.hasNext(); ) {
String name = (String)iter.next();
String announceURL = (String)trackers.get(name);
// we inject whitespace in sort(...) to guarantee uniqueness, but we can strip it off here
out.write("\t<option value=\"" + announceURL + "\">" + name.trim() + "</option>\n");
int e = announceURL.indexOf('=');
if (e > 0)
announceURL = announceURL.substring(0, e);
out.write("\t<option value=\"" + announceURL + "\">" + name + "</option>\n");
}
out.write("</select>\n");
out.write("or <input type=\"text\" name=\"announceURLOther\" size=\"50\" value=\"http://\" " +
@@ -592,18 +634,6 @@ public class I2PSnarkServlet extends HttpServlet {
out.write("</form>\n</span>\n");
}
private Map sort(Map trackers) {
TreeMap rv = new TreeMap();
for (Iterator iter = trackers.keySet().iterator(); iter.hasNext(); ) {
String url = (String)iter.next();
String name = (String)trackers.get(url);
while (rv.containsKey(name))
name = name + " ";
rv.put(name, url);
}
return rv;
}
private void writeConfigForm(PrintWriter out, HttpServletRequest req) throws IOException {
String uri = req.getRequestURI();
String dataDir = _manager.getDataDir().getAbsolutePath();

View File

@@ -597,6 +597,9 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
}
}
private static String jumpServers[] = {"http://orion.i2p/jump/",
"http://trevorreznik.i2p/cgi-bin/jump.php?hostname="
};
private static void writeErrorMessage(byte[] errMessage, OutputStream out, String targetRequest,
boolean usingWWWProxy, String wwwProxy, boolean showAddrHelper) throws IOException {
if (out != null) {
@@ -615,11 +618,16 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
out.write("</a>".getBytes());
if (usingWWWProxy) out.write(("<br>WWW proxy: " + wwwProxy).getBytes());
if (showAddrHelper) {
out.write("<br><br>Click below to try an address helper link:<br><br><a href=\"http://orion.i2p/jump/".getBytes());
out.write(uri.getBytes());
out.write("\">http://orion.i2p/jump/".getBytes());
out.write(uri.getBytes());
out.write("</a>".getBytes());
out.write("<br><br>Click a link below to look for an address helper by using a \"jump\" service:<br>".getBytes());
for (int i = 0; i < jumpServers.length; i++) {
out.write("<br><a href=\"".getBytes());
out.write(jumpServers[i].getBytes());
out.write(uri.getBytes());
out.write("\">".getBytes());
out.write(jumpServers[i].getBytes());
out.write(uri.getBytes());
out.write("</a>".getBytes());
}
}
}
out.write("</div><p><i>I2P HTTP Proxy Server<br>Generated on: ".getBytes());

View File

@@ -41,6 +41,8 @@ public class ConfigNetHandler extends FormHandler {
private String _ntcpPort;
private String _tcpPort;
private String _udpPort;
private boolean _ntcpAutoIP;
private boolean _ntcpAutoPort;
private String _inboundRate;
private String _inboundBurstRate;
private String _inboundBurst;
@@ -70,6 +72,8 @@ public class ConfigNetHandler extends FormHandler {
public void setDynamicKeys(String moo) { _dynamicKeys = true; }
public void setUpdateratesonly(String moo) { _ratesOnly = true; }
public void setEnableloadtesting(String moo) { _enableLoadTesting = true; }
public void setNtcpAutoIP(String moo) { _ntcpAutoIP = true; }
public void setNtcpAutoPort(String moo) { _ntcpAutoPort = true; }
public void setHostname(String hostname) {
_hostname = (hostname != null ? hostname.trim() : null);
@@ -142,27 +146,49 @@ public class ConfigNetHandler extends FormHandler {
}
}
if ( (_ntcpHostname != null) && (_ntcpHostname.length() > 0) && (_ntcpPort != null) && (_ntcpPort.length() > 0) ) {
String oldHost = _context.router().getConfigSetting(ConfigNetHelper.PROP_I2NP_NTCP_HOSTNAME);
String oldPort = _context.router().getConfigSetting(ConfigNetHelper.PROP_I2NP_NTCP_PORT);
if ( (oldHost == null) || (!oldHost.equalsIgnoreCase(_ntcpHostname)) ||
(oldPort == null) || (!oldPort.equalsIgnoreCase(_ntcpPort)) ) {
_context.router().setConfigSetting(ConfigNetHelper.PROP_I2NP_NTCP_HOSTNAME, _ntcpHostname);
_context.router().setConfigSetting(ConfigNetHelper.PROP_I2NP_NTCP_PORT, _ntcpPort);
addFormNotice("Updating inbound TCP settings from " + oldHost + ":" + oldPort
+ " to " + _ntcpHostname + ":" + _ntcpPort);
restartRequired = true;
}
} else {
String oldHost = _context.router().getConfigSetting(ConfigNetHelper.PROP_I2NP_NTCP_HOSTNAME);
String oldPort = _context.router().getConfigSetting(ConfigNetHelper.PROP_I2NP_NTCP_PORT);
if ( (oldHost != null) || (oldPort != null) ) {
// Normalize some things to make the following code a little easier...
String oldNHost = _context.router().getConfigSetting(ConfigNetHelper.PROP_I2NP_NTCP_HOSTNAME);
if (oldNHost == null) oldNHost = "";
String oldNPort = _context.router().getConfigSetting(ConfigNetHelper.PROP_I2NP_NTCP_PORT);
if (oldNPort == null) oldNPort = "";
String sAutoHost = _context.router().getConfigSetting(ConfigNetHelper.PROP_I2NP_NTCP_AUTO_IP);
String sAutoPort = _context.router().getConfigSetting(ConfigNetHelper.PROP_I2NP_NTCP_AUTO_PORT);
boolean oldAutoHost = "true".equalsIgnoreCase(sAutoHost);
boolean oldAutoPort = "true".equalsIgnoreCase(sAutoPort);
if (_ntcpHostname == null) _ntcpHostname = "";
if (_ntcpPort == null) _ntcpPort = "";
if (oldAutoHost != _ntcpAutoIP || ! oldNHost.equalsIgnoreCase(_ntcpHostname)) {
if (_ntcpAutoIP) {
_context.router().setConfigSetting(ConfigNetHelper.PROP_I2NP_NTCP_AUTO_IP, "true");
_context.router().removeConfigSetting(ConfigNetHelper.PROP_I2NP_NTCP_HOSTNAME);
_context.router().removeConfigSetting(ConfigNetHelper.PROP_I2NP_NTCP_PORT);
addFormNotice("Updating inbound TCP settings from " + oldHost + ":" + oldPort
+ " so that we no longer receive inbound TCP connections");
restartRequired = true;
addFormNotice("Updating inbound TCP address to auto");
} else if (_ntcpHostname.length() > 0) {
_context.router().setConfigSetting(ConfigNetHelper.PROP_I2NP_NTCP_HOSTNAME, _ntcpHostname);
_context.router().removeConfigSetting(ConfigNetHelper.PROP_I2NP_NTCP_AUTO_IP);
addFormNotice("Updating inbound TCP address to " + _ntcpHostname);
} else {
_context.router().removeConfigSetting(ConfigNetHelper.PROP_I2NP_NTCP_HOSTNAME);
_context.router().removeConfigSetting(ConfigNetHelper.PROP_I2NP_NTCP_AUTO_IP);
addFormNotice("Disabling inbound TCP");
}
restartRequired = true;
}
if (oldAutoPort != _ntcpAutoPort || ! oldNPort.equals(_ntcpPort)) {
if ( _ntcpAutoPort ) {
_context.router().setConfigSetting(ConfigNetHelper.PROP_I2NP_NTCP_AUTO_PORT, "true");
_context.router().removeConfigSetting(ConfigNetHelper.PROP_I2NP_NTCP_PORT);
addFormNotice("Updating inbound TCP port to auto");
} else if (_ntcpPort.length() > 0) {
_context.router().setConfigSetting(ConfigNetHelper.PROP_I2NP_NTCP_PORT, _ntcpPort);
_context.router().removeConfigSetting(ConfigNetHelper.PROP_I2NP_NTCP_AUTO_PORT);
addFormNotice("Updating inbound TCP port to " + _ntcpPort);
} else {
_context.router().removeConfigSetting(ConfigNetHelper.PROP_I2NP_NTCP_PORT);
_context.router().removeConfigSetting(ConfigNetHelper.PROP_I2NP_NTCP_AUTO_PORT);
addFormNotice("Disabling inbound TCP");
}
restartRequired = true;
}
if ( (_udpPort != null) && (_udpPort.length() > 0) ) {

View File

@@ -50,6 +50,8 @@ public class ConfigNetHelper {
}
public final static String PROP_I2NP_NTCP_HOSTNAME = "i2np.ntcp.hostname";
public final static String PROP_I2NP_NTCP_PORT = "i2np.ntcp.port";
public final static String PROP_I2NP_NTCP_AUTO_PORT = "i2np.ntcp.autoip";
public final static String PROP_I2NP_NTCP_AUTO_IP = "i2np.ntcp.autoport";
public String getNtcphostname() {
String hostname = _context.getProperty(PROP_I2NP_NTCP_HOSTNAME);
if (hostname == null) return "";
@@ -69,6 +71,26 @@ public class ConfigNetHelper {
return ua.toString();
}
public String getUdpIP() {
RouterAddress addr = _context.router().getRouterInfo().getTargetAddress("SSU");
if (addr == null)
return "unknown";
UDPAddress ua = new UDPAddress(addr);
if (ua.getHost() == null)
return "unknown";
return ua.getHost();
}
public String getUdpPort() {
RouterAddress addr = _context.router().getRouterInfo().getTargetAddress("SSU");
if (addr == null)
return "unknown";
UDPAddress ua = new UDPAddress(addr);
if (ua.getPort() <= 0)
return "unknown";
return "" + ua.getPort();
}
public String getEnableTimeSyncChecked() {
String disabled = _context.getProperty(Timestamper.PROP_DISABLED, "false");
if ( (disabled != null) && ("true".equalsIgnoreCase(disabled)) )
@@ -93,6 +115,22 @@ public class ConfigNetHelper {
return "";
}
public String getTcpAutoPortChecked() {
String enabled = _context.getProperty(PROP_I2NP_NTCP_AUTO_PORT, "false");
if ( (enabled != null) && ("true".equalsIgnoreCase(enabled)) )
return " checked ";
else
return "";
}
public String getTcpAutoIPChecked() {
String enabled = _context.getProperty(PROP_I2NP_NTCP_AUTO_IP, "false");
if ( (enabled != null) && ("true".equalsIgnoreCase(enabled)) )
return " checked ";
else
return "";
}
public String getRequireIntroductionsChecked() {
short status = _context.commSystem().getReachabilityStatus();
switch (status) {
@@ -236,4 +274,23 @@ public class ConfigNetHelper {
buf.append("</select>\n");
return buf.toString();
}
public int getShareBandwidth() {
String irate = _context.getProperty(PROP_INBOUND_KBPS);
String orate = _context.getProperty(PROP_OUTBOUND_KBPS);
String pctStr = _context.getProperty(PROP_SHARE_PERCENTAGE);
if ( (irate != null) && (orate != null) && (pctStr != null)) {
try {
int irateKBps = Integer.parseInt(irate);
int orateKBps = Integer.parseInt(orate);
if (irateKBps < 0 || orateKBps < 0)
return 0;
int pct = Integer.parseInt(pctStr);
return (int) (((float) pct) * Math.min(irateKBps, orateKBps) / 100);
} catch (NumberFormatException nfe) {
// ignore
}
}
return 0;
}
}

View File

@@ -17,6 +17,7 @@ import net.i2p.stat.StatManager;
public class ConfigStatsHandler extends FormHandler {
private String _filename;
private List _stats;
private String _graphs;
private boolean _explicitFilter;
private String _explicitFilterValue;
@@ -48,6 +49,25 @@ public class ConfigStatsHandler extends FormHandler {
_log.debug("Updated stats: " + _stats);
}
public void setGraphList(String stats[]) {
if (stats != null) {
String s = "";
for (int i = 0; i < stats.length; i++) {
String cur = stats[i].trim();
if (cur.length() > 0) {
if (s.length() > 0)
s = s + ",";
s = s + cur;
}
}
_graphs = s;
} else {
_graphs = "";
}
if (_log.shouldLog(Log.DEBUG))
_log.debug("Updated graphs: " + _graphs);
}
public void setExplicitFilter(String foo) { _explicitFilter = true; }
public void setExplicitFilterValue(String filter) { _explicitFilterValue = filter; }
@@ -88,11 +108,13 @@ public class ConfigStatsHandler extends FormHandler {
}
_context.router().setConfigSetting(StatManager.PROP_STAT_FILTER, stats.toString());
_context.router().setConfigSetting("stat.summaries", _graphs);
boolean ok = _context.router().saveConfig();
if (ok)
addFormNotice("Stat filter and location updated successfully to: " + stats.toString());
else
addFormError("Failed to update the stat filter and location");
addFormNotice("Graph list updated, may take up to 60s to be reflected here and on the <a href=\"graphs.jsp\">Graphs Page</a>");
}
}

View File

@@ -7,6 +7,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import net.i2p.stat.Rate;
import net.i2p.stat.RateStat;
import net.i2p.stat.FrequencyStat;
import net.i2p.router.RouterContext;
@@ -20,12 +21,15 @@ public class ConfigStatsHelper {
/** list of names of stats which are remaining, ordered by nested groups */
private List _stats;
private String _currentStatName;
private String _currentGraphName;
private String _currentStatDescription;
private String _currentGroup;
/** true if the current stat is the first in the group */
private boolean _currentIsFirstInGroup;
/** true if the stat is being logged */
private boolean _currentIsLogged;
private boolean _currentIsGraphed;
private boolean _currentCanBeGraphed;
/**
* Configure this bean to query a particular router context
@@ -71,6 +75,7 @@ public class ConfigStatsHelper {
public boolean hasMoreStats() {
if (_stats.size() <= 0)
return false;
_currentIsGraphed = false;
_currentStatName = (String)_stats.remove(0);
RateStat rs = _context.statManager().getRate(_currentStatName);
if (rs != null) {
@@ -82,6 +87,16 @@ public class ConfigStatsHelper {
else
_currentIsFirstInGroup = false;
_currentGroup = rs.getGroupName();
long period = rs.getPeriods()[0]; // should be the minimum
if (period <= 10*60*1000) {
Rate r = rs.getRate(period);
_currentCanBeGraphed = r != null;
if (_currentCanBeGraphed)
_currentIsGraphed = r.getSummaryListener() != null;
_currentGraphName = _currentStatName + "." + period;
} else {
_currentCanBeGraphed = false;
}
} else {
FrequencyStat fs = _context.statManager().getFrequency(_currentStatName);
if (fs != null) {
@@ -93,6 +108,7 @@ public class ConfigStatsHelper {
else
_currentIsFirstInGroup = false;
_currentGroup = fs.getGroupName();
_currentCanBeGraphed = false;
} else {
if (_log.shouldLog(Log.ERROR))
_log.error("Stat does not exist?! [" + _currentStatName + "]");
@@ -119,7 +135,10 @@ public class ConfigStatsHelper {
/** What group is the current stat in */
public String getCurrentGroupName() { return _currentGroup; }
public String getCurrentStatName() { return _currentStatName; }
public String getCurrentGraphName() { return _currentGraphName; }
public String getCurrentStatDescription() { return _currentStatDescription; }
public boolean getCurrentIsLogged() { return _currentIsLogged; }
public boolean getCurrentIsGraphed() { return _currentIsGraphed; }
public boolean getCurrentCanBeGraphed() { return _currentCanBeGraphed; }
public String getExplicitFilter() { return _filter; }
}

View File

@@ -55,20 +55,37 @@ public class GraphHelper {
public String getImages() {
try {
_out.write("<img src=\"viewstat.jsp?stat=bw.combined"
+ "&amp;periodCount=" + _periodCount
+ "&amp;width=" + _width
+ "&amp;height=" + _height
+ "\" title=\"Combined bandwidth graph\" />\n");
List listeners = StatSummarizer.instance().getListeners();
TreeSet ordered = new TreeSet(new AlphaComparator());
ordered.addAll(listeners);
// go to some trouble to see if we have the data for the combined bw graph
boolean hasTx = false;
boolean hasRx = false;
for (Iterator iter = ordered.iterator(); iter.hasNext(); ) {
SummaryListener lsnr = (SummaryListener)iter.next();
String title = lsnr.getRate().getRateStat().getName();
if (title.equals("bw.sendRate")) hasTx = true;
else if (title.equals("bw.recvRate")) hasRx = true;
}
if (hasTx && hasRx && !_showEvents)
_out.write("<img width=\""
+ (_width + 83) + "\" height=\"" + (_height + 92)
+ "\" src=\"viewstat.jsp?stat=bw.combined"
+ "&amp;periodCount=" + _periodCount
+ "&amp;width=" + _width
+ "&amp;height=" + (_height - 14)
+ "\" title=\"Combined bandwidth graph\" />\n");
for (Iterator iter = ordered.iterator(); iter.hasNext(); ) {
SummaryListener lsnr = (SummaryListener)iter.next();
Rate r = lsnr.getRate();
String title = r.getRateStat().getName() + " for " + DataHelper.formatDuration(_periodCount * r.getPeriod());
_out.write("<img src=\"viewstat.jsp?stat=" + r.getRateStat().getName()
_out.write("<img width=\""
+ (_width + 83) + "\" height=\"" + (_height + 92)
+ "\" src=\"viewstat.jsp?stat="
+ r.getRateStat().getName()
+ "&amp;showEvents=" + _showEvents
+ "&amp;period=" + r.getPeriod()
+ "&amp;periodCount=" + _periodCount
@@ -86,6 +103,7 @@ public class GraphHelper {
}
public String getForm() {
try {
_out.write("<p /><a href=\"configstats.jsp\">Select Stats to Graph</a><p />");
_out.write("<form action=\"graphs.jsp\" method=\"GET\">");
_out.write("Periods: <input size=\"3\" type=\"text\" name=\"periodCount\" value=\"" + _periodCount + "\" /><br />\n");
_out.write("Plot averages: <input type=\"radio\" name=\"showEvents\" value=\"false\" " + (_showEvents ? "" : "checked=\"true\" ") + " /> ");
@@ -119,4 +137,4 @@ class AlphaComparator implements Comparator {
String rName = r.getRate().getRateStat().getName() + "." + r.getRate().getPeriod();
return lName.compareTo(rName);
}
}
}

View File

@@ -3,7 +3,6 @@ package net.i2p.router.web;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
@@ -13,18 +12,51 @@ import java.util.Iterator;
import java.util.Set;
import net.i2p.I2PAppContext;
import net.i2p.router.RouterContext;
import net.i2p.util.Log;
import net.i2p.util.I2PThread;
import net.i2p.util.EepGet;
/**
* Handler to deal with reseed requests. This reseed from the URL
* http://dev.i2p.net/i2pdb2/ unless the java env property "i2p.reseedURL" is
* http://dev.i2p.net/i2pdb2/ unless the I2P configuration property "i2p.reseedURL" is
* set. It always writes to ./netDb/, so don't mess with that.
*
*/
public class ReseedHandler {
private static ReseedRunner _reseedRunner;
private RouterContext _context;
private Log _log;
// Reject unreasonably big files, because we download into a ByteArrayOutputStream.
private static final long MAX_RESEED_RESPONSE_SIZE = 8 * 1024 * 1024;
private static final String DEFAULT_SEED_URL = "http://dev.i2p.net/i2pdb2/";
public ReseedHandler() {
this(ContextHelper.getContext(null));
}
public ReseedHandler(RouterContext ctx) {
_context = ctx;
_log = ctx.logManager().getLog(ReseedHandler.class);
}
/**
* 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);
_log = _context.logManager().getLog(ReseedHandler.class);
} catch (Throwable t) {
t.printStackTrace();
}
}
private static ReseedRunner _reseedRunner = new ReseedRunner();
public void setReseedNonce(String nonce) {
if (nonce == null) return;
if (nonce.equals(System.getProperty("net.i2p.router.web.ReseedHandler.nonce")) ||
@@ -33,22 +65,28 @@ public class ReseedHandler {
}
}
public static void requestReseed() {
synchronized (_reseedRunner) {
public void requestReseed() {
synchronized (ReseedHandler.class) {
if (_reseedRunner == null)
_reseedRunner = new ReseedRunner();
if (_reseedRunner.isRunning()) {
return;
} else {
System.setProperty("net.i2p.router.web.ReseedHandler.reseedInProgress", "true");
System.out.println("Reseeding");
I2PThread reseed = new I2PThread(_reseedRunner, "Reseed");
reseed.start();
}
}
}
public static class ReseedRunner implements Runnable {
public class ReseedRunner implements Runnable, EepGet.StatusListener {
private boolean _isRunning;
public ReseedRunner() { _isRunning = false; }
public ReseedRunner() {
_isRunning = false;
System.setProperty("net.i2p.router.web.ReseedHandler.statusMessage","Reseeding.");
}
public boolean isRunning() { return _isRunning; }
public void run() {
_isRunning = true;
@@ -57,141 +95,148 @@ public class ReseedHandler {
System.setProperty("net.i2p.router.web.ReseedHandler.reseedInProgress", "false");
_isRunning = false;
}
}
static final String DEFAULT_SEED_URL = "http://dev.i2p.net/i2pdb2/";
/**
* Reseed has been requested, so lets go ahead and do it. Fetch all of
* the routerInfo-*.dat files from the specified URL (or the default) and
* save them into this router's netDb dir.
*
*/
private static void reseed(boolean echoStatus) {
String seedURL = I2PAppContext.getGlobalContext().getProperty("i2p.reseedURL", DEFAULT_SEED_URL);
if ( (seedURL == null) || (seedURL.trim().length() <= 0) )
seedURL = DEFAULT_SEED_URL;
try {
URL dir = new URL(seedURL);
byte contentRaw[] = readURL(dir);
if (contentRaw == null) return;
String content = new String(contentRaw);
Set urls = new HashSet();
int cur = 0;
while (true) {
int start = content.indexOf("href=\"routerInfo-", cur);
if (start < 0)
break;
int end = content.indexOf(".dat\">", start);
String name = content.substring(start+"href=\"routerInfo-".length(), end);
urls.add(name);
cur = end + 1;
}
// EepGet status listeners
public void attemptFailed(String url, long bytesTransferred, long bytesRemaining, int currentAttempt, int numRetries, Exception cause) {
// Since readURL() runs an EepGet with 0 retries,
// we can report errors with attemptFailed() instead of transferFailed().
// It has the benefit of providing cause of failure, which helps resolve issues.
if (_log.shouldLog(Log.ERROR)) _log.error("EepGet failed on " + url, cause);
}
public void bytesTransferred(long alreadyTransferred, int currentWrite, long bytesTransferred, long bytesRemaining, String url) {}
public void transferComplete(long alreadyTransferred, long bytesTransferred, long bytesRemaining, String url, String outputFile, boolean notModified) {}
public void transferFailed(String url, long bytesTransferred, long bytesRemaining, int currentAttempt) {}
public void headerReceived(String url, int attemptNum, String key, String val) {}
// End of EepGet status listeners
int fetched = 0;
int errors = 0;
for (Iterator iter = urls.iterator(); iter.hasNext(); ) {
try {
fetchSeed(seedURL, (String)iter.next());
fetched++;
if (echoStatus) {
System.out.print(".");
if (fetched % 60 == 0)
System.out.println();
}
} catch (Exception e) {
errors++;
/**
* Reseed has been requested, so lets go ahead and do it. Fetch all of
* the routerInfo-*.dat files from the specified URL (or the default) and
* save them into this router's netDb dir.
*
*/
private void reseed(boolean echoStatus) {
String seedURL = _context.getProperty("i2p.reseedURL", DEFAULT_SEED_URL);
if ( (seedURL == null) || (seedURL.trim().length() <= 0) )
seedURL = DEFAULT_SEED_URL;
try {
System.setProperty("net.i2p.router.web.ReseedHandler.errorMessage","");
System.setProperty("net.i2p.router.web.ReseedHandler.statusMessage","Reseeding: fetching seed URL.");
URL dir = new URL(seedURL);
byte contentRaw[] = readURL(dir);
if (contentRaw == null) {
System.setProperty("net.i2p.router.web.ReseedHandler.errorMessage",
"Last reseed failed fully (failed reading seed URL). " +
"Ensure that nothing blocks outbound HTTP, check <a href=logs.jsp>logs</a> " +
"and if nothing helps, read FAQ about reseeding manually.");
// Logging deprecated here since attemptFailed() provides better info
_log.debug("Failed reading seed URL: " + seedURL);
return;
}
}
if (echoStatus) System.out.println();
} catch (Throwable t) {
I2PAppContext.getGlobalContext().logManager().getLog(ReseedHandler.class).error("Error reseeding", t);
}
}
private static void fetchSeed(String seedURL, String peer) throws Exception {
URL url = new URL(seedURL + (seedURL.endsWith("/") ? "" : "/") + "routerInfo-" + peer + ".dat");
String content = new String(contentRaw);
Set urls = new HashSet();
int cur = 0;
while (true) {
int start = content.indexOf("href=\"routerInfo-", cur);
if (start < 0)
break;
byte data[] = readURL(url);
//System.out.println("read: " + (data != null ? data.length : -1));
writeSeed(peer, data);
}
private static byte[] readURL(URL url) throws Exception {
ByteArrayOutputStream baos = new ByteArrayOutputStream(4*1024);
String hostname = url.getHost();
int port = url.getPort();
if (port < 0)
port = 80;
Socket s = new Socket(hostname, port);
OutputStream out = s.getOutputStream();
InputStream in = s.getInputStream();
String request = getRequest(url);
//System.out.println("Sending to " + hostname +":"+ port + ": " + request);
out.write(request.getBytes());
out.flush();
// skip the HTTP response headers
// (if we were smart, we'd check for HTTP 200, content-length, etc)
int consecutiveNL = 0;
while (true) {
int cur = in.read();
switch (cur) {
case -1:
return null;
case '\n':
case '\r':
consecutiveNL++;
break;
default:
consecutiveNL = 0;
int end = content.indexOf(".dat\">", start);
String name = content.substring(start+"href=\"routerInfo-".length(), end);
urls.add(name);
cur = end + 1;
}
if (urls.size() <= 0) {
_log.error("Read " + contentRaw.length + " bytes from seed " + seedURL + ", but found no routerInfo URLs.");
System.setProperty("net.i2p.router.web.ReseedHandler.errorMessage",
"Last reseed failed fully (no routerInfo URLs at seed URL). " +
"Ensure that nothing blocks outbound HTTP, check <a href=logs.jsp>logs</a> " +
"and if nothing helps, read FAQ about reseeding manually.");
return;
}
int fetched = 0;
int errors = 0;
for (Iterator iter = urls.iterator(); iter.hasNext(); ) {
try {
System.setProperty("net.i2p.router.web.ReseedHandler.statusMessage",
"Reseeding: fetching router info from seed URL (" +
fetched + " successful, " + errors + " errors, " + urls.size() + " total).");
fetchSeed(seedURL, (String)iter.next());
fetched++;
if (echoStatus) {
System.out.print(".");
if (fetched % 60 == 0)
System.out.println();
}
} catch (Exception e) {
errors++;
}
}
if (echoStatus) System.out.println();
if (errors > 0) {
System.setProperty("net.i2p.router.web.ReseedHandler.errorMessage",
"Last reseed failed partly (" + errors + " of " + urls.size() + "). " +
"Ensure that nothing blocks outbound HTTP, check <a href=logs.jsp>logs</a> " +
"and if nothing helps, read FAQ about reseeding manually.");
}
} catch (Throwable t) {
System.setProperty("net.i2p.router.web.ReseedHandler.errorMessage",
"Last reseed failed fully (exception caught). " +
"Ensure that nothing blocks outbound HTTP, check <a href=logs.jsp>logs</a> " +
"and if nothing helps, read FAQ about reseeding manually.");
_log.error("Error reseeding", t);
}
if (consecutiveNL == 4)
break;
}
// ok, past the headers, grab the goods
byte buf[] = new byte[1024];
while (true) {
int read = in.read(buf);
if (read < 0)
break;
baos.write(buf, 0, read);
/* Since we don't return a value, we should always throw an exception if something fails. */
private void fetchSeed(String seedURL, String peer) throws Exception {
Log log = I2PAppContext.getGlobalContext().logManager().getLog(ReseedHandler.class);
URL url = new URL(seedURL + (seedURL.endsWith("/") ? "" : "/") + "routerInfo-" + peer + ".dat");
byte data[] = readURL(url);
if (data == null) {
// Logging deprecated here since attemptFailed() provides better info
_log.debug("Failed fetching seed: " + url.toString());
throw new Exception ("Failed fetching seed.");
}
//System.out.println("read: " + (data != null ? data.length : -1));
writeSeed(peer, data);
}
in.close();
s.close();
return baos.toByteArray();
}
private static String getRequest(URL url) {
StringBuffer buf = new StringBuffer(512);
String path = url.getPath();
if ("".equals(path))
path = "/";
buf.append("GET ").append(path).append(" HTTP/1.0\n");
buf.append("Host: ").append(url.getHost());
int port = url.getPort();
if ( (port > 0) && (port != 80) )
buf.append(":").append(port);
buf.append("\nConnection: close\n\n");
return buf.toString();
}
private static void writeSeed(String name, byte data[]) throws Exception {
String dirName = "netDb"; // _context.getProperty("router.networkDatabase.dbDir", "netDb");
File netDbDir = new File(dirName);
if (!netDbDir.exists()) {
boolean ok = netDbDir.mkdirs();
private byte[] readURL(URL url) throws Exception {
ByteArrayOutputStream baos = new ByteArrayOutputStream(4*1024);
// Do a non-proxied eepget into our ByteArrayOutputStream with 0 retries
EepGet get = new EepGet( I2PAppContext.getGlobalContext(), false, null, -1, 0, 0, MAX_RESEED_RESPONSE_SIZE,
null, baos, url.toString(), false, null, null);
get.addStatusListener(ReseedRunner.this);
if (get.fetch()) return baos.toByteArray(); else return null;
}
FileOutputStream fos = new FileOutputStream(new File(netDbDir, "routerInfo-" + name + ".dat"));
fos.write(data);
fos.close();
}
private void writeSeed(String name, byte data[]) throws Exception {
String dirName = "netDb"; // _context.getProperty("router.networkDatabase.dbDir", "netDb");
File netDbDir = new File(dirName);
if (!netDbDir.exists()) {
boolean ok = netDbDir.mkdirs();
}
FileOutputStream fos = new FileOutputStream(new File(netDbDir, "routerInfo-" + name + ".dat"));
fos.write(data);
fos.close();
}
}
public static void main(String args[]) {
if ( (args != null) && (args.length == 1) && (!Boolean.valueOf(args[0]).booleanValue()) ) {
System.out.println("Not reseeding, as requested");
return; // not reseeding on request
}
System.out.println("Reseeding");
reseed(true);
ReseedHandler reseedHandler = new ReseedHandler();
reseedHandler.requestReseed();
}
}

View File

@@ -88,7 +88,8 @@ public class RouterConsoleRunner {
// get i2p started - they can reseed later in the web console)
String names[] = (netDb.exists() ? netDb.list() : null);
if ( (names == null) || (names.length < 15) ) {
ReseedHandler.requestReseed();
ReseedHandler reseedHandler = new ReseedHandler();
reseedHandler.requestReseed();
}
}

View File

@@ -45,27 +45,27 @@ public class StatSummarizer implements Runnable {
private static final String DEFAULT_DATABASES = "bw.sendRate.60000" +
",bw.recvRate.60000" +
",tunnel.testSuccessTime.60000" +
",udp.outboundActiveCount.60000" +
",udp.receivePacketSize.60000" +
",udp.receivePacketSkew.60000" +
",udp.sendConfirmTime.60000" +
",udp.sendPacketSize.60000" +
",router.activePeers.60000" +
",router.activeSendPeers.60000" +
",tunnel.acceptLoad.60000" +
",tunnel.dropLoadProactive.60000" +
",tunnel.buildExploratorySuccess.60000" +
",tunnel.buildExploratoryReject.60000" +
",tunnel.buildExploratoryExpire.60000" +
",client.sendAckTime.60000" +
",client.dispatchNoACK.60000" +
",ntcp.sendTime.60000" +
",ntcp.transmitTime.60000" +
",ntcp.sendBacklogTime.60000" +
",ntcp.receiveTime.60000" +
",transport.sendMessageFailureLifetime.60000" +
",transport.sendProcessingTime.60000";
// ",tunnel.testSuccessTime.60000" +
// ",udp.outboundActiveCount.60000" +
// ",udp.receivePacketSize.60000" +
// ",udp.receivePacketSkew.60000" +
// ",udp.sendConfirmTime.60000" +
// ",udp.sendPacketSize.60000" +
",router.activePeers.60000";
// ",router.activeSendPeers.60000" +
// ",tunnel.acceptLoad.60000" +
// ",tunnel.dropLoadProactive.60000" +
// ",tunnel.buildExploratorySuccess.60000" +
// ",tunnel.buildExploratoryReject.60000" +
// ",tunnel.buildExploratoryExpire.60000" +
// ",client.sendAckTime.60000" +
// ",client.dispatchNoACK.60000" +
// ",ntcp.sendTime.60000" +
// ",ntcp.transmitTime.60000" +
// ",ntcp.sendBacklogTime.60000" +
// ",ntcp.receiveTime.60000" +
// ",transport.sendMessageFailureLifetime.60000" +
// ",transport.sendProcessingTime.60000";
private String adjustDatabases(String oldSpecs) {
String spec = _context.getProperty("stat.summaries", DEFAULT_DATABASES);
@@ -142,16 +142,17 @@ public class StatSummarizer implements Runnable {
}
public boolean renderRatePng(OutputStream out, int width, int height, boolean hideLegend, boolean hideGrid, boolean hideTitle, boolean showEvents, int periodCount, boolean showCredit) throws IOException {
long end = _context.clock().now();
long end = _context.clock().now() - 60*1000;
if (periodCount <= 0) periodCount = SummaryListener.PERIODS;
if (periodCount > SummaryListener.PERIODS)
periodCount = SummaryListener.PERIODS;
long period = 60*1000;
long start = end - period*periodCount;
long begin = System.currentTimeMillis();
//long begin = System.currentTimeMillis();
try {
RrdGraphDef def = new RrdGraphDef();
def.setTimePeriod(start/1000, end/1000);
def.setTimePeriod(start/1000, 0);
def.setBaseValue(1024);
String title = "Bandwidth usage";
if (!hideTitle)
def.setTitle(title);
@@ -159,15 +160,15 @@ public class StatSummarizer implements Runnable {
String recvName = SummaryListener.createName(_context, "bw.recvRate.60000");
def.datasource(sendName, sendName, sendName, "AVERAGE", "MEMORY");
def.datasource(recvName, recvName, recvName, "AVERAGE", "MEMORY");
def.area(sendName, Color.BLUE, "Outbound bytes/second");
//def.line(sendName, Color.BLUE, "Outbound bytes/second", 3);
//def.line(recvName, Color.RED, "Inbound bytes/second@r", 3);
def.area(recvName, Color.RED, "Inbound bytes/second@r");
def.area(sendName, Color.BLUE, "Outbound bytes/sec");
//def.line(sendName, Color.BLUE, "Outbound bytes/sec", 3);
def.line(recvName, Color.RED, "Inbound bytes/sec@r", 3);
//def.area(recvName, Color.RED, "Inbound bytes/sec@r");
if (!hideLegend) {
def.gprint(sendName, "AVERAGE", "outbound average: @2@sbytes/second");
def.gprint(sendName, "MAX", " max: @2@sbytes/second@r");
def.gprint(recvName, "AVERAGE", "inbound average: @2bytes/second@s");
def.gprint(recvName, "MAX", " max: @2@sbytes/second@r");
def.gprint(sendName, "AVERAGE", "out average: @2@sbytes/sec");
def.gprint(sendName, "MAX", " max: @2@sbytes/sec@r");
def.gprint(recvName, "AVERAGE", "in average: @2@sbytes/sec");
def.gprint(recvName, "MAX", " max: @2@sbytes/sec@r");
}
if (!showCredit)
def.setShowSignature(false);
@@ -188,7 +189,7 @@ public class StatSummarizer implements Runnable {
data = graph.getPNGBytes();
else
data = graph.getPNGBytes(width, height);
long timeToPlot = System.currentTimeMillis() - begin;
//long timeToPlot = System.currentTimeMillis() - begin;
out.write(data);
//File t = File.createTempFile("jrobinData", ".xml");
//_listener.getData().dumpXml(new FileOutputStream(t));
@@ -201,6 +202,9 @@ public class StatSummarizer implements Runnable {
} catch (IOException ioe) {
_log.error("Error rendering", ioe);
throw ioe;
} catch (OutOfMemoryError oom) {
_log.error("Error rendering", oom);
throw new IOException("Error plotting: " + oom.getMessage());
}
}

View File

@@ -154,7 +154,7 @@ class SummaryRenderer {
*
*/
public static synchronized void render(I2PAppContext ctx, OutputStream out, String filename) throws IOException {
long end = ctx.clock().now();
long end = ctx.clock().now() - 60*1000;
long start = end - 60*1000*SummaryListener.PERIODS;
long begin = System.currentTimeMillis();
try {
@@ -174,17 +174,26 @@ class SummaryRenderer {
}
public void render(OutputStream out) throws IOException { render(out, -1, -1, false, false, false, false, -1, true); }
public void render(OutputStream out, int width, int height, boolean hideLegend, boolean hideGrid, boolean hideTitle, boolean showEvents, int periodCount, boolean showCredit) throws IOException {
long end = _listener.now();
long end = _listener.now() - 60*1000;
if (periodCount <= 0) periodCount = SummaryListener.PERIODS;
if (periodCount > SummaryListener.PERIODS)
periodCount = SummaryListener.PERIODS;
long start = end - _listener.getRate().getPeriod()*periodCount;
long begin = System.currentTimeMillis();
//long begin = System.currentTimeMillis();
try {
RrdGraphDef def = new RrdGraphDef();
def.setTimePeriod(start/1000, end/1000);
String title = _listener.getRate().getRateStat().getName() + " averaged for "
+ DataHelper.formatDuration(_listener.getRate().getPeriod());
def.setTimePeriod(start/1000, 0);
String name = _listener.getRate().getRateStat().getName();
// heuristic to set K=1024
if ((name.startsWith("bw.") || name.indexOf("Size") >= 0 || name.indexOf("Bps") >= 0)
&& !showEvents)
def.setBaseValue(1024);
String title = name;
if (showEvents)
title = title + " events in ";
else
title = title + " averaged for ";
title = title + DataHelper.formatDuration(_listener.getRate().getPeriod());
if (!hideTitle)
def.setTitle(title);
String path = _listener.getData().getPath();
@@ -203,8 +212,9 @@ class SummaryRenderer {
def.datasource(plotName, path, plotName, "AVERAGE", "MEMORY");
def.area(plotName, Color.BLUE, descr + "@r");
if (!hideLegend) {
def.gprint(plotName, "AVERAGE", "average: @2@s");
def.gprint(plotName, "MAX", " max: @2@s@r");
def.gprint(plotName, "AVERAGE", "avg: @2@s");
def.gprint(plotName, "MAX", " max: @2@s");
def.gprint(plotName, "LAST", " now: @2@s@r");
}
if (!showCredit)
def.setShowSignature(false);
@@ -233,7 +243,7 @@ class SummaryRenderer {
data = graph.getPNGBytes();
else
data = graph.getPNGBytes(width, height);
long timeToPlot = System.currentTimeMillis() - begin;
//long timeToPlot = System.currentTimeMillis() - begin;
out.write(data);
//File t = File.createTempFile("jrobinData", ".xml");
//_listener.getData().dumpXml(new FileOutputStream(t));
@@ -245,6 +255,9 @@ class SummaryRenderer {
} catch (IOException ioe) {
_log.error("Error rendering", ioe);
throw ioe;
} catch (OutOfMemoryError oom) {
_log.error("Error rendering", oom);
throw new IOException("Error plotting: " + oom.getMessage());
}
}
}

View File

@@ -43,9 +43,21 @@
A negative rate means a default limit of 16KBytes per second.</i><br />
Bandwidth share percentage:
<jsp:getProperty name="nethelper" property="sharePercentageBox" /><br />
Sharing a higher percentage will improve your anonymity and help the network<br />
<% int share = nethelper.getShareBandwidth();
if (share < 12) {
out.print("<b>NOTE</b>: You have configured I2P to share only " + share + "KBps. ");
out.print("I2P requires at least 12KBps to enable sharing. ");
out.print("Please enable sharing (participating in tunnels) by configuring more bandwidth. ");
out.print("It improves your anonymity by creating cover traffic, and helps the network.<br />");
} else {
out.print("You have configured I2P to share " + share + "KBps. ");
out.print("The higher the share bandwidth the more you improve your anonymity and help the network.<br />");
}
%>
<p>
<input type="submit" name="save" value="Save changes" /> <input type="reset" value="Cancel" /><br />
<hr />
<!--
<b>Enable load testing: </b>
<input type="checkbox" name="enableloadtesting" value="true" <jsp:getProperty name="nethelper" property="enableLoadTesting" /> />
<p>If enabled, your router will periodically anonymously probe some of your peers
@@ -54,6 +66,7 @@
load testing is fed into the profiles as well as the
<a href="oldstats.jsp#test.rtt">test.rtt</a> and related stats.</p>
<hr />
-->
<b>External UDP address:</b> <i><jsp:getProperty name="nethelper" property="udpAddress" /></i><br />
<b>Require SSU introductions? </b>
<input type="checkbox" name="requireIntroductions" value="true" <jsp:getProperty name="nethelper" property="requireIntroductionsChecked" /> /><br />
@@ -70,14 +83,21 @@
Externally reachable hostname or IP address:
<input name ="ntcphost" type="text" size="16" value="<jsp:getProperty name="nethelper" property="ntcphostname" />" />
(dyndns and the like are fine)<br />
OR use IP address detected by SSU
(currently <jsp:getProperty name="nethelper" property="udpIP" />)?
<input type="checkbox" name="ntcpAutoIP" value="true" <jsp:getProperty name="nethelper" property="tcpAutoIPChecked" /> /><br />
<p>
Externally reachable TCP port:
<input name ="ntcpport" type="text" size="6" value="<jsp:getProperty name="nethelper" property="ntcpport" />" /><br />
OR use the same port configured for SSU
(currently <jsp:getProperty name="nethelper" property="udpPort" />)?
<input type="checkbox" name="ntcpAutoPort" value="true" <jsp:getProperty name="nethelper" property="tcpAutoPortChecked" /> /><br />
<p>You do <i>not</i> need to allow inbound TCP connections - outbound connections work with no
configuration. However, if you want to receive inbound TCP connections, you <b>must</b> poke a hole
in your NAT or firewall for unsolicited TCP connections. If you specify the wrong IP address or
hostname, or do not properly configure your NAT or firewall, your network performance will degrade
substantially. When in doubt, leave the hostname and port number blank.</p>
<p><b>Note: changing this setting will terminate all of your connections and effectively
<p><b>Note: changing any of these settings will terminate all of your connections and effectively
restart your router.</b>
<hr />
<!--

View File

@@ -78,22 +78,26 @@ function toggleAll(category)
<table>
<% while (statshelper.hasMoreStats()) {
while (statshelper.groupRequired()) { %>
<tr><td valign="top" align="left" colspan="2">
<tr><td valign="top" align="left" colspan="3">
<b><%=statshelper.getCurrentGroupName()%></b>
(<a href="javascript: void(null);" onclick="toggleAll('<%=statshelper.getCurrentGroupName()%>')">toggle all</a>)
</td></tr><%
</td></tr><tr><td>Log</td><td>Graph</td><td></td></tr><%
} // end iterating over required groups for the current stat %>
<tr><td valign="top" align="left">
<input id="<%=statshelper.getCurrentGroupName()%>" type="checkbox" name="statList" value="<%=statshelper.getCurrentStatName()%>" <%
if (statshelper.getCurrentIsLogged()) { %>checked="true" <% } %>/></td>
<td valign="top" align="left">
<% if (statshelper.getCurrentCanBeGraphed()) { %>
<input id="<%=statshelper.getCurrentGroupName()%>" type="checkbox" name="graphList" value="<%=statshelper.getCurrentGraphName()%>" <%
if (statshelper.getCurrentIsGraphed()) { %>checked="true" <% } %>/><% } %></td>
<td valign="top" align="left"><b><%=statshelper.getCurrentStatName()%>:</b><br />
<%=statshelper.getCurrentStatDescription()%></td></tr><%
} // end iterating over all stats %>
<tr><td colspan="2"><hr /></td></tr>
<tr><td colspan="3"><hr /></td></tr>
<tr><td><input type="checkbox" name="explicitFilter" /></td>
<td>Advanced filter:
<td colspan="2">Advanced filter:
<input type="text" name="explicitFilterValue" value="<%=statshelper.getExplicitFilter()%>" size="40" /></td></tr>
<tr><td colspan="2"><hr /></td></tr>
<tr><td colspan="3"><hr /></td></tr>
<tr><td><input type="submit" name="shouldsave" value="Save changes" /> </td>
<td><input type="reset" value="Cancel" /></td></tr>
</form>
@@ -101,4 +105,4 @@ function toggleAll(category)
</div>
</body>
</html>
</html>

View File

@@ -5,6 +5,7 @@
<html><head>
<title>I2P Router Console - home</title>
<link rel="stylesheet" href="default.css" type="text/css" />
<link rel="shortcut icon" href="favicon.ico" />
</head><body>
<%
if (System.getProperty("router.consoleNonce") == null) {

View File

@@ -24,7 +24,7 @@
<!-- Could not find docs/toolbar.html! -->
<a href="susimail/susimail">Susimail</a> |
<a href="susidns/index.jsp">SusiDNS</a> |
<a href="syndie/">Syndie</a> |
<!-- <a href="syndie/">Syndie</a> | -->
<a href="i2psnark/">I2PSnark</a> |
<a href="http://localhost:7658/">My Eepsite</a> <br>
<a href="i2ptunnel/index.jsp">I2PTunnel</a> |

View File

@@ -43,13 +43,16 @@
<b>Failing:</b> <jsp:getProperty name="helper" property="failingPeers" /><br />
<!-- <b>Shitlisted:</b> <jsp:getProperty name="helper" property="shitlistedPeers" /><br /> -->
<b>Known:</b> <jsp:getProperty name="helper" property="allPeers" /><br /><%
if (helper.getActivePeers() <= 0) {
if (helper.getActivePeers() <= 0) {
%><b><a href="config.jsp">check your NAT/firewall</a></b><br /><%
}
}
// If showing the reseed link is allowed
if (helper.allowReseed()) {
if ("true".equals(System.getProperty("net.i2p.router.web.ReseedHandler.reseedInProgress", "false"))) {
out.print(" <i>reseeding</i>");
// While reseed occurring, show status message instead
out.print("<i>" + System.getProperty("net.i2p.router.web.ReseedHandler.statusMessage","") + "</i><br />");
} else {
// While no reseed occurring, show reseed link
long nonce = new java.util.Random().nextLong();
String prev = System.getProperty("net.i2p.router.web.ReseedHandler.nonce");
if (prev != null) System.setProperty("net.i2p.router.web.ReseedHandler.noncePrev", prev);
@@ -59,7 +62,14 @@
uri = uri + "&reseedNonce=" + nonce;
else
uri = uri + "?reseedNonce=" + nonce;
out.print(" <a href=\"" + uri + "\">reseed</a>");
out.print(" <a href=\"" + uri + "\">reseed</a><br />");
}
}
// If a new reseed ain't running, and the last reseed had errors, show error message
if ("false".equals(System.getProperty("net.i2p.router.web.ReseedHandler.reseedInProgress", "false"))) {
String reseedErrorMessage = System.getProperty("net.i2p.router.web.ReseedHandler.errorMessage","");
if (reseedErrorMessage.length() > 0) {
out.print("<i>" + reseedErrorMessage + "</i><br />");
}
}
%><hr />

View File

@@ -29,9 +29,15 @@ public class I2PSocketFull implements I2PSocket {
if (c == null) return;
if (c.getIsConnected()) {
OutputStream out = c.getOutputStream();
if (out != null)
out.close();
c.disconnect(true);
if (out != null) {
try {
out.close();
} catch (IOException ioe) {
// ignore any write error, as we want to keep on and kill the
// con (thanks Complication!)
}
}
c.disconnect(true);
} else {
//throw new IOException("Not connected");
}

View File

@@ -30,7 +30,7 @@
<ant dir="apps/addressbook/" target="war" />
<ant dir="apps/susimail/" target="war" />
<ant dir="apps/susidns/src" target="all" />
<ant dir="apps/syndie/java/" target="jar" />
<!-- <ant dir="apps/syndie/java/" target="jar" /> -->
<ant dir="apps/i2psnark/java/" target="standalone" />
</target>
<target name="buildrouter">
@@ -103,9 +103,11 @@
<copy file="apps/addressbook/dist/addressbook.war" todir="build/" />
<copy file="apps/susimail/susimail.war" todir="build/" />
<copy file="apps/susidns/src/susidns.war" todir="build/" />
<!--
<copy file="apps/syndie/syndie.war" todir="build/" />
<copy file="apps/syndie/java/build/syndie.jar" todir="build/" />
<copy file="apps/syndie/java/build/sucker.jar" todir="build/" />
-->
<copy file="apps/i2psnark/i2psnark.war" todir="build/" />
<copy file="apps/i2psnark/java/build/i2psnark.jar" todir="build/" />
<copy file="apps/jdom/jdom.jar" todir="build/" />
@@ -195,7 +197,7 @@
<copy file="build/routerconsole.jar" todir="pkg-temp/lib/" />
<copy file="build/sam.jar" todir="pkg-temp/lib/" />
<copy file="build/systray.jar" todir="pkg-temp/lib" />
<copy file="build/sucker.jar" todir="pkg-temp/lib" />
<!-- <copy file="build/sucker.jar" todir="pkg-temp/lib" /> -->
<copy file="build/i2psnark.jar" todir="pkg-temp/lib/" />
<copy file="i2p.exe" todir="pkg-temp/" failonerror="false" />
<copy file="installer/resources/runplain.sh" todir="pkg-temp/" />
@@ -209,7 +211,7 @@
<copy file="build/addressbook.war" todir="pkg-temp/webapps/" />
<copy file="build/susimail.war" todir="pkg-temp/webapps/" />
<copy file="build/susidns.war" todir="pkg-temp/webapps/" />
<copy file="build/syndie.war" todir="pkg-temp/webapps/" />
<!-- <copy file="build/syndie.war" todir="pkg-temp/webapps/" /> -->
<copy file="build/i2psnark.war" todir="pkg-temp/webapps/" />
<copy file="apps/i2psnark/java/build/launch-i2psnark.jar" todir="pkg-temp/" />
<copy file="apps/i2psnark/jetty-i2psnark.xml" todir="pkg-temp/" />
@@ -279,11 +281,13 @@
<copy file="installer/resources/eepsite_index.html" tofile="pkg-temp/eepsite/docroot/index.html" />
<copy file="installer/resources/favicon.ico" tofile="pkg-temp/eepsite/docroot/favicon.ico" />
<copy file="installer/resources/jetty.xml" tofile="pkg-temp/eepsite/jetty.xml" />
<!--
<mkdir dir="pkg-temp/syndie" />
<mkdir dir="pkg-temp/syndie/archive" />
<mkdir dir="pkg-temp/syndie/archive/ovpBy2mpO1CQ7deYhQ1cDGAwI6pQzLbWOm1Sdd0W06c=" />
<copy file="installer/resources/blogMeta.snm" tofile="pkg-temp/syndie/archive/ovpBy2mpO1CQ7deYhQ1cDGAwI6pQzLbWOm1Sdd0W06c=/meta.snm" />
<copy file="installer/resources/blogPost.snd" tofile="pkg-temp/syndie/archive/ovpBy2mpO1CQ7deYhQ1cDGAwI6pQzLbWOm1Sdd0W06c=/1132012800001.snd" />
-->
</target>
<target name="tarball" depends="preppkg">
<tar compression="bzip2" destfile="i2p.tar.bz2">
@@ -320,7 +324,7 @@
<copy file="build/addressbook.war" todir="pkg-temp/webapps/" />
<copy file="build/susimail.war" todir="pkg-temp/webapps/" />
<copy file="build/susidns.war" todir="pkg-temp/webapps/" />
<copy file="build/syndie.war" todir="pkg-temp/webapps/" />
<!-- <copy file="build/syndie.war" todir="pkg-temp/webapps/" /> -->
<copy file="build/i2psnark.war" todir="pkg-temp/webapps/" />
<!-- <copy file="apps/i2psnark/java/build/launch-i2psnark.jar" todir="pkg-temp/" /> -->
<copy file="apps/i2psnark/jetty-i2psnark.xml" todir="pkg-temp/" />
@@ -351,11 +355,13 @@
<mkdir dir="pkg-temp/eepsite" />
<mkdir dir="pkg-temp/eepsite/webapps" />
<mkdir dir="pkg-temp/eepsite/cgi-bin" />
<!--
<mkdir dir="pkg-temp/syndie" />
<mkdir dir="pkg-temp/syndie/archive" />
<mkdir dir="pkg-temp/syndie/archive/ovpBy2mpO1CQ7deYhQ1cDGAwI6pQzLbWOm1Sdd0W06c=" />
<copy file="installer/resources/blogMeta.snm" tofile="pkg-temp/syndie/archive/ovpBy2mpO1CQ7deYhQ1cDGAwI6pQzLbWOm1Sdd0W06c=/meta.snm" />
<copy file="installer/resources/blogPost.snd" tofile="pkg-temp/syndie/archive/ovpBy2mpO1CQ7deYhQ1cDGAwI6pQzLbWOm1Sdd0W06c=/1132012800001.snd" />
-->
</target>
<target name="prepjupdate" depends="prepupdate, buildWEB">
<copy file="build/ant.jar" todir="pkg-temp/lib/" />

View File

@@ -14,8 +14,8 @@ package net.i2p;
*
*/
public class CoreVersion {
public final static String ID = "$Revision: 1.70 $ $Date: 2007-02-15 18:25:05 $";
public final static String VERSION = "0.6.1.28";
public final static String ID = "$Revision: 1.71 $ $Date: 2007-03-17 16:19:10 $";
public final static String VERSION = "0.6.1.29";
public static void main(String args[]) {
System.out.println("I2P Core version: " + VERSION);

View File

@@ -184,6 +184,7 @@ public class Rate {
private static final int SLACK = 2000;
public void coalesce() {
long now = now();
double correctedTotalValue; // for summaryListener which divides by rounded EventCount
synchronized (_lock) {
long measuredPeriod = now - _lastCoalesceDate;
if (measuredPeriod < _period - SLACK) {
@@ -198,9 +199,14 @@ public class Rate {
// how much were we off by? (so that we can sample down the measured values)
double periodFactor = measuredPeriod / (double)_period;
_lastTotalValue = _currentTotalValue / periodFactor;
_lastEventCount = (long) ( (_currentEventCount + periodFactor - 1) / periodFactor);
_lastEventCount = (long) (0.499999 + (_currentEventCount / periodFactor));
_lastTotalEventTime = (long) (_currentTotalEventTime / periodFactor);
_lastCoalesceDate = now;
if (_currentEventCount == 0)
correctedTotalValue = 0;
else
correctedTotalValue = _currentTotalValue *
(_lastEventCount / (double) _currentEventCount);
if (_lastTotalValue > _extremeTotalValue) {
_extremeTotalValue = _lastTotalValue;
@@ -213,7 +219,7 @@ public class Rate {
_currentTotalEventTime = 0;
}
if (_summaryListener != null)
_summaryListener.add(_lastTotalValue, _lastEventCount, _lastTotalEventTime, _period);
_summaryListener.add(correctedTotalValue, _lastEventCount, _lastTotalEventTime, _period);
}
public void setSummaryListener(RateSummaryListener listener) { _summaryListener = listener; }

View File

@@ -33,7 +33,10 @@ public class EepGet {
private String _proxyHost;
private int _proxyPort;
private int _numRetries;
private long _minSize; // minimum and maximum acceptable response size, -1 signifies unlimited,
private long _maxSize; // applied both against whole responses and chunks
private String _outputFile;
private OutputStream _outputStream;
private String _url;
private String _postData;
private boolean _allowCaching;
@@ -53,35 +56,48 @@ public class EepGet {
private boolean _notModified;
private String _contentType;
// Constructor 7, calls 3 with: do proxy
public EepGet(I2PAppContext ctx, String proxyHost, int proxyPort, int numRetries, String outputFile, String url) {
this(ctx, true, proxyHost, proxyPort, numRetries, outputFile, url);
}
// Constructor 6, calls 1 with: do proxy, no etag
public EepGet(I2PAppContext ctx, String proxyHost, int proxyPort, int numRetries, String outputFile, String url, boolean allowCaching) {
this(ctx, true, proxyHost, proxyPort, numRetries, outputFile, url, allowCaching, null);
}
// Constructor 5, calls 3 with: no proxy
public EepGet(I2PAppContext ctx, int numRetries, String outputFile, String url) {
this(ctx, false, null, -1, numRetries, outputFile, url);
}
// Constructor 4, calls 1 with: no proxy, no etag
public EepGet(I2PAppContext ctx, int numRetries, String outputFile, String url, boolean allowCaching) {
this(ctx, false, null, -1, numRetries, outputFile, url, allowCaching, null);
}
// Constructor 3, calls 1 with: do caching, no etag
public EepGet(I2PAppContext ctx, boolean shouldProxy, String proxyHost, int proxyPort, int numRetries, String outputFile, String url) {
this(ctx, shouldProxy, proxyHost, proxyPort, numRetries, outputFile, url, true, null);
}
// Constructor 2, calls 0 with: no output buffer, do caching, no etag
public EepGet(I2PAppContext ctx, boolean shouldProxy, String proxyHost, int proxyPort, int numRetries, String outputFile, String url, String postData) {
this(ctx, shouldProxy, proxyHost, proxyPort, numRetries, outputFile, url, true, null, postData);
this(ctx, shouldProxy, proxyHost, proxyPort, numRetries, -1, -1, outputFile, null, url, true, null, postData);
}
// Constructor 1, calls 0 with: no output buffer, no postdata
public EepGet(I2PAppContext ctx, boolean shouldProxy, String proxyHost, int proxyPort, int numRetries, String outputFile, String url, boolean allowCaching, String etag) {
this(ctx, shouldProxy, proxyHost, proxyPort, numRetries, outputFile, url, allowCaching, etag, null);
this(ctx, shouldProxy, proxyHost, proxyPort, numRetries, -1, -1, outputFile, null, url, allowCaching, etag, null);
}
public EepGet(I2PAppContext ctx, boolean shouldProxy, String proxyHost, int proxyPort, int numRetries, String outputFile, String url, boolean allowCaching, String etag, String postData) {
// Constructor 0, real constructor
public EepGet(I2PAppContext ctx, boolean shouldProxy, String proxyHost, int proxyPort, int numRetries, long minSize, long maxSize,
String outputFile, OutputStream outputStream, String url, boolean allowCaching,
String etag, String postData) {
_context = ctx;
_log = ctx.logManager().getLog(EepGet.class);
_shouldProxy = shouldProxy;
_proxyHost = proxyHost;
_proxyPort = proxyPort;
_numRetries = numRetries;
_outputFile = outputFile;
_minSize = minSize;
_maxSize = maxSize;
_outputFile = outputFile; // if outputFile is set, outputStream must be null
_outputStream = outputStream; // if both are set, outputStream overrides outputFile
_url = url;
_postData = postData;
_alreadyTransferred = 0;
@@ -352,14 +368,20 @@ public class EepGet {
return false;
}
/** return true if the URL was completely retrieved */
/** a single fetch attempt */
private void doFetch() throws IOException {
readHeaders();
if (_log.shouldLog(Log.DEBUG))
_log.debug("Headers read completely, reading " + _bytesRemaining);
boolean strictSize = (_bytesRemaining >= 0);
// If minimum or maximum size defined, ensure they aren't exceeded
if ((_minSize > -1) && (_bytesRemaining < _minSize))
throw new IOException("HTTP response size " + _bytesRemaining + " violates minimum of " + _minSize + " bytes");
if ((_maxSize > -1) && (_bytesRemaining > _maxSize))
throw new IOException("HTTP response size " + _bytesRemaining + " violates maximum of " + _maxSize + " bytes");
int remaining = (int)_bytesRemaining;
byte buf[] = new byte[1024];
while (_keepFetching && ( (remaining > 0) || !strictSize )) {
@@ -371,6 +393,11 @@ public class EepGet {
break;
_out.write(buf, 0, read);
_bytesTransferred += read;
// This seems necessary to properly resume a partial download into a stream,
// as nothing else increments _alreadyTransferred, and there's no file length to check.
// Hopefully this won't break compatibility with existing status listeners
// (cause them to behave weird, or show weird numbers).
_alreadyTransferred += read;
remaining -= read;
if (remaining==0 && _encodingChunked) {
if(_proxyIn.read()=='\r' && _proxyIn.read()=='\n') {
@@ -419,12 +446,14 @@ public class EepGet {
boolean rcOk = false;
switch (responseCode) {
case 200: // full
_out = new FileOutputStream(_outputFile, false);
if (_outputStream != null) _out = _outputStream;
else _out = new FileOutputStream(_outputFile, false);
_alreadyTransferred = 0;
rcOk = true;
break;
case 206: // partial
_out = new FileOutputStream(_outputFile, true);
if (_outputStream != null) _out = _outputStream;
else _out = new FileOutputStream(_outputFile, true);
rcOk = true;
break;
case 304: // not modified
@@ -588,9 +617,16 @@ public class EepGet {
private boolean isNL(byte b) { return (b == NL); }
private void sendRequest() throws IOException {
File outFile = new File(_outputFile);
if (outFile.exists())
_alreadyTransferred = outFile.length();
if (_outputStream != null) {
// We are reading into a stream supplied by a caller,
// for which we cannot easily determine how much we've written.
// Assume that _alreadyTransferred holds the right value
// (we should never be restarted to work on an old stream).
} else {
File outFile = new File(_outputFile);
if (outFile.exists())
_alreadyTransferred = outFile.length();
}
String req = getRequest();

View File

@@ -1,4 +1,116 @@
$Id: history.txt,v 1.561 2007-03-17 16:18:12 jrandom Exp $
$Id: history.txt,v 1.583 2007-08-13 14:42:59 zzz Exp $
* 2007-08-23 0.6.1.29 released
2007-08-12 zzz
* readme.html - Add inproxy.tino.i2p, replace search.i2p with eepsites.i2p,
tweak the eepsite and troubleshooting sections
2007-08-11 zzz
* Add stats for individual tunnel rates (nice when graphed)
* i2psnark: Fix outbound tunnel nickname
2007-08-05 Complication
* Update the sharing calculator on config.jsp
and explain the trade-off even more thoroughly.
2007-08-04 Complication
* Lower the threshold between the K and L bandwidth class,
so that K is now < 12 KB/s, instead of <= 16 KB/s.
Hopefully this lets people with 128 kbit/s (16 KB/s) upload lines
participate in routing, if they keep the default share percentage.
2007-07-16 zzz
* i2psnark: Add tooltip info for choked/uninterested
2007-07-16 zzz
* Make selection of graphed data configurable via configstats.jsp,
remove most of the default graphs to save some memory
2007-07-15 zzz
* Add current values to graph legends
* Fix up previous Rate fix to check for divide by zero
2007-07-14 Complication
* Take the post-download routerInfo size check back out of ReseedHandler,
since it wasn't helpful, and a lower limit caused false warnings.
* Give EepGet ability to enforce a min/max HTTP response size.
* Enforce a maximum response size of 8 MB when ReseedHandler
downloads into a ByteArrayOutputStream.
* Refactor ReseedHandler/ReseedRunner from static to ordinary classes,
change invocation from RouterConsoleRunner accordingly.
* Add an EepGet status listener to ReseedHandler to log causes of reseed failure,
provide status reports to indicate the progress of reseeding.
* Enable icon for default eepsite, and the index page
of the router console (more later).
2007-07-14 zzz
* Clean up graphs.jsp - set K=1024 where appropriate,
output image sizes in html, catch ooms, other minor tweaks
* Fix current event count truncation which fixes graphs with low
60-sec event counts displaying high values
(bw.* and router.* graphs for example were 1.5x too high)
Affects all "events per period" (non-lifetime) counts.
2007-07-09 zzz
* i2psnark: give a better error message for a non-i2p torrent
2007-07-07 zzz
* Add auto-detect IP/Port to NTCP. When enabled on config.jsp,
SSU will notify/restart NTCP when the external address changes.
Now you can enable inbound TCP without a static IP or dyndns service.
2007-07-04 zzz
* Display calculated share bandwidth and remove load testing
on config.jsp
2007-07-01 zzz
* Replace broken option i2np.udp.alwaysPreferred with
i2np.udp.preferred and adjust UDP bids; possible settings are
"false" (default), "true", and "always".
Default setting results in same behavior as before
(NTCP is preferred unless it isn't established and UDP is established).
Use to compare NTCP and UDP transports.
2007-06-27 jrandom
* fix for a streaming lib bug that could leave a thread waiting
indefinitely (thanks Complication!)
2007-06-16 Complication
* First pass on EepGet and ReseedHandler improvements,
please avoid use on routers which matter!
* Give EepGet ability of downloading into an OutputStream,
such as the ByteArrayOutputStream of ReseedHandler.
* Detect failure to reseed better, report it persistently
and more verbosely, provide a link to logs
and suggest manual reseed.
2007-05-06 Complication
* Fix the build.xml file, so the preppkg build target won't try copying files
which became deprecated with the old Syndie (thanks for alerting, itsu!)
2007-03-31 zzz
* Add trevorreznik jump server to the http proxy error page
* Add anonymity to the trackers supporting details links in i2psnark
2007-03-24 zzz
* Remove Syndie from build targets and navbar
2007-03-22 zzz
* i2psnark tracker handling tweaks:
- Add link to tracker details page (Postman only for now, requires bytemonsoon patch)
- Add Base URL to tracker list configuration
- Web page links built from tracker list Base URLs
- Only build and sort tracker list once
- Add anonymityWeb tracker to default list
- Add tooltip info for TrackerErrs
- Stop torrent if not registered with tracker
- Mark temp files as delete on exit
2007-03-18 zzz
* i2psnark: Cleanup some handling of saved partial pieces
* i2psnark: Put bit counting in Bitfield.java for efficiency
* i2psnark: Save torrent completion state in i2psnark.config
* 2007-03-17 0.6.1.28 released

View File

@@ -1,5 +1,5 @@
<i2p.news date="$Date: 2007-02-15 18:25:04 $">
<i2p.release version="0.6.1.28" date="2007/02/15" minVersion="0.6"
<i2p.news date="$Date: 2007-03-17 20:47:59 $">
<i2p.release version="0.6.1.29" date="2007/02/15" minVersion="0.6"
anonurl="http://i2p/NF2RLVUxVulR3IqK0sGJR0dHQcGXAzwa6rEO4WAWYXOHw-DoZhKnlbf1nzHXwMEJoex5nFTyiNMqxJMWlY54cvU~UenZdkyQQeUSBZXyuSweflUXFqKN-y8xIoK2w9Ylq1k8IcrAFDsITyOzjUKoOPfVq34rKNDo7fYyis4kT5bAHy~2N1EVMs34pi2RFabATIOBk38Qhab57Umpa6yEoE~rbyR~suDRvD7gjBvBiIKFqhFueXsR2uSrPB-yzwAGofTXuklofK3DdKspciclTVzqbDjsk5UXfu2nTrC1agkhLyqlOfjhyqC~t1IXm-Vs2o7911k7KKLGjB4lmH508YJ7G9fLAUyjuB-wwwhejoWqvg7oWvqo4oIok8LG6ECR71C3dzCvIjY2QcrhoaazA9G4zcGMm6NKND-H4XY6tUWhpB~5GefB3YczOqMbHq4wi0O9MzBFrOJEOs3X4hwboKWANf7DT5PZKJZ5KorQPsYRSq0E3wSOsFCSsdVCKUGsAAAA/i2p/i2pupdate.sud"
publicurl="http://dev.i2p.net/i2p/i2pupdate.sud"
anonannouncement="http://i2p/NF2RLVUxVulR3IqK0sGJR0dHQcGXAzwa6rEO4WAWYXOHw-DoZhKnlbf1nzHXwMEJoex5nFTyiNMqxJMWlY54cvU~UenZdkyQQeUSBZXyuSweflUXFqKN-y8xIoK2w9Ylq1k8IcrAFDsITyOzjUKoOPfVq34rKNDo7fYyis4kT5bAHy~2N1EVMs34pi2RFabATIOBk38Qhab57Umpa6yEoE~rbyR~suDRvD7gjBvBiIKFqhFueXsR2uSrPB-yzwAGofTXuklofK3DdKspciclTVzqbDjsk5UXfu2nTrC1agkhLyqlOfjhyqC~t1IXm-Vs2o7911k7KKLGjB4lmH508YJ7G9fLAUyjuB-wwwhejoWqvg7oWvqo4oIok8LG6ECR71C3dzCvIjY2QcrhoaazA9G4zcGMm6NKND-H4XY6tUWhpB~5GefB3YczOqMbHq4wi0O9MzBFrOJEOs3X4hwboKWANf7DT5PZKJZ5KorQPsYRSq0E3wSOsFCSsdVCKUGsAAAA/pipermail/i2p/2005-September/000878.html"

View File

@@ -4,7 +4,7 @@
<info>
<appname>i2p</appname>
<appversion>0.6.1.28</appversion>
<appversion>0.6.1.29</appversion>
<authors>
<author name="I2P" email="support@i2p.net"/>
</authors>

View File

@@ -1,6 +1,7 @@
<html>
<head>
<title>Welcome to your eepsite</title>
<link rel="shortcut icon" href="favicon.ico" />
</head>
<body>
<h1>Welcome to your eepsite</h1>

View File

@@ -1,5 +1,5 @@
<i2p.news date="$Date: 2007-03-15 03:21:35 $">
<i2p.release version="0.6.1.28" date="2007/02/15" minVersion="0.6"
<i2p.news date="$Date: 2007-07-19 13:05:44 $">
<i2p.release version="0.6.1.29" date="2007/02/15" minVersion="0.6"
anonurl="http://i2p/NF2RLVUxVulR3IqK0sGJR0dHQcGXAzwa6rEO4WAWYXOHw-DoZhKnlbf1nzHXwMEJoex5nFTyiNMqxJMWlY54cvU~UenZdkyQQeUSBZXyuSweflUXFqKN-y8xIoK2w9Ylq1k8IcrAFDsITyOzjUKoOPfVq34rKNDo7fYyis4kT5bAHy~2N1EVMs34pi2RFabATIOBk38Qhab57Umpa6yEoE~rbyR~suDRvD7gjBvBiIKFqhFueXsR2uSrPB-yzwAGofTXuklofK3DdKspciclTVzqbDjsk5UXfu2nTrC1agkhLyqlOfjhyqC~t1IXm-Vs2o7911k7KKLGjB4lmH508YJ7G9fLAUyjuB-wwwhejoWqvg7oWvqo4oIok8LG6ECR71C3dzCvIjY2QcrhoaazA9G4zcGMm6NKND-H4XY6tUWhpB~5GefB3YczOqMbHq4wi0O9MzBFrOJEOs3X4hwboKWANf7DT5PZKJZ5KorQPsYRSq0E3wSOsFCSsdVCKUGsAAAA/i2p/i2pupdate.sud"
publicurl="http://dev.i2p.net/i2p/i2pupdate.sud"
anonannouncement="http://i2p/NF2RLVUxVulR3IqK0sGJR0dHQcGXAzwa6rEO4WAWYXOHw-DoZhKnlbf1nzHXwMEJoex5nFTyiNMqxJMWlY54cvU~UenZdkyQQeUSBZXyuSweflUXFqKN-y8xIoK2w9Ylq1k8IcrAFDsITyOzjUKoOPfVq34rKNDo7fYyis4kT5bAHy~2N1EVMs34pi2RFabATIOBk38Qhab57Umpa6yEoE~rbyR~suDRvD7gjBvBiIKFqhFueXsR2uSrPB-yzwAGofTXuklofK3DdKspciclTVzqbDjsk5UXfu2nTrC1agkhLyqlOfjhyqC~t1IXm-Vs2o7911k7KKLGjB4lmH508YJ7G9fLAUyjuB-wwwhejoWqvg7oWvqo4oIok8LG6ECR71C3dzCvIjY2QcrhoaazA9G4zcGMm6NKND-H4XY6tUWhpB~5GefB3YczOqMbHq4wi0O9MzBFrOJEOs3X4hwboKWANf7DT5PZKJZ5KorQPsYRSq0E3wSOsFCSsdVCKUGsAAAA/pipermail/i2p/2005-September/000878.html"
@@ -10,16 +10,26 @@
anonlogs="http://i2p/Nf3ab-ZFkmI-LyMt7GjgT-jfvZ3zKDl0L96pmGQXF1B82W2Bfjf0n7~288vafocjFLnQnVcmZd~-p0-Oolfo9aW2Rm-AhyqxnxyLlPBqGxsJBXjPhm1JBT4Ia8FB-VXt0BuY0fMKdAfWwN61-tj4zIcQWRxv3DFquwEf035K~Ra4SWOqiuJgTRJu7~o~DzHVljVgWIzwf8Z84cz0X33pv-mdG~~y0Bsc2qJVnYwjjR178YMcRSmNE0FVMcs6f17c6zqhMw-11qjKpY~EJfHYCx4lBWF37CD0obbWqTNUIbL~78vxqZRT3dgAgnLixog9nqTO-0Rh~NpVUZnoUi7fNR~awW5U3Cf7rU7nNEKKobLue78hjvRcWn7upHUF45QqTDuaM3yZa7OsjbcH-I909DOub2Q0Dno6vIwuA7yrysccN1sbnkwZbKlf4T6~iDdhaSLJd97QCyPOlbyUfYy9QLNExlRqKgNVJcMJRrIual~Lb1CLbnzt0uvobM57UpqSAAAA/meeting141"
publiclogs="http://www.i2p.net/meeting141" />
&#149;
2007-02-16: 0.6.1.27
<a href="http://dev.i2p/pipermail/i2p/2007-February/001335.html">released</a>
with
<a href="http://forum.i2p/viewtopic.php?t=2027">i2psnark</a>
and floodfill fixes and improvements.
2007-07-19:
We need bandwidth!
Please help the network by
<a href="/config.jsp">increasing your bandwidth limits and share percentage</a>.
Unless the share percentage times the minimum rate is more than 16KBps,
you are not sharing at all!
Increasing your rate limits will also help your own transfer rates.
Thanks!
<br />
&#149;
2007-03-13:
<a href="http://dev.i2p/pipermail/i2p/2007-March/001338.html">status notes</a>
2007-03-17: 0.6.1.28
<a href="http://dev.i2p/pipermail/i2p/2007-March/001340.html">released</a>
with
streaming lib optimizations, i2psnark
improvements, and priority operation within the router.
<br />
&#149;
2007-04-10:
<a href="http://dev.i2p/pipermail/i2p/2007-April/001343.html">status notes</a>
and
<a href="http://www.i2p/meeting202">meeting log</a>
<a href="http://www.i2p/meeting206">meeting log</a>
<br />
</i2p.news>

View File

@@ -1,5 +1,5 @@
<p>If you've just started I2P, the Active: number on the left should start to
grow over the next few minutes and you'll see some local "destinations" listed
<p>If you've just started I2P, the Active: numbers on the left should start to
grow over the next few minutes and you'll see a "shared clients" local destination listed
on the left (if not, <a href="#trouble">see below</a>). Once those show up,
you can:</p>
<ul>
@@ -12,9 +12,10 @@ you can:</p>
browse to an eepsite -
<ul>
<li><a href="http://orion.i2p/">orion.i2p</a>: a site which tracks eepsite uptime and changes</li>
<li><a href="http://inproxy.tino.i2p/status.php">inproxy.tino.i2p</a>: a site which tracks active eepsites</li>
<li><a href="http://forum.i2p/">forum.i2p</a>: a secure and anonymous connection to <a href="http://forum.i2p.net/">forum.i2p.net</a></li>
<li><a href="http://www.i2p/">www.i2p</a>: a secure and anonymous connection to <a href="http://www.i2p.net/">www.i2p.net</a></li>
<li><a href="http://search.i2p/">search.i2p</a>: an anonymously hosted search engine of eepsites</li>
<li><a href="http://eepsites.i2p/">eepsites.i2p</a>: an anonymously hosted search engine of eepsites</li>
<li><a href="http://ugha.i2p/">ugha.i2p</a>: ugha's eepsite, a wiki that anyone can edit, and lots of links</li>
<li><a href="http://dev.i2p/">dev.i2p</a>: a secure and anonymous connection to <a href="http://dev.i2p.net/">dev.i2p.net</a></li>
<li>Freenet proxy: <a href="http://fproxy.tino.i2p">fproxy.tino.i2p</a></li>
@@ -27,8 +28,7 @@ you can:</p>
through the I2P network.</li>
<li><b>transfer files</b> - there is an integrated <a href="i2psnark/">port</a> of the
<a href="http://www.klomp.org/snark/">Snark</a> <a href="http://www.bittorrent.com/">BitTorrent</a>
client, which is compatible with the Python
<a href="http://i2p-bt.postman.i2p/">mainline I2P-BT</a>.</li>
client.</li>
<li><b>use anonymous email</b> - postman has created a mail system compatible with normal mail
clients (POP3 / SMTP) that allows email within I2P as well as mail from and to the normal
internet! get your account at <a href="http://hq.postman.i2p/">hq.postman.i2p</a>.
@@ -44,18 +44,20 @@ you can:</p>
<a href="http://localhost:7658/">http://localhost:7658/</a>. Simply place your files in
the <code>eepsite/docroot/</code> directory (or place any standard JSP/Servlet <code>.war</code>
files under <code>eepsite/webapps</code>, or standard CGI script under <code>eepsite/cgi-bin</code>)
and they'll show up. After starting up an <a href="/i2ptunnel/">eepsite tunnel</a> pointing at it, your eepsite's
<i>destination</i> (which uniquely and securely identifies it) will be visible.
If you want other people to see your eepsite,
you need to give them that really huge string. Just paste it into the
<a href="http://forum.i2p/viewforum.php?f=16">Eepsite announce</a> forum, add it to
ugha's <a href="http://ugha.i2p/I2pLinks">wiki</a>, <a href="http://orion.i2p/">orion's list</a>, or paste it in the #i2p or #i2p-chat channels on
IRC (be sure to split it into two lines, as its too long for one).</p>
and they'll show up. After starting up an <a href="/i2ptunnel/">eepsite tunnel</a> pointing at it, your eepsite
will be visible to others.
Detailed instructions for starting your eepsite are on
<a href="http://localhost:7658/">your temporary eepsite page</a>.
</p>
<h2><a name="trouble">Troubleshooting</a></h2>
<p>If, after 5 or 10 minutes, your Active: x/y count has less than 20 active
peers, you may want to review the information on the
<p>Be patient - I2P may be slow to start the first time as it searches for peers.
If, after 30 minutes, your Active: connected/recent count has less than 10 connected
peers, you should open port 8887 on your firewall for better connectivity.
If you cannot see any eepsites at all (even <a href="http://www.i2p">www.i2p</a>),
be sure your browser proxy is set to localhost port 4444.
You may also want to review the information on the
<a href="http://www.i2p.net/">I2P website</a>, post up messages to the
<a href="http://forum.i2p.net/">I2P discussion forum</a>, or swing by #i2p or
#i2p-chat on IRC at <a href="irc://irc.freenode.net/#i2p">irc.freenode.net</a>, irc.postman.i2p or irc.freshcoffee.i2p (they're linked together).</p>

View File

@@ -14,6 +14,7 @@ import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import net.i2p.data.RouterAddress;
/**
* Manages the communication subsystem between peers, including connections,
@@ -52,6 +53,10 @@ public abstract class CommSystemFacade implements Service {
public short getReachabilityStatus() { return STATUS_OK; }
public void recheckReachability() {}
/**
* Tell other transports our address changed
*/
public void notifyReplaceAddress(RouterAddress UDPAddr) {}
/**
* We are able to receive unsolicited connections
*/

View File

@@ -363,7 +363,7 @@ public class Router {
// publicize our ballpark capacity - this does not affect anything at
// the moment
public static final char CAPABILITY_BW16 = 'K';
public static final char CAPABILITY_BW12 = 'K';
public static final char CAPABILITY_BW32 = 'L';
public static final char CAPABILITY_BW64 = 'M';
public static final char CAPABILITY_BW128 = 'N';
@@ -382,8 +382,8 @@ public class Router {
if (_log.shouldLog(Log.WARN))
_log.warn("Adding capabilities w/ bw limit @ " + bwLim, new Exception("caps"));
if (bwLim <= 16) {
ri.addCapability(CAPABILITY_BW16);
if (bwLim < 12) {
ri.addCapability(CAPABILITY_BW12);
} else if (bwLim <= 32) {
ri.addCapability(CAPABILITY_BW32);
} else if (bwLim <= 64) {

View File

@@ -15,8 +15,8 @@ import net.i2p.CoreVersion;
*
*/
public class RouterVersion {
public final static String ID = "$Revision: 1.497 $ $Date: 2007-03-15 13:26:06 $";
public final static String VERSION = "0.6.1.28";
public final static String ID = "$Revision: 1.518 $ $Date: 2007-08-13 14:43:01 $";
public final static String VERSION = "0.6.1.29";
public final static long BUILD = 0;
public static void main(String args[]) {
System.out.println("I2P Router version: " + VERSION + "-" + BUILD);

View File

@@ -26,6 +26,7 @@ import net.i2p.router.RouterContext;
import net.i2p.router.transport.ntcp.NTCPAddress;
import net.i2p.router.transport.ntcp.NTCPTransport;
import net.i2p.router.transport.tcp.TCPTransport;
import net.i2p.router.transport.udp.UDPAddress;
import net.i2p.util.Log;
public class CommSystemFacadeImpl extends CommSystemFacade {
@@ -194,6 +195,8 @@ public class CommSystemFacadeImpl extends CommSystemFacade {
public final static String PROP_I2NP_NTCP_HOSTNAME = "i2np.ntcp.hostname";
public final static String PROP_I2NP_NTCP_PORT = "i2np.ntcp.port";
public final static String PROP_I2NP_NTCP_AUTO_PORT = "i2np.ntcp.autoip";
public final static String PROP_I2NP_NTCP_AUTO_IP = "i2np.ntcp.autoport";
public static RouterAddress createNTCPAddress(RouterContext ctx) {
if (!TransportManager.enableNTCP(ctx)) return null;
@@ -235,4 +238,80 @@ public class CommSystemFacadeImpl extends CommSystemFacade {
//}
return addr;
}
/**
* UDP changed addresses, tell NTCP and restart
*/
public void notifyReplaceAddress(RouterAddress UDPAddr) {
if (UDPAddr == null)
return;
NTCPTransport t = (NTCPTransport) _manager.getNTCPTransport();
if (t == null)
return;
Properties UDPProps = UDPAddr.getOptions();
if (UDPProps == null)
return;
Properties newProps;
RouterAddress oldAddr = t.getCurrentAddress();
//_log.warn("Changing NTCP Address? was " + oldAddr);
RouterAddress newAddr = oldAddr;
if (newAddr == null) {
newAddr = new RouterAddress();
newAddr.setCost(10);
newAddr.setExpiration(null);
newAddr.setTransportStyle(NTCPTransport.STYLE);
newProps = new Properties();
} else {
newProps = newAddr.getOptions();
if (newProps == null)
newProps = new Properties();
}
boolean changed = false;
String oport = newProps.getProperty(NTCPAddress.PROP_PORT);
String enabled = _context.getProperty(PROP_I2NP_NTCP_AUTO_PORT, "false");
if ( (enabled != null) && ("true".equalsIgnoreCase(enabled)) ) {
String nport = UDPProps.getProperty(UDPAddress.PROP_PORT);
if (nport == null || nport.length() <= 0)
return;
if (oport == null || ! oport.equals(nport)) {
newProps.setProperty(NTCPAddress.PROP_PORT, nport);
changed = true;
}
} else if (oport == null || oport.length() <= 0) {
return;
}
String ohost = newProps.getProperty(NTCPAddress.PROP_HOST);
enabled = _context.getProperty(PROP_I2NP_NTCP_AUTO_IP, "false");
if ( (enabled != null) && ("true".equalsIgnoreCase(enabled)) ) {
String nhost = UDPProps.getProperty(UDPAddress.PROP_HOST);
if (nhost == null || nhost.length() <= 0)
return;
if (ohost == null || ! ohost.equalsIgnoreCase(nhost)) {
newProps.setProperty(NTCPAddress.PROP_HOST, nhost);
changed = true;
}
} else if (ohost == null || ohost.length() <= 0) {
return;
}
if (!changed) {
//_log.warn("No change to NTCP Address");
return;
}
// stopListening stops the pumper, readers, and writers, so required even if
// oldAddr == null since startListening starts them all again
_log.warn("Halting NTCP to change address");
t.stopListening();
newAddr.setOptions(newProps);
// Give NTCP Pumper time to stop so we don't end up with two...
// Need better way
try { Thread.sleep(5*1000); } catch (InterruptedException ie) {}
t.restartListening(newAddr);
_log.warn("Changed NTCP Address and started up, address is now " + newAddr);
return;
}
}

View File

@@ -367,7 +367,10 @@ public abstract class TransportImpl implements Transport {
* one.
*/
protected void replaceAddress(RouterAddress address) {
// _log.error("Replacing address for " + getStyle() + " was " + _currentAddress + " now " + address);
_currentAddress = address;
if ("SSU".equals(getStyle()))
_context.commSystem().notifyReplaceAddress(address);
}
/** Who to notify on message availability */

View File

@@ -124,6 +124,15 @@ public class TransportManager implements TransportEventListener {
_transports.clear();
}
public Transport getNTCPTransport() {
for (int i = 0; i < _transports.size(); i++) {
Transport t = (Transport)_transports.get(i);
if("NTCP".equals(t.getStyle()))
return t;
}
return null;
}
int getTransportCount() { return _transports.size(); }
private boolean isSupported(Set addresses, Transport t) {

View File

@@ -379,7 +379,21 @@ public class NTCPTransport extends TransportImpl {
_writer.startWriting(NUM_CONCURRENT_WRITERS);
configureLocalAddress();
return bindAddress();
}
public RouterAddress restartListening(RouterAddress addr) {
if (_log.shouldLog(Log.DEBUG)) _log.debug("Restarting ntcp transport listening");
_pumper.startPumping();
_reader.startReading(NUM_CONCURRENT_READERS);
_writer.startWriting(NUM_CONCURRENT_WRITERS);
_myAddress = new NTCPAddress(addr);
return bindAddress();
}
private RouterAddress bindAddress() {
if (_myAddress != null) {
try {
ServerSocketChannel chan = ServerSocketChannel.open();

View File

@@ -73,9 +73,13 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
/** shared fast bid for connected peers */
private TransportBid _fastBid;
/** shared slow bid for unconnected peers */
private TransportBid _slowBid;
/** shared slow bid for unconnected peers when we want to prefer UDP */
private TransportBid _slowBid;
/** shared slow bid for unconnected peers */
private TransportBid _slowestBid;
/** shared fast bid for unconnected peers when we want to prefer UDP */
private TransportBid _fastPreferredBid;
/** shared slow bid for unconnected peers when we want to always prefer UDP */
private TransportBid _slowPreferredBid;
/** list of RemoteHostId for peers whose packets we want to drop outright */
@@ -92,14 +96,17 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
/** define this to explicitly set an external port */
public static final String PROP_EXTERNAL_PORT = "i2np.udp.port";
/**
* If i2np.udp.alwaysPreferred is set, the UDP bids will always be under
* If i2np.udp.preferred is set to "always", the UDP bids will always be under
* the bid from the TCP transport - even if a TCP connection already
* exists. If this is true (the default), it will always prefer UDP, otherwise
* exists. If it is set to "true",
* it will prefer UDP unless no UDP session exists and a TCP connection
* already exists.
* If it is set to "false" (the default),
* it will prefer TCP unless no TCP session exists and a UDP connection
* already exists.
*/
public static final String PROP_ALWAYS_PREFER_UDP = "i2np.udp.alwaysPreferred";
private static final String DEFAULT_ALWAYS_PREFER_UDP = "true";
public static final String PROP_PREFER_UDP = "i2np.udp.preferred";
private static final String DEFAULT_PREFER_UDP = "false";
public static final String PROP_FIXED_PORT = "i2np.udp.fixedPort";
private static final String DEFAULT_FIXED_PORT = "true";
@@ -139,8 +146,10 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
_activeThrottle = mq;
_fastBid = new SharedBid(50);
_slowBid = new SharedBid(1000);
_slowPreferredBid = new SharedBid(75);
_slowBid = new SharedBid(65);
_fastPreferredBid = new SharedBid(15);
_slowPreferredBid = new SharedBid(20);
_slowestBid = new SharedBid(1000);
_fragments = new OutboundMessageFragments(_context, this, _activeThrottle);
_inboundFragments = new InboundMessageFragments(_context, _fragments, this);
@@ -843,7 +852,10 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
if (peer != null) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("bidding on a message to an established peer: " + peer);
return _fastBid;
if (preferUDP())
return _fastPreferredBid;
else
return _fastBid;
} else {
if (null == toAddress.getTargetAddress(STYLE))
return null;
@@ -852,14 +864,21 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
_log.debug("bidding on a message to an unestablished peer: " + to.toBase64());
if (alwaysPreferUDP())
return _slowPreferredBid;
else
else if (preferUDP())
return _slowBid;
else
return _slowestBid;
}
}
private boolean preferUDP() {
String pref = _context.getProperty(PROP_PREFER_UDP, DEFAULT_PREFER_UDP);
return (pref != null) && ! "false".equals(pref);
}
private boolean alwaysPreferUDP() {
String pref = _context.getProperty(PROP_ALWAYS_PREFER_UDP, DEFAULT_ALWAYS_PREFER_UDP);
return (pref != null) && "true".equals(pref);
String pref = _context.getProperty(PROP_PREFER_UDP, DEFAULT_PREFER_UDP);
return (pref != null) && "always".equals(pref);
}
private static final int MAX_IDLE_TIME = 5*60*1000;

View File

@@ -277,7 +277,7 @@ public abstract class TunnelPeerSelector {
private static char[] getExcludeCaps(RouterContext ctx) {
String excludeCaps = ctx.getProperty("router.excludePeerCaps",
String.valueOf(Router.CAPABILITY_BW16));
String.valueOf(Router.CAPABILITY_BW12));
Set peers = new HashSet();
if (excludeCaps != null) {
char excl[] = excludeCaps.toCharArray();

View File

@@ -34,6 +34,9 @@ public class TunnelPool {
private long _lastSelectionPeriod;
private int _expireSkew;
private long _started;
private long _lastRateUpdate;
private long _lastLifetimeProcessed;
private String _rateName;
public TunnelPool(RouterContext ctx, TunnelPoolManager mgr, TunnelPoolSettings settings, TunnelPeerSelector sel) {
_context = ctx;
@@ -48,12 +51,19 @@ public class TunnelPool {
_lifetimeProcessed = 0;
_expireSkew = _context.random().nextInt(90*1000);
_started = System.currentTimeMillis();
_lastRateUpdate = _started;
_lastLifetimeProcessed = 0;
_rateName = "tunnel.Bps." +
(_settings.isExploratory() ? "exploratory" : _settings.getDestinationNickname()) +
(_settings.isInbound() ? ".in" : ".out");
refreshSettings();
}
public void startup() {
_alive = true;
_started = System.currentTimeMillis();
_lastRateUpdate = _started;
_lastLifetimeProcessed = 0;
_manager.getExecutor().repoll();
if (_settings.isInbound() && (_settings.getDestination() != null) ) {
// we just reconnected and didn't require any new tunnel builders.
@@ -66,6 +76,9 @@ public class TunnelPool {
if (ls != null)
_context.clientManager().requestLeaseSet(_settings.getDestination(), ls);
}
_context.statManager().createRateStat(_rateName,
"Tunnel Bandwidth", "Tunnels",
new long[] { 5*60*1000l });
}
public void shutdown() {
@@ -249,6 +262,7 @@ public class TunnelPool {
_manager.getExecutor().repoll();
_lifetimeProcessed += info.getProcessedMessagesCount();
updateRate();
long lifetimeConfirmed = info.getVerifiedBytesTransferred();
long lifetime = 10*60*1000;
@@ -295,6 +309,7 @@ public class TunnelPool {
_manager.tunnelFailed();
_lifetimeProcessed += cfg.getProcessedMessagesCount();
updateRate();
if (_settings.isInbound() && (_settings.getDestination() != null) ) {
if (ls != null) {
@@ -303,6 +318,17 @@ public class TunnelPool {
}
}
void updateRate() {
long now = _context.clock().now();
long et = now - _lastRateUpdate;
if (et > 2*60*1000) {
long bw = 1024 * (_lifetimeProcessed - _lastLifetimeProcessed) * 1000 / et; // Bps
_context.statManager().addRateData(_rateName, bw, 0);
_lastRateUpdate = now;
_lastLifetimeProcessed = _lifetimeProcessed;
}
}
void refreshLeaseSet() {
if (_log.shouldLog(Log.DEBUG))
_log.debug(toString() + ": refreshing leaseSet on tunnel expiration (but prior to grace timeout)");

View File

@@ -535,14 +535,14 @@ public class TunnelPoolManager implements TunnelManagerFacade {
RouterInfo info = _context.netDb().lookupRouterInfoLocally(peer);
if (info != null) {
String caps = info.getCapabilities();
if (caps.indexOf(Router.CAPABILITY_BW16) >= 0) {
return "[&lt;16&nbsp;]";
if (caps.indexOf(Router.CAPABILITY_BW12) >= 0) {
return "[&lt;12&nbsp;]";
} else if (caps.indexOf(Router.CAPABILITY_BW32) >= 0) {
return "[&lt;32&nbsp;]";
return "[&lt;=32&nbsp;]";
} else if (caps.indexOf(Router.CAPABILITY_BW64) >= 0) {
return "[&lt;64&nbsp;]";
return "[&lt;=64&nbsp;]";
} else if (caps.indexOf(Router.CAPABILITY_BW128) >= 0) {
return "<b>[&lt;128]</b>";
return "<b>[&lt;=128]</b>";
} else if (caps.indexOf(Router.CAPABILITY_BW256) >= 0) {
return "<b>[&gt;128]</b>";
} else {