forked from I2P_Developers/i2p.i2p
propagate from branch 'i2p.i2p.zzz.ipv6' (head 5c147c6e394fae03752dcf497923a90e3f2db529)
to branch 'i2p.i2p' (head 7af6987d5546664f76589afe0cbeeb780f4b5d58)
This commit is contained in:
@ -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 = 13;
|
||||
public final static long BUILD = 2;
|
||||
|
||||
/** for example "-test" */
|
||||
public final static String EXTRA = "";
|
||||
|
@ -58,7 +58,7 @@ import net.i2p.util.SimpleTimer;
|
||||
class ClientConnectionRunner {
|
||||
protected final Log _log;
|
||||
protected final RouterContext _context;
|
||||
private final ClientManager _manager;
|
||||
protected final ClientManager _manager;
|
||||
/** socket for this particular peer connection */
|
||||
private final Socket _socket;
|
||||
/** output stream of the socket that I2CP messages bound to the client should be written to */
|
||||
@ -137,7 +137,7 @@ class ClientConnectionRunner {
|
||||
if (_dead || _reader != null)
|
||||
throw new IllegalStateException();
|
||||
_reader = new I2CPMessageReader(new BufferedInputStream(_socket.getInputStream(), BUF_SIZE),
|
||||
new ClientMessageEventListener(_context, this, true));
|
||||
createListener());
|
||||
_writer = new ClientWriterRunner(_context, this);
|
||||
I2PThread t = new I2PThread(_writer);
|
||||
t.setName("I2CP Writer " + __id.incrementAndGet());
|
||||
@ -148,6 +148,14 @@ class ClientConnectionRunner {
|
||||
// TODO need a cleaner for unclaimed items in _messages, but we have no timestamps...
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow override for testing
|
||||
* @since 0.9.8
|
||||
*/
|
||||
protected I2CPMessageReader.I2CPMessageEventListener createListener() {
|
||||
return new ClientMessageEventListener(_context, this, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Die a horrible death. Cannot be restarted.
|
||||
*/
|
||||
@ -460,8 +468,8 @@ class ClientConnectionRunner {
|
||||
* @param set LeaseSet with requested leases - this object must be updated to contain the
|
||||
* signed version (as well as any changed/added/removed Leases)
|
||||
* @param expirationTime ms to wait before failing
|
||||
* @param onCreateJob Job to run after the LeaseSet is authorized
|
||||
* @param onFailedJob Job to run after the timeout passes without receiving authorization
|
||||
* @param onCreateJob Job to run after the LeaseSet is authorized, null OK
|
||||
* @param onFailedJob Job to run after the timeout passes without receiving authorization, null OK
|
||||
*/
|
||||
void requestLeaseSet(LeaseSet set, long expirationTime, Job onCreateJob, Job onFailedJob) {
|
||||
if (_dead) {
|
||||
|
@ -10,6 +10,7 @@ package net.i2p.router.client;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
@ -44,7 +45,7 @@ import net.i2p.util.Log;
|
||||
*/
|
||||
class ClientManager {
|
||||
private final Log _log;
|
||||
private ClientListenerRunner _listener;
|
||||
protected ClientListenerRunner _listener;
|
||||
// Destination --> ClientConnectionRunner
|
||||
// Locked for adds/removes but not lookups
|
||||
private final Map<Destination, ClientConnectionRunner> _runners;
|
||||
@ -53,8 +54,9 @@ class ClientManager {
|
||||
private final Map<Hash, ClientConnectionRunner> _runnersByHash;
|
||||
// ClientConnectionRunner for clients w/out a Dest yet
|
||||
private final Set<ClientConnectionRunner> _pendingRunners;
|
||||
private final RouterContext _ctx;
|
||||
private volatile boolean _isStarted;
|
||||
protected final RouterContext _ctx;
|
||||
protected final int _port;
|
||||
protected volatile boolean _isStarted;
|
||||
|
||||
/** Disable external interface, allow internal clients only @since 0.8.3 */
|
||||
private static final String PROP_DISABLE_EXTERNAL = "i2cp.disableInterface";
|
||||
@ -65,6 +67,10 @@ class ClientManager {
|
||||
|
||||
private static final long REQUEST_LEASESET_TIMEOUT = 60*1000;
|
||||
|
||||
/**
|
||||
* Does not start the listeners.
|
||||
* Caller must call start()
|
||||
*/
|
||||
public ClientManager(RouterContext context, int port) {
|
||||
_ctx = context;
|
||||
_log = context.logManager().getLog(ClientManager.class);
|
||||
@ -75,22 +81,27 @@ class ClientManager {
|
||||
_runners = new ConcurrentHashMap();
|
||||
_runnersByHash = new ConcurrentHashMap();
|
||||
_pendingRunners = new HashSet();
|
||||
startListeners(port);
|
||||
_port = port;
|
||||
// following are for RequestLeaseSetJob
|
||||
_ctx.statManager().createRateStat("client.requestLeaseSetSuccess", "How frequently the router requests successfully a new leaseSet?", "ClientMessages", new long[] { 60*60*1000 });
|
||||
_ctx.statManager().createRateStat("client.requestLeaseSetTimeout", "How frequently the router requests a new leaseSet but gets no reply?", "ClientMessages", new long[] { 60*60*1000 });
|
||||
_ctx.statManager().createRateStat("client.requestLeaseSetDropped", "How frequently the router requests a new leaseSet but the client drops?", "ClientMessages", new long[] { 60*60*1000 });
|
||||
}
|
||||
|
||||
/** @since 0.9.8 */
|
||||
public synchronized void start() {
|
||||
startListeners();
|
||||
}
|
||||
|
||||
/** Todo: Start a 3rd listener for IPV6? */
|
||||
private void startListeners(int port) {
|
||||
protected void startListeners() {
|
||||
if (!_ctx.getBooleanProperty(PROP_DISABLE_EXTERNAL)) {
|
||||
// there's no option to start both an SSL and non-SSL listener
|
||||
if (_ctx.getBooleanProperty(PROP_ENABLE_SSL))
|
||||
_listener = new SSLClientListenerRunner(_ctx, this, port);
|
||||
_listener = new SSLClientListenerRunner(_ctx, this, _port);
|
||||
else
|
||||
_listener = new ClientListenerRunner(_ctx, this, port);
|
||||
Thread t = new I2PThread(_listener, "ClientListener:" + port, true);
|
||||
_listener = new ClientListenerRunner(_ctx, this, _port);
|
||||
Thread t = new I2PThread(_listener, "ClientListener:" + _port, true);
|
||||
t.start();
|
||||
}
|
||||
_isStarted = true;
|
||||
@ -102,9 +113,7 @@ class ClientManager {
|
||||
// to let the old listener die
|
||||
try { Thread.sleep(2*1000); } catch (InterruptedException ie) {}
|
||||
|
||||
int port = _ctx.getProperty(ClientManagerFacadeImpl.PROP_CLIENT_PORT,
|
||||
ClientManagerFacadeImpl.DEFAULT_PORT);
|
||||
startListeners(port);
|
||||
startListeners();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -404,12 +413,18 @@ class ClientManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return unmodifiable, not a copy
|
||||
*/
|
||||
Set<Destination> getRunnerDestinations() {
|
||||
Set<Destination> dests = new HashSet();
|
||||
dests.addAll(_runners.keySet());
|
||||
return dests;
|
||||
return Collections.unmodifiableSet(_runners.keySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Unused
|
||||
*
|
||||
* @param dest null for all local destinations
|
||||
*/
|
||||
public void reportAbuse(Destination dest, String reason, int severity) {
|
||||
if (dest != null) {
|
||||
ClientConnectionRunner runner = getRunner(dest);
|
||||
@ -417,9 +432,7 @@ class ClientManager {
|
||||
runner.reportAbuse(reason, severity);
|
||||
}
|
||||
} else {
|
||||
Set dests = getRunnerDestinations();
|
||||
for (Iterator iter = dests.iterator(); iter.hasNext(); ) {
|
||||
Destination d = (Destination)iter.next();
|
||||
for (Destination d : _runners.keySet()) {
|
||||
reportAbuse(d, reason, severity);
|
||||
}
|
||||
}
|
||||
|
@ -56,6 +56,7 @@ public class ClientManagerFacadeImpl extends ClientManagerFacade implements Inte
|
||||
_log.info("Starting up the client subsystem");
|
||||
int port = _context.getProperty(PROP_CLIENT_PORT, DEFAULT_PORT);
|
||||
_manager = new ClientManager(_context, port);
|
||||
_manager.start();
|
||||
}
|
||||
|
||||
public synchronized void shutdown() {
|
||||
@ -82,12 +83,12 @@ public class ClientManagerFacadeImpl extends ClientManagerFacade implements Inte
|
||||
public boolean isAlive() { return _manager != null && _manager.isAlive(); }
|
||||
|
||||
private static final long MAX_TIME_TO_REBUILD = 10*60*1000;
|
||||
|
||||
@Override
|
||||
public boolean verifyClientLiveliness() {
|
||||
if (_manager == null) return true;
|
||||
boolean lively = true;
|
||||
for (Iterator iter = _manager.getRunnerDestinations().iterator(); iter.hasNext(); ) {
|
||||
Destination dest = (Destination)iter.next();
|
||||
for (Destination dest : _manager.getRunnerDestinations()) {
|
||||
ClientConnectionRunner runner = _manager.getRunner(dest);
|
||||
if ( (runner == null) || (runner.getIsDead())) continue;
|
||||
LeaseSet ls = runner.getLeaseSet();
|
||||
|
@ -46,8 +46,8 @@ import net.i2p.util.RandomSource;
|
||||
*/
|
||||
class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventListener {
|
||||
private final Log _log;
|
||||
private final RouterContext _context;
|
||||
private final ClientConnectionRunner _runner;
|
||||
protected final RouterContext _context;
|
||||
protected final ClientConnectionRunner _runner;
|
||||
private final boolean _enforceAuth;
|
||||
|
||||
private static final String PROP_AUTH = "i2cp.auth";
|
||||
@ -73,40 +73,40 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi
|
||||
_log.debug("Message received: \n" + message);
|
||||
switch (message.getType()) {
|
||||
case GetDateMessage.MESSAGE_TYPE:
|
||||
handleGetDate(reader, (GetDateMessage)message);
|
||||
handleGetDate((GetDateMessage)message);
|
||||
break;
|
||||
case SetDateMessage.MESSAGE_TYPE:
|
||||
handleSetDate(reader, (SetDateMessage)message);
|
||||
handleSetDate((SetDateMessage)message);
|
||||
break;
|
||||
case CreateSessionMessage.MESSAGE_TYPE:
|
||||
handleCreateSession(reader, (CreateSessionMessage)message);
|
||||
handleCreateSession((CreateSessionMessage)message);
|
||||
break;
|
||||
case SendMessageMessage.MESSAGE_TYPE:
|
||||
handleSendMessage(reader, (SendMessageMessage)message);
|
||||
handleSendMessage((SendMessageMessage)message);
|
||||
break;
|
||||
case SendMessageExpiresMessage.MESSAGE_TYPE:
|
||||
handleSendMessage(reader, (SendMessageExpiresMessage)message);
|
||||
handleSendMessage((SendMessageExpiresMessage)message);
|
||||
break;
|
||||
case ReceiveMessageBeginMessage.MESSAGE_TYPE:
|
||||
handleReceiveBegin(reader, (ReceiveMessageBeginMessage)message);
|
||||
handleReceiveBegin((ReceiveMessageBeginMessage)message);
|
||||
break;
|
||||
case ReceiveMessageEndMessage.MESSAGE_TYPE:
|
||||
handleReceiveEnd(reader, (ReceiveMessageEndMessage)message);
|
||||
handleReceiveEnd((ReceiveMessageEndMessage)message);
|
||||
break;
|
||||
case CreateLeaseSetMessage.MESSAGE_TYPE:
|
||||
handleCreateLeaseSet(reader, (CreateLeaseSetMessage)message);
|
||||
handleCreateLeaseSet((CreateLeaseSetMessage)message);
|
||||
break;
|
||||
case DestroySessionMessage.MESSAGE_TYPE:
|
||||
handleDestroySession(reader, (DestroySessionMessage)message);
|
||||
handleDestroySession((DestroySessionMessage)message);
|
||||
break;
|
||||
case DestLookupMessage.MESSAGE_TYPE:
|
||||
handleDestLookup(reader, (DestLookupMessage)message);
|
||||
handleDestLookup((DestLookupMessage)message);
|
||||
break;
|
||||
case ReconfigureSessionMessage.MESSAGE_TYPE:
|
||||
handleReconfigureSession(reader, (ReconfigureSessionMessage)message);
|
||||
handleReconfigureSession((ReconfigureSessionMessage)message);
|
||||
break;
|
||||
case GetBandwidthLimitsMessage.MESSAGE_TYPE:
|
||||
handleGetBWLimits(reader, (GetBandwidthLimitsMessage)message);
|
||||
handleGetBWLimits((GetBandwidthLimitsMessage)message);
|
||||
break;
|
||||
default:
|
||||
if (_log.shouldLog(Log.ERROR))
|
||||
@ -131,7 +131,7 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi
|
||||
_runner.disconnected();
|
||||
}
|
||||
|
||||
private void handleGetDate(I2CPMessageReader reader, GetDateMessage message) {
|
||||
private void handleGetDate(GetDateMessage message) {
|
||||
// sent by clients >= 0.8.7
|
||||
String clientVersion = message.getVersion();
|
||||
if (clientVersion != null)
|
||||
@ -148,7 +148,7 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi
|
||||
/**
|
||||
* As of 0.8.7, does nothing. Do not allow a client to set the router's clock.
|
||||
*/
|
||||
private void handleSetDate(I2CPMessageReader reader, SetDateMessage message) {
|
||||
private void handleSetDate(SetDateMessage message) {
|
||||
//_context.clock().setNow(message.getDate().getTime());
|
||||
}
|
||||
|
||||
@ -160,7 +160,7 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi
|
||||
* DisconnectMessage in return, and not wait around for our DisconnectMessage.
|
||||
* So keep it simple.
|
||||
*/
|
||||
private void handleCreateSession(I2CPMessageReader reader, CreateSessionMessage message) {
|
||||
private void handleCreateSession(CreateSessionMessage message) {
|
||||
SessionConfig in = message.getSessionConfig();
|
||||
if (in.verifySignature()) {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
@ -209,17 +209,24 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi
|
||||
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("after sessionEstablished for " + message.getSessionConfig().getDestination().calculateHash().toBase64());
|
||||
|
||||
_context.jobQueue().addJob(new CreateSessionJob(_context, _runner));
|
||||
startCreateSessionJob();
|
||||
}
|
||||
|
||||
/**
|
||||
* Override for testing
|
||||
* @since 0.9.8
|
||||
*
|
||||
*/
|
||||
protected void startCreateSessionJob() {
|
||||
_context.jobQueue().addJob(new CreateSessionJob(_context, _runner));
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a SendMessageMessage: give it a message Id, have the ClientManager distribute
|
||||
* it, and send the client an ACCEPTED message
|
||||
*
|
||||
*/
|
||||
private void handleSendMessage(I2CPMessageReader reader, SendMessageMessage message) {
|
||||
private void handleSendMessage(SendMessageMessage message) {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("handleSendMessage called");
|
||||
long beforeDistribute = _context.clock().now();
|
||||
@ -236,7 +243,7 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi
|
||||
* The client asked for a message, so we send it to them.
|
||||
*
|
||||
*/
|
||||
private void handleReceiveBegin(I2CPMessageReader reader, ReceiveMessageBeginMessage message) {
|
||||
private void handleReceiveBegin(ReceiveMessageBeginMessage message) {
|
||||
if (_runner.isDead()) return;
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Handling recieve begin: id = " + message.getMessageId());
|
||||
@ -266,17 +273,18 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi
|
||||
* pending queue, though it should.
|
||||
*
|
||||
*/
|
||||
private void handleReceiveEnd(I2CPMessageReader reader, ReceiveMessageEndMessage message) {
|
||||
private void handleReceiveEnd(ReceiveMessageEndMessage message) {
|
||||
_runner.removePayload(new MessageId(message.getMessageId()));
|
||||
}
|
||||
|
||||
private void handleDestroySession(I2CPMessageReader reader, DestroySessionMessage message) {
|
||||
private void handleDestroySession(DestroySessionMessage message) {
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("Destroying client session " + _runner.getSessionId());
|
||||
_runner.stopRunning();
|
||||
}
|
||||
|
||||
private void handleCreateLeaseSet(I2CPMessageReader reader, CreateLeaseSetMessage message) {
|
||||
/** override for testing */
|
||||
protected void handleCreateLeaseSet(CreateLeaseSetMessage message) {
|
||||
if ( (message.getLeaseSet() == null) || (message.getPrivateKey() == null) || (message.getSigningPrivateKey() == null) ) {
|
||||
if (_log.shouldLog(Log.ERROR))
|
||||
_log.error("Null lease set granted: " + message);
|
||||
@ -293,7 +301,8 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi
|
||||
_runner.leaseSetCreated(message.getLeaseSet());
|
||||
}
|
||||
|
||||
private void handleDestLookup(I2CPMessageReader reader, DestLookupMessage message) {
|
||||
/** override for testing */
|
||||
protected void handleDestLookup(DestLookupMessage message) {
|
||||
_context.jobQueue().addJob(new LookupDestJob(_context, _runner, message.getHash()));
|
||||
}
|
||||
|
||||
@ -305,7 +314,7 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi
|
||||
* Note that this does NOT update the few options handled in
|
||||
* ClientConnectionRunner.sessionEstablished(). Those can't be changed later.
|
||||
*/
|
||||
private void handleReconfigureSession(I2CPMessageReader reader, ReconfigureSessionMessage message) {
|
||||
private void handleReconfigureSession(ReconfigureSessionMessage message) {
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("Updating options - old: " + _runner.getConfig() + " new: " + message.getSessionConfig());
|
||||
if (!message.getSessionConfig().getDestination().equals(_runner.getConfig().getDestination())) {
|
||||
@ -343,7 +352,7 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi
|
||||
* This could someday give a different answer to each client.
|
||||
* But it's not enforced anywhere.
|
||||
*/
|
||||
private void handleGetBWLimits(I2CPMessageReader reader, GetBandwidthLimitsMessage message) {
|
||||
protected void handleGetBWLimits(GetBandwidthLimitsMessage message) {
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("Got BW Limits request");
|
||||
int in = _context.bandwidthLimiter().getInboundKBytesPerSecond() * 4 / 7;
|
||||
|
@ -809,4 +809,30 @@ public abstract class TransportImpl implements Transport {
|
||||
return TransportUtil.isPubliclyRoutable(addr,
|
||||
getIPv6Config() != TransportUtil.IPv6Config.IPV6_DISABLED);
|
||||
}
|
||||
|
||||
private static final String BUNDLE_NAME = "net.i2p.router.web.messages";
|
||||
|
||||
/**
|
||||
* Translate
|
||||
* @since 0.9.8 moved from transports
|
||||
*/
|
||||
protected String _(String s) {
|
||||
return Translate.getString(s, _context, BUNDLE_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate
|
||||
* @since 0.9.8 moved from transports
|
||||
*/
|
||||
protected String _(String s, Object o) {
|
||||
return Translate.getString(s, o, _context, BUNDLE_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate
|
||||
* @since 0.9.8
|
||||
*/
|
||||
protected String ngettext(String s, String p, int n) {
|
||||
return Translate.getString(n, s, p, _context, BUNDLE_NAME);
|
||||
}
|
||||
}
|
||||
|
@ -261,7 +261,9 @@ public class DHSessionKeyBuilder {
|
||||
/**
|
||||
* Retrieve the extra bytes beyond the session key resulting from the DH exchange.
|
||||
* If there aren't enough bytes (with all of them being consumed by the 32 byte key),
|
||||
* the SHA256 of the key itself is used.
|
||||
* the SHA256 of the key itself is used - but that won't ever happen.
|
||||
*
|
||||
* Used only by UDP. getData() will be non-null and have at least 32 bytes after call to getSessionKey()
|
||||
*
|
||||
* @return non-null (but rv.getData() may be null)
|
||||
*/
|
||||
@ -270,23 +272,35 @@ public class DHSessionKeyBuilder {
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate a session key based on the private value and the public peer value
|
||||
* Calculate a session key based on the private value and the public peer value.
|
||||
*
|
||||
* This is the first 32 bytes of the exchanged key (nominally 256 bytes),
|
||||
* EXCEPT that the first byte will be zero if the most significant bit was a 1
|
||||
* (Java BigInteger.toByteArray() format)
|
||||
*
|
||||
* Side effect - sets extraExchangedBytes to the next 32 bytes.
|
||||
*/
|
||||
private final SessionKey calculateSessionKey(BigInteger myPrivateValue, BigInteger publicPeerValue) {
|
||||
//long start = System.currentTimeMillis();
|
||||
SessionKey key = new SessionKey();
|
||||
BigInteger exchangedKey = publicPeerValue.modPow(myPrivateValue, CryptoConstants.elgp);
|
||||
// surprise! leading zero byte half the time!
|
||||
// probably was a mistake, too late now...
|
||||
byte buf[] = exchangedKey.toByteArray();
|
||||
byte val[] = new byte[32];
|
||||
if (buf.length < val.length) {
|
||||
System.arraycopy(buf, 0, val, 0, buf.length);
|
||||
byte remaining[] = SHA256Generator.getInstance().calculateHash(val).getData();
|
||||
byte val[] = new byte[SessionKey.KEYSIZE_BYTES];
|
||||
if (buf.length < 2 * SessionKey.KEYSIZE_BYTES) {
|
||||
// UDP requires at least 32 bytes in _extraExchangedBytes for the mac key
|
||||
// Won't ever happen, typ buf is 256 or 257 bytes
|
||||
System.arraycopy(buf, 0, val, 0, Math.min(buf.length, SessionKey.KEYSIZE_BYTES));
|
||||
byte remaining[] = new byte[SessionKey.KEYSIZE_BYTES]; // == Hash.HASH_LENGTH
|
||||
// non-caching version
|
||||
SHA256Generator.getInstance().calculateHash(buf, 0, buf.length, remaining, 0);
|
||||
_extraExchangedBytes.setData(remaining);
|
||||
//if (_log.shouldLog(Log.DEBUG))
|
||||
// _log.debug("Storing " + remaining.length + " bytes from the DH exchange by SHA256 the session key");
|
||||
} else { // (buf.length >= val.length)
|
||||
System.arraycopy(buf, 0, val, 0, val.length);
|
||||
} else {
|
||||
// Will always be here, typ buf is 256 or 257 bytes
|
||||
System.arraycopy(buf, 0, val, 0, SessionKey.KEYSIZE_BYTES);
|
||||
// feed the extra bytes into the PRNG
|
||||
RandomSource.getInstance().harvester().feedEntropy("DH", buf, val.length, buf.length-val.length);
|
||||
byte remaining[] = new byte[buf.length - val.length];
|
||||
|
@ -44,7 +44,6 @@ import net.i2p.util.Addresses;
|
||||
import net.i2p.util.ConcurrentHashSet;
|
||||
import net.i2p.util.Log;
|
||||
import net.i2p.util.OrderedProperties;
|
||||
import net.i2p.util.Translate;
|
||||
|
||||
/**
|
||||
* The NIO TCP transport
|
||||
@ -1173,8 +1172,9 @@ public class NTCPTransport extends TransportImpl {
|
||||
|
||||
if (!peers.isEmpty()) {
|
||||
// buf.append("<tr> <td colspan=\"11\"><hr></td></tr>\n");
|
||||
buf.append("<tr class=\"tablefooter\"><td colspan=\"4\" align=\"left\"><b>").append(_("SUMMARY"))
|
||||
.append("</b>");
|
||||
buf.append("<tr class=\"tablefooter\"><td align=\"center\"><b>")
|
||||
.append(ngettext("{0} peer", "{0} peers", peers.size()))
|
||||
.append("</b></td><td> </td><td> ");
|
||||
buf.append("</td><td align=\"center\"><b>").append(formatRate(bpsRecv/1024)).append(THINSP).append(formatRate(bpsSend/1024)).append("</b>");
|
||||
buf.append("</td><td align=\"center\"><b>").append(DataHelper.formatDuration2(totalUptime/peers.size()));
|
||||
buf.append("</b></td><td align=\"center\"><b>").append(DataHelper.formatDuration2(offsetTotal*1000/peers.size()));
|
||||
|
@ -50,7 +50,6 @@ import net.i2p.util.OrderedProperties;
|
||||
import net.i2p.util.SimpleScheduler;
|
||||
import net.i2p.util.SimpleTimer;
|
||||
import net.i2p.util.SimpleTimer2;
|
||||
import net.i2p.util.Translate;
|
||||
|
||||
/**
|
||||
* The SSU transport
|
||||
@ -2718,7 +2717,9 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
|
||||
if (numPeers > 0) {
|
||||
// buf.append("<tr><td colspan=\"16\"><hr></td></tr>\n");
|
||||
buf.append("<tr class=\"tablefooter\"><td colspan=\"4\" align=\"left\"><b>").append(_("SUMMARY")).append("</b></td>" +
|
||||
buf.append("<tr class=\"tablefooter\"><td colspan=\"3\" align=\"left\"><b>")
|
||||
.append(ngettext("{0} peer", "{0} peers", peers.size()))
|
||||
.append("</b></td>" +
|
||||
"<td align=\"center\" nowrap><b>");
|
||||
buf.append(formatKBps(bpsIn)).append(THINSP).append(formatKBps(bpsOut));
|
||||
long x = uptimeMsTotal/numPeers;
|
||||
|
@ -547,6 +547,12 @@ class BuildHandler implements Runnable {
|
||||
boolean isInGW = req.readIsInboundGateway();
|
||||
boolean isOutEnd = req.readIsOutboundEndpoint();
|
||||
|
||||
if (isInGW && isOutEnd) {
|
||||
_context.statManager().addRateData("tunnel.rejectHostile", 1);
|
||||
_log.error("Dropping build request, IBGW+OBEP");
|
||||
return;
|
||||
}
|
||||
|
||||
// Loop checks
|
||||
if ((!isOutEnd) && _context.routerHash().equals(nextPeer)) {
|
||||
_context.statManager().addRateData("tunnel.rejectHostile", 1);
|
||||
|
@ -1084,7 +1084,7 @@ public class TunnelPool {
|
||||
int len = settings.getLengthOverride();
|
||||
if (len < 0)
|
||||
len = settings.getLength();
|
||||
if (len > 0 && _context.random().nextBoolean()) {
|
||||
if (len > 0 && (!settings.isExploratory()) && _context.random().nextBoolean()) {
|
||||
// look for a tunnel to reuse, if the right length and expiring soon
|
||||
// ignore variance for now.
|
||||
len++; // us
|
||||
|
@ -0,0 +1,67 @@
|
||||
package net.i2p.router.client;
|
||||
|
||||
import java.net.Socket;
|
||||
|
||||
import net.i2p.data.Destination;
|
||||
import net.i2p.data.Hash;
|
||||
import net.i2p.data.Lease;
|
||||
import net.i2p.data.LeaseSet;
|
||||
import net.i2p.data.i2cp.I2CPMessageException;
|
||||
import net.i2p.data.i2cp.I2CPMessageReader;
|
||||
import net.i2p.data.i2cp.RequestVariableLeaseSetMessage;
|
||||
import net.i2p.router.Job;
|
||||
import net.i2p.router.RouterContext;
|
||||
|
||||
/**
|
||||
* For testing
|
||||
*
|
||||
* @since 0.9.8
|
||||
*/
|
||||
class LocalClientConnectionRunner extends ClientConnectionRunner {
|
||||
|
||||
/**
|
||||
* Create a new runner with the given queues
|
||||
*
|
||||
*/
|
||||
public LocalClientConnectionRunner(RouterContext context, ClientManager manager, Socket socket) {
|
||||
super(context, manager, socket);
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom listener
|
||||
*/
|
||||
@Override
|
||||
protected I2CPMessageReader.I2CPMessageEventListener createListener() {
|
||||
return new LocalClientMessageEventListener(_context, this, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Just send the message directly,
|
||||
* don't instantiate a RequestLeaseSetJob
|
||||
*/
|
||||
@Override
|
||||
void requestLeaseSet(LeaseSet set, long expirationTime, Job onCreateJob, Job onFailedJob) {
|
||||
RequestVariableLeaseSetMessage msg = new RequestVariableLeaseSetMessage();
|
||||
msg.setSessionId(getSessionId());
|
||||
for (int i = 0; i < set.getLeaseCount(); i++) {
|
||||
Lease lease = set.getLease(i);
|
||||
msg.addEndpoint(lease);
|
||||
}
|
||||
try {
|
||||
doSend(msg);
|
||||
} catch (I2CPMessageException ime) {
|
||||
ime.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* So LocalClientMessageEventListener can lookup other local dests
|
||||
*/
|
||||
public Destination localLookup(Hash h) {
|
||||
for (Destination d : _manager.getRunnerDestinations()) {
|
||||
if (d.calculateHash().equals(h))
|
||||
return d;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package net.i2p.router.client;
|
||||
|
||||
import net.i2p.router.RouterContext;
|
||||
|
||||
/**
|
||||
* For testing
|
||||
*
|
||||
* @since 0.9.8
|
||||
*/
|
||||
class LocalClientListenerRunner extends ClientListenerRunner {
|
||||
|
||||
public LocalClientListenerRunner(RouterContext context, ClientManager manager, int port) {
|
||||
super(context, manager, port);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void runConnection(Socket socket) {
|
||||
ClientConnectionRunner runner = new LocalClientConnectionRunner(_context, _manager, socket);
|
||||
_manager.registerConnection(runner);
|
||||
}
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
package net.i2p.router.client;
|
||||
/*
|
||||
* free (adj.): unencumbered; not under the control of others
|
||||
* Written by jrandom in 2003 and released into the public domain
|
||||
* with no warranty of any kind, either expressed or implied.
|
||||
* It probably won't make your computer catch on fire, or eat
|
||||
* your children, but it might. Use at your own risk.
|
||||
*
|
||||
*/
|
||||
|
||||
import net.i2p.data.Destination;
|
||||
import net.i2p.data.Payload;
|
||||
import net.i2p.data.i2cp.MessageId;
|
||||
import net.i2p.data.i2cp.MessageStatusMessage;
|
||||
import net.i2p.router.RouterContext;
|
||||
import net.i2p.util.I2PThread;
|
||||
|
||||
/**
|
||||
* For testing clients without a full router.
|
||||
* A complete router-side I2CP implementation, without requiring a router
|
||||
* or any RouterContext subsystems or threads.
|
||||
* Clients may connect only to other local clients.
|
||||
* Lookups and bw limit messages also supported.
|
||||
*
|
||||
* @since 0.9.8
|
||||
*/
|
||||
class LocalClientManager extends ClientManager {
|
||||
|
||||
/**
|
||||
* @param context stub, may be constructed with new RouterContext(null),
|
||||
* no initAll() necessary
|
||||
*/
|
||||
public LocalClientManager(RouterContext context, int port) {
|
||||
super(context, port);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startListeners() {
|
||||
_listener = new LocalClientListenerRunner(_ctx, this, _port);
|
||||
Thread t = new I2PThread(_listener, "ClientListener:" + _port, true);
|
||||
t.start();
|
||||
_isStarted = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Local only
|
||||
* TODO: add simulated delay and random drops to test streaming.
|
||||
*
|
||||
* @param flags ignored for local
|
||||
*/
|
||||
@Override
|
||||
void distributeMessage(Destination fromDest, Destination toDest, Payload payload, MessageId msgId, long expiration, int flags) {
|
||||
// check if there is a runner for it
|
||||
ClientConnectionRunner sender = getRunner(fromDest);
|
||||
ClientConnectionRunner runner = getRunner(toDest);
|
||||
if (runner != null) {
|
||||
runner.receiveMessage(toDest, fromDest, payload);
|
||||
if (sender != null)
|
||||
sender.updateMessageDeliveryStatus(msgId, MessageStatusMessage.STATUS_SEND_SUCCESS_LOCAL);
|
||||
} else {
|
||||
// remote. ignore.
|
||||
System.out.println("Message " + msgId + " is targeting a REMOTE destination - DROPPED");
|
||||
if (sender != null)
|
||||
sender.updateMessageDeliveryStatus(msgId, MessageStatusMessage.STATUS_SEND_GUARANTEED_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String args[]) {
|
||||
RouterContext ctx = new RouterContext(null);
|
||||
int port = ClientManagerFacadeImpl.DEFAULT_PORT;
|
||||
ClientManager mgr = new LocalClientManager(ctx, port);
|
||||
mgr.start();
|
||||
System.out.println("Listening on port " + port);
|
||||
try { Thread.sleep(5*60*1000); } catch (InterruptedException ie) {}
|
||||
System.out.println("Done listening on port " + port);
|
||||
}
|
||||
}
|
@ -0,0 +1,94 @@
|
||||
package net.i2p.router.client;
|
||||
/*
|
||||
* free (adj.): unencumbered; not under the control of others
|
||||
* Written by jrandom in 2003 and released into the public domain
|
||||
* with no warranty of any kind, either expressed or implied.
|
||||
* It probably won't make your computer catch on fire, or eat
|
||||
* your children, but it might. Use at your own risk.
|
||||
*
|
||||
*/
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import net.i2p.data.Destination;
|
||||
import net.i2p.data.Hash;
|
||||
import net.i2p.data.Lease;
|
||||
import net.i2p.data.LeaseSet;
|
||||
import net.i2p.data.TunnelId;
|
||||
import net.i2p.data.i2cp.BandwidthLimitsMessage;
|
||||
import net.i2p.data.i2cp.CreateLeaseSetMessage;
|
||||
import net.i2p.data.i2cp.DestLookupMessage;
|
||||
import net.i2p.data.i2cp.DestReplyMessage;
|
||||
import net.i2p.data.i2cp.GetBandwidthLimitsMessage;
|
||||
import net.i2p.data.i2cp.I2CPMessageException;
|
||||
import net.i2p.router.RouterContext;
|
||||
|
||||
/**
|
||||
* For testing
|
||||
*
|
||||
* @since 0.9.8
|
||||
*/
|
||||
class LocalClientMessageEventListener extends ClientMessageEventListener {
|
||||
|
||||
public LocalClientMessageEventListener(RouterContext context, ClientConnectionRunner runner, boolean enforceAuth) {
|
||||
super(context, runner, enforceAuth);
|
||||
}
|
||||
|
||||
/**
|
||||
* Immediately send a fake leaseset
|
||||
*/
|
||||
@Override
|
||||
protected void startCreateSessionJob() {
|
||||
long exp = _context.clock().now() + 10*60*1000;
|
||||
LeaseSet ls = new LeaseSet();
|
||||
Lease lease = new Lease();
|
||||
lease.setGateway(Hash.FAKE_HASH);
|
||||
TunnelId id = new TunnelId(1);
|
||||
lease.setTunnelId(id);
|
||||
Date date = new Date(exp);
|
||||
lease.setEndDate(date);
|
||||
ls.addLease(lease);
|
||||
_runner.requestLeaseSet(ls, exp, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't tell the netdb or key manager
|
||||
*/
|
||||
@Override
|
||||
protected void handleCreateLeaseSet(CreateLeaseSetMessage message) {
|
||||
_runner.leaseSetCreated(message.getLeaseSet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Look only in current local dests
|
||||
*/
|
||||
@Override
|
||||
protected void handleDestLookup(DestLookupMessage message) {
|
||||
Hash h = message.getHash();
|
||||
DestReplyMessage msg;
|
||||
Destination d = ((LocalClientConnectionRunner)_runner).localLookup(h);
|
||||
if (d != null)
|
||||
msg = new DestReplyMessage(d);
|
||||
else
|
||||
msg = new DestReplyMessage(h);
|
||||
try {
|
||||
_runner.doSend(msg);
|
||||
} catch (I2CPMessageException ime) {
|
||||
ime.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send dummy limits
|
||||
*/
|
||||
@Override
|
||||
protected void handleGetBWLimits(GetBandwidthLimitsMessage message) {
|
||||
int limit = 1024*1024;
|
||||
BandwidthLimitsMessage msg = new BandwidthLimitsMessage(limit, limit);
|
||||
try {
|
||||
_runner.doSend(msg);
|
||||
} catch (I2CPMessageException ime) {
|
||||
ime.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user