propagate from branch 'i2p.i2p' (head a89e68077114f79902a76649affe78e8ab709787)

to branch 'i2p.i2p.729' (head 11fde36281469d5ac8757bca1d7f93f679e0cb74)
This commit is contained in:
zab2
2013-06-02 12:41:02 +00:00
111 changed files with 801 additions and 739 deletions

View File

@@ -132,7 +132,7 @@ Installer:
Java Service Wrapper Community Edition 32-bit 3.5.13:
Java Service Wrapper Community Edition 32-bit 3.5.19:
Copyright (C) 1999-2011 Tanuki Software, Ltd. All Rights Reserved.
See licenses/LICENSE-Wrapper.txt
@@ -177,7 +177,7 @@ Applications:
By welterde.
See licenses/LICENSE-GPLv2.txt
Jetty 7.6.10.v20130312:
Jetty 7.6.11.v20130520:
See licenses/ABOUT-Jetty.html
See licenses/NOTICE-Jetty.html
See licenses/LICENSE-Apache2.0.txt
@@ -243,8 +243,8 @@ Applications:
Bundles systray4j-2.4.1:
See licenses/LICENSE-LGPLv2.1.txt
Tomcat 6.0.36:
Copyright 1999-2012 The Apache Software Foundation
Tomcat 6.0.37:
Copyright 1999-2013 The Apache Software Foundation
See licenses/LICENSE-Apache2.0.txt
See licenses/NOTICE-Tomcat.txt

View File

@@ -47,7 +47,7 @@ import net.i2p.util.SecureDirectory;
public class Daemon {
public static final String VERSION = "2.0.4";
private static final Daemon _instance = new Daemon();
private boolean _running;
private volatile boolean _running;
private static final boolean DEBUG = false;
/**

View File

@@ -37,7 +37,9 @@ class BWLimits {
return rv;
}
/****
public static void main(String args[]) {
System.out.println(Arrays.toString(getBWLimits("127.0.0.1", 7654)));
}
****/
}

View File

@@ -33,11 +33,10 @@ import net.i2p.data.Hash;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
import net.i2p.util.ObjectCounter;
import net.i2p.util.SimpleScheduler;
import net.i2p.util.SimpleTimer;
import net.i2p.util.SimpleTimer2;
/**
* Accepts connections on a TCP port and routes them to sub-acceptors.
* Accepts connections on a I2PServerSocket and routes them to PeerAcceptors.
*/
class ConnectionAcceptor implements Runnable
{
@@ -47,14 +46,22 @@ class ConnectionAcceptor implements Runnable
private Thread thread;
private final I2PSnarkUtil _util;
private final ObjectCounter<Hash> _badCounter = new ObjectCounter();
private final SimpleTimer2.TimedEvent _cleaner;
private boolean stop;
private volatile boolean stop;
private boolean socketChanged;
private static final int MAX_BAD = 2;
// protocol errors before blacklisting.
private static final int MAX_BAD = 1;
private static final long BAD_CLEAN_INTERVAL = 30*60*1000;
public ConnectionAcceptor(I2PSnarkUtil util) { _util = util; }
/**
* Multitorrent
*/
public ConnectionAcceptor(I2PSnarkUtil util) {
_util = util;
_cleaner = new Cleaner();
}
public synchronized void startAccepting(PeerCoordinatorSet set, I2PServerSocket socket) {
if (serverSocket != socket) {
@@ -67,11 +74,14 @@ class ConnectionAcceptor implements Runnable
thread = new I2PAppThread(this, "I2PSnark acceptor");
thread.setDaemon(true);
thread.start();
_util.getContext().simpleScheduler().addPeriodicEvent(new Cleaner(), BAD_CLEAN_INTERVAL);
_cleaner.schedule(BAD_CLEAN_INTERVAL);
}
}
}
/**
* Unused (single torrent)
*/
public ConnectionAcceptor(I2PSnarkUtil util, I2PServerSocket serverSocket,
PeerAcceptor peeracceptor)
{
@@ -82,7 +92,7 @@ class ConnectionAcceptor implements Runnable
thread = new I2PAppThread(this, "I2PSnark acceptor");
thread.setDaemon(true);
thread.start();
_util.getContext().simpleScheduler().addPeriodicEvent(new Cleaner(), BAD_CLEAN_INTERVAL);
_cleaner = new Cleaner();
}
public void halt()
@@ -101,14 +111,20 @@ class ConnectionAcceptor implements Runnable
Thread t = thread;
if (t != null)
t.interrupt();
_cleaner.cancel();
}
/**
* Effectively unused, would only be called if we changed
* I2CP host/port, which is hidden in the gui if in router context
*/
public void restart() {
serverSocket = _util.getServerSocket();
socketChanged = true;
Thread t = thread;
if (t != null)
t.interrupt();
_cleaner.schedule(BAD_CLEAN_INTERVAL);
}
public int getPort()
@@ -150,9 +166,11 @@ class ConnectionAcceptor implements Runnable
try { socket.close(); } catch (IOException ioe) {}
continue;
}
if (_badCounter.count(socket.getPeerDestination().calculateHash()) >= MAX_BAD) {
int bad = _badCounter.count(socket.getPeerDestination().calculateHash());
if (bad >= MAX_BAD) {
if (_log.shouldLog(Log.WARN))
_log.warn("Rejecting connection from " + socket.getPeerDestination().calculateHash() + " after " + MAX_BAD + " failures");
_log.warn("Rejecting connection from " + socket.getPeerDestination().calculateHash() +
" after " + bad + " failures, max is " + MAX_BAD);
try { socket.close(); } catch (IOException ioe) {}
continue;
}
@@ -214,7 +232,17 @@ class ConnectionAcceptor implements Runnable
}
/** @since 0.9.1 */
private class Cleaner implements SimpleTimer.TimedEvent {
public void timeReached() { _badCounter.clear(); }
private class Cleaner extends SimpleTimer2.TimedEvent {
public Cleaner() {
super(_util.getContext().simpleTimer2());
}
public void timeReached() {
if (stop)
return;
_badCounter.clear();
schedule(BAD_CLEAN_INTERVAL);
}
}
}

View File

@@ -37,8 +37,20 @@ interface CoordinatorListener
*/
void gotMetaInfo(PeerCoordinator coordinator, MetaInfo metainfo);
/**
* Is this number of uploaders over the per-torrent limit?
*/
public boolean overUploadLimit(int uploaders);
/**
* Are we currently over the upstream bandwidth limit?
*/
public boolean overUpBWLimit();
/**
* Is the total (in Bps) over the upstream bandwidth limit?
*/
public boolean overUpBWLimit(long total);
public void addMessage(String message);
}

View File

@@ -158,7 +158,7 @@ public class I2PSnarkUtil {
}
/**
* This updates the session options and tells the router
* This updates ALL the session options (not just the bw) and tells the router
* @param limit KBps
*/
public void setMaxUpBW(int limit) {

View File

@@ -0,0 +1,120 @@
/*
* Released into the public domain
* with no warranty of any kind, either expressed or implied.
*/
package org.klomp.snark;
import java.util.Map;
import java.util.Properties;
import net.i2p.client.I2PSession;
import net.i2p.client.streaming.I2PSocketManager;
import net.i2p.util.Log;
import net.i2p.util.SimpleTimer2;
/**
* Periodically check for idle condition based on connected peers,
* and reduce/restore tunnel count as necessary.
* We can't use the I2CP idle detector because it's based on traffic,
* so DHT and announces would keep it non-idle.
*
* @since 0.9.7
*/
class IdleChecker extends SimpleTimer2.TimedEvent {
private final I2PSnarkUtil _util;
private final PeerCoordinatorSet _pcs;
private final Log _log;
private int _consec;
private boolean _isIdle;
private static final long CHECK_TIME = 63*1000;
private static final int MAX_CONSEC_IDLE = 4;
/**
* Caller must schedule
*/
public IdleChecker(I2PSnarkUtil util, PeerCoordinatorSet pcs) {
super(util.getContext().simpleTimer2());
_log = util.getContext().logManager().getLog(IdleChecker.class);
_util = util;
_pcs = pcs;
}
public void timeReached() {
if (_util.connected()) {
boolean hasPeers = false;
for (PeerCoordinator pc : _pcs) {
if (pc.getPeers() > 0) {
hasPeers = true;
break;
}
}
if (hasPeers) {
if (_isIdle)
restoreTunnels();
} else {
if (!_isIdle) {
if (_consec++ >= MAX_CONSEC_IDLE)
reduceTunnels();
}
}
} else {
_isIdle = false;
_consec = 0;
}
schedule(CHECK_TIME);
}
/**
* Reduce to 1 in / 1 out tunnel
*/
private void reduceTunnels() {
_isIdle = true;
if (_log.shouldLog(Log.INFO))
_log.info("Reducing tunnels on idle");
setTunnels("1", "1", "0", "0");
}
/**
* Restore tunnel count
*/
private void restoreTunnels() {
_isIdle = false;
if (_log.shouldLog(Log.INFO))
_log.info("Restoring tunnels on activity");
Map<String, String> opts = _util.getI2CPOptions();
String i = opts.get("inbound.quantity");
if (i == null)
i = "3";
String o = opts.get("outbound.quantity");
if (o == null)
o = "3";
String ib = opts.get("inbound.backupQuantity");
if (ib == null)
ib = "0";
String ob= opts.get("outbound.backupQuantity");
if (ob == null)
ob = "0";
setTunnels(i, o, ib, ob);
}
/**
* Set in / out / in backup / out backup tunnel counts
*/
private void setTunnels(String i, String o, String ib, String ob) {
_consec = 0;
I2PSocketManager mgr = _util.getSocketManager();
if (mgr != null) {
I2PSession sess = mgr.getSession();
if (sess != null) {
Properties newProps = new Properties();
newProps.setProperty("inbound.quantity", i);
newProps.setProperty("outbound.quantity", o);
newProps.setProperty("inbound.backupQuantity", ib);
newProps.setProperty("outbound.backupQuantity", ob);
sess.updateOptions(newProps);
}
}
}
}

View File

@@ -12,7 +12,7 @@ import net.i2p.crypto.SHA1Hash;
* Each PeerCoordinator is added to the set from within the Snark (and removed
* from it there too)
*/
class PeerCoordinatorSet {
class PeerCoordinatorSet implements Iterable<PeerCoordinator> {
private final Map<SHA1Hash, PeerCoordinator> _coordinators;
public PeerCoordinatorSet() {

View File

@@ -27,6 +27,8 @@ import net.i2p.data.DataHelper;
/**
* TimerTask that monitors the peers and total up/download speeds.
* Works together with the main Snark class to report periodical statistics.
*
* @deprecated unused, for command line client only, commented out in Snark.java
*/
class PeerMonitorTask implements Runnable
{
@@ -45,6 +47,7 @@ class PeerMonitorTask implements Runnable
public void run()
{
/*****
// Get some statistics
int peers = 0;
int uploaders = 0;
@@ -117,5 +120,6 @@ class PeerMonitorTask implements Runnable
lastDownloaded = downloaded;
lastUploaded = uploaded;
****/
}
}

View File

@@ -1226,8 +1226,7 @@ public class Snark
if (_peerCoordinatorSet == null || uploaders <= 0)
return false;
int totalUploaders = 0;
for (Iterator<PeerCoordinator> iter = _peerCoordinatorSet.iterator(); iter.hasNext(); ) {
PeerCoordinator c = iter.next();
for (PeerCoordinator c : _peerCoordinatorSet) {
if (!c.halted())
totalUploaders += c.uploaders;
}
@@ -1240,8 +1239,7 @@ public class Snark
if (_peerCoordinatorSet == null)
return false;
long total = 0;
for (Iterator<PeerCoordinator> iter = _peerCoordinatorSet.iterator(); iter.hasNext(); ) {
PeerCoordinator c = iter.next();
for (PeerCoordinator c : _peerCoordinatorSet) {
if (!c.halted())
total += c.getCurrentUploadRate();
}

View File

@@ -37,6 +37,7 @@ import net.i2p.util.SecureDirectory;
import net.i2p.util.SecureFileOutputStream;
import net.i2p.util.SimpleScheduler;
import net.i2p.util.SimpleTimer;
import net.i2p.util.SimpleTimer2;
import org.klomp.snark.dht.DHT;
@@ -70,6 +71,7 @@ public class SnarkManager implements CompleteListener {
private final Map<String, Tracker> _trackerMap;
private UpdateManager _umgr;
private UpdateHandler _uhandler;
private SimpleTimer2.TimedEvent _idleChecker;
public static final String PROP_I2CP_HOST = "i2psnark.i2cpHost";
public static final String PROP_I2CP_PORT = "i2psnark.i2cpPort";
@@ -126,7 +128,7 @@ public class SnarkManager implements CompleteListener {
,"Welterde", "http://tracker.welterde.i2p/a=http://tracker.welterde.i2p/stats?mode=top5"
,"Diftracker", "http://diftracker.i2p/announce.php=http://diftracker.i2p/"
// , "CRSTRACK", "http://b4G9sCdtfvccMAXh~SaZrPqVQNyGQbhbYMbw6supq2XGzbjU4NcOmjFI0vxQ8w1L05twmkOvg5QERcX6Mi8NQrWnR0stLExu2LucUXg1aYjnggxIR8TIOGygZVIMV3STKH4UQXD--wz0BUrqaLxPhrm2Eh9Hwc8TdB6Na4ShQUq5Xm8D4elzNUVdpM~RtChEyJWuQvoGAHY3ppX-EJJLkiSr1t77neS4Lc-KofMVmgI9a2tSSpNAagBiNI6Ak9L1T0F9uxeDfEG9bBSQPNMOSUbAoEcNxtt7xOW~cNOAyMyGydwPMnrQ5kIYPY8Pd3XudEko970vE0D6gO19yoBMJpKx6Dh50DGgybLQ9CpRaynh2zPULTHxm8rneOGRcQo8D3mE7FQ92m54~SvfjXjD2TwAVGI~ae~n9HDxt8uxOecAAvjjJ3TD4XM63Q9TmB38RmGNzNLDBQMEmJFpqQU8YeuhnS54IVdUoVQFqui5SfDeLXlSkh4vYoMU66pvBfWbAAAA.i2p/tracker/announce.php=http://crstrack.i2p/tracker/"
// ,"Exotrack", "http://blbgywsjubw3d2zih2giokakhe3o2cko7jtte4risb3hohbcoyva.b32.i2p/announce.php=http://exotrack.i2p/"
,"Exotrack", "http://blbgywsjubw3d2zih2giokakhe3o2cko7jtte4risb3hohbcoyva.b32.i2p/announce.php=http://exotrack.i2p/"
};
/** comma delimited list of name=announceURL=baseURL for the trackers to be displayed */
@@ -178,6 +180,8 @@ public class SnarkManager implements CompleteListener {
_context.simpleScheduler().addEvent(new Register(), 4*60*1000);
// Not required, Jetty has a shutdown hook
//_context.addShutdownTask(new SnarkManagerShutdown());
_idleChecker = new IdleChecker(_util, _peerCoordinatorSet);
_idleChecker.schedule(5*60*1000);
}
/** @since 0.9.4 */
@@ -210,6 +214,7 @@ public class SnarkManager implements CompleteListener {
_running = false;
_monitor.interrupt();
_connectionAcceptor.halt();
_idleChecker.cancel();
stopAllTorrents(true);
}
@@ -635,6 +640,7 @@ public class SnarkManager implements CompleteListener {
addMessage(_("I2CP options changed to {0}", i2cpOpts));
_util.setI2CPConfig(oldI2CPHost, oldI2CPPort, opts);
} else {
// Won't happen, I2CP host/port, are hidden in the GUI if in router context
if (_util.connected()) {
_util.disconnect();
addMessage(_("Disconnecting old I2CP destination"));
@@ -658,6 +664,8 @@ public class SnarkManager implements CompleteListener {
for (Snark snark : _snarks.values()) {
if (snark.restartAcceptor()) {
addMessage(_("I2CP listener restarted for \"{0}\"", snark.getBaseName()));
// this is the common ConnectionAcceptor, so we only need to do it once
break;
}
}
}

View File

@@ -38,6 +38,7 @@ import net.i2p.I2PAppContext;
import net.i2p.data.ByteArray;
import net.i2p.util.ByteCache;
import net.i2p.util.Log;
import net.i2p.util.SystemVersion;
/* ------------------------------------------------------------ */
@@ -528,7 +529,10 @@ class BasicServlet extends HttpServlet
protected static String addPaths(String base, String path) {
if (path == null)
return base;
return (new File(base, path)).toString();
String rv = (new File(base, path)).toString();
if (SystemVersion.isWindows())
rv = rv.replace("\\", "/");
return rv;
}
/**

View File

@@ -216,7 +216,7 @@ input.default { width: 1px; height: 1px; visibility: hidden; }
<%=intl._("Length")%>(<span class="accessKey">t</span>):
</label>
<select id="tunnelDepth" name="tunnelDepth" title="Length of each Tunnel" class="selectbox">
<% int tunnelDepth = editBean.getTunnelDepth(curTunnel, 2);
<% int tunnelDepth = editBean.getTunnelDepth(curTunnel, 3);
%><option value="0"<%=(tunnelDepth == 0 ? " selected=\"selected\"" : "") %>><%=intl._("0 hop tunnel (low anonymity, low latency)")%></option>
<option value="1"<%=(tunnelDepth == 1 ? " selected=\"selected\"" : "") %>><%=intl._("1 hop tunnel (medium anonymity, medium latency)")%></option>
<option value="2"<%=(tunnelDepth == 2 ? " selected=\"selected\"" : "") %>><%=intl._("2 hop tunnel (high anonymity, high latency)")%></option>

View File

@@ -233,7 +233,7 @@ input.default { width: 1px; height: 1px; visibility: hidden; }
<%=intl._("Length")%>(<span class="accessKey">t</span>):
</label>
<select id="tunnelDepth" name="tunnelDepth" title="Length of each Tunnel" class="selectbox">
<% int tunnelDepth = editBean.getTunnelDepth(curTunnel, 2);
<% int tunnelDepth = editBean.getTunnelDepth(curTunnel, 3);
%><option value="0"<%=(tunnelDepth == 0 ? " selected=\"selected\"" : "") %>><%=intl._("0 hop tunnel (low anonymity, low latency)")%></option>
<option value="1"<%=(tunnelDepth == 1 ? " selected=\"selected\"" : "") %>><%=intl._("1 hop tunnel (medium anonymity, medium latency)")%></option>
<option value="2"<%=(tunnelDepth == 2 ? " selected=\"selected\"" : "") %>><%=intl._("2 hop tunnel (high anonymity, high latency)")%></option>

View File

@@ -107,7 +107,7 @@
%>
<div class="nameField rowItem">
<label><%=intl._("Name")%>:</label>
<span class="text"><a href="edit?tunnel=<%=curServer%>" title="Edit Server Tunnel Settings for <%=indexBean.getTunnelName(curServer)%>" target="_top"><%=indexBean.getTunnelName(curServer)%></a></span>
<span class="text"><a href="edit?tunnel=<%=curServer%>" title="Edit Server Tunnel Settings for <%=indexBean.getTunnelName(curServer)%>"><%=indexBean.getTunnelName(curServer)%></a></span>
</div>
<div class="previewField rowItem">
<label><%=intl._("Points at")%>:</label>

View File

@@ -471,7 +471,7 @@
<%=intl._("The wizard will set reasonably sensible default values for these, but you can view and/or edit these by clicking on the tunnel's name in the main I2PTunnel page.")%>
</p>
<input type="hidden" name="tunnelDepth" value="2" />
<input type="hidden" name="tunnelDepth" value="3" />
<input type="hidden" name="tunnelVariance" value="0" />
<input type="hidden" name="tunnelQuantity" value="2" />
<input type="hidden" name="tunnelBackupQuantity" value="0" />

View File

@@ -1,5 +1,5 @@
Apache Tomcat
Copyright 1999-2012 The Apache Software Foundation
Copyright 1999-2013 The Apache Software Foundation
This product includes software developed by
The Apache Software Foundation (http://www.apache.org/).

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.10.v20130312" />
<property name="jetty.ver" value="7.6.11.v20130520" />
<property name="jetty.base" value="jetty-distribution-${jetty.ver}" />
<property name="jetty.sha1" value="8c0ff0ad83756de118f5af71b88ca9c78ebf6420" />
<property name="jetty.sha1" value="d32ee389ed711a0655de0432810b75b57ad3e500" />
<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,434 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package net.i2p.jetty;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ConcurrentMap;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpHeaders;
import org.eclipse.jetty.security.SecurityHandler;
import org.eclipse.jetty.security.ServerAuthException;
import org.eclipse.jetty.security.UserAuthentication;
import org.eclipse.jetty.security.authentication.DeferredAuthentication;
import org.eclipse.jetty.security.authentication.DigestAuthenticator;
import org.eclipse.jetty.server.Authentication;
import org.eclipse.jetty.server.Authentication.User;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.UserIdentity;
import org.eclipse.jetty.util.B64Code;
import org.eclipse.jetty.util.QuotedStringTokenizer;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.security.Constraint;
import org.eclipse.jetty.util.security.Credential;
/**
* I2P fixes for out-of-order nonce counts.
* Based on DigestAuthenticator in Jetty 7.6.10.
* Includes the nonce count verification code from Tomcat 7.0.35.
* ref: http://jira.codehaus.org/browse/JETTY-1468 which was closed not-a-bug.
* ref: https://bugs.eclipse.org/bugs/show_bug.cgi?id=336443 in which the
* Jetty implementation was introduced.
*
* @since 0.9.6
*
* @version $Rev: 4793 $ $Date: 2009-03-19 00:00:01 +0100 (Thu, 19 Mar 2009) $
*
* The nonce max age in ms can be set with the {@link SecurityHandler#setInitParameter(String, String)}
* using the name "maxNonceAge"
*/
public class I2PDigestAuthenticator extends DigestAuthenticator
{
// shadows super
private static final Logger LOG = Log.getLogger(I2PDigestAuthenticator.class);
SecureRandom _random = new SecureRandom();
// shadows super
private long _maxNonceAgeMs = 60*60*1000L;
private ConcurrentMap<String, Nonce> _nonceCount = new ConcurrentHashMap<String, Nonce>();
// shadows super
private Queue<Nonce> _nonceQueue = new ConcurrentLinkedQueue<Nonce>();
/*
* Shadows super
*
* Contains code from Tomcat 7.0.35 DigestAuthenticator.NonceInfo
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
private static class Nonce
{
final String _nonce;
final long _ts;
private volatile boolean seen[];
private volatile int offset;
private volatile int count = 0;
private static final int seenWindowSize = 100;
public Nonce(String nonce, long ts)
{
_nonce=nonce;
_ts=ts;
seen = new boolean[seenWindowSize];
offset = seenWindowSize / 2;
}
public synchronized boolean nonceCountValid(long nonceCount) {
if ((count - offset) >= nonceCount ||
(nonceCount > count - offset + seen.length)) {
return false;
}
int checkIndex = (int) ((nonceCount + offset) % seen.length);
if (seen[checkIndex]) {
return false;
} else {
seen[checkIndex] = true;
seen[count % seen.length] = false;
count++;
return true;
}
}
}
/* ------------------------------------------------------------ */
public I2PDigestAuthenticator()
{
super();
}
/* ------------------------------------------------------------ */
/**
* Store local copy since field in super is private
*/
@Override
public synchronized void setMaxNonceAge(long maxNonceAgeInMillis)
{
super.setMaxNonceAge(maxNonceAgeInMillis);
_maxNonceAgeMs = maxNonceAgeInMillis;
}
/* ------------------------------------------------------------ */
/**
* No changes from super
*/
@Override
public Authentication validateRequest(ServletRequest req, ServletResponse res, boolean mandatory) throws ServerAuthException
{
if (!mandatory)
return new DeferredAuthentication(this);
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)res;
String credentials = request.getHeader(HttpHeaders.AUTHORIZATION);
try
{
boolean stale = false;
if (credentials != null)
{
if (LOG.isDebugEnabled())
LOG.debug("Credentials: " + credentials);
QuotedStringTokenizer tokenizer = new QuotedStringTokenizer(credentials, "=, ", true, false);
final Digest digest = new Digest(request.getMethod());
String last = null;
String name = null;
while (tokenizer.hasMoreTokens())
{
String tok = tokenizer.nextToken();
char c = (tok.length() == 1) ? tok.charAt(0) : '\0';
switch (c)
{
case '=':
name = last;
last = tok;
break;
case ',':
name = null;
break;
case ' ':
break;
default:
last = tok;
if (name != null)
{
if ("username".equalsIgnoreCase(name))
digest.username = tok;
else if ("realm".equalsIgnoreCase(name))
digest.realm = tok;
else if ("nonce".equalsIgnoreCase(name))
digest.nonce = tok;
else if ("nc".equalsIgnoreCase(name))
digest.nc = tok;
else if ("cnonce".equalsIgnoreCase(name))
digest.cnonce = tok;
else if ("qop".equalsIgnoreCase(name))
digest.qop = tok;
else if ("uri".equalsIgnoreCase(name))
digest.uri = tok;
else if ("response".equalsIgnoreCase(name))
digest.response = tok;
name=null;
}
}
}
int n = checkNonce(digest,(Request)request);
if (n > 0)
{
UserIdentity user = _loginService.login(digest.username,digest);
if (user!=null)
{
renewSession(request,response);
return new UserAuthentication(getAuthMethod(),user);
}
}
else if (n == 0)
stale = true;
}
if (!DeferredAuthentication.isDeferred(response))
{
String domain = request.getContextPath();
if (domain == null)
domain = "/";
response.setHeader(HttpHeaders.WWW_AUTHENTICATE, "Digest realm=\"" + _loginService.getName()
+ "\", domain=\""
+ domain
+ "\", nonce=\""
+ newNonce((Request)request)
+ "\", algorithm=MD5, qop=\"auth\","
+ " stale=" + stale);
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
return Authentication.SEND_CONTINUE;
}
return Authentication.UNAUTHENTICATED;
}
catch (IOException e)
{
throw new ServerAuthException(e);
}
}
/* ------------------------------------------------------------ */
/**
* No changes from super
*/
@Override
public String newNonce(Request request)
{
Nonce nonce;
do
{
byte[] nounce = new byte[24];
_random.nextBytes(nounce);
nonce = new Nonce(new String(B64Code.encode(nounce)),request.getTimeStamp());
}
while (_nonceCount.putIfAbsent(nonce._nonce,nonce)!=null);
_nonceQueue.add(nonce);
return nonce._nonce;
}
/**
* @param nstring nonce to check
* @param request
* @return -1 for a bad nonce, 0 for a stale none, 1 for a good nonce
*/
/* ------------------------------------------------------------ */
/**
* Contains fixes
*/
private int checkNonce(Digest digest, Request request)
{
// firstly let's expire old nonces
long expired;
synchronized (this)
{
expired = request.getTimeStamp()-_maxNonceAgeMs;
}
Nonce nonce=_nonceQueue.peek();
while (nonce!=null && nonce._ts<expired)
{
_nonceQueue.remove(nonce);
_nonceCount.remove(nonce._nonce);
nonce=_nonceQueue.peek();
}
try
{
nonce = _nonceCount.get(digest.nonce);
if (nonce==null)
return 0;
long count = Long.parseLong(digest.nc,16);
if (count>Integer.MAX_VALUE)
return 0;
if (!nonce.nonceCountValid(count)) {
return -1;
}
return 1;
}
catch (Exception e)
{
LOG.ignore(e);
}
return -1;
}
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/**
* Shadows super.
* No changes from super
*/
private static class Digest extends Credential
{
private static final long serialVersionUID = -2484639019549527724L;
final String method;
String username = "";
String realm = "";
String nonce = "";
String nc = "";
String cnonce = "";
String qop = "";
String uri = "";
String response = "";
/* ------------------------------------------------------------ */
Digest(String m)
{
method = m;
}
/* ------------------------------------------------------------ */
@Override
public boolean check(Object credentials)
{
if (credentials instanceof char[])
credentials=new String((char[])credentials);
String password = (credentials instanceof String) ? (String) credentials : credentials.toString();
try
{
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] ha1;
if (credentials instanceof Credential.MD5)
{
// Credentials are already a MD5 digest - assume it's in
// form user:realm:password (we have no way to know since
// it's a digest, alright?)
ha1 = ((Credential.MD5) credentials).getDigest();
}
else
{
// calc A1 digest
md.update(username.getBytes(StringUtil.__ISO_8859_1));
md.update((byte) ':');
md.update(realm.getBytes(StringUtil.__ISO_8859_1));
md.update((byte) ':');
md.update(password.getBytes(StringUtil.__ISO_8859_1));
ha1 = md.digest();
}
// calc A2 digest
md.reset();
md.update(method.getBytes(StringUtil.__ISO_8859_1));
md.update((byte) ':');
md.update(uri.getBytes(StringUtil.__ISO_8859_1));
byte[] ha2 = md.digest();
// calc digest
// request-digest = <"> < KD ( H(A1), unq(nonce-value) ":"
// nc-value ":" unq(cnonce-value) ":" unq(qop-value) ":" H(A2) )
// <">
// request-digest = <"> < KD ( H(A1), unq(nonce-value) ":" H(A2)
// ) > <">
md.update(TypeUtil.toString(ha1, 16).getBytes(StringUtil.__ISO_8859_1));
md.update((byte) ':');
md.update(nonce.getBytes(StringUtil.__ISO_8859_1));
md.update((byte) ':');
md.update(nc.getBytes(StringUtil.__ISO_8859_1));
md.update((byte) ':');
md.update(cnonce.getBytes(StringUtil.__ISO_8859_1));
md.update((byte) ':');
md.update(qop.getBytes(StringUtil.__ISO_8859_1));
md.update((byte) ':');
md.update(TypeUtil.toString(ha2, 16).getBytes(StringUtil.__ISO_8859_1));
byte[] digest = md.digest();
// check digest
return (TypeUtil.toString(digest, 16).equalsIgnoreCase(response));
}
catch (Exception e)
{
LOG.warn(e);
}
return false;
}
public String toString()
{
return username + "," + response;
}
}
}

View File

@@ -70,7 +70,6 @@ public class ConsoleUpdateManager implements UpdateManager {
/** downloaded AND installed */
private final Map<UpdateItem, Version> _installed;
private static final DecimalFormat _pct = new DecimalFormat("0.0%");
private static final VersionComparator _versionComparator = new VersionComparator();
private volatile String _status;
@@ -1289,7 +1288,7 @@ public class ConsoleUpdateManager implements UpdateManager {
}
public int compareTo(Version r) {
return _versionComparator.compare(version, r.version);
return VersionComparator.comp(version, r.version);
}
@Override

View File

@@ -252,7 +252,7 @@ class PluginUpdateRunner extends UpdateRunner {
String minVersion = ConfigClientsHelper.stripHTML(props, "min-i2p-version");
if (minVersion != null &&
(new VersionComparator()).compare(CoreVersion.VERSION, minVersion) < 0) {
VersionComparator.comp(CoreVersion.VERSION, minVersion) < 0) {
to.delete();
statusDone("<b>" + _("This plugin requires I2P version {0} or higher", minVersion) + "</b>");
return;
@@ -260,7 +260,7 @@ class PluginUpdateRunner extends UpdateRunner {
minVersion = ConfigClientsHelper.stripHTML(props, "min-java-version");
if (minVersion != null &&
(new VersionComparator()).compare(System.getProperty("java.version"), minVersion) < 0) {
VersionComparator.comp(System.getProperty("java.version"), minVersion) < 0) {
to.delete();
statusDone("<b>" + _("This plugin requires Java version {0} or higher", minVersion) + "</b>");
return;
@@ -295,21 +295,21 @@ class PluginUpdateRunner extends UpdateRunner {
}
String oldVersion = oldProps.getProperty("version");
if (oldVersion == null ||
(new VersionComparator()).compare(oldVersion, version) >= 0) {
VersionComparator.comp(oldVersion, version) >= 0) {
to.delete();
statusDone("<b>" + _("Downloaded plugin version {0} is not newer than installed plugin", version) + "</b>");
return;
}
minVersion = ConfigClientsHelper.stripHTML(props, "min-installed-version");
if (minVersion != null &&
(new VersionComparator()).compare(minVersion, oldVersion) > 0) {
VersionComparator.comp(minVersion, oldVersion) > 0) {
to.delete();
statusDone("<b>" + _("Plugin update requires installed plugin version {0} or higher", minVersion) + "</b>");
return;
}
String maxVersion = ConfigClientsHelper.stripHTML(props, "max-installed-version");
if (maxVersion != null &&
(new VersionComparator()).compare(maxVersion, oldVersion) < 0) {
VersionComparator.comp(maxVersion, oldVersion) < 0) {
to.delete();
statusDone("<b>" + _("Plugin update requires installed plugin version {0} or lower", maxVersion) + "</b>");
return;
@@ -317,14 +317,14 @@ class PluginUpdateRunner extends UpdateRunner {
oldVersion = LogsHelper.jettyVersion();
minVersion = ConfigClientsHelper.stripHTML(props, "min-jetty-version");
if (minVersion != null &&
(new VersionComparator()).compare(minVersion, oldVersion) > 0) {
VersionComparator.comp(minVersion, oldVersion) > 0) {
to.delete();
statusDone("<b>" + _("Plugin requires Jetty version {0} or higher", minVersion) + "</b>");
return;
}
maxVersion = ConfigClientsHelper.stripHTML(props, "max-jetty-version");
if (maxVersion != null &&
(new VersionComparator()).compare(maxVersion, oldVersion) < 0) {
VersionComparator.comp(maxVersion, oldVersion) < 0) {
to.delete();
statusDone("<b>" + _("Plugin requires Jetty version {0} or lower", maxVersion) + "</b>");
return;

View File

@@ -184,7 +184,7 @@ class UpdateRunner extends I2PAppThread implements UpdateTask, EepGet.StatusList
if (_isPartial) {
// Compare version with what we have now
String newVersion = TrustedUpdate.getVersionString(new ByteArrayInputStream(_baos.toByteArray()));
boolean newer = (new VersionComparator()).compare(newVersion, RouterVersion.VERSION) > 0;
boolean newer = VersionComparator.comp(newVersion, RouterVersion.VERSION) > 0;
if (newer) {
_newVersion = newVersion;
} else {

View File

@@ -37,7 +37,7 @@ public class CSSHelper extends HelperBase {
public String getTheme(String userAgent) {
String url = BASE_THEME_PATH;
if (userAgent != null && userAgent.contains("MSIE")) {
if (userAgent != null && (userAgent.contains("MSIE") && !userAgent.contains("Trident/6"))) {
url += FORCE + "/";
} else {
// This is the first thing to use _context on most pages

View File

@@ -144,7 +144,7 @@ public class ConfigServiceHandler extends FormHandler {
if (ctx.hasWrapper() && _wrapperListener == null &&
!SystemVersion.isWindows()) {
String wv = System.getProperty("wrapper.version");
if (wv != null && (new VersionComparator()).compare(wv, LISTENER_AVAILABLE) >= 0) {
if (wv != null && VersionComparator.comp(wv, LISTENER_AVAILABLE) >= 0) {
try {
_wrapperListener = new WrapperListener(ctx);
} catch (Throwable t) {}

View File

@@ -14,8 +14,8 @@ public class ConfigTunnelsHelper extends HelperBase {
private static final String HOPS = ngettext("1 hop", "{0} hops");
private static final String TUNNELS = ngettext("1 tunnel", "{0} tunnels");
public ConfigTunnelsHelper() {}
private static final String PROP_ADVANCED = "routerconsole.advanced";
public String getForm() {
StringBuilder buf = new StringBuilder(1024);
// HTML: <input> cannot be inside a <table>
@@ -58,14 +58,19 @@ public class ConfigTunnelsHelper extends HelperBase {
private static final int WARN_LENGTH = 4;
private static final int MAX_LENGTH = 4;
private static final int MAX_ADVANCED_LENGTH = 7;
private static final int WARN_QUANTITY = 5;
private static final int MAX_QUANTITY = 6;
private static final int MAX_ADVANCED_QUANTITY = 16;
private static final int MAX_BACKUP_QUANTITY = 3;
private static final int MAX_ADVANCED_BACKUP_QUANTITY = 16;
private static final int MAX_VARIANCE = 2;
private static final int MIN_NEG_VARIANCE = -1;
private void renderForm(StringBuilder buf, int index, String prefix, String name, TunnelPoolSettings in, TunnelPoolSettings out) {
boolean advanced = _context.getBooleanProperty(PROP_ADVANCED);
buf.append("<tr><th colspan=\"3\"><a name=\"").append(prefix).append("\">");
buf.append(name).append("</a></th></tr>\n");
if (in.getLength() <= 0 ||
@@ -90,18 +95,19 @@ public class ConfigTunnelsHelper extends HelperBase {
// buf.append("<tr><th></th><th>Inbound</th><th>Outbound</th></tr>\n");
// tunnel depth
int maxLength = advanced ? MAX_ADVANCED_LENGTH : MAX_LENGTH;
buf.append("<tr><td align=\"right\" class=\"mediumtags\">" + _("Length") + ":</td>\n");
buf.append("<td align=\"center\"><select name=\"").append(index).append(".depthInbound\">\n");
int now = in.getLength();
renderOptions(buf, 0, MAX_LENGTH, now, "", HOP);
if (now > MAX_LENGTH)
renderOptions(buf, 0, maxLength, now, "", HOP);
if (now > maxLength)
renderOptions(buf, now, now, now, "", HOP);
buf.append("</select></td>\n");
buf.append("<td align=\"center\"><select name=\"").append(index).append(".depthOutbound\">\n");
now = out.getLength();
renderOptions(buf, 0, MAX_LENGTH, now, "", HOP);
if (now > MAX_LENGTH)
renderOptions(buf, 0, maxLength, now, "", HOP);
if (now > maxLength)
renderOptions(buf, now, now, now, "", HOP);
buf.append("</select></td>\n");
buf.append("</tr>\n");
@@ -131,35 +137,37 @@ public class ConfigTunnelsHelper extends HelperBase {
buf.append("</select></td>\n");
// tunnel quantity
int maxQuantity = advanced ? MAX_ADVANCED_QUANTITY : MAX_QUANTITY;
buf.append("<tr><td align=\"right\" class=\"mediumtags\">" + _("Quantity") + ":</td>\n");
buf.append("<td align=\"center\"><select name=\"").append(index).append(".quantityInbound\">\n");
now = in.getQuantity();
renderOptions(buf, 1, MAX_QUANTITY, now, "", TUNNEL);
if (now > MAX_QUANTITY)
renderOptions(buf, 1, maxQuantity, now, "", TUNNEL);
if (now > maxQuantity)
renderOptions(buf, now, now, now, "", TUNNEL);
buf.append("</select></td>\n");
buf.append("<td align=\"center\"><select name=\"").append(index).append(".quantityOutbound\">\n");
now = out.getQuantity();
renderOptions(buf, 1, MAX_QUANTITY, now, "", TUNNEL);
if (now > MAX_QUANTITY)
renderOptions(buf, 1, maxQuantity, now, "", TUNNEL);
if (now > maxQuantity)
renderOptions(buf, now, now, now, "", TUNNEL);
buf.append("</select></td>\n");
buf.append("</tr>\n");
// tunnel backup quantity
int maxBQuantity = advanced ? MAX_ADVANCED_BACKUP_QUANTITY : MAX_BACKUP_QUANTITY;
buf.append("<tr><td align=\"right\" class=\"mediumtags\">" + _("Backup quantity") + ":</td>\n");
buf.append("<td align=\"center\"><select name=\"").append(index).append(".backupInbound\">\n");
now = in.getBackupQuantity();
renderOptions(buf, 0, MAX_BACKUP_QUANTITY, now, "", TUNNEL);
if (now > MAX_BACKUP_QUANTITY)
renderOptions(buf, 0, maxBQuantity, now, "", TUNNEL);
if (now > maxBQuantity)
renderOptions(buf, now, now, now, "", TUNNEL);
buf.append("</select></td>\n");
buf.append("<td align=\"center\"><select name=\"").append(index).append(".backupOutbound\">\n");
now = out.getBackupQuantity();
renderOptions(buf, 0, MAX_BACKUP_QUANTITY, now, "", TUNNEL);
if (now > MAX_BACKUP_QUANTITY)
renderOptions(buf, 0, maxBQuantity, now, "", TUNNEL);
if (now > maxBQuantity)
renderOptions(buf, now, now, now, "", TUNNEL);
buf.append("</select></td>\n");
buf.append("</tr>\n");

View File

@@ -48,7 +48,7 @@ public class LogsHelper extends HelperBase {
File f = null;
if (ctx.hasWrapper()) {
String wv = System.getProperty("wrapper.version");
if (wv != null && (new VersionComparator()).compare(wv, LOCATION_AVAILABLE) >= 0) {
if (wv != null && VersionComparator.comp(wv, LOCATION_AVAILABLE) >= 0) {
try {
f = WrapperManager.getWrapperLogFile();
} catch (Throwable t) {}

View File

@@ -73,7 +73,7 @@ public class PluginStarter implements Runnable {
!NewsHelper.isUpdateInProgress()) {
String prev = _context.getProperty("router.previousVersion");
if (prev != null &&
(new VersionComparator()).compare(RouterVersion.VERSION, prev) > 0) {
VersionComparator.comp(RouterVersion.VERSION, prev) > 0) {
updateAll(_context, true);
}
}
@@ -236,7 +236,7 @@ public class PluginStarter implements Runnable {
String minVersion = ConfigClientsHelper.stripHTML(props, "min-i2p-version");
if (minVersion != null &&
(new VersionComparator()).compare(CoreVersion.VERSION, minVersion) < 0) {
VersionComparator.comp(CoreVersion.VERSION, minVersion) < 0) {
String foo = "Plugin " + appName + " requires I2P version " + minVersion + " or higher";
log.error(foo);
disablePlugin(appName);
@@ -245,7 +245,7 @@ public class PluginStarter implements Runnable {
minVersion = ConfigClientsHelper.stripHTML(props, "min-java-version");
if (minVersion != null &&
(new VersionComparator()).compare(System.getProperty("java.version"), minVersion) < 0) {
VersionComparator.comp(System.getProperty("java.version"), minVersion) < 0) {
String foo = "Plugin " + appName + " requires Java version " + minVersion + " or higher";
log.error(foo);
disablePlugin(appName);
@@ -255,7 +255,7 @@ public class PluginStarter implements Runnable {
String jVersion = LogsHelper.jettyVersion();
minVersion = ConfigClientsHelper.stripHTML(props, "min-jetty-version");
if (minVersion != null &&
(new VersionComparator()).compare(minVersion, jVersion) > 0) {
VersionComparator.comp(minVersion, jVersion) > 0) {
String foo = "Plugin " + appName + " requires Jetty version " + minVersion + " or higher";
log.error(foo);
disablePlugin(appName);
@@ -264,7 +264,7 @@ public class PluginStarter implements Runnable {
String maxVersion = ConfigClientsHelper.stripHTML(props, "max-jetty-version");
if (maxVersion != null &&
(new VersionComparator()).compare(maxVersion, jVersion) < 0) {
VersionComparator.comp(maxVersion, jVersion) < 0) {
String foo = "Plugin " + appName + " requires Jetty version " + maxVersion + " or lower";
log.error(foo);
disablePlugin(appName);

View File

@@ -29,7 +29,6 @@ import static net.i2p.app.ClientAppState.*;
import net.i2p.apps.systray.SysTray;
import net.i2p.data.Base32;
import net.i2p.data.DataHelper;
import net.i2p.jetty.I2PDigestAuthenticator;
import net.i2p.jetty.I2PLogger;
import net.i2p.router.RouterContext;
import net.i2p.router.update.ConsoleUpdateManager;
@@ -106,7 +105,7 @@ public class RouterConsoleRunner implements RouterApp {
private static final String DEFAULT_WEBAPP_CONFIG_FILENAME = "webapps.config";
// Jetty Auth
private static final DigestAuthenticator authenticator = new I2PDigestAuthenticator();
private static final DigestAuthenticator authenticator = new DigestAuthenticator();
static {
// default changed from 0 (forever) in Jetty 6 to 60*1000 ms in Jetty 7
authenticator.setMaxNonceAge(7*24*60*60*1000L);

View File

@@ -36,7 +36,7 @@ input.default {
<input type="hidden" name="action" value="blah" >
<%
String userAgent = request.getHeader("User-Agent");
if (userAgent == null || !userAgent.contains("MSIE")) {
if (userAgent == null || userAgent.contains("Trident/6") || !userAgent.contains("MSIE")) {
%>
<jsp:getProperty name="uihelper" property="settings" />
<% } else { %>

View File

@@ -1,6 +1,6 @@
package gnu.crypto.prng;
import java.util.HashMap;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.LinkedBlockingQueue;
@@ -77,8 +77,7 @@ public class AsyncFortunaStandalone extends FortunaStandalone implements Runnabl
/** the seed is only propogated once the prng is started with startup() */
@Override
public void seed(byte val[]) {
Map props = new HashMap(1);
props.put(SEED, val);
Map props = Collections.singletonMap(SEED, val);
init(props);
//fillBlock();
}

View File

@@ -58,10 +58,10 @@ public abstract class BasePRNGStandalone implements IRandomStandalone {
protected final String name;
/** Indicate if this instance has already been initialised or not. */
protected boolean initialised;
protected volatile boolean initialised;
/** A temporary buffer to serve random bytes. */
protected byte[] buffer;
protected volatile byte[] buffer;
/** The index into buffer of where the next byte will come from. */
protected int ndx;

View File

@@ -48,7 +48,7 @@ import java.io.Serializable;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Collections;
import java.util.Map;
import net.i2p.crypto.CryptixAESKeyCache;
@@ -131,8 +131,7 @@ public class FortunaStandalone extends BasePRNGStandalone implements Serializabl
}
public void seed(byte val[]) {
Map props = new HashMap(1);
props.put(SEED, val);
Map props = Collections.singletonMap(SEED, val);
init(props);
fillBlock();
}

View File

@@ -222,7 +222,10 @@ public interface I2PSession {
public Destination lookupDest(Hash h, long maxWait) throws I2PSessionException;
/**
* Pass updated options to the router.
* Does not remove properties previously present but missing from this options parameter.
* Fails silently if session is not connected.
*
* @param options non-null
* @since 0.8.4
*/

View File

@@ -150,11 +150,20 @@ public class SessionKeyManager {
}
/**
* Accept the given tags and associate them with the given key for decryption
*
* Accept the given tags and associate them with the given key for decryption,
* with the default expiration.
*/
public void tagsReceived(SessionKey key, Set<SessionTag> sessionTags) { // nop
}
public void tagsReceived(SessionKey key, Set<SessionTag> sessionTags) {}
/**
* Accept the given tags and associate them with the given key for decryption,
* with specified expiration.
*
* @param sessionTags modifiable; NOT copied
* @param expire time from now
* @since 0.9.7
*/
public void tagsReceived(SessionKey key, Set<SessionTag> sessionTags, long expire) {}
/**
* Determine if we have received a session key associated with the given session tag,

View File

@@ -89,9 +89,8 @@ public class TransientSessionKeyManager extends SessionKeyManager {
private final int _lowThreshold;
/**
* Let session tags sit around for this long before expiring them. We can now have such a large
* value since there is the persistent session key manager. This value is for outbound tags -
* inbound tags are managed by SESSION_LIFETIME_MAX_MS
* Let outbound session tags sit around for this long before expiring them.
* Inbound tag expiration is set by SESSION_LIFETIME_MAX_MS
*/
private final static long SESSION_TAG_DURATION_MS = 12 * 60 * 1000;
@@ -99,6 +98,8 @@ public class TransientSessionKeyManager extends SessionKeyManager {
* Keep unused inbound session tags around for this long (a few minutes longer than
* session tags are used on the outbound side so that no reasonable network lag
* can cause failed decrypts)
*
* This is also the max idle time for an outbound session.
*/
private final static long SESSION_LIFETIME_MAX_MS = SESSION_TAG_DURATION_MS + 3 * 60 * 1000;
@@ -499,11 +500,24 @@ public class TransientSessionKeyManager extends SessionKeyManager {
/**
* Accept the given tags and associate them with the given key for decryption
*
* @param sessionTags modifiable; NOT copied
*/
@Override
public void tagsReceived(SessionKey key, Set<SessionTag> sessionTags) {
int overage = 0;
TagSet tagSet = new TagSet(sessionTags, key, _context.clock().now(), _rcvTagSetID.incrementAndGet());
tagsReceived(key, sessionTags, SESSION_LIFETIME_MAX_MS);
}
/**
* Accept the given tags and associate them with the given key for decryption
*
* @param sessionTags modifiable; NOT copied
* @param expire time from now
* @since 0.9.7
*/
@Override
public void tagsReceived(SessionKey key, Set<SessionTag> sessionTags, long expire) {
TagSet tagSet = new TagSet(sessionTags, key, _context.clock().now() + expire,
_rcvTagSetID.incrementAndGet());
if (_log.shouldLog(Log.INFO))
_log.info("Received " + tagSet);
TagSet old = null;
@@ -513,7 +527,6 @@ public class TransientSessionKeyManager extends SessionKeyManager {
//if (_log.shouldLog(Log.DEBUG))
// _log.debug("Receiving tag " + tag + " in tagSet: " + tagSet);
old = _inboundTagSets.put(tag, tagSet);
overage = _inboundTagSets.size() - MAX_INBOUND_SESSION_TAGS;
if (old != null) {
if (!old.getAssociatedKey().equals(tagSet.getAssociatedKey())) {
_inboundTagSets.remove(tag);
@@ -546,6 +559,7 @@ public class TransientSessionKeyManager extends SessionKeyManager {
}
}
int overage = _inboundTagSets.size() - MAX_INBOUND_SESSION_TAGS;
if (overage > 0)
clearExcess(overage);
@@ -573,25 +587,23 @@ public class TransientSessionKeyManager extends SessionKeyManager {
_log.log(Log.CRIT, "TOO MANY SESSION TAGS! Starting cleanup, overage = " + overage);
List<TagSet> removed = new ArrayList(toRemove);
synchronized (_inboundTagSets) {
for (Iterator<TagSet> iter = _inboundTagSets.values().iterator(); iter.hasNext(); ) {
TagSet set = iter.next();
for (TagSet set : _inboundTagSets.values()) {
int size = set.getTags().size();
if (size > 1000)
absurd++;
if (size > 100)
large++;
if (now - set.getDate() > SESSION_LIFETIME_MAX_MS)
if (now >= set.getDate())
old++;
else if (now - set.getDate() < 1*60*1000)
else if (set.getDate() - now > 10*60*1000)
recent++;
if ((removed.size() < (toRemove)) || (now - set.getDate() > SESSION_LIFETIME_MAX_MS))
if ((removed.size() < (toRemove)) || (now >= set.getDate()))
removed.add(set);
}
for (int i = 0; i < removed.size(); i++) {
TagSet cur = removed.get(i);
for (Iterator<SessionTag> iter = cur.getTags().iterator(); iter.hasNext(); ) {
SessionTag tag = iter.next();
for (SessionTag tag : cur.getTags()) {
_inboundTagSets.remove(tag);
tags++;
}
@@ -616,21 +628,21 @@ public class TransientSessionKeyManager extends SessionKeyManager {
*/
@Override
public SessionKey consumeTag(SessionTag tag) {
//if (false) aggressiveExpire();
TagSet tagSet;
synchronized (_inboundTagSets) {
TagSet tagSet = _inboundTagSets.remove(tag);
tagSet = _inboundTagSets.remove(tag);
if (tagSet == null) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Cannot consume IB " + tag + " as it is not known");
return null;
}
tagSet.consume(tag);
SessionKey key = tagSet.getAssociatedKey();
if (_log.shouldLog(Log.DEBUG))
_log.debug("IB Tag consumed: " + tag + " from: " + tagSet);
return key;
}
SessionKey key = tagSet.getAssociatedKey();
if (_log.shouldLog(Log.DEBUG))
_log.debug("IB Tag consumed: " + tag + " from: " + tagSet);
return key;
}
private OutboundSession getSession(PublicKey target) {
@@ -660,44 +672,28 @@ public class TransientSessionKeyManager extends SessionKeyManager {
/**
* Aggressively expire inbound tag sets and outbound sessions
*
* @return number of tag sets expired
* @return number of tag sets expired (bogus as it overcounts inbound)
*/
private int aggressiveExpire() {
int removed = 0;
int remaining = 0;
long now = _context.clock().now();
StringBuilder buf = null;
//StringBuilder bufSummary = null;
if (_log.shouldLog(Log.DEBUG)) {
buf = new StringBuilder(128);
buf.append("Expiring inbound: ");
//bufSummary = new StringBuilder(1024);
}
synchronized (_inboundTagSets) {
for (Iterator<SessionTag> iter = _inboundTagSets.keySet().iterator(); iter.hasNext();) {
SessionTag tag = iter.next();
TagSet ts = _inboundTagSets.get(tag);
long age = now - ts.getDate();
if (age > SESSION_LIFETIME_MAX_MS) {
//if (ts.getDate() < now - SESSION_LIFETIME_MAX_MS) {
for (Iterator<TagSet> iter = _inboundTagSets.values().iterator(); iter.hasNext();) {
TagSet ts = iter.next();
// for inbound tagsets, getDate() is the expire time
if (ts.getDate() <= now) {
iter.remove();
// bug, this counts inbound tags, not tag sets
removed++;
if (buf != null)
buf.append(tag).append(" @ age ").append(DataHelper.formatDuration(age));
//} else if (false && (bufSummary != null) ) {
// bufSummary.append("\nTagSet: " + ts + ", key: " + ts.getAssociatedKey()
// + ": tag: " + tag);
}
}
remaining = _inboundTagSets.size();
}
_context.statManager().addRateData("crypto.sessionTagsRemaining", remaining, 0);
if ( (buf != null) && (removed > 0) )
_log.debug(buf.toString());
//if (bufSummary != null)
// _log.debug("Cleaning up with remaining: " + bufSummary.toString());
//_log.warn("Expiring tags: [" + tagsToDrop + "]");
if (removed > 0 && _log.shouldLog(Log.DEBUG))
_log.debug("Expired inbound: " + removed);
synchronized (_outboundSessions) {
for (Iterator<OutboundSession> iter = _outboundSessions.values().iterator(); iter.hasNext();) {
@@ -722,10 +718,12 @@ public class TransientSessionKeyManager extends SessionKeyManager {
Set<TagSet> inbound = getInboundTagSets();
Map<SessionKey, Set<TagSet>> inboundSets = new HashMap(inbound.size());
// Build a map of the inbound tag sets, grouped by SessionKey
for (Iterator<TagSet> iter = inbound.iterator(); iter.hasNext();) {
TagSet ts = iter.next();
if (!inboundSets.containsKey(ts.getAssociatedKey())) inboundSets.put(ts.getAssociatedKey(), new HashSet());
for (TagSet ts : inbound) {
Set<TagSet> sets = inboundSets.get(ts.getAssociatedKey());
if (sets == null) {
sets = new HashSet();
inboundSets.put(ts.getAssociatedKey(), sets);
}
sets.add(ts);
}
int total = 0;
@@ -741,8 +739,12 @@ public class TransientSessionKeyManager extends SessionKeyManager {
TagSet ts = siter.next();
int size = ts.getTags().size();
total += size;
buf.append("<li><b>ID: ").append(ts.getID())
.append(" Received:</b> ").append(DataHelper.formatDuration2(now - ts.getDate())).append(" ago with ");
buf.append("<li><b>ID: ").append(ts.getID());
long expires = ts.getDate() - now;
if (expires > 0)
buf.append(" Expires in:</b> ").append(DataHelper.formatDuration2(expires)).append(" with ");
else
buf.append(" Expired:</b> ").append(DataHelper.formatDuration2(0 - expires)).append(" ago with ");
buf.append(size).append('/').append(ts.getOriginalSize()).append(" tags remaining</li>");
}
buf.append("</ul></td></tr>\n");
@@ -802,7 +804,10 @@ public class TransientSessionKeyManager extends SessionKeyManager {
*/
private static class TagSetComparator implements Comparator<TagSet> {
public int compare(TagSet l, TagSet r) {
return (int) (l.getDate() - r.getDate());
int rv = (int) (l.getDate() - r.getDate());
if (rv != 0)
return rv;
return l.hashCode() - r.hashCode();
}
}
@@ -1088,6 +1093,9 @@ public class TransientSessionKeyManager extends SessionKeyManager {
/** did we get an ack for this tagset? Only for outbound tagsets */
private boolean _acked;
/**
* @param date For inbound: when the TagSet will expire; for outbound: creation time
*/
public TagSet(Set<SessionTag> tags, SessionKey key, long date, int id) {
if (key == null) throw new IllegalArgumentException("Missing key");
if (tags == null) throw new IllegalArgumentException("Missing tags");
@@ -1104,7 +1112,9 @@ public class TransientSessionKeyManager extends SessionKeyManager {
//}
}
/** when the tag set was created */
/**
* For inbound: when the TagSet will expire; for outbound: creation time
*/
public long getDate() {
return _date;
}
@@ -1135,23 +1145,29 @@ public class TransientSessionKeyManager extends SessionKeyManager {
}
/**
* Let's do this without counting the elements first.
* For outbound only.
* Caller must synch.
* @return a tag or null
*/
public SessionTag consumeNext() {
SessionTag first;
try {
first = _sessionTags.iterator().next();
} catch (NoSuchElementException nsee) {
Iterator<SessionTag> iter = _sessionTags.iterator();
if (!iter.hasNext())
return null;
}
_sessionTags.remove(first);
SessionTag first = iter.next();
iter.remove();
return first;
}
//public Exception getCreatedBy() { return _createdBy; }
/**
* For outbound only.
*/
public void setAcked() { _acked = true; }
/**
* For outbound only.
*/
public boolean getAcked() { return _acked; }
/****** this will return a dup if two in the same ms, so just use java

View File

@@ -302,7 +302,7 @@ riCe6OlAEiNpcc6mMyIYYWFICbrDFTrDR3wXqwc/Jkcx6L5VVWoagpSzbo3yGhc=
* version, otherwise <code>false</code>.
*/
public static final boolean needsUpdate(String currentVersion, String newVersion) {
return (new VersionComparator()).compare(currentVersion, newVersion) < 0;
return VersionComparator.comp(currentVersion, newVersion) < 0;
}
/** @return success */

View File

@@ -22,6 +22,7 @@ import java.util.StringTokenizer;
import net.i2p.I2PAppContext;
import net.i2p.data.Base64;
import net.i2p.data.ByteArray;
import net.i2p.data.DataHelper;
import net.i2p.util.InternalSocket;
@@ -1240,6 +1241,8 @@ public class EepGet {
protected class Gunzipper implements Runnable {
private final InputStream _inRaw;
private final OutputStream _out;
private static final int CACHE_SIZE = 8*1024;
private final ByteCache _cache = ByteCache.getInstance(8, CACHE_SIZE);
public Gunzipper(InputStream in, OutputStream out) {
_inRaw = in;
@@ -1247,13 +1250,14 @@ public class EepGet {
}
public void run() {
ReusableGZIPInputStream in = null;
ReusableGZIPInputStream in = ReusableGZIPInputStream.acquire();
ByteArray ba = null;
long written = 0;
try {
in = ReusableGZIPInputStream.acquire();
// blocking
in.initialize(_inRaw);
byte buf[] = new byte[8*1024];
ba = _cache.acquire();
byte buf[] = ba.getData();
int read = -1;
while ( (read = in.read(buf)) != -1) {
_out.write(buf, 0, read);
@@ -1269,8 +1273,9 @@ public class EepGet {
if (_out != null) try {
_out.close();
} catch (IOException ioe) {}
if (in != null)
ReusableGZIPInputStream.release(in);
ReusableGZIPInputStream.release(in);
if (ba != null)
_cache.release(ba);
}
}
}

View File

@@ -757,6 +757,9 @@ public class NativeBigInteger extends BigInteger {
else if (sCPUType.equals(JBIGI_OPTIMIZATION_COREI) && (!_is64) && ((_isKFreebsd) || (_isNetbsd) || (_isOpenbsd)))
// corei and core2 are identical on 32bit kfreebsd, openbsd, and netbsd
sAppend = JBIGI_OPTIMIZATION_CORE2;
else if (sCPUType.equals(JBIGI_OPTIMIZATION_PENTIUM2) && _isSunos && _isX86)
// pentium2 and pentium3 identical on X86 Solaris
sAppend = JBIGI_OPTIMIZATION_PENTIUM3;
else if (sCPUType.equals(JBIGI_OPTIMIZATION_VIAC32))
// viac32 and pentium3 identical
sAppend = JBIGI_OPTIMIZATION_PENTIUM3;

View File

@@ -56,7 +56,7 @@ public abstract class SystemVersion {
if (_isAndroid) {
_oneDotSix = _androidSDK >= 9;
} else {
_oneDotSix = (new VersionComparator()).compare(System.getProperty("java.version"), "1.6") >= 0;
_oneDotSix = VersionComparator.comp(System.getProperty("java.version"), "1.6") >= 0;
}
}

View File

@@ -11,9 +11,15 @@ import java.util.Comparator;
*/
public class VersionComparator implements Comparator<String> {
@Override
public int compare(String l, String r) {
return comp(l, r);
}
/**
* To avoid churning comparators
* @since 0.9.7
*/
public static int comp(String l, String r) {
if (l.equals(r))
return 0;

View File

@@ -139,8 +139,8 @@ Debian wrapper.config to try to prevent confusion.
}
showsetusermesg() {
- echo "`gettext 'Please edit i2prouter and set the variable RUN_AS_USER'`."
+ echo "`gettext 'Please edit /etc/default/i2p and set the variable RUN_AS_USER'`."
- echo "`gettext \"Please edit $0 and set the variable RUN_AS_USER\"`."
+ echo "`gettext "Please edit /etc/default/i2p and set the variable RUN_AS_USER"`."
}
checkifstartingasroot() {
@@ -148,12 +148,12 @@ Debian wrapper.config to try to prevent confusion.
echo "`gettext 'Running I2P as the root user is *not* recommended.'`"
showsetusermesg
echo
- echo "`gettext 'To run as root anyway, edit i2prouter and set ALLOW_ROOT=true.'`"
+ echo "`gettext 'To run as root anyway, edit /etc/default/i2p and set ALLOW_ROOT=true.'`"
- echo "`gettext \"To run as root anyway, edit $0 and set ALLOW_ROOT=true.\"`"
+ echo "`gettext \"To run as root anyway, edit /etc/default/i2p and set ALLOW_ROOT=true.\"`"
exit 1
fi
}
@@ -1858,24 +1806,9 @@
@@ -1858,23 +1806,9 @@
status
;;
@@ -174,13 +174,12 @@ Debian wrapper.config to try to prevent confusion.
-
- 'remove' | 'uninstall')
- removedaemon
- ;;
+ 'install' | 'remove' | 'uninstall')
+ echo "Use \"dpkg-reconfigure i2p\" to configure the initscript."
+ exit 1
;;
'dump')
checkUser "" "$COMMAND"
--- a/installer/resources/runplain.sh
+++ b/installer/resources/runplain.sh
@@ -11,8 +11,8 @@
@@ -325,8 +324,8 @@ Debian wrapper.config to try to prevent confusion.
msgstr "Falls gestartet, fordere einen Java Thread dump an"
#: ../i2prouter:1788
-msgid "Please edit i2prouter and set the variable RUN_AS_USER"
-msgstr "Bitte bearbeite i2prouter und setze die Variable RUN_AS_USER"
-msgid "Please edit $0 and set the variable RUN_AS_USER"
-msgstr "Bitte bearbeite $0 und setze die Variable RUN_AS_USER"
+msgid "Please edit /etc/default/i2p and set the variable RUN_AS_USER"
+msgstr "Bitte bearbeite /etc/default/i2p und setze die Variable RUN_AS_USER"
@@ -335,10 +334,10 @@ Debian wrapper.config to try to prevent confusion.
msgstr "I2P als root Benutzer auszuführen ist *nicht* empfehlenswert."
#: ../i2prouter:1796
-msgid "To run as root anyway, edit i2prouter and set ALLOW_ROOT=true."
-msgid "To run as root anyway, edit $0 and set ALLOW_ROOT=true."
+msgid "To run as root anyway, edit /etc/default/i2p and set ALLOW_ROOT=true."
msgstr ""
-"Um I2P trotzdem als root auszuführen bearbeite i2prouter und setze ALLOW_ROOT=true."
-"Um I2P trotzdem als root auszuführen bearbeite $0 und setze ALLOW_ROOT=true."
+"Um I2P trotzdem als root auszuführen bearbeite /etc/default/i2p und setze ALLOW_ROOT=true."
--- a/installer/resources/locale/po/messages_en.po
+++ b/installer/resources/locale/po/messages_en.po
@@ -346,7 +345,7 @@ Debian wrapper.config to try to prevent confusion.
msgstr ""
#: ../i2prouter:1788
-msgid "Please edit i2prouter and set the variable RUN_AS_USER"
-msgid "Please edit $0 and set the variable RUN_AS_USER"
+msgid "Please edit /etc/default/i2p and set the variable RUN_AS_USER"
msgstr ""
@@ -355,7 +354,7 @@ Debian wrapper.config to try to prevent confusion.
msgstr ""
#: ../i2prouter:1796
-msgid "To run as root anyway, edit i2prouter and set ALLOW_ROOT=true."
-msgid "To run as root anyway, edit $0 and set ALLOW_ROOT=true."
+msgid "To run as root anyway, edit /etc/default/i2p and set ALLOW_ROOT=true."
msgstr ""
--- a/installer/resources/locale/po/messages_fr.po
@@ -364,7 +363,7 @@ Debian wrapper.config to try to prevent confusion.
msgstr ""
#: ../i2prouter:1780
-msgid "Please edit i2prouter and set the variable RUN_AS_USER"
-msgid "Please edit $0 and set the variable RUN_AS_USER"
+msgid "Please edit /etc/default/i2p and set the variable RUN_AS_USER"
msgstr ""
@@ -373,7 +372,7 @@ Debian wrapper.config to try to prevent confusion.
"Faire fonctionner I2P en tant qu'utilisateur root n'est *pas* recommandé."
#: ../i2prouter:1788
-msgid "To run as root anyway, edit i2prouter and set ALLOW_ROOT=true."
-msgid "To run as root anyway, edit $0 and set ALLOW_ROOT=true."
+msgid "To run as root anyway, edit /etc/default/i2p and set ALLOW_ROOT=true."
msgstr ""
--- a/installer/resources/locale/po/messages_it.po
@@ -382,7 +381,7 @@ Debian wrapper.config to try to prevent confusion.
msgstr ""
#: ../i2prouter:1780
-msgid "Please edit i2prouter and set the variable RUN_AS_USER"
-msgid "Please edit $0 and set the variable RUN_AS_USER"
+msgid "Please edit /etc/default/i2p and set the variable RUN_AS_USER"
msgstr ""
@@ -391,7 +390,7 @@ Debian wrapper.config to try to prevent confusion.
msgstr ""
#: ../i2prouter:1788
-msgid "To run as root anyway, edit i2prouter and set ALLOW_ROOT=true."
-msgid "To run as root anyway, edit $0 and set ALLOW_ROOT=true."
+msgid "To run as root anyway, edit /etc/default/i2p and set ALLOW_ROOT=true."
msgstr ""
--- a/installer/resources/locale/po/messages_ru.po
@@ -400,7 +399,7 @@ Debian wrapper.config to try to prevent confusion.
msgstr ""
#: ../i2prouter:1780
-msgid "Please edit i2prouter and set the variable RUN_AS_USER"
-msgid "Please edit $0 and set the variable RUN_AS_USER"
+msgid "Please edit /etc/default/i2p and set the variable RUN_AS_USER"
msgstr ""
@@ -409,26 +408,6 @@ Debian wrapper.config to try to prevent confusion.
msgstr ""
#: ../i2prouter:1788
-msgid "To run as root anyway, edit i2prouter and set ALLOW_ROOT=true."
-msgid "To run as root anyway, edit $0 and set ALLOW_ROOT=true."
+msgid "To run as root anyway, edit /etc/default/i2p and set ALLOW_ROOT=true."
msgstr ""
--- a/installer/resources/locale/po/messages_sv.po
+++ b/installer/resources/locale/po/messages_sv.po
@@ -187,13 +187,13 @@
msgstr "Fråga efter en Java thread dump vid drift."
#: ../i2prouter:1780
-msgid "Please edit i2prouter and set the variable RUN_AS_USER"
-msgstr "Var god ändra i2prouter och sätt variabeln RUN_AS_USER"
+msgid "Please edit /etc/default/i2p and set the variable RUN_AS_USER"
+msgstr "Var god ändra /etc/default/i2p och sätt variabeln RUN_AS_USER"
#: ../i2prouter:1785
msgid "Running I2P as the root user is *not* recommended."
msgstr "Att köra I2P som användare root är *inte* rekommenderat."
#: ../i2prouter:1788
-msgid "To run as root anyway, edit i2prouter and set ALLOW_ROOT=true."
-msgstr "För att köra som root iallafall, ändra i2prouter och sätt ALLOW_ROOT=true"
+msgid "To run as root anyway, edit /etc/default/i2p and set ALLOW_ROOT=true."
+msgstr "För att köra som root iallafall, ändra /etc/default/i2p och sätt ALLOW_ROOT=true"

View File

@@ -1,3 +1,43 @@
2013-06-01 zzz
* EepGet: Used cached byte array in uncompressor
* i2psnark:
- Add idle detector, reduce tunnel count when idle (prep for torrent updates)
- Cancel CoordinatorAcceptor cleaner when halted
- Make PeerCoordinatorSet an Iterable
- Reduce max protocol errors to 1
- Disable unused PeerMonitorTask
2013-05-31 zzz
* configtunnels.jsp: Allow more hops and tunnels when routerconsole.advanced=true
* i2psnark: Fix details page on Windows
* NetDB:
- Add DLM fields for requesting an encrypted reply
- Add support for encrypted DSRM and DSM in response to a DLM
- Fix netDb.alwaysQuery debug setting so it works again, and always
sends to that router first (move from FNDF to IterativeSearchJob)
* PRNG: Cleanups using Collections.singletonMap()
* Router utils: New RemovableSingletonSet
* TransientSessionKeyManager:
- Support variable expiration for inbound tag sets
- Several efficiency improvements
* VersionComparator: Add static method, use most places
2013-05-30 kytv
* Update Java Service Wrapper to v3.5.19
- Windows: Self-compiled with VS2010 in Windows 7. The icon has been
changed from Tanuki's default to Itoopie.
- Linux ARMv6: Compiled on a RaspberryPi using gcc 4.6.3-14+rpi1,
Icedtea6 6b27-1.12.5-1+rpi1 and stripped
- All other binaries are from the "community edition" deltapack offered by
Tanuki.
* Allow themes to be used in IE >= 10
2013-05-29 zzz
* Console: Remove I2PDigestAuthenticator workaround, as Jetty 7.6.11 has the fix
* i2ptunnel: Default to 3 hops (ticket #936)
* Jetty 7.6.11
* Tomcat 6.0.37
* 2013-05-28 0.9.6 released
2013-05-24 kytv
@@ -278,7 +318,7 @@
changed from Tanuki's default to Itoopie.
- FreeBSD: Self-compiled in FreeBSD 7.4 to eliminate the dependency on the
compat6x port.
- Linux x86, Linux x64, Linux ARMv5, Linux-PPC32, MacOSX & Solaris: Binares
- Linux x86, Linux x64, Linux ARMv5, Linux-PPC32, MacOSX & Solaris: Binaries
are from the "community edition" deltapack offered by Tanuki. The Linux
binaries have been stripped.

View File

@@ -10,26 +10,21 @@ From the delta pack, strip the binaries in lib/
(if you have the tools to do so for that architecture) and copy
to xxx/librapper.so, libwrapper.jnilib, or wrapper.dll for the following directories.
Don't forget to disable the execute bit.
freebsd (x86-32)
freebsd64 (x86-64)
linux (x86-32)
linux64 (x86-64)
linux-ppc (linux-ppc-32)
linux-armv5 (armv5/armv7)
solaris (sparc-32)
From the delta pack, strip the binaries in bin/ and copy
From the delta pack, strip the binaries in bin/ (if needed) and copy
to xxx/i2psvc for the same directories as above.
Don't forget to disable the execute bit.
For armv6, build from source following the instructions
in linux-armv6/README.txt.
Don't forget to strip the binaries and disable the execute bit.
We use a trimslice for armv7 building.
For freebsd and freebsd64, we don't use the Tanuki binaries
because they are compiled in FBSD v6. Compile from source in
FreeBSD 7.4 to eliminate the dependency on the compat6x port.
Don't forget to strip the binaries and disable the execute bit.
A walkthrough can be found in freebsd/README.txt.
For macosx, combine (if possible) the universal-32 and universal-64 files
from the delta pack (each is a 2-architecture fat file)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,4 +1,4 @@
Changes may be needed for newer versions than 3.5.17.
Changes may be needed for newer versions than 3.5.19.
To use the patch in this directory, copy Makefile-windows-x86-32.nmake to
Makefile-windows-x86-64.nmake then "patch < x64-win.patch".

View File

@@ -1793,7 +1793,7 @@ showUsage() {
}
showsetusermesg() {
echo "`gettext 'Please edit i2prouter and set the variable RUN_AS_USER'`."
echo "`gettext \"Please edit $0 and set the variable RUN_AS_USER\"`."
}
checkifstartingasroot() {
@@ -1801,7 +1801,7 @@ checkifstartingasroot() {
echo "`gettext 'Running I2P as the root user is *not* recommended.'`"
showsetusermesg
echo
echo "`gettext 'To run as root anyway, edit i2prouter and set ALLOW_ROOT=true.'`"
echo "`gettext \"To run as root anyway, edit $0 and set ALLOW_ROOT=true.\"`"
exit 1
fi
}

View File

@@ -192,14 +192,14 @@ msgid "Request a Java thread dump if running."
msgstr "Falls gestartet, fordere einen Java Thread dump an"
#: ../i2prouter:1788
msgid "Please edit i2prouter and set the variable RUN_AS_USER"
msgstr "Bitte bearbeite i2prouter und setze die Variable RUN_AS_USER"
msgid "Please edit $0 and set the variable RUN_AS_USER"
msgstr "Bitte bearbeite $0 und setze die Variable RUN_AS_USER"
#: ../i2prouter:1793
msgid "Running I2P as the root user is *not* recommended."
msgstr "I2P als root Benutzer auszuführen ist *nicht* empfehlenswert."
#: ../i2prouter:1796
msgid "To run as root anyway, edit i2prouter and set ALLOW_ROOT=true."
msgid "To run as root anyway, edit $0 and set ALLOW_ROOT=true."
msgstr ""
"Um I2P trotzdem als root auszuführen bearbeite i2prouter und setze ALLOW_ROOT=true."
"Um I2P trotzdem als root auszuführen bearbeite $0 und setze ALLOW_ROOT=true."

View File

@@ -185,7 +185,7 @@ msgid "Request a Java thread dump if running."
msgstr ""
#: ../i2prouter:1788
msgid "Please edit i2prouter and set the variable RUN_AS_USER"
msgid "Please edit $0 and set the variable RUN_AS_USER"
msgstr ""
#: ../i2prouter:1793
@@ -193,5 +193,5 @@ msgid "Running I2P as the root user is *not* recommended."
msgstr ""
#: ../i2prouter:1796
msgid "To run as root anyway, edit i2prouter and set ALLOW_ROOT=true."
msgid "To run as root anyway, edit $0 and set ALLOW_ROOT=true."
msgstr ""

View File

@@ -187,7 +187,7 @@ msgid "Request a Java thread dump if running."
msgstr ""
#: ../i2prouter:1780
msgid "Please edit i2prouter and set the variable RUN_AS_USER"
msgid "Please edit $0 and set the variable RUN_AS_USER"
msgstr ""
#: ../i2prouter:1785
@@ -196,5 +196,5 @@ msgstr ""
"Faire fonctionner I2P en tant qu'utilisateur root n'est *pas* recommandé."
#: ../i2prouter:1788
msgid "To run as root anyway, edit i2prouter and set ALLOW_ROOT=true."
msgid "To run as root anyway, edit $0 and set ALLOW_ROOT=true."
msgstr ""

View File

@@ -187,7 +187,7 @@ msgid "Request a Java thread dump if running."
msgstr ""
#: ../i2prouter:1780
msgid "Please edit i2prouter and set the variable RUN_AS_USER"
msgid "Please edit $0 and set the variable RUN_AS_USER"
msgstr ""
#: ../i2prouter:1785
@@ -195,5 +195,5 @@ msgid "Running I2P as the root user is *not* recommended."
msgstr ""
#: ../i2prouter:1788
msgid "To run as root anyway, edit i2prouter and set ALLOW_ROOT=true."
msgid "To run as root anyway, edit $0 and set ALLOW_ROOT=true."
msgstr ""

View File

@@ -188,7 +188,7 @@ msgid "Request a Java thread dump if running."
msgstr ""
#: ../i2prouter:1780
msgid "Please edit i2prouter and set the variable RUN_AS_USER"
msgid "Please edit $0 and set the variable RUN_AS_USER"
msgstr ""
#: ../i2prouter:1785
@@ -196,5 +196,5 @@ msgid "Running I2P as the root user is *not* recommended."
msgstr ""
#: ../i2prouter:1788
msgid "To run as root anyway, edit i2prouter and set ALLOW_ROOT=true."
msgid "To run as root anyway, edit $0 and set ALLOW_ROOT=true."
msgstr ""

View File

@@ -187,13 +187,13 @@ msgid "Request a Java thread dump if running."
msgstr "Fråga efter en Java thread dump vid drift."
#: ../i2prouter:1780
msgid "Please edit i2prouter and set the variable RUN_AS_USER"
msgstr "Var god ändra i2prouter och sätt variabeln RUN_AS_USER"
msgid "Please edit $0 and set the variable RUN_AS_USER"
msgstr "Var god ändra $0 och sätt variabeln RUN_AS_USER"
#: ../i2prouter:1785
msgid "Running I2P as the root user is *not* recommended."
msgstr "Att köra I2P som användare root är *inte* rekommenderat."
#: ../i2prouter:1788
msgid "To run as root anyway, edit i2prouter and set ALLOW_ROOT=true."
msgstr "För att köra som root iallafall, ändra i2prouter och sätt ALLOW_ROOT=true"
msgid "To run as root anyway, edit $0 and set ALLOW_ROOT=true."
msgstr "För att köra som root iallafall, ändra $0 och sätt ALLOW_ROOT=true"

View File

@@ -17,8 +17,12 @@ import java.util.Set;
import net.i2p.I2PAppContext;
import net.i2p.data.DataHelper;
import net.i2p.data.Hash;
import net.i2p.data.RouterInfo;
import net.i2p.data.SessionKey;
import net.i2p.data.SessionTag;
import net.i2p.data.TunnelId;
//import net.i2p.util.Log;
import net.i2p.util.VersionComparator;
/**
* Defines the message a router sends to another router to search for a
@@ -34,6 +38,8 @@ public class DatabaseLookupMessage extends FastI2NPMessageImpl {
private TunnelId _replyTunnel;
/** this must be kept as a list to preserve the order and not break the checksum */
private List<Hash> _dontIncludePeers;
private SessionKey _replyKey;
private SessionTag _replyTag;
//private static volatile long _currentLookupPeriod = 0;
//private static volatile int _currentLookupCount = 0;
@@ -45,6 +51,16 @@ public class DatabaseLookupMessage extends FastI2NPMessageImpl {
Have to prevent a huge alloc on rcv of a malicious msg though */
private static final int MAX_NUM_PEERS = 512;
private static final byte FLAG_TUNNEL = 0x01;
private static final byte FLAG_ENCRYPT = 0x02;
/**
* It's not supported until 0.9.7, but as of
* 0.9.6 we can specify the bit in the flags without
* the receiver rejecting the whole message as invalid.
*/
private static final String MIN_ENCRYPTION_VERSION = "0.9.7";
public DatabaseLookupMessage(I2PAppContext context) {
this(context, false);
}
@@ -144,6 +160,49 @@ public class DatabaseLookupMessage extends FastI2NPMessageImpl {
_replyTunnel = replyTunnel;
}
/**
* Does this router support encrypted replies?
*
* @param to null OK
* @since 0.9.7
*/
public static boolean supportsEncryptedReplies(RouterInfo to) {
if (to == null)
return false;
String v = to.getOption("router.version");
return v != null &&
VersionComparator.comp(v, MIN_ENCRYPTION_VERSION) >= 0;
}
/**
* The included session key or null if unset
*
* @since 0.9.7
*/
public SessionKey getReplyKey() { return _replyKey; }
/**
* The included session tag or null if unset
*
* @since 0.9.7
*/
public SessionTag getReplyTag() { return _replyTag; }
/**
* Only worthwhile if sending reply via tunnel
*
* @throws IllegalStateException if key or tag previously set, to protect saved checksum
* @param encryptKey non-null
* @param encryptTag non-null
* @since 0.9.7
*/
public void setReplySession(SessionKey encryptKey, SessionTag encryptTag) {
if (_replyKey != null || _replyTag != null)
throw new IllegalStateException();
_replyKey = encryptKey;
_replyTag = encryptTag;
}
/**
* Set of peers that a lookup reply should NOT include.
* WARNING - returns a copy.
@@ -224,7 +283,8 @@ public class DatabaseLookupMessage extends FastI2NPMessageImpl {
// as of 0.9.6, ignore other 7 bits of the flag byte
// TODO store the whole flag byte
boolean tunnelSpecified = (data[curIndex] & 0x01) != 0;
boolean tunnelSpecified = (data[curIndex] & FLAG_TUNNEL) != 0;
boolean replyKeySpecified = (data[curIndex] & FLAG_ENCRYPT) != 0;
curIndex++;
if (tunnelSpecified) {
@@ -246,6 +306,15 @@ public class DatabaseLookupMessage extends FastI2NPMessageImpl {
peers.add(p);
}
_dontIncludePeers = peers;
if (replyKeySpecified) {
byte[] rk = new byte[SessionKey.KEYSIZE_BYTES];
System.arraycopy(data, curIndex, rk, 0, SessionKey.KEYSIZE_BYTES);
_replyKey = new SessionKey(rk);
curIndex += SessionKey.KEYSIZE_BYTES;
byte[] rt = new byte[SessionTag.BYTE_LENGTH];
System.arraycopy(data, curIndex, rt, 0, SessionTag.BYTE_LENGTH);
_replyTag = new SessionTag(rt);
}
}
@@ -258,6 +327,8 @@ public class DatabaseLookupMessage extends FastI2NPMessageImpl {
totalLength += 2; // numPeers
if (_dontIncludePeers != null)
totalLength += Hash.HASH_LENGTH * _dontIncludePeers.size();
if (_replyKey != null)
totalLength += SessionKey.KEYSIZE_BYTES + SessionTag.BYTE_LENGTH;
return totalLength;
}
@@ -269,12 +340,17 @@ public class DatabaseLookupMessage extends FastI2NPMessageImpl {
curIndex += Hash.HASH_LENGTH;
System.arraycopy(_fromHash.getData(), 0, out, curIndex, Hash.HASH_LENGTH);
curIndex += Hash.HASH_LENGTH;
// TODO allow specification of the other 7 bits of the flag byte
// Generate the flag byte
if (_replyTunnel != null) {
out[curIndex++] = 0x01;
byte flag = FLAG_TUNNEL;
if (_replyKey != null)
flag |= FLAG_ENCRYPT;
out[curIndex++] = flag;
byte id[] = DataHelper.toLong(4, _replyTunnel.getTunnelId());
System.arraycopy(id, 0, out, curIndex, 4);
curIndex += 4;
} else if (_replyKey != null) {
out[curIndex++] = FLAG_ENCRYPT;
} else {
out[curIndex++] = 0x00;
}
@@ -293,6 +369,12 @@ public class DatabaseLookupMessage extends FastI2NPMessageImpl {
curIndex += Hash.HASH_LENGTH;
}
}
if (_replyKey != null) {
System.arraycopy(_replyKey.getData(), 0, out, curIndex, SessionKey.KEYSIZE_BYTES);
curIndex += SessionKey.KEYSIZE_BYTES;
System.arraycopy(_replyTag.getData(), 0, out, curIndex, SessionTag.BYTE_LENGTH);
curIndex += SessionTag.BYTE_LENGTH;
}
return curIndex;
}
@@ -326,6 +408,10 @@ public class DatabaseLookupMessage extends FastI2NPMessageImpl {
buf.append("\n\tSearch Key: ").append(_key);
buf.append("\n\tFrom: ").append(_fromHash);
buf.append("\n\tReply Tunnel: ").append(_replyTunnel);
if (_replyKey != null)
buf.append("\n\tReply Key: ").append(_replyKey);
if (_replyTag != null)
buf.append("\n\tReply Tag: ").append(_replyTag);
buf.append("\n\tDont Include Peers: ");
if (_dontIncludePeers != null)
buf.append(_dontIncludePeers.size());

View File

@@ -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 = 0;
public final static long BUILD = 4;
/** for example "-test" */
public final static String EXTRA = "";

View File

@@ -8,6 +8,7 @@ package net.i2p.router.networkdb;
*
*/
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
@@ -16,6 +17,7 @@ import net.i2p.data.Hash;
import net.i2p.data.LeaseSet;
import net.i2p.data.RouterIdentity;
import net.i2p.data.RouterInfo;
import net.i2p.data.SessionKey;
import net.i2p.data.TunnelId;
import net.i2p.data.i2np.DatabaseLookupMessage;
import net.i2p.data.i2np.DatabaseSearchReplyMessage;
@@ -27,6 +29,7 @@ import net.i2p.router.JobImpl;
import net.i2p.router.OutNetMessage;
import net.i2p.router.Router;
import net.i2p.router.RouterContext;
import net.i2p.router.networkdb.kademlia.MessageWrapper;
import net.i2p.router.message.SendMessageDirectJob;
import net.i2p.util.Log;
@@ -36,8 +39,10 @@ import net.i2p.util.Log;
* Unused directly - see kademlia/ for extension
*/
public class HandleDatabaseLookupMessageJob extends JobImpl {
private Log _log;
private DatabaseLookupMessage _message;
private final Log _log;
private final DatabaseLookupMessage _message;
private boolean _replyKeyConsumed;
private final static int MAX_ROUTERS_RETURNED = 3;
private final static int CLOSENESS_THRESHOLD = 8; // FNDF.MAX_TO_FLOOD + 1
private final static int REPLY_TIMEOUT = 60*1000;
@@ -149,8 +154,7 @@ public class HandleDatabaseLookupMessageJob extends JobImpl {
if ( (info.getIdentity().isHidden()) || (isUnreachable(info) && !publishUnreachable()) ) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Not answering a query for a netDb peer who isn't reachable");
Set<Hash> us = new HashSet<Hash>(1);
us.add(getContext().routerHash());
Set<Hash> us = Collections.singleton(getContext().routerHash());
sendClosest(_message.getSearchKey(), us, fromKey, _message.getReplyTunnel());
//} else if (info.isHidden()) {
// // Don't return hidden nodes
@@ -203,9 +207,11 @@ public class HandleDatabaseLookupMessageJob extends JobImpl {
*/
private Set<Hash> getNearestRouters() {
Set<Hash> dontInclude = _message.getDontIncludePeers();
Hash us = getContext().routerHash();
if (dontInclude == null)
dontInclude = new HashSet(1);
dontInclude.add(getContext().routerHash());
dontInclude = Collections.singleton(us);
else
dontInclude.add(us);
// Honor flag to exclude all floodfills
//if (dontInclude.contains(Hash.FAKE_HASH)) {
// This is handled in FloodfillPeerSelector
@@ -289,6 +295,21 @@ public class HandleDatabaseLookupMessageJob extends JobImpl {
getContext().tunnelDispatcher().dispatch(m);
} else {
// if we aren't the gateway, forward it on
if (!_replyKeyConsumed) {
// if we send a followup DSM w/ our RI, don't reuse key
SessionKey replyKey = _message.getReplyKey();
if (replyKey != null) {
// encrypt the reply
if (_log.shouldLog(Log.INFO))
_log.info("Sending encrypted reply to " + toPeer + ' ' + replyKey + ' ' + _message.getReplyTag());
message = MessageWrapper.wrap(getContext(), message, replyKey, _message.getReplyTag());
if (message == null) {
_log.error("Encryption error");
return;
}
_replyKeyConsumed = true;
}
}
TunnelGatewayMessage m = new TunnelGatewayMessage(getContext());
m.setMessage(message);
m.setMessageExpiration(message.getMessageExpiration());

View File

@@ -28,8 +28,6 @@ public class FloodfillNetworkDatabaseFacade extends KademliaNetworkDatabaseFacad
public static final char CAPABILITY_FLOODFILL = 'f';
private final Map<Hash, FloodSearchJob> _activeFloodQueries;
private boolean _floodfillEnabled;
/** for testing, see isFloodfill() below */
private static String _alwaysQuery;
private final Set<Hash> _verifiesInProgress;
private FloodThrottler _floodThrottler;
private LookupThrottler _lookupThrottler;
@@ -49,7 +47,6 @@ public class FloodfillNetworkDatabaseFacade extends KademliaNetworkDatabaseFacad
super(context);
_activeFloodQueries = new HashMap();
_verifiesInProgress = new ConcurrentHashSet(8);
_alwaysQuery = _context.getProperty("netDb.alwaysQuery");
_context.statManager().createRequiredRateStat("netDb.successTime", "Time for successful lookup (ms)", "NetworkDatabase", new long[] { 60*60*1000l, 24*60*60*1000l });
_context.statManager().createRateStat("netDb.failedTime", "How long a failed search takes", "NetworkDatabase", new long[] { 60*60*1000l, 24*60*60*1000l });
@@ -273,19 +270,6 @@ public class FloodfillNetworkDatabaseFacade extends KademliaNetworkDatabaseFacad
*/
public static boolean isFloodfill(RouterInfo peer) {
if (peer == null) return false;
// For testing or local networks... we will
// pretend that the specified router is floodfill.
// Must be set at startup since it's static.
// In that router, set netDb.floodfillOnly=false.
// Warning - experts only!
if (_alwaysQuery != null) {
Hash aq = new Hash();
try {
aq.fromBase64(_alwaysQuery);
if (aq.equals(peer.getIdentity().getHash()))
return true;
} catch (DataFormatException dfe) {}
}
String caps = peer.getCapabilities();
return caps.indexOf(FloodfillNetworkDatabaseFacade.CAPABILITY_FLOODFILL) >= 0;
}

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