propagate from branch 'i2p.i2p.zzz.test2' (head ec8e362ce8b93280b518c599a3cc075b89085d2b)

to branch 'i2p.i2p' (head c9b1eef91f61f4482ad11c4f2b2d01be67a17ad2)
This commit is contained in:
zzz
2013-12-10 02:26:32 +00:00
54 changed files with 362 additions and 281 deletions

View File

@ -177,7 +177,7 @@ Applications:
By welterde.
See licenses/LICENSE-GPLv2.txt
Jetty 7.6.13.v20130916:
Jetty 7.6.14.v20131031:
See licenses/ABOUT-Jetty.html
See licenses/NOTICE-Jetty.html
See licenses/LICENSE-Apache2.0.txt

View File

@ -252,6 +252,8 @@ public class I2PSnarkUtil {
opts.setProperty("i2p.streaming.enforceProtocol", "true");
if (opts.getProperty("i2p.streaming.disableRejectLogging") == null)
opts.setProperty("i2p.streaming.disableRejectLogging", "true");
if (opts.getProperty("i2p.streaming.answerPings") == null)
opts.setProperty("i2p.streaming.answerPings", "false");
_manager = I2PSocketManagerFactory.createManager(_i2cpHost, _i2cpPort, opts);
_connecting = false;
}

View File

@ -112,7 +112,7 @@ public class SnarkManager implements CompleteListener {
* "name", "announceURL=websiteURL" pairs
* '=' in announceURL must be escaped as ,
*/
public static final String DEFAULT_TRACKERS[] = {
private static final String DEFAULT_TRACKERS[] = {
// "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/"
@ -129,6 +129,17 @@ public class SnarkManager implements CompleteListener {
// ,"Exotrack", "http://blbgywsjubw3d2zih2giokakhe3o2cko7jtte4risb3hohbcoyva.b32.i2p/announce.php=http://exotrack.i2p/"
};
public static final Set<String> DEFAULT_TRACKER_ANNOUNCES;
static {
Set<String> ann = new HashSet();
for (int i = 1; i < DEFAULT_TRACKERS.length; i += 2) {
String urls[] = DEFAULT_TRACKERS[i].split("=", 2);
ann.add(urls[0]);
}
DEFAULT_TRACKER_ANNOUNCES = Collections.unmodifiableSet(ann);
}
/** comma delimited list of name=announceURL=baseURL for the trackers to be displayed */
public static final String PROP_TRACKERS = "i2psnark.trackers";

View File

@ -1998,12 +1998,8 @@ public class I2PSnarkServlet extends BasicServlet {
if (privateTrackers.contains(t.announceURL)) {
buf.append(" checked=\"checked\"");
} else {
for (int i = 1; i < SnarkManager.DEFAULT_TRACKERS.length; i += 2) {
if (SnarkManager.DEFAULT_TRACKERS[i].contains(t.announceURL)) {
buf.append(" disabled=\"disabled\"");
break;
}
}
if (SnarkManager.DEFAULT_TRACKER_ANNOUNCES.contains(t.announceURL))
buf.append(" disabled=\"disabled\"");
}
buf.append(">" +
"</td><td>").append(urlify(announceURL, 35))

View File

@ -194,6 +194,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
Boolean.parseBoolean(tunnel.getClientOptions().getProperty(I2PTunnelIRCClient.PROP_DCC));
if (!dccEnabled)
tunnel.getClientOptions().setProperty("i2cp.dontPublishLeaseSet", "true");
if (tunnel.getClientOptions().getProperty("i2p.streaming.answerPings") == null)
tunnel.getClientOptions().setProperty("i2p.streaming.answerPings", "false");
boolean openNow = !Boolean.parseBoolean(tunnel.getClientOptions().getProperty("i2cp.delayOpen"));
if (openNow) {

View File

@ -39,7 +39,7 @@ abstract class IRCFilter {
final String[] allowedCommands =
{
// "NOTICE", // can contain CTCP
//"PING",
"PING",
//"PONG",
"MODE",
"JOIN",
@ -76,8 +76,6 @@ abstract class IRCFilter {
} catch(NumberFormatException nfe){}
if ("PING".equals(command))
return "PING 127.0.0.1"; // no way to know what the ircd to i2ptunnel server con is, so localhost works
if ("PONG".equals(command)) {
// Turn the received ":irc.freshcoffee.i2p PONG irc.freshcoffee.i2p :127.0.0.1"
// into ":127.0.0.1 PONG 127.0.0.1 " so that the caller can append the client's extra parameter
@ -175,7 +173,7 @@ abstract class IRCFilter {
// "PART", // replace with filtered PART to hide client part messages
"PASS",
// "PING",
// "PONG", // replaced with a filtered PING/PONG since some clients send the server IP (thanks aardvax!)
"PONG",
// "QUIT", // replace with a filtered QUIT to hide client quit messages
"RULES",
"SETNAME",
@ -291,8 +289,6 @@ abstract class IRCFilter {
return rv;
}
if ("PONG".equals(command))
return "PONG 127.0.0.1"; // no way to know what the ircd to i2ptunnel server con is, so localhost works
// Allow all allowedCommands
if (_allowedOutbound.contains(command))

View File

@ -1,8 +1,3 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package net.i2p.i2ptunnel.streamr;
import java.util.concurrent.CopyOnWriteArrayList;
@ -17,6 +12,7 @@ import net.i2p.i2ptunnel.udp.*;
* @author zzz modded for I2PTunnel
*/
public class MultiSource implements Source, Sink {
public MultiSource() {
this.sinks = new CopyOnWriteArrayList<Destination>();
}
@ -45,20 +41,6 @@ public class MultiSource implements Source, Sink {
this.sinks.remove(sink);
}
private Sink sink;
private List<Destination> sinks;
private final List<Destination> sinks;
}

View File

@ -7,9 +7,11 @@ import net.i2p.i2ptunnel.udp.*;
* @author welterde/zzz
*/
public class Pinger implements Source, Runnable {
public Pinger() {
this.thread = new Thread(this);
}
public void setSink(Sink sink) {
this.sink = sink;
}
@ -53,7 +55,7 @@ public class Pinger implements Source, Runnable {
}
protected Sink sink;
protected Thread thread;
protected final Thread thread;
private final Object waitlock = new Object();
protected boolean running;
protected volatile boolean running;
}

View File

@ -1,8 +1,3 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package net.i2p.i2ptunnel.streamr;
import java.net.InetAddress;
@ -52,16 +47,7 @@ public class StreamrConsumer extends I2PTunnelUDPClientBase {
this.sink.stop();
return super.close(forced);
}
private UDPSink sink;
private Pinger pinger;
private final UDPSink sink;
private final Pinger pinger;
}

View File

@ -1,14 +1,7 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package net.i2p.i2ptunnel.streamr;
// system
import java.io.File;
// i2p
import net.i2p.i2ptunnel.I2PTunnel;
import net.i2p.i2ptunnel.Logging;
import net.i2p.i2ptunnel.udp.*;
@ -57,17 +50,8 @@ public class StreamrProducer extends I2PTunnelUDPServerBase {
this.multi.stop();
return super.close(forced);
}
private MultiSource multi;
private UDPSource server;
private Sink subscriber;
private final MultiSource multi;
private final UDPSource server;
private final Sink subscriber;
}

View File

@ -1,11 +1,5 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package net.i2p.i2ptunnel.streamr;
// system
import java.util.Set;
import net.i2p.data.Destination;
@ -51,15 +45,6 @@ public class Subscriber implements Sink {
}
}
private Set<Destination> subscriptions;
private MultiSource multi;
private final Set<Destination> subscriptions;
private final MultiSource multi;
}

View File

@ -1,11 +1,5 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package net.i2p.i2ptunnel.udp;
// i2p
import net.i2p.client.I2PSession;
import net.i2p.client.I2PSessionException;
import net.i2p.data.Destination;
@ -19,17 +13,23 @@ import net.i2p.client.datagram.I2PDatagramMaker;
* @author welterde
*/
public class I2PSink implements Sink {
public I2PSink(I2PSession sess, Destination dest) {
this(sess, dest, false);
}
public I2PSink(I2PSession sess, Destination dest, boolean raw) {
this.sess = sess;
this.dest = dest;
this.raw = raw;
// create maker
if (!raw)
if (raw) {
this.maker = null;
} else {
this.maker = new I2PDatagramMaker();
this.maker.setI2PDatagramMaker(this.sess);
}
}
/** @param src ignored */
@ -46,7 +46,8 @@ public class I2PSink implements Sink {
// send message
try {
this.sess.sendMessage(this.dest, payload, I2PSession.PROTO_DATAGRAM,
this.sess.sendMessage(this.dest, payload,
(this.raw ? I2PSession.PROTO_DATAGRAM_RAW : I2PSession.PROTO_DATAGRAM),
I2PSession.PORT_UNSPECIFIED, I2PSession.PORT_UNSPECIFIED);
} catch(I2PSessionException exc) {
// TODO: handle better
@ -54,8 +55,8 @@ public class I2PSink implements Sink {
}
}
protected boolean raw;
protected I2PSession sess;
protected Destination dest;
protected final I2PDatagramMaker maker= new I2PDatagramMaker(); // FIXME should be final and use a factory. FIXME
protected final boolean raw;
protected final I2PSession sess;
protected final Destination dest;
protected final I2PDatagramMaker maker;
}

View File

@ -1,11 +1,5 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package net.i2p.i2ptunnel.udp;
// i2p
import net.i2p.client.I2PSession;
import net.i2p.client.I2PSessionException;
import net.i2p.data.Destination;
@ -19,16 +13,22 @@ import net.i2p.client.datagram.I2PDatagramMaker;
* @author zzz modded from I2PSink by welterde
*/
public class I2PSinkAnywhere implements Sink {
public I2PSinkAnywhere(I2PSession sess) {
this(sess, false);
}
public I2PSinkAnywhere(I2PSession sess, boolean raw) {
this.sess = sess;
this.raw = raw;
// create maker
if (!raw)
if (raw) {
this.maker = null;
} else {
this.maker = new I2PDatagramMaker();
this.maker.setI2PDatagramMaker(this.sess);
}
}
/** @param to - where it's going */
@ -44,7 +44,8 @@ public class I2PSinkAnywhere implements Sink {
// send message
try {
this.sess.sendMessage(to, payload, I2PSession.PROTO_DATAGRAM,
this.sess.sendMessage(to, payload,
(this.raw ? I2PSession.PROTO_DATAGRAM_RAW : I2PSession.PROTO_DATAGRAM),
I2PSession.PORT_UNSPECIFIED, I2PSession.PORT_UNSPECIFIED);
} catch(I2PSessionException exc) {
// TODO: handle better
@ -52,8 +53,7 @@ public class I2PSinkAnywhere implements Sink {
}
}
protected boolean raw;
protected I2PSession sess;
protected Destination dest;
protected final I2PDatagramMaker maker = new I2PDatagramMaker();
protected final boolean raw;
protected final I2PSession sess;
protected final I2PDatagramMaker maker;
}

View File

@ -1,15 +1,8 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package net.i2p.i2ptunnel.udp;
// system
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
// i2p
import net.i2p.client.I2PSession;
import net.i2p.client.I2PSessionListener;
import net.i2p.client.datagram.I2PDatagramDissector;
@ -19,15 +12,17 @@ import net.i2p.client.datagram.I2PDatagramDissector;
* @author welterde
*/
public class I2PSource implements Source, Runnable {
public I2PSource(I2PSession sess) {
this(sess, true, false);
}
public I2PSource(I2PSession sess, boolean verify) {
this(sess, verify, false);
}
public I2PSource(I2PSession sess, boolean verify, boolean raw) {
this.sess = sess;
this.sink = null;
this.verify = verify;
this.raw = raw;
@ -80,11 +75,6 @@ public class I2PSource implements Source, Runnable {
}
}
protected class Listener implements I2PSessionListener {
public void messageAvailable(I2PSession sess, int id, long size) {
@ -109,15 +99,10 @@ public class I2PSource implements Source, Runnable {
}
protected I2PSession sess;
protected BlockingQueue<Integer> queue;
protected final I2PSession sess;
protected final BlockingQueue<Integer> queue;
protected Sink sink;
protected Thread thread;
protected boolean verify;
protected boolean raw;
protected final Thread thread;
protected final boolean verify;
protected final boolean raw;
}

View File

@ -1,11 +1,5 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package net.i2p.i2ptunnel.udp;
// i2p
import net.i2p.data.Destination;
/**

View File

@ -1,8 +1,3 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package net.i2p.i2ptunnel.udp;
/**

View File

@ -1,8 +1,3 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package net.i2p.i2ptunnel.udp;
/**

View File

@ -1,16 +1,9 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package net.i2p.i2ptunnel.udp;
// system
import java.net.DatagramSocket;
import java.net.DatagramPacket;
import java.net.InetAddress;
// i2p
import net.i2p.data.Destination;
/**
@ -18,6 +11,7 @@ import net.i2p.data.Destination;
* @author welterde
*/
public class UDPSink implements Sink {
public UDPSink(InetAddress host, int port) {
// create socket
try {
@ -61,17 +55,8 @@ public class UDPSink implements Sink {
this.sock.close();
}
protected DatagramSocket sock;
protected InetAddress remoteHost;
protected int remotePort;
protected final DatagramSocket sock;
protected final InetAddress remoteHost;
protected final int remotePort;
}

View File

@ -1,11 +1,5 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package net.i2p.i2ptunnel.udp;
// system
import java.net.DatagramSocket;
import java.net.DatagramPacket;
@ -15,9 +9,8 @@ import java.net.DatagramPacket;
*/
public class UDPSource implements Source, Runnable {
public static final int MAX_SIZE = 15360;
public UDPSource(int port) {
this.sink = null;
// create udp-socket
try {
this.sock = new DatagramSocket(port);
@ -31,7 +24,6 @@ public class UDPSource implements Source, Runnable {
/** use socket from UDPSink */
public UDPSource(DatagramSocket sock) {
this.sink = null;
this.sock = sock;
this.thread = new Thread(this);
}
@ -73,19 +65,7 @@ public class UDPSource implements Source, Runnable {
this.sock.close();
}
protected DatagramSocket sock;
protected final DatagramSocket sock;
protected Sink sink;
protected Thread thread;
protected final Thread thread;
}

View File

@ -51,14 +51,15 @@ import net.i2p.util.EventDispatcher;
private static final AtomicLong __clientId = new AtomicLong();
protected long _clientId;
protected Destination dest = null;
protected Destination dest;
private final Object startLock = new Object();
private I2PSession _session;
private Source _i2pSource;
private Sink _i2pSink;
private Destination _otherDest;
private final I2PSession _session;
private final Source _i2pSource;
private final Sink _i2pSink;
private final Destination _otherDest;
/**
* @throws IllegalArgumentException if the I2CP configuration is b0rked so
* badly that we cant create a socketManager
@ -105,6 +106,7 @@ import net.i2p.util.EventDispatcher;
}
_i2pSink = new I2PSink(_session, _otherDest, false);
} else {
_otherDest = null;
_i2pSink = new I2PSinkAnywhere(_session, false);
}
}

View File

@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<project basedir="." default="all" name="jetty">
<property name="jetty.ver" value="7.6.13.v20130916" />
<property name="jetty.ver" value="7.6.14.v20131031" />
<property name="jetty.base" value="jetty-distribution-${jetty.ver}" />
<property name="jetty.sha1" value="35cf80c8d2ac8f6a44643bcc23b59fe77c40f87f" />
<property name="jetty.sha1" value="f83894b5641f920ed8ac31501b473528e52a23fd" />
<property name="jetty.filename" value="${jetty.base}.zip" />
<property name="jetty.url" value="http://download.eclipse.org/jetty/${jetty.ver}/dist/${jetty.filename}" />
<property name="verified.filename" value="verified.txt" />

View File

@ -1,5 +1,7 @@
package net.i2p.router.web;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@ -49,15 +51,30 @@ public class CSSHelper extends HelperBase {
return url;
}
/** change default language for the router AND save it */
/**
* change default language for the router AND save it
* @param lang xx OR xx_XX
*/
public void setLang(String lang) {
// Protected with nonce in css.jsi
if (lang != null && lang.length() == 2 && !lang.equals(_context.getProperty(Messages.PROP_LANG))) {
_context.router().saveConfig(Messages.PROP_LANG, lang);
if (lang != null) {
Map m = new HashMap(2);
if (lang.length() == 2) {
m.put(Messages.PROP_LANG, lang.toLowerCase(Locale.US));
m.put(Messages.PROP_COUNTRY, "");
_context.router().saveConfig(m, null);
} else if (lang.length() == 5) {
m.put(Messages.PROP_LANG, lang.substring(0, 2).toLowerCase(Locale.US));
m.put(Messages.PROP_COUNTRY, lang.substring(3, 5).toUpperCase(Locale.US));
_context.router().saveConfig(m, null);
}
}
}
/** needed for conditional css loads for zh */
/**
* needed for conditional css loads for zh
* @return two-letter only, lower-case
*/
public String getLang() {
return Messages.getLanguage(_context);
}

View File

@ -65,36 +65,66 @@ public class ConfigUIHelper extends HelperBase {
}
/**
* Each language has the ISO code, the flag, and the name.
* Each language has the ISO code, the flag, the name, and the optional country name.
* Alphabetical by the ISO code please.
* See http://en.wikipedia.org/wiki/ISO_639-1 .
* Any language-specific flag added to the icon set must be
* added to the top-level build.xml for the updater.
*/
private static final String langs[] = {"ar", "cs", "da", "de", "et", "el", "en", "es", "fi",
"fr", "hu", "it", "ja", "nb", "nl", "pl", "pt", "ro", "ru",
"sv", "tr", "uk", "vi", "zh"};
private static final String flags[] = {"lang_ar", "cz", "dk", "de", "ee", "gr", "us", "es", "fi",
"fr", "hu", "it", "jp", "nl", "no", "pl", "pt", "ro", "ru",
"se", "tr", "ua", "vn", "cn"};
private static final String xlangs[] = {_x("Arabic"), _x("Czech"), _x("Danish"),
_x("German"), _x("Estonian"), _x("Greek"), _x("English"), _x("Spanish"), _x("Finnish"),
_x("French"), _x("Hungarian"), _x("Italian"), _x("Japanese"), _x("Dutch"), _x("Norwegian Bokmaal"), _x("Polish"),
_x("Portuguese"), _x("Romanian"), _x("Russian"), _x("Swedish"),
_x("Turkish"), _x("Ukrainian"), _x("Vietnamese"), _x("Chinese")};
private static final String langs[][] = {
{ "ar", "lang_ar", _x("Arabic"), null },
{ "cs", "cz", _x("Czech"), null },
{ "da", "dk", _x("Danish"), null },
{ "de", "de", _x("German"), null },
{ "et", "ee", _x("Estonian"), null },
{ "el", "gr", _x("Greek"), null },
{ "en", "us", _x("English"), null },
{ "es", "es", _x("Spanish"), null },
{ "fi", "fi", _x("Finnish"), null },
{ "fr", "fr", _x("French"), null },
{ "hu", "hu", _x("Hungarian"), null },
{ "it", "it", _x("Italian"), null },
{ "ja", "jp", _x("Japanese"), null },
{ "nb", "nl", _x("Dutch"), null },
{ "nl", "no", _x("Norwewgian Bokmaal"), null },
{ "pl", "pl", _x("Polish"), null },
{ "pt", "pt", _x("Portuguese"), null },
// { "pt_BR", "br", _x("Portuguese"), "Brazil" },
{ "ro", "ro", _x("Romainian"), null },
{ "ru", "ru", _x("Russian"), null },
{ "sv", "se", _x("Swedish"), null },
{ "tr", "tr", _x("Turkish"), null },
{ "uk", "ua", _x("Ukrainian"), null },
{ "vi", "vn", _x("Vietnamese"), null },
{ "zh", "cn", _x("Chinese"), null }
};
/** todo sort by translated string */
public String getLangSettings() {
StringBuilder buf = new StringBuilder(512);
String current = Messages.getLanguage(_context);
String country = Messages.getCountry(_context);
if (country != null && country.length() > 0)
current += '_' + country;
for (int i = 0; i < langs.length; i++) {
// we use "lang" so it is set automagically in CSSHelper
buf.append("<input type=\"radio\" class=\"optbox\" name=\"lang\" ");
if (langs[i].equals(current))
String lang = langs[i][0];
if (lang.equals(current))
buf.append("checked=\"checked\" ");
buf.append("value=\"").append(langs[i]).append("\">")
.append("<img height=\"11\" width=\"16\" alt=\"\" src=\"/flags.jsp?c=").append(flags[i]).append("\"> ")
.append(Messages.getDisplayLanguage(langs[i], xlangs[i], _context)).append("<br>\n");
buf.append("value=\"").append(lang).append("\">")
.append("<img height=\"11\" width=\"16\" alt=\"\" src=\"/flags.jsp?c=").append(langs[i][1]).append("\"> ");
String slang = lang.length() > 2 ? lang.substring(0, 2) : lang;
buf.append(Messages.getDisplayLanguage(slang, langs[i][2], _context));
String name = langs[i][3];
if (name != null) {
buf.append(" (")
.append(Messages.getString(name, _context, Messages.COUNTRY_BUNDLE_NAME))
.append(')');
}
buf.append("<br>\n");
}
return buf.toString();
}

View File

@ -9,6 +9,8 @@ import net.i2p.util.Translate;
public class Messages extends Translate {
private static final String BUNDLE_NAME = "net.i2p.router.web.messages";
static final String COUNTRY_BUNDLE_NAME = "net.i2p.router.countries.messages";
/** lang in routerconsole.lang property, else current locale */
public static String getString(String key, I2PAppContext ctx) {
return Translate.getString(key, ctx, BUNDLE_NAME);

View File

@ -350,8 +350,6 @@ public class NetDbRenderer {
out.flush();
}
private static final String COUNTRY_BUNDLE_NAME = "net.i2p.router.countries.messages";
/**
* Countries now in a separate bundle
* @param code two-letter country code
@ -359,7 +357,7 @@ public class NetDbRenderer {
*/
private String getTranslatedCountry(String code) {
String name = _context.commSystem().getCountryName(code);
return Translate.getString(name, _context, COUNTRY_BUNDLE_NAME);
return Translate.getString(name, _context, Messages.COUNTRY_BUNDLE_NAME);
}
/** sort by translated country name using rules for the current language setting */

View File

@ -252,6 +252,8 @@ public class SummaryBarRenderer {
.append(_("Addressbook"))
.append("</a>\n");
if (_context.getBooleanProperty(HelperBase.PROP_ADVANCED))
buf.append("<a href=\"/debug\">Debug</a>\n");
File javadoc = new File(_context.getBaseDir(), "docs/javadoc/index.html");
if (javadoc.exists())
buf.append("<a href=\"/javadoc/index.html\" target=\"_blank\">Javadoc</a>\n");

View File

@ -10,6 +10,9 @@ import net.i2p.data.SigningPublicKey;
*
*/
public class DummyDSAEngine extends DSAEngine {
private static final Signature FAKE_SIGNATURE = new Signature(new byte[Signature.SIGNATURE_BYTES]);
public DummyDSAEngine(I2PAppContext context) {
super(context);
}
@ -21,8 +24,6 @@ public class DummyDSAEngine extends DSAEngine {
@Override
public Signature sign(byte data[], SigningPrivateKey signingKey) {
Signature sig = new Signature();
sig.setData(Signature.FAKE_SIGNATURE);
return sig;
return FAKE_SIGNATURE;
}
}
}

View File

@ -399,6 +399,7 @@ public class DataHelper {
* - Leading whitespace is not trimmed
* - '=' is the only key-termination character (not ':' or whitespace)
*
* As of 0.9.10, an empty value is allowed.
*/
public static void loadProps(Properties props, File file) throws IOException {
loadProps(props, file, false);
@ -442,11 +443,12 @@ public class DataHelper {
// it was a horrible idea anyway
//val = val.replaceAll("\\\\r","\r");
//val = val.replaceAll("\\\\n","\n");
if ( (key.length() > 0) && (val.length() > 0) )
if (forceLowerCase)
props.setProperty(key.toLowerCase(Locale.US), val);
else
props.setProperty(key, val);
// as of 0.9.10, an empty value is allowed
if (forceLowerCase)
props.setProperty(key.toLowerCase(Locale.US), val);
else
props.setProperty(key, val);
}
} finally {
if (in != null) try { in.close(); } catch (IOException ioe) {}

View File

@ -191,13 +191,21 @@ public class PrivateKeyFile {
this.dest = d;
}
/** change cert type - caller must also call write() */
/**
* Change cert type - caller must also call write().
* Side effect - creates new Destination object.
*/
public Certificate setCertType(int t) {
if (this.dest == null)
throw new IllegalArgumentException("Dest is null");
Certificate c = new Certificate();
c.setCertificateType(t);
this.dest.setCertificate(c);
// dests now immutable, must create new
Destination newdest = new Destination();
newdest.setPublicKey(dest.getPublicKey());
newdest.setSigningPublicKey(dest.getSigningPublicKey());
newdest.setCertificate(c);
dest = newdest;
return c;
}

View File

@ -25,7 +25,11 @@ public class Signature extends SimpleDataStructure {
private static final SigType DEF_TYPE = SigType.DSA_SHA1;
/** 40 */
public final static int SIGNATURE_BYTES = DEF_TYPE.getSigLen();
/** all zeros */
/**
* all zeros
* @deprecated to be removed
*/
public final static byte[] FAKE_SIGNATURE = new byte[SIGNATURE_BYTES];
private final SigType _type;

View File

@ -25,7 +25,12 @@ import net.i2p.util.ConcurrentHashSet;
*/
public abstract class Translate {
public static final String PROP_LANG = "routerconsole.lang";
/** @since 0.9.10 */
public static final String PROP_COUNTRY = "routerconsole.country";
/** non-null, two-letter lower case, may be "" */
private static final String _localeLang = Locale.getDefault().getLanguage();
/** non-null, two-letter upper case, may be "" */
private static final String _localeCountry = Locale.getDefault().getCountry();
private static final Map<String, ResourceBundle> _bundles = new ConcurrentHashMap<String, ResourceBundle>(16);
private static final Set<String> _missing = new ConcurrentHashSet<String>(16);
/** use to look for untagged strings */
@ -42,7 +47,7 @@ public abstract class Translate {
// shouldnt happen but dont dump the po headers if it does
if (key.equals(""))
return key;
ResourceBundle bundle = findBundle(bun, lang);
ResourceBundle bundle = findBundle(bun, lang, getCountry(ctx));
if (bundle == null)
return key;
try {
@ -110,7 +115,7 @@ public abstract class Translate {
return TEST_STRING + '(' + n + ')' + TEST_STRING;
ResourceBundle bundle = null;
if (!lang.equals("en"))
bundle = findBundle(bun, lang);
bundle = findBundle(bun, lang, getCountry(ctx));
String x;
if (bundle == null)
x = n == 1 ? s : p;
@ -129,7 +134,10 @@ public abstract class Translate {
}
}
/** @return lang in routerconsole.lang property, else current locale */
/**
* Two-letter lower case
* @return lang in routerconsole.lang property, else current locale
*/
public static String getLanguage(I2PAppContext ctx) {
String lang = ctx.getProperty(PROP_LANG);
if (lang == null || lang.length() <= 0)
@ -137,14 +145,39 @@ public abstract class Translate {
return lang;
}
/** cache both found and not found for speed */
private static ResourceBundle findBundle(String bun, String lang) {
String key = bun + '-' + lang;
/**
* Two-letter upper case or ""
* @return country in routerconsole.country property, else current locale
* @since 0.9.10
*/
public static String getCountry(I2PAppContext ctx) {
// property may be empty so we don't have a non-default
// language and a default country
return ctx.getProperty(PROP_COUNTRY, _localeCountry);
}
/**
* cache both found and not found for speed
* @param lang non-null, if "" returns null
* @param country non-null, may be ""
* @return null if not found
*/
private static ResourceBundle findBundle(String bun, String lang, String country) {
String key = bun + '-' + lang + '-' + country;
ResourceBundle rv = _bundles.get(key);
if (rv == null && !_missing.contains(key)) {
if ("".equals(lang)) {
_missing.add(key);
return null;
}
try {
Locale loc;
if ("".equals(country))
loc = new Locale(lang);
else
loc = new Locale(lang, country);
// We must specify the class loader so that a webapp can find the bundle in the .war
rv = ResourceBundle.getBundle(bun, new Locale(lang), Thread.currentThread().getContextClassLoader());
rv = ResourceBundle.getBundle(bun, loc, Thread.currentThread().getContextClassLoader());
if (rv != null)
_bundles.put(key, rv);
} catch (MissingResourceException e) {

View File

@ -229,13 +229,28 @@ public class Router implements RouterClock.ClockShiftListener {
// for the ping file
// Check for other router but do not start a thread yet so the update doesn't cause
// a NCDFE
if (!isOnlyRouterRunning()) {
_eventLog.addEvent(EventLog.ABORTED, "Another router running");
System.err.println("ERROR: There appears to be another router already running!");
System.err.println(" Please make sure to shut down old instances before starting up");
System.err.println(" a new one. If you are positive that no other instance is running,");
System.err.println(" please delete the file " + getPingFile().getAbsolutePath());
System.exit(-1);
for (int i = 0; i < 14; i++) {
// Wrapper can start us up too quickly after a crash, the ping file
// may still be less than LIVELINESS_DELAY (60s) old.
// So wait at least 60s to be sure.
if (isOnlyRouterRunning()) {
if (i > 0)
System.err.println("INFO: No, there wasn't another router already running. Proceeding with startup.");
break;
}
if (i < 13) {
if (i == 0)
System.err.println("WARN: There may be another router already running. Waiting a while to be sure...");
// yes this is ugly to sleep in the constructor.
try { Thread.sleep(5000); } catch (InterruptedException ie) {}
} else {
_eventLog.addEvent(EventLog.ABORTED, "Another router running");
System.err.println("ERROR: There appears to be another router already running!");
System.err.println(" Please make sure to shut down old instances before starting up");
System.err.println(" a new one. If you are positive that no other instance is running,");
System.err.println(" please delete the file " + getPingFile().getAbsolutePath());
System.exit(-1);
}
}
if (_config.get("router.firstVersion") == null) {

View File

@ -289,14 +289,22 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi
if ( (message.getLeaseSet() == null) || (message.getPrivateKey() == null) || (message.getSigningPrivateKey() == null) ) {
if (_log.shouldLog(Log.ERROR))
_log.error("Null lease set granted: " + message);
_runner.disconnectClient("Invalid CreateLeaseSetMessage");
return;
}
_context.keyManager().registerKeys(message.getLeaseSet().getDestination(), message.getSigningPrivateKey(), message.getPrivateKey());
try {
_context.netDb().publish(message.getLeaseSet());
} catch (IllegalArgumentException iae) {
if (_log.shouldLog(Log.ERROR))
_log.error("Invalid leaseset from client", iae);
_runner.disconnectClient("Invalid leaseset: " + iae);
return;
}
if (_log.shouldLog(Log.INFO))
_log.info("New lease set granted for destination "
+ message.getLeaseSet().getDestination().calculateHash().toBase64());
_context.keyManager().registerKeys(message.getLeaseSet().getDestination(), message.getSigningPrivateKey(), message.getPrivateKey());
_context.netDb().publish(message.getLeaseSet());
// leaseSetCreated takes care of all the LeaseRequestState stuff (including firing any jobs)
_runner.leaseSetCreated(message.getLeaseSet());

View File

@ -527,14 +527,17 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
private static final long PUBLISH_DELAY = 3*1000;
public void publish(LeaseSet localLeaseSet) {
/**
* @throws IllegalArgumentException if the leaseSet is not valid
*/
public void publish(LeaseSet localLeaseSet) throws IllegalArgumentException {
if (!_initialized) return;
Hash h = localLeaseSet.getDestination().calculateHash();
try {
store(h, localLeaseSet);
} catch (IllegalArgumentException iae) {
_log.error("wtf, locally published leaseSet is not valid?", iae);
return;
throw iae;
}
if (!_context.clientManager().shouldPublishLeaseSet(h))
return;

View File

@ -25,6 +25,7 @@ import net.i2p.router.Router;
import net.i2p.router.RouterContext;
import net.i2p.router.networkdb.kademlia.FloodfillNetworkDatabaseFacade;
import net.i2p.util.ConcurrentHashSet;
import net.i2p.util.I2PThread;
import net.i2p.util.Log;
import net.i2p.util.SimpleTimer2;
@ -89,6 +90,24 @@ class PeerManager {
super(_context.simpleTimer2(), REORGANIZE_TIME);
}
public void timeReached() {
(new ReorgThread(this)).start();
}
}
/**
* This takes too long to run on the SimpleTimer2 queue
* @since 0.9.10
*/
private class ReorgThread extends I2PThread {
private SimpleTimer2.TimedEvent _event;
public ReorgThread(SimpleTimer2.TimedEvent event) {
super("PeerManager Reorg");
setDaemon(true);
_event = event;
}
public void run() {
long start = System.currentTimeMillis();
try {
_organizer.reorganize(true);
@ -104,7 +123,7 @@ class PeerManager {
delay = REORGANIZE_TIME_MEDIUM;
else
delay = REORGANIZE_TIME;
schedule(delay);
_event.schedule(delay);
}
}

View File

@ -25,6 +25,7 @@ import net.i2p.router.RouterContext;
import net.i2p.router.transport.udp.UDPTransport;
import net.i2p.router.util.EventLog;
import net.i2p.util.Addresses;
import net.i2p.util.I2PThread;
import net.i2p.util.Log;
import net.i2p.util.SimpleTimer;
import net.i2p.util.SimpleTimer2;
@ -222,6 +223,7 @@ public class CommSystemFacadeImpl extends CommSystemFacade {
/* We hope the routerinfos are read in and things have settled down by now, but it's not required to be so */
private static final int START_DELAY = 5*60*1000;
private static final int LOOKUP_TIME = 30*60*1000;
private void startGeoIP() {
_context.simpleScheduler().addEvent(new QueueAll(), START_DELAY);
}
@ -247,7 +249,26 @@ public class CommSystemFacadeImpl extends CommSystemFacade {
private class Lookup implements SimpleTimer.TimedEvent {
public void timeReached() {
(new LookupThread()).start();
}
}
/**
* This takes too long to run on the SimpleTimer2 queue
* @since 0.9.10
*/
private class LookupThread extends I2PThread {
public LookupThread() {
super("GeoIP Lookup");
setDaemon(true);
}
public void run() {
long start = System.currentTimeMillis();
_geoIP.blockingLookup();
if (_log.shouldLog(Log.INFO))
_log.info("GeoIP lookup took " + (System.currentTimeMillis() - start));
}
}

View File

@ -211,7 +211,7 @@ class EventPumper implements Runnable {
int failsafeInvalid = 0;
// Increase allowed idle time if we are well under allowed connections, otherwise decrease
if (_transport.haveCapacity(60))
if (_transport.haveCapacity(45))
_expireIdleWriteTime = Math.min(_expireIdleWriteTime + 1000, MAX_EXPIRE_IDLE_TIME);
else
_expireIdleWriteTime = Math.max(_expireIdleWriteTime - 3000, MIN_EXPIRE_IDLE_TIME);

View File

@ -11,6 +11,7 @@ import java.util.Map;
import java.util.Set;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;
import net.i2p.data.Hash;
import net.i2p.data.SessionKey;
@ -119,9 +120,9 @@ class PeerState {
*/
//private boolean _remoteWantsPreviousACKs;
/** how many bytes should we send to the peer in a second */
private volatile int _sendWindowBytes;
private int _sendWindowBytes;
/** how many bytes can we send to the peer in the current second */
private volatile int _sendWindowBytesRemaining;
private int _sendWindowBytesRemaining;
private long _lastSendRefill;
private int _sendBps;
private int _sendBytes;
@ -225,13 +226,13 @@ class PeerState {
/** Make sure a 4229 byte TunnelBuildMessage can be sent in one volley with small MTU */
private static final int MIN_CONCURRENT_MSGS = 8;
/** how many concurrent outbound messages do we allow throws OutboundMessageFragments to send */
private volatile int _concurrentMessagesAllowed = MIN_CONCURRENT_MSGS;
private int _concurrentMessagesAllowed = MIN_CONCURRENT_MSGS;
/**
* how many outbound messages are currently being transmitted. Not thread safe, as we're not strict
*/
private volatile int _concurrentMessagesActive = 0;
private int _concurrentMessagesActive;
/** how many concurrency rejections have we had in a row */
private volatile int _consecutiveRejections = 0;
private int _consecutiveRejections;
/** is it inbound? **/
private final boolean _isInbound;
/** Last time it was made an introducer **/
@ -436,9 +437,19 @@ class PeerState {
//public boolean getRemoteWantsPreviousACKs() { return _remoteWantsPreviousACKs; }
/** how many bytes should we send to the peer in a second */
public int getSendWindowBytes() { return _sendWindowBytes; }
public int getSendWindowBytes() {
synchronized(_outboundMessages) {
return _sendWindowBytes;
}
}
/** how many bytes can we send to the peer in the current second */
public int getSendWindowBytesRemaining() { return _sendWindowBytesRemaining; }
public int getSendWindowBytesRemaining() {
synchronized(_outboundMessages) {
return _sendWindowBytesRemaining;
}
}
/** what IP is the peer sending and receiving packets on? */
public byte[] getRemoteIP() { return _remoteIP; }
@ -580,20 +591,24 @@ class PeerState {
/** return the smoothed send transfer rate */
public int getSendBps() { return _sendBps; }
public int getReceiveBps() { return _receiveBps; }
public int incrementConsecutiveFailedSends() {
_concurrentMessagesActive--;
if (_concurrentMessagesActive < 0)
_concurrentMessagesActive = 0;
//long now = _context.clock().now()/(10*1000);
//if (_lastFailedSendPeriod >= now) {
// // ignore... too fast
//} else {
// _lastFailedSendPeriod = now;
_consecutiveFailedSends++;
//}
return _consecutiveFailedSends;
synchronized(_outboundMessages) {
_concurrentMessagesActive--;
if (_concurrentMessagesActive < 0)
_concurrentMessagesActive = 0;
//long now = _context.clock().now()/(10*1000);
//if (_lastFailedSendPeriod >= now) {
// // ignore... too fast
//} else {
// _lastFailedSendPeriod = now;
_consecutiveFailedSends++;
//}
return _consecutiveFailedSends;
}
}
public long getInactivityTime() {
long now = _context.clock().now();
long lastActivity = Math.max(_lastReceiveTime, _lastSendFullyTime);
@ -620,15 +635,17 @@ class PeerState {
* returning true if the full size can be decremented, false if it
* cannot. If it is not decremented, the window size remaining is
* not adjusted at all.
*
* Caller should synch
*/
public boolean allocateSendingBytes(int size, int messagePushCount) { return allocateSendingBytes(size, false, messagePushCount); }
private boolean allocateSendingBytes(int size, int messagePushCount) { return allocateSendingBytes(size, false, messagePushCount); }
public boolean allocateSendingBytes(int size, boolean isForACK) { return allocateSendingBytes(size, isForACK, -1); }
//private boolean allocateSendingBytes(int size, boolean isForACK) { return allocateSendingBytes(size, isForACK, -1); }
/**
* Caller should synch
*/
public boolean allocateSendingBytes(int size, boolean isForACK, int messagePushCount) {
private boolean allocateSendingBytes(int size, boolean isForACK, int messagePushCount) {
long now = _context.clock().now();
long duration = now - _lastSendRefill;
if (duration >= 1000) {
@ -694,9 +711,25 @@ class PeerState {
****/
public int getSlowStartThreshold() { return _slowStartThreshold; }
public int getConcurrentSends() { return _concurrentMessagesActive; }
public int getConcurrentSendWindow() { return _concurrentMessagesAllowed; }
public int getConsecutiveSendRejections() { return _consecutiveRejections; }
public int getConcurrentSends() {
synchronized(_outboundMessages) {
return _concurrentMessagesActive;
}
}
public int getConcurrentSendWindow() {
synchronized(_outboundMessages) {
return _concurrentMessagesAllowed;
}
}
public int getConsecutiveSendRejections() {
synchronized(_outboundMessages) {
return _consecutiveRejections;
}
}
public boolean isInbound() { return _isInbound; }
/** @since IPv6 */
@ -1674,6 +1707,8 @@ class PeerState {
/**
* Have 3 return values, because if allocateSendingBytes() returns false,
* then allocateSend() can stop iterating
*
* Caller should synch
*/
private ShouldSend locked_shouldSend(OutboundMessageState state) {
long now = _context.clock().now();

View File

@ -2846,7 +2846,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
public void timeReached() {
// Increase allowed idle time if we are well under allowed connections, otherwise decrease
if (haveCapacity(60)) {
if (haveCapacity(45)) {
long inc;
// don't adjust too quickly if we are looping fast
if (_lastLoopShort)