forked from I2P_Developers/i2p.i2p
propagate from branch 'i2p.i2p' (head b026fe071e77884ef6d104635c793ef16357ec71)
to branch 'i2p.i2p.str4d.eddsa' (head 0d928736c4a34d8a337e1f55e095fe90564ea1fb)
This commit is contained in:
@@ -74,7 +74,7 @@ public class Storage
|
||||
/** The default piece size. */
|
||||
private static final int DEFAULT_PIECE_SIZE = 256*1024;
|
||||
/** bigger than this will be rejected */
|
||||
public static final int MAX_PIECE_SIZE = 4*1024*1024;
|
||||
public static final int MAX_PIECE_SIZE = 8*1024*1024;
|
||||
/** The maximum number of pieces in a torrent. */
|
||||
public static final int MAX_PIECES = 10*1024;
|
||||
public static final long MAX_TOTAL_SIZE = MAX_PIECE_SIZE * (long) MAX_PIECES;
|
||||
@@ -601,7 +601,6 @@ public class Storage
|
||||
* Doesn't really reopen the file descriptors for a restart.
|
||||
* Just does an existence check but no length check or data reverification
|
||||
*
|
||||
* @param rootDir ignored
|
||||
* @throws IOE on fail
|
||||
*/
|
||||
public void reopen() throws IOException
|
||||
|
||||
@@ -56,6 +56,10 @@ class URIUtil
|
||||
}
|
||||
|
||||
/** Encode a URI path.
|
||||
*
|
||||
* Somewhat oddly, this encodes all chars >= 0x80 if buf is null, (strict RFC 2396)
|
||||
* but only the control, space, and special chars if buf is non-null.
|
||||
*
|
||||
* @param path The path the encode
|
||||
* @param buf StringBuilder to encode path into (or null)
|
||||
* @return The StringBuilder or null if no substitutions required.
|
||||
@@ -83,7 +87,7 @@ class URIUtil
|
||||
buf=new StringBuilder(path.length()*2);
|
||||
break loop;
|
||||
default:
|
||||
if (c>127)
|
||||
if (c >= 0x7f || c <= 0x1f)
|
||||
{
|
||||
bytes = DataHelper.getUTF8(path);
|
||||
buf=new StringBuilder(path.length()*2);
|
||||
@@ -132,12 +136,12 @@ class URIUtil
|
||||
case ' ':
|
||||
buf.append("%20");
|
||||
continue;
|
||||
case 0x7f:
|
||||
buf.append("%7F");
|
||||
continue;
|
||||
default:
|
||||
if (c<0)
|
||||
{
|
||||
buf.append('%');
|
||||
if (c <= 0x1f) // includes negative
|
||||
toHex(c,buf);
|
||||
}
|
||||
else
|
||||
buf.append((char)c);
|
||||
continue;
|
||||
@@ -180,7 +184,10 @@ class URIUtil
|
||||
buf.append("%20");
|
||||
continue;
|
||||
default:
|
||||
buf.append(c);
|
||||
if (c <= 0x1f || (c >= 0x7f && c <= 0x9f) || Character.isSpaceChar(c))
|
||||
toHex(c,buf);
|
||||
else
|
||||
buf.append(c);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -195,11 +202,27 @@ class URIUtil
|
||||
*/
|
||||
private static void toHex(byte b, StringBuilder buf)
|
||||
{
|
||||
buf.append('%');
|
||||
int d=0xf&((0xF0&b)>>4);
|
||||
buf.append((char)((d>9?('A'-10):'0')+d));
|
||||
d=0xf&b;
|
||||
buf.append((char)((d>9?('A'-10):'0')+d));
|
||||
}
|
||||
|
||||
/**
|
||||
* UTF-8
|
||||
*/
|
||||
private static void toHex(char c, StringBuilder buf)
|
||||
{
|
||||
if (c > 0x7f) {
|
||||
byte[] b = DataHelper.getUTF8(Character.toString(c));
|
||||
for (int i = 0; i < b.length; i++) {
|
||||
toHex(b[i], buf);
|
||||
}
|
||||
} else {
|
||||
toHex((byte) c, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -24,6 +24,8 @@ import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import javax.net.ssl.SSLServerSocketFactory;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.I2PException;
|
||||
import net.i2p.client.I2PSession;
|
||||
@@ -86,6 +88,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
|
||||
private static int _executorThreadCount;
|
||||
private static final Object _executorLock = new Object();
|
||||
|
||||
public static final String PROP_USE_SSL = I2PTunnelServer.PROP_USE_SSL;
|
||||
|
||||
/**
|
||||
* This constructor always starts the tunnel (ignoring the i2cp.delayOpen option).
|
||||
* It is used to add a client to an existing socket manager.
|
||||
@@ -599,7 +603,24 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
|
||||
}
|
||||
return;
|
||||
}
|
||||
ss = new ServerSocket(localPort, 0, addr);
|
||||
Properties opts = getTunnel().getClientOptions();
|
||||
boolean useSSL = Boolean.parseBoolean(opts.getProperty(PROP_USE_SSL));
|
||||
if (useSSL) {
|
||||
// was already done in web/IndexBean.java when saving the config
|
||||
boolean wasCreated = SSLClientUtil.verifyKeyStore(opts);
|
||||
if (wasCreated) {
|
||||
// From here, we can't save the config.
|
||||
// We shouldn't get here, as SSL isn't the default, so it would
|
||||
// be enabled via the GUI only.
|
||||
// If it was done manually, the keys will be regenerated at every startup,
|
||||
// which is bad.
|
||||
_log.logAlways(Log.WARN, "Created new i2ptunnel SSL keys but can't save the config, disable and enable via i2ptunnel GUI");
|
||||
}
|
||||
SSLServerSocketFactory fact = SSLClientUtil.initializeFactory(opts);
|
||||
ss = fact.createServerSocket(localPort, 0, addr);
|
||||
} else {
|
||||
ss = new ServerSocket(localPort, 0, addr);
|
||||
}
|
||||
|
||||
// If a free port was requested, find out what we got
|
||||
if (localPort == 0) {
|
||||
|
||||
203
apps/i2ptunnel/java/src/net/i2p/i2ptunnel/SSLClientUtil.java
Normal file
203
apps/i2ptunnel/java/src/net/i2p/i2ptunnel/SSLClientUtil.java
Normal file
@@ -0,0 +1,203 @@
|
||||
package net.i2p.i2ptunnel;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.KeyStore;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.net.ssl.KeyManagerFactory;
|
||||
import javax.net.ssl.SSLServerSocketFactory;
|
||||
import javax.net.ssl.SSLContext;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.crypto.KeyStoreUtil;
|
||||
import net.i2p.util.Log;
|
||||
import net.i2p.util.SecureDirectory;
|
||||
|
||||
/**
|
||||
* Utilities for I2PTunnel client SSL server sockets.
|
||||
*
|
||||
* @since 0.9.15 adopted from net.i2p.router.client.SSLClientListenerRunner
|
||||
*/
|
||||
public class SSLClientUtil {
|
||||
|
||||
private static final String PROP_KEYSTORE_PASSWORD = "keystorePassword";
|
||||
private static final String DEFAULT_KEYSTORE_PASSWORD = "changeit";
|
||||
private static final String PROP_KEY_PASSWORD = "keyPassword";
|
||||
private static final String PROP_KEY_ALIAS = "keyAlias";
|
||||
private static final String ASCII_KEYFILE_SUFFIX = ".local.crt";
|
||||
private static final String PROP_KS_NAME = "keystoreFile";
|
||||
private static final String KS_DIR = "keystore";
|
||||
private static final String PREFIX = "i2ptunnel-";
|
||||
private static final String KS_SUFFIX = ".ks";
|
||||
private static final String CERT_DIR = "certificates/i2ptunnel";
|
||||
|
||||
/**
|
||||
* Create a new selfsigned cert and keystore and pubkey cert if they don't exist.
|
||||
* May take a while.
|
||||
*
|
||||
* @param opts in/out, updated if rv is true
|
||||
* @return false if it already exists; if true, caller must save opts
|
||||
* @throws IOException on creation fail
|
||||
*/
|
||||
public static boolean verifyKeyStore(Properties opts) throws IOException {
|
||||
return verifyKeyStore(opts, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new selfsigned cert and keystore and pubkey cert if they don't exist.
|
||||
* May take a while.
|
||||
*
|
||||
* @param opts in/out, updated if rv is true
|
||||
* @param optPfx add this prefix when getting/setting options
|
||||
* @return false if it already exists; if true, caller must save opts
|
||||
* @throws IOException on creation fail
|
||||
*/
|
||||
public static boolean verifyKeyStore(Properties opts, String optPfx) throws IOException {
|
||||
String name = opts.getProperty(optPfx + PROP_KEY_ALIAS);
|
||||
if (name == null) {
|
||||
name = KeyStoreUtil.randomString();
|
||||
opts.setProperty(optPfx + PROP_KEY_ALIAS, name);
|
||||
}
|
||||
String ksname = opts.getProperty(optPfx + PROP_KS_NAME);
|
||||
if (ksname == null) {
|
||||
ksname = PREFIX + name + KS_SUFFIX;
|
||||
opts.setProperty(optPfx + PROP_KS_NAME, ksname);
|
||||
}
|
||||
File ks = new File(ksname);
|
||||
if (!ks.isAbsolute()) {
|
||||
ks = new File(I2PAppContext.getGlobalContext().getConfigDir(), KS_DIR);
|
||||
ks = new File(ks, ksname);
|
||||
}
|
||||
if (ks.exists())
|
||||
return false;
|
||||
File dir = ks.getParentFile();
|
||||
if (!dir.exists()) {
|
||||
File sdir = new SecureDirectory(dir.getAbsolutePath());
|
||||
if (!sdir.mkdirs())
|
||||
throw new IOException("Unable to create keystore " + ks);
|
||||
}
|
||||
boolean rv = createKeyStore(ks, name, opts, optPfx);
|
||||
if (!rv)
|
||||
throw new IOException("Unable to create keystore " + ks);
|
||||
|
||||
// Now read it back out of the new keystore and save it in ascii form
|
||||
// where the clients can get to it.
|
||||
// Failure of this part is not fatal.
|
||||
exportCert(ks, name, opts, optPfx);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Call out to keytool to create a new keystore with a keypair in it.
|
||||
*
|
||||
* @param name used in CNAME
|
||||
* @param opts in/out, updated if rv is true, must contain PROP_KEY_ALIAS
|
||||
* @param optPfx add this prefix when getting/setting options
|
||||
* @return success, if true, opts will have password properties added to be saved
|
||||
*/
|
||||
private static boolean createKeyStore(File ks, String name, Properties opts, String optPfx) {
|
||||
// make a random 48 character password (30 * 8 / 5)
|
||||
String keyPassword = KeyStoreUtil.randomString();
|
||||
// and one for the cname
|
||||
String cname = name + ".i2ptunnel.i2p.net";
|
||||
|
||||
String keyName = opts.getProperty(optPfx + PROP_KEY_ALIAS);
|
||||
boolean success = KeyStoreUtil.createKeys(ks, keyName, cname, "I2PTUNNEL", keyPassword);
|
||||
if (success) {
|
||||
success = ks.exists();
|
||||
if (success) {
|
||||
opts.setProperty(optPfx + PROP_KEYSTORE_PASSWORD, DEFAULT_KEYSTORE_PASSWORD);
|
||||
opts.setProperty(optPfx + PROP_KEY_PASSWORD, keyPassword);
|
||||
}
|
||||
}
|
||||
if (success) {
|
||||
logAlways("Created self-signed certificate for " + cname + " in keystore: " + ks.getAbsolutePath() + "\n" +
|
||||
"The certificate name was generated randomly, and is not associated with your " +
|
||||
"IP address, host name, router identity, or destination keys.");
|
||||
} else {
|
||||
error("Failed to create I2PTunnel SSL keystore.\n" +
|
||||
"If you create the keystore manually, you must add " + optPfx + PROP_KEYSTORE_PASSWORD + " and " + optPfx + PROP_KEY_PASSWORD +
|
||||
" to " + (new File(I2PAppContext.getGlobalContext().getConfigDir(), "i2ptunnel.config")).getAbsolutePath());
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pull the cert back OUT of the keystore and save it as ascii
|
||||
* so the clients can get to it.
|
||||
*
|
||||
* @param name used to generate output file name
|
||||
* @param opts must contain optPfx + PROP_KEY_ALIAS
|
||||
* @param optPfx add this prefix when getting options
|
||||
*/
|
||||
private static void exportCert(File ks, String name, Properties opts, String optPfx) {
|
||||
File sdir = new SecureDirectory(I2PAppContext.getGlobalContext().getConfigDir(), CERT_DIR);
|
||||
if (sdir.exists() || sdir.mkdirs()) {
|
||||
String keyAlias = opts.getProperty(optPfx + PROP_KEY_ALIAS);
|
||||
String ksPass = opts.getProperty(optPfx + PROP_KEYSTORE_PASSWORD, DEFAULT_KEYSTORE_PASSWORD);
|
||||
File out = new File(sdir, PREFIX + name + ASCII_KEYFILE_SUFFIX);
|
||||
boolean success = KeyStoreUtil.exportCert(ks, ksPass, keyAlias, out);
|
||||
if (!success)
|
||||
error("Error getting SSL cert to save as ASCII");
|
||||
} else {
|
||||
error("Error saving ASCII SSL keys");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the SSLContext and sets the socket factory.
|
||||
* No option prefix allowed.
|
||||
*
|
||||
* @throws IOException; GeneralSecurityExceptions are wrapped in IOE for convenience
|
||||
* @return factory, throws on all errors
|
||||
*/
|
||||
public static SSLServerSocketFactory initializeFactory(Properties opts) throws IOException {
|
||||
String ksPass = opts.getProperty(PROP_KEYSTORE_PASSWORD, DEFAULT_KEYSTORE_PASSWORD);
|
||||
String keyPass = opts.getProperty(PROP_KEY_PASSWORD);
|
||||
if (keyPass == null) {
|
||||
throw new IOException("No key password, set " + PROP_KEY_PASSWORD + " in " +
|
||||
(new File(I2PAppContext.getGlobalContext().getConfigDir(), "i2ptunnel.config")).getAbsolutePath());
|
||||
}
|
||||
String ksname = opts.getProperty(PROP_KS_NAME);
|
||||
if (ksname == null) {
|
||||
throw new IOException("No keystore, set " + PROP_KS_NAME + " in " +
|
||||
(new File(I2PAppContext.getGlobalContext().getConfigDir(), "i2ptunnel.config")).getAbsolutePath());
|
||||
}
|
||||
File ks = new File(ksname);
|
||||
if (!ks.isAbsolute()) {
|
||||
ks = new File(I2PAppContext.getGlobalContext().getConfigDir(), KS_DIR);
|
||||
ks = new File(ks, ksname);
|
||||
}
|
||||
|
||||
InputStream fis = null;
|
||||
try {
|
||||
SSLContext sslc = SSLContext.getInstance("TLS");
|
||||
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
fis = new FileInputStream(ks);
|
||||
keyStore.load(fis, ksPass.toCharArray());
|
||||
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
|
||||
kmf.init(keyStore, keyPass.toCharArray());
|
||||
sslc.init(kmf.getKeyManagers(), null, I2PAppContext.getGlobalContext().random());
|
||||
return sslc.getServerSocketFactory();
|
||||
} catch (GeneralSecurityException gse) {
|
||||
IOException ioe = new IOException("keystore error");
|
||||
ioe.initCause(gse);
|
||||
throw ioe;
|
||||
} finally {
|
||||
if (fis != null) try { fis.close(); } catch (IOException ioe) {}
|
||||
}
|
||||
}
|
||||
|
||||
private static void error(String s) {
|
||||
I2PAppContext.getGlobalContext().logManager().getLog(SSLClientUtil.class).error(s);
|
||||
}
|
||||
|
||||
private static void logAlways(String s) {
|
||||
I2PAppContext.getGlobalContext().logManager().getLog(SSLClientUtil.class).logAlways(Log.INFO, s);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package net.i2p.i2ptunnel.streamr;
|
||||
|
||||
import net.i2p.i2ptunnel.udp.*;
|
||||
import net.i2p.util.I2PAppThread;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -9,7 +10,7 @@ import net.i2p.i2ptunnel.udp.*;
|
||||
public class Pinger implements Source, Runnable {
|
||||
|
||||
public Pinger() {
|
||||
this.thread = new Thread(this);
|
||||
this.thread = new I2PAppThread(this);
|
||||
}
|
||||
|
||||
public void setSink(Sink sink) {
|
||||
|
||||
@@ -6,6 +6,7 @@ import java.util.concurrent.BlockingQueue;
|
||||
import net.i2p.client.I2PSession;
|
||||
import net.i2p.client.I2PSessionListener;
|
||||
import net.i2p.client.datagram.I2PDatagramDissector;
|
||||
import net.i2p.util.I2PAppThread;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -33,7 +34,7 @@ public class I2PSource implements Source, Runnable {
|
||||
this.sess.setSessionListener(new Listener());
|
||||
|
||||
// create thread
|
||||
this.thread = new Thread(this);
|
||||
this.thread = new I2PAppThread(this);
|
||||
}
|
||||
|
||||
public void setSink(Sink sink) {
|
||||
|
||||
@@ -3,6 +3,8 @@ package net.i2p.i2ptunnel.udp;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.DatagramPacket;
|
||||
|
||||
import net.i2p.util.I2PAppThread;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author welterde
|
||||
@@ -19,13 +21,13 @@ public class UDPSource implements Source, Runnable {
|
||||
}
|
||||
|
||||
// create thread
|
||||
this.thread = new Thread(this);
|
||||
this.thread = new I2PAppThread(this);
|
||||
}
|
||||
|
||||
/** use socket from UDPSink */
|
||||
public UDPSource(DatagramSocket sock) {
|
||||
this.sock = sock;
|
||||
this.thread = new Thread(this);
|
||||
this.thread = new I2PAppThread(this);
|
||||
}
|
||||
|
||||
public void setSink(Sink sink) {
|
||||
|
||||
@@ -26,15 +26,18 @@ import net.i2p.app.ClientAppManager;
|
||||
import net.i2p.app.Outproxy;
|
||||
import net.i2p.client.I2PClient;
|
||||
import net.i2p.data.Certificate;
|
||||
import net.i2p.data.DataHelper;
|
||||
import net.i2p.data.Destination;
|
||||
import net.i2p.data.PrivateKeyFile;
|
||||
import net.i2p.data.SessionKey;
|
||||
import net.i2p.i2ptunnel.I2PTunnelClientBase;
|
||||
import net.i2p.i2ptunnel.I2PTunnelConnectClient;
|
||||
import net.i2p.i2ptunnel.I2PTunnelHTTPClient;
|
||||
import net.i2p.i2ptunnel.I2PTunnelHTTPClientBase;
|
||||
import net.i2p.i2ptunnel.I2PTunnelHTTPServer;
|
||||
import net.i2p.i2ptunnel.I2PTunnelIRCClient;
|
||||
import net.i2p.i2ptunnel.I2PTunnelServer;
|
||||
import net.i2p.i2ptunnel.SSLClientUtil;
|
||||
import net.i2p.i2ptunnel.TunnelController;
|
||||
import net.i2p.i2ptunnel.TunnelControllerGroup;
|
||||
import net.i2p.util.Addresses;
|
||||
@@ -255,7 +258,7 @@ public class IndexBean {
|
||||
// give the messages a chance to make it to the window
|
||||
try { Thread.sleep(1000); } catch (InterruptedException ie) {}
|
||||
// and give them something to look at in any case
|
||||
return _("Starting tunnel") + ' ' + getTunnelName(_tunnel) + "…";
|
||||
return _("Starting tunnel") + ' ' + getTunnelName(_tunnel) + "...";
|
||||
}
|
||||
|
||||
private String stop() {
|
||||
@@ -268,7 +271,7 @@ public class IndexBean {
|
||||
// give the messages a chance to make it to the window
|
||||
try { Thread.sleep(1000); } catch (InterruptedException ie) {}
|
||||
// and give them something to look at in any case
|
||||
return _("Stopping tunnel") + ' ' + getTunnelName(_tunnel) + "…";
|
||||
return _("Stopping tunnel") + ' ' + getTunnelName(_tunnel) + "...";
|
||||
}
|
||||
|
||||
private String saveChanges() {
|
||||
@@ -276,7 +279,27 @@ public class IndexBean {
|
||||
TunnelController cur = getController(_tunnel);
|
||||
|
||||
Properties config = getConfig();
|
||||
|
||||
|
||||
String ksMsg = null;
|
||||
String type = config.getProperty(TunnelController.PROP_TYPE);
|
||||
if (TunnelController.TYPE_STD_CLIENT.equals(type) || TunnelController.TYPE_IRC_CLIENT.equals(type)) {
|
||||
//
|
||||
// If we switch to SSL, create the keystore here, so we can store the new properties.
|
||||
// Down in I2PTunnelClientBase it's very hard to save the config.
|
||||
//
|
||||
if (Boolean.parseBoolean(config.getProperty(OPT + I2PTunnelClientBase.PROP_USE_SSL))) {
|
||||
try {
|
||||
boolean created = SSLClientUtil.verifyKeyStore(config, OPT);
|
||||
if (created) {
|
||||
// config now contains new keystore props
|
||||
ksMsg = "Created new self-signed certificate for tunnel " + getTunnelName(_tunnel);
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
ksMsg = "Failed to create new self-signed certificate for tunnel " +
|
||||
getTunnelName(_tunnel) + ", check logs: " + ioe;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cur == null) {
|
||||
// creating new
|
||||
cur = new TunnelController(config, "", true);
|
||||
@@ -327,6 +350,8 @@ public class IndexBean {
|
||||
}
|
||||
|
||||
List<String> msgs = doSave();
|
||||
if (ksMsg != null)
|
||||
msgs.add(ksMsg);
|
||||
return getMessages(msgs);
|
||||
}
|
||||
|
||||
@@ -397,6 +422,7 @@ public class IndexBean {
|
||||
* Executes any action requested (start/stop/etc) and dump out the
|
||||
* messages.
|
||||
*
|
||||
* @return HTML escaped
|
||||
*/
|
||||
public String getMessages() {
|
||||
if (_group == null)
|
||||
@@ -405,13 +431,14 @@ public class IndexBean {
|
||||
StringBuilder buf = new StringBuilder(512);
|
||||
if (_action != null) {
|
||||
try {
|
||||
buf.append(processAction()).append("\n");
|
||||
buf.append(processAction()).append('\n');
|
||||
} catch (Exception e) {
|
||||
_log.log(Log.CRIT, "Error processing " + _action, e);
|
||||
buf.append("Error: ").append(e.toString()).append('\n');
|
||||
}
|
||||
}
|
||||
getMessages(_group.clearAllMessages(), buf);
|
||||
return buf.toString();
|
||||
return DataHelper.escapeHTML(buf.toString());
|
||||
}
|
||||
|
||||
////
|
||||
@@ -1293,7 +1320,8 @@ public class IndexBean {
|
||||
I2PTunnelIRCClient.PROP_DCC
|
||||
};
|
||||
private static final String _booleanClientOpts[] = {
|
||||
"i2cp.reduceOnIdle", "i2cp.closeOnIdle", "i2cp.newDestOnResume", "persistentClientKey", "i2cp.delayOpen"
|
||||
"i2cp.reduceOnIdle", "i2cp.closeOnIdle", "i2cp.newDestOnResume", "persistentClientKey", "i2cp.delayOpen",
|
||||
I2PTunnelClientBase.PROP_USE_SSL,
|
||||
};
|
||||
private static final String _booleanProxyOpts[] = {
|
||||
I2PTunnelHTTPClientBase.PROP_OUTPROXY_AUTH,
|
||||
|
||||
@@ -140,6 +140,14 @@ input.default { width: 1px; height: 1px; visibility: hidden; }
|
||||
</select>
|
||||
<% } /* streamrclient */ %>
|
||||
</div>
|
||||
<% if ("client".equals(tunnelType) || "ircclient".equals(tunnelType)) {
|
||||
%><div id="portField" class="rowItem">
|
||||
<label>
|
||||
<%=intl._("Use SSL?")%>
|
||||
</label>
|
||||
<input value="1" type="checkbox" id="startOnLoad" name="useSSL" title="Clients use SSL to connect" <%=(editBean.isSSLEnabled(curTunnel) ? " checked=\"checked\"" : "")%> class="tickbox" />
|
||||
</div>
|
||||
<% } /* tunnel types */ %>
|
||||
|
||||
<div class="subdivider">
|
||||
<hr />
|
||||
|
||||
@@ -244,6 +244,8 @@
|
||||
<%
|
||||
String cPort= indexBean.getClientPort2(curClient);
|
||||
out.write(cPort);
|
||||
if (indexBean.isSSLEnabled(curClient))
|
||||
out.write(" SSL");
|
||||
%>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -25,7 +25,15 @@ import net.i2p.util.Log;
|
||||
*/
|
||||
public class I2PSocketManagerFactory {
|
||||
|
||||
/**
|
||||
* Ignored since 0.9.12, cannot be changed via properties.
|
||||
* @deprecated
|
||||
*/
|
||||
public static final String PROP_MANAGER = "i2p.streaming.manager";
|
||||
|
||||
/**
|
||||
* The one and only manager.
|
||||
*/
|
||||
public static final String DEFAULT_MANAGER = "net.i2p.client.streaming.impl.I2PSocketManagerFull";
|
||||
|
||||
/**
|
||||
|
||||
@@ -1629,8 +1629,8 @@ public class DataHelper {
|
||||
return rv;
|
||||
}
|
||||
|
||||
private static final String escapeChars[] = {"&", "\"", "<", ">", "\"", "'"};
|
||||
private static final String escapeCodes[] = {"&", """, "<", ">", """, "'"};
|
||||
private static final String escapeChars[] = {"&", "\"", "<", ">", "'"};
|
||||
private static final String escapeCodes[] = {"&", """, "<", ">", "'"};
|
||||
|
||||
/**
|
||||
* Escape a string for inclusion in HTML
|
||||
|
||||
@@ -97,7 +97,7 @@ public class Clock implements Timestamper.UpdateListener {
|
||||
getLog().info("Updating clock offset to " + offsetMs + "ms from " + _offset + "ms");
|
||||
|
||||
if (!_statCreated) {
|
||||
_context.statManager().createRequiredRateStat("clock.skew", "Clock step adjustment (ms)", "Clock", new long[] { 10*60*1000, 3*60*60*1000, 24*60*60*60 });
|
||||
_context.statManager().createRequiredRateStat("clock.skew", "Clock step adjustment (ms)", "Clock", new long[] { 10*60*1000, 3*60*60*1000, 24*60*60*1000 });
|
||||
_statCreated = true;
|
||||
}
|
||||
_context.statManager().addRateData("clock.skew", delta, 0);
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
2014-08-21 zzz
|
||||
* i2psnark:
|
||||
- Escape control chars in encodePath()
|
||||
- Increase max piece size to 8 MB (ticket #1347)
|
||||
* i2ptunnel: Add local SSL support for std. and IRC client tunnels (ticket #1107)
|
||||
|
||||
2014-08-19 zzz
|
||||
* i2psnark:
|
||||
- Don't filter create torrent form, and
|
||||
|
||||
@@ -161,7 +161,7 @@ public class RouterClock extends Clock {
|
||||
getLog().info("Updating target clock offset to " + offsetMs + "ms from " + _offset + "ms, Stratum " + stratum);
|
||||
|
||||
if (!_statCreated) {
|
||||
_context.statManager().createRequiredRateStat("clock.skew", "Clock step adjustment (ms)", "Clock", new long[] { 10*60*1000, 3*60*60*1000, 24*60*60*60 });
|
||||
_context.statManager().createRequiredRateStat("clock.skew", "Clock step adjustment (ms)", "Clock", new long[] { 10*60*1000, 3*60*60*1000, 24*60*60*1000 });
|
||||
_statCreated = true;
|
||||
}
|
||||
_context.statManager().addRateData("clock.skew", delta);
|
||||
|
||||
@@ -18,7 +18,7 @@ public class RouterVersion {
|
||||
/** deprecated */
|
||||
public final static String ID = "Monotone";
|
||||
public final static String VERSION = CoreVersion.VERSION;
|
||||
public final static long BUILD = 7;
|
||||
public final static long BUILD = 8;
|
||||
|
||||
/** for example "-test" */
|
||||
public final static String EXTRA = "";
|
||||
|
||||
@@ -48,6 +48,8 @@ class BatchedPreprocessor extends TrivialPreprocessor {
|
||||
private long _pendingSince;
|
||||
private final String _name;
|
||||
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
public BatchedPreprocessor(RouterContext ctx, String name) {
|
||||
super(ctx);
|
||||
_name = name;
|
||||
@@ -175,7 +177,8 @@ class BatchedPreprocessor extends TrivialPreprocessor {
|
||||
+ " len=" + cur.getData().length + " alloc=" + allocated);
|
||||
if (timingBuf != null)
|
||||
timingBuf.append(" sent " + cur);
|
||||
notePreprocessing(cur.getMessageId(), cur.getFragmentNumber(), cur.getData().length, cur.getMessageIds(), "flushed allocated");
|
||||
if (DEBUG)
|
||||
notePreprocessing(cur.getMessageId(), cur.getFragmentNumber(), cur.getData().length, cur.getMessageIds(), "flushed allocated");
|
||||
_context.statManager().addRateData("tunnel.batchFragmentation", cur.getFragmentNumber() + 1);
|
||||
_context.statManager().addRateData("tunnel.writeDelay", cur.getLifetime(), cur.getData().length);
|
||||
}
|
||||
@@ -184,7 +187,8 @@ class BatchedPreprocessor extends TrivialPreprocessor {
|
||||
PendingGatewayMessage cur = pending.remove(0);
|
||||
if (timingBuf != null)
|
||||
timingBuf.append(" sent perfect fit " + cur).append(".");
|
||||
notePreprocessing(cur.getMessageId(), cur.getFragmentNumber(), msg.getData().length, msg.getMessageIds(), "flushed tail, remaining: " + pending);
|
||||
if (DEBUG)
|
||||
notePreprocessing(cur.getMessageId(), cur.getFragmentNumber(), msg.getData().length, msg.getMessageIds(), "flushed tail, remaining: " + pending);
|
||||
_context.statManager().addRateData("tunnel.batchFragmentation", cur.getFragmentNumber() + 1);
|
||||
_context.statManager().addRateData("tunnel.writeDelay", cur.getLifetime(), cur.getData().length);
|
||||
}
|
||||
@@ -234,7 +238,8 @@ class BatchedPreprocessor extends TrivialPreprocessor {
|
||||
if (cur.getOffset() < cur.getData().length)
|
||||
break;
|
||||
pending.remove(0);
|
||||
notePreprocessing(cur.getMessageId(), cur.getFragmentNumber(), cur.getData().length, cur.getMessageIds(), "flushed remaining");
|
||||
if (DEBUG)
|
||||
notePreprocessing(cur.getMessageId(), cur.getFragmentNumber(), cur.getData().length, cur.getMessageIds(), "flushed remaining");
|
||||
_context.statManager().addRateData("tunnel.batchFragmentation", cur.getFragmentNumber() + 1);
|
||||
_context.statManager().addRateData("tunnel.writeDelay", cur.getLifetime(), cur.getData().length);
|
||||
}
|
||||
@@ -383,9 +388,12 @@ class BatchedPreprocessor extends TrivialPreprocessor {
|
||||
}
|
||||
|
||||
long msgId = sender.sendPreprocessed(preprocessed, rec);
|
||||
for (int i = 0; i < pending.size(); i++) {
|
||||
PendingGatewayMessage cur = pending.get(i);
|
||||
cur.addMessageId(msgId);
|
||||
if (DEBUG) {
|
||||
// creates a list in PGM
|
||||
for (int i = 0; i < pending.size(); i++) {
|
||||
PendingGatewayMessage cur = pending.get(i);
|
||||
cur.addMessageId(msgId);
|
||||
}
|
||||
}
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Sent " + startAt + ":" + sendThrough + " out of " + pending + " in message " + msgId);
|
||||
|
||||
@@ -11,8 +11,8 @@ import net.i2p.router.RouterContext;
|
||||
*
|
||||
*/
|
||||
class BatchedRouterPreprocessor extends BatchedPreprocessor {
|
||||
private TunnelCreatorConfig _config;
|
||||
protected HopConfig _hopConfig;
|
||||
private final TunnelCreatorConfig _config;
|
||||
protected final HopConfig _hopConfig;
|
||||
private final long _sendDelay;
|
||||
|
||||
/**
|
||||
@@ -34,12 +34,14 @@ class BatchedRouterPreprocessor extends BatchedPreprocessor {
|
||||
public BatchedRouterPreprocessor(RouterContext ctx, TunnelCreatorConfig cfg) {
|
||||
super(ctx, getName(cfg));
|
||||
_config = cfg;
|
||||
_hopConfig = null;
|
||||
_sendDelay = initialSendDelay();
|
||||
}
|
||||
|
||||
/** for IBGWs */
|
||||
public BatchedRouterPreprocessor(RouterContext ctx, HopConfig cfg) {
|
||||
super(ctx, getName(cfg));
|
||||
_config = null;
|
||||
_hopConfig = cfg;
|
||||
_sendDelay = initialSendDelay();
|
||||
}
|
||||
|
||||
@@ -10,30 +10,30 @@ import net.i2p.util.Log;
|
||||
*
|
||||
*/
|
||||
class OutboundSender implements TunnelGateway.Sender {
|
||||
private final I2PAppContext _context;
|
||||
private final Log _log;
|
||||
//private final I2PAppContext _context;
|
||||
//private final Log _log;
|
||||
private final TunnelCreatorConfig _config;
|
||||
private final OutboundGatewayProcessor _processor;
|
||||
|
||||
//static final boolean USE_ENCRYPTION = HopProcessor.USE_ENCRYPTION;
|
||||
|
||||
public OutboundSender(I2PAppContext ctx, TunnelCreatorConfig config) {
|
||||
_context = ctx;
|
||||
_log = ctx.logManager().getLog(OutboundSender.class);
|
||||
//_context = ctx;
|
||||
//_log = ctx.logManager().getLog(OutboundSender.class);
|
||||
_config = config;
|
||||
_processor = new OutboundGatewayProcessor(_context, config);
|
||||
_processor = new OutboundGatewayProcessor(ctx, config);
|
||||
}
|
||||
|
||||
public long sendPreprocessed(byte[] preprocessed, TunnelGateway.Receiver receiver) {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("preprocessed data going out " + _config + ": " + Base64.encode(preprocessed));
|
||||
//if (_log.shouldLog(Log.DEBUG))
|
||||
// _log.debug("preprocessed data going out " + _config + ": " + Base64.encode(preprocessed));
|
||||
//if (USE_ENCRYPTION)
|
||||
_processor.process(preprocessed, 0, preprocessed.length);
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("after wrapping up the preprocessed data on " + _config);
|
||||
//if (_log.shouldLog(Log.DEBUG))
|
||||
// _log.debug("after wrapping up the preprocessed data on " + _config);
|
||||
long rv = receiver.receiveEncrypted(preprocessed);
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("after receiving on " + _config + ": receiver = " + receiver);
|
||||
//if (_log.shouldLog(Log.DEBUG))
|
||||
// _log.debug("after receiving on " + _config + ": receiver = " + receiver);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,9 @@ import net.i2p.util.SimpleByteCache;
|
||||
* optimal throughput.
|
||||
*
|
||||
* See FragmentHandler Javadoc for tunnel message fragment format
|
||||
*
|
||||
* Not instantiated directly except in unit tests; see BatchedPreprocessor
|
||||
*
|
||||
*/
|
||||
class TrivialPreprocessor implements TunnelGateway.QueuePreprocessor {
|
||||
protected final RouterContext _context;
|
||||
@@ -48,7 +51,7 @@ class TrivialPreprocessor implements TunnelGateway.QueuePreprocessor {
|
||||
* NOTE: Unused here, see BatchedPreprocessor override, super is not called.
|
||||
*/
|
||||
public boolean preprocessQueue(List<PendingGatewayMessage> pending, TunnelGateway.Sender sender, TunnelGateway.Receiver rec) {
|
||||
throw new IllegalArgumentException("unused, right?");
|
||||
throw new UnsupportedOperationException("unused, right?");
|
||||
}
|
||||
|
||||
protected void notePreprocessing(long messageId, int numFragments, int totalLength, List<Long> messageIds, String msg) {}
|
||||
@@ -265,7 +268,7 @@ class TrivialPreprocessor implements TunnelGateway.QueuePreprocessor {
|
||||
* Does NOT include 4 for the message ID if the message will be fragmented;
|
||||
* call getInstructionAugmentationSize() for that.
|
||||
*/
|
||||
protected int getInstructionsSize(PendingGatewayMessage msg) {
|
||||
protected static int getInstructionsSize(PendingGatewayMessage msg) {
|
||||
if (msg.getFragmentNumber() > 0)
|
||||
return 7;
|
||||
// control byte
|
||||
@@ -283,7 +286,7 @@ class TrivialPreprocessor implements TunnelGateway.QueuePreprocessor {
|
||||
}
|
||||
|
||||
/** @return 0 or 4 */
|
||||
protected int getInstructionAugmentationSize(PendingGatewayMessage msg, int offset, int instructionsSize) {
|
||||
protected static int getInstructionAugmentationSize(PendingGatewayMessage msg, int offset, int instructionsSize) {
|
||||
int payloadLength = msg.getData().length - msg.getOffset();
|
||||
if (offset + payloadLength + instructionsSize + IV_SIZE + 1 + 4 > PREPROCESSED_SIZE) {
|
||||
// requires fragmentation, so include the messageId
|
||||
|
||||
@@ -33,7 +33,7 @@ import net.i2p.util.SimpleTimer2;
|
||||
*
|
||||
* Unused directly - see PumpedTunnelGateway, ThrottledPumpedTunnelGateway, and TunnelGatewayZeroHop overrides.
|
||||
*/
|
||||
class TunnelGateway {
|
||||
abstract class TunnelGateway {
|
||||
protected final RouterContext _context;
|
||||
protected final Log _log;
|
||||
protected final List<PendingGatewayMessage> _queue;
|
||||
|
||||
@@ -66,8 +66,8 @@ public class FragmentTest {
|
||||
|
||||
try {
|
||||
pre.preprocessQueue(messages, new SenderImpl(), receiver);
|
||||
fail("should have thrown IAE");
|
||||
} catch (IllegalArgumentException expected){}
|
||||
fail("should have thrown UOE");
|
||||
} catch (UnsupportedOperationException expected){}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -89,8 +89,8 @@ public class FragmentTest {
|
||||
|
||||
try {
|
||||
pre.preprocessQueue(messages, new SenderImpl(), receiver);
|
||||
fail("should have thrown IAE");
|
||||
} catch (IllegalArgumentException expected){}
|
||||
fail("should have thrown UOE");
|
||||
} catch (UnsupportedOperationException expected){}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user