forked from I2P_Developers/i2p.i2p
* 2005-07-27 0.6 released
2005-07-27 jrandom * Enabled SSU as the default top priority transport, adjusting the config.jsp page accordingly. * Add verification fields to the SSU and TCP connection negotiation (not compatible with previous builds) * Enable the backwards incompatible tunnel crypto change as documented in tunnel-alt.html (have each hop encrypt the received IV before using it, then encrypt it again before sending it on) * Disable the I2CP encryption, leaving in place the end to end garlic encryption (another backwards incompatible change) * Adjust the protocol versions on the TCP and SSU transports so that they won't talk to older routers. * Fix up the config stats handling again * Fix a rare off-by-one in the SSU fragmentation * Reduce some unnecessary netDb resending by inluding the peers queried successfully in the store redundancy count.
This commit is contained in:
@ -15,9 +15,9 @@ import net.i2p.CoreVersion;
|
||||
*
|
||||
*/
|
||||
public class RouterVersion {
|
||||
public final static String ID = "$Revision: 1.207 $ $Date: 2005/07/21 17:37:15 $";
|
||||
public final static String VERSION = "0.5.0.7";
|
||||
public final static long BUILD = 19;
|
||||
public final static String ID = "$Revision: 1.208 $ $Date: 2005/07/22 19:15:58 $";
|
||||
public final static String VERSION = "0.6";
|
||||
public final static long BUILD = 0;
|
||||
public static void main(String args[]) {
|
||||
System.out.println("I2P Router version: " + VERSION);
|
||||
System.out.println("Router ID: " + RouterVersion.ID);
|
||||
|
@ -102,12 +102,12 @@ public class StatisticsManager implements Service {
|
||||
stats.putAll(_context.profileManager().summarizePeers(_publishedStats));
|
||||
|
||||
includeThroughput(stats);
|
||||
includeRate("router.invalidMessageTime", stats, new long[] { 10*60*1000 });
|
||||
//includeRate("router.invalidMessageTime", stats, new long[] { 10*60*1000 });
|
||||
includeRate("router.duplicateMessageId", stats, new long[] { 24*60*60*1000 });
|
||||
includeRate("tunnel.duplicateIV", stats, new long[] { 24*60*60*1000 });
|
||||
//includeRate("tunnel.duplicateIV", stats, new long[] { 24*60*60*1000 });
|
||||
includeRate("tunnel.fragmentedDropped", stats, new long[] { 10*60*1000, 3*60*60*1000 });
|
||||
includeRate("tunnel.fullFragments", stats, new long[] { 10*60*1000, 3*60*60*1000 });
|
||||
includeRate("tunnel.smallFragments", stats, new long[] { 10*60*1000, 3*60*60*1000 });
|
||||
//includeRate("tunnel.fullFragments", stats, new long[] { 10*60*1000, 3*60*60*1000 });
|
||||
//includeRate("tunnel.smallFragments", stats, new long[] { 10*60*1000, 3*60*60*1000 });
|
||||
includeRate("tunnel.testFailedTime", stats, new long[] { 60*60*1000 });
|
||||
|
||||
includeRate("tunnel.buildFailure", stats, new long[] { 60*60*1000 });
|
||||
@ -117,22 +117,26 @@ public class StatisticsManager implements Service {
|
||||
includeRate("tunnel.batchMultipleCount", stats, new long[] { 10*60*1000, 60*60*1000 });
|
||||
includeRate("tunnel.corruptMessage", stats, new long[] { 60*60*1000l, 3*60*60*1000l });
|
||||
|
||||
includeRate("router.throttleTunnelProbTestSlow", stats, new long[] { 60*60*1000 });
|
||||
includeRate("router.throttleTunnelProbTooFast", stats, new long[] { 60*60*1000 });
|
||||
includeRate("router.throttleTunnelProcessingTime1m", stats, new long[] { 60*60*1000 });
|
||||
//includeRate("router.throttleTunnelProbTestSlow", stats, new long[] { 60*60*1000 });
|
||||
//includeRate("router.throttleTunnelProbTooFast", stats, new long[] { 60*60*1000 });
|
||||
//includeRate("router.throttleTunnelProcessingTime1m", stats, new long[] { 60*60*1000 });
|
||||
|
||||
includeRate("router.fastPeers", stats, new long[] { 60*60*1000 });
|
||||
|
||||
includeRate("clock.skew", stats, new long[] { 10*60*1000, 3*60*60*1000, 24*60*60*1000 });
|
||||
|
||||
includeRate("transport.sendProcessingTime", stats, new long[] { 60*60*1000 });
|
||||
includeRate("jobQueue.jobRunSlow", stats, new long[] { 10*60*1000l, 60*60*1000l });
|
||||
//includeRate("transport.sendProcessingTime", stats, new long[] { 60*60*1000 });
|
||||
//includeRate("jobQueue.jobRunSlow", stats, new long[] { 10*60*1000l, 60*60*1000l });
|
||||
includeRate("crypto.elGamal.encrypt", stats, new long[] { 60*60*1000 });
|
||||
includeRate("tunnel.participatingTunnels", stats, new long[] { 5*60*1000, 60*60*1000 });
|
||||
includeRate("tunnel.testSuccessTime", stats, new long[] { 60*60*1000l, 24*60*60*1000l });
|
||||
includeRate("client.sendAckTime", stats, new long[] { 60*60*1000 }, true);
|
||||
includeRate("stream.con.sendDuplicateSize", stats, new long[] { 60*60*1000 });
|
||||
includeRate("stream.con.receiveDuplicateSize", stats, new long[] { 60*60*1000 });
|
||||
includeRate("udp.sendConfirmTime", stats, new long[] { 10*60*1000 });
|
||||
includeRate("udp.sendVolleyTime", stats, new long[] { 10*60*1000 });
|
||||
includeRate("udp.ignoreRecentDuplicate", stats, new long[] { 10*60*1000 });
|
||||
includeRate("udp.congestionOccurred", stats, new long[] { 10*60*1000 });
|
||||
//includeRate("stream.con.sendDuplicateSize", stats, new long[] { 60*60*1000 });
|
||||
//includeRate("stream.con.receiveDuplicateSize", stats, new long[] { 60*60*1000 });
|
||||
stats.setProperty("stat_uptime", DataHelper.formatDuration(_context.router().getUptime()));
|
||||
stats.setProperty("stat__rateKey", "avg;maxAvg;pctLifetime;[sat;satLim;maxSat;maxSatLim;][num;lifetimeFreq;maxFreq]");
|
||||
_log.debug("Publishing peer rankings");
|
||||
|
@ -281,7 +281,7 @@ class StoreJob extends JobImpl {
|
||||
getContext().profileManager().dbStoreSent(_peer.getIdentity().getHash(), howLong);
|
||||
getContext().statManager().addRateData("netDb.ackTime", howLong, howLong);
|
||||
|
||||
if (_state.getSuccessful().size() >= REDUNDANCY) {
|
||||
if (_state.getCompleteCount() >= REDUNDANCY) {
|
||||
succeed();
|
||||
} else {
|
||||
sendNext();
|
||||
|
@ -21,6 +21,7 @@ class StoreState {
|
||||
private HashSet _successfulExploratoryPeers;
|
||||
private HashSet _failedPeers;
|
||||
private HashSet _attemptedPeers;
|
||||
private int _completeCount;
|
||||
private volatile long _completed;
|
||||
private volatile long _started;
|
||||
|
||||
@ -34,8 +35,10 @@ class StoreState {
|
||||
_pendingPeers = new HashSet(16);
|
||||
_pendingPeerTimes = new HashMap(16);
|
||||
_attemptedPeers = new HashSet(16);
|
||||
if (toSkip != null)
|
||||
if (toSkip != null) {
|
||||
_attemptedPeers.addAll(toSkip);
|
||||
_completeCount = toSkip.size();
|
||||
}
|
||||
_failedPeers = new HashSet(16);
|
||||
_successfulPeers = new HashSet(16);
|
||||
_successfulExploratoryPeers = new HashSet(16);
|
||||
@ -75,6 +78,7 @@ class StoreState {
|
||||
if (completed)
|
||||
_completed = _context.clock().now();
|
||||
}
|
||||
public int getCompleteCount() { return _completeCount; }
|
||||
|
||||
public long getWhenStarted() { return _started; }
|
||||
public long getWhenCompleted() { return _completed; }
|
||||
@ -110,6 +114,7 @@ class StoreState {
|
||||
synchronized (_successfulPeers) {
|
||||
_successfulPeers.add(peer);
|
||||
}
|
||||
_completeCount++;
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,7 @@ public class TransportManager implements TransportEventListener {
|
||||
|
||||
private final static String PROP_DISABLE_TCP = "i2np.tcp.disable";
|
||||
private final static String PROP_ENABLE_UDP = "i2np.udp.enable";
|
||||
private static final String DEFAULT_ENABLE_UDP = "true";
|
||||
|
||||
public TransportManager(RouterContext context) {
|
||||
_context = context;
|
||||
@ -63,7 +64,9 @@ public class TransportManager implements TransportEventListener {
|
||||
_transports.add(t);
|
||||
}
|
||||
String enableUDP = _context.router().getConfigSetting(PROP_ENABLE_UDP);
|
||||
if ( (enableUDP != null) && (Boolean.valueOf(enableUDP).booleanValue())) {
|
||||
if (enableUDP == null)
|
||||
enableUDP = DEFAULT_ENABLE_UDP;
|
||||
if ("true".equalsIgnoreCase(enableUDP)) {
|
||||
UDPTransport udp = new UDPTransport(_context);
|
||||
udp.setListener(this);
|
||||
_transports.add(udp);
|
||||
|
@ -529,8 +529,12 @@ public class ConnectionBuilder {
|
||||
return false;
|
||||
}
|
||||
|
||||
// our public == X, since we are establishing the connection
|
||||
byte X[] = builder.getMyPublicValueBytes();
|
||||
byte Y[] = builder.getPeerPublicValueBytes();
|
||||
|
||||
// send: routerInfo + currentTime
|
||||
// + S(routerInfo + currentTime + nonce + nextTag, routerIdent.signingKey)
|
||||
// + S(routerInfo + currentTime + nonce + nextTag + X + Y, routerIdent.signingKey)
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(512);
|
||||
_context.router().getRouterInfo().writeBytes(baos);
|
||||
@ -540,6 +544,8 @@ public class ConnectionBuilder {
|
||||
|
||||
baos.write(_nonce.getData());
|
||||
baos.write(_nextConnectionTag.getData());
|
||||
baos.write(X);
|
||||
baos.write(Y);
|
||||
Signature sig = _context.dsa().sign(baos.toByteArray(),
|
||||
_context.keyManager().getSigningPrivateKey());
|
||||
|
||||
@ -556,7 +562,7 @@ public class ConnectionBuilder {
|
||||
}
|
||||
|
||||
// read: routerInfo + status + properties
|
||||
// + S(routerInfo + status + properties + nonce + nextTag, routerIdent.signingKey)
|
||||
// + S(routerInfo + status + properties + nonce + nextTag + X + Y, routerIdent.signingKey)
|
||||
try {
|
||||
RouterInfo peer = new RouterInfo();
|
||||
peer.readBytes(_rawIn);
|
||||
@ -578,6 +584,8 @@ public class ConnectionBuilder {
|
||||
DataHelper.writeProperties(baos, props);
|
||||
baos.write(_nonce.getData());
|
||||
baos.write(_nextConnectionTag.getData());
|
||||
baos.write(X);
|
||||
baos.write(Y);
|
||||
ok = _context.dsa().verifySignature(sig, baos.toByteArray(),
|
||||
peer.getIdentity().getSigningPublicKey());
|
||||
|
||||
|
@ -555,8 +555,12 @@ public class ConnectionHandler {
|
||||
long clockSkew = 0;
|
||||
boolean sigOk = false;
|
||||
|
||||
// our public == Y, since we are receiving the connection
|
||||
byte X[] = builder.getPeerPublicValueBytes();
|
||||
byte Y[] = builder.getMyPublicValueBytes();
|
||||
|
||||
// read: routerInfo + currentTime
|
||||
// + S(routerInfo + currentTime + nonce + nextTag, routerIdent.signingKey)
|
||||
// + S(routerInfo + currentTime + nonce + nextTag + X + Y, routerIdent.signingKey)
|
||||
try {
|
||||
RouterInfo info = new RouterInfo();
|
||||
info.readBytes(_rawIn);
|
||||
@ -569,6 +573,8 @@ public class ConnectionHandler {
|
||||
DataHelper.writeDate(baos, now);
|
||||
baos.write(_nonce.getData());
|
||||
baos.write(_nextConnectionTag.getData());
|
||||
baos.write(X);
|
||||
baos.write(Y);
|
||||
|
||||
sigOk = _context.dsa().verifySignature(sig, baos.toByteArray(),
|
||||
info.getIdentity().getSigningPublicKey());
|
||||
@ -589,7 +595,7 @@ public class ConnectionHandler {
|
||||
boolean reachable = verifyReachability();
|
||||
|
||||
// send: routerInfo + status + properties
|
||||
// + S(routerInfo + status + properties + nonce + nextTag, routerIdent.signingKey)
|
||||
// + S(routerInfo + status + properties + nonce + nextTag + X + Y, routerIdent.signingKey)
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(512);
|
||||
_context.router().getRouterInfo().writeBytes(baos);
|
||||
@ -629,6 +635,8 @@ public class ConnectionHandler {
|
||||
|
||||
baos.write(_nonce.getData());
|
||||
baos.write(_nextConnectionTag.getData());
|
||||
baos.write(X);
|
||||
baos.write(Y);
|
||||
|
||||
Signature sig = _context.dsa().sign(baos.toByteArray(),
|
||||
_context.keyManager().getSigningPrivateKey());
|
||||
|
@ -89,7 +89,7 @@ public class TCPTransport extends TransportImpl {
|
||||
public static final int DEFAULT_ESTABLISHERS = 3;
|
||||
|
||||
/** Ordered list of supported I2NP protocols */
|
||||
public static final int[] SUPPORTED_PROTOCOLS = new int[] { 4 }; // drop <= 0.5.0.3
|
||||
public static final int[] SUPPORTED_PROTOCOLS = new int[] { 5 }; // drop < 0.6
|
||||
/** blah, people shouldnt use defaults... */
|
||||
public static final int DEFAULT_LISTEN_PORT = 8887;
|
||||
|
||||
|
@ -98,7 +98,8 @@ public class ACKSender implements Runnable {
|
||||
|
||||
if ( (ackBitfields != null) && (ackBitfields.size() > 0) ) {
|
||||
_context.statManager().addRateData("udp.sendACKCount", ackBitfields.size(), 0);
|
||||
_context.statManager().addRateData("udp.sendACKRemaining", remaining, 0);
|
||||
if (remaining > 0)
|
||||
_context.statManager().addRateData("udp.sendACKRemaining", remaining, 0);
|
||||
now = _context.clock().now();
|
||||
if (lastSend < 0)
|
||||
lastSend = now - 1;
|
||||
|
@ -63,8 +63,7 @@ public class EstablishmentManager {
|
||||
/**
|
||||
* Grab the active establishing state
|
||||
*/
|
||||
InboundEstablishState getInboundState(InetAddress fromHost, int fromPort) {
|
||||
RemoteHostId from = new RemoteHostId(fromHost.getAddress(), fromPort);
|
||||
InboundEstablishState getInboundState(RemoteHostId from) {
|
||||
synchronized (_inboundStates) {
|
||||
InboundEstablishState state = (InboundEstablishState)_inboundStates.get(from);
|
||||
if ( (state == null) && (_log.shouldLog(Log.DEBUG)) )
|
||||
@ -73,8 +72,7 @@ public class EstablishmentManager {
|
||||
}
|
||||
}
|
||||
|
||||
OutboundEstablishState getOutboundState(InetAddress fromHost, int fromPort) {
|
||||
RemoteHostId from = new RemoteHostId(fromHost.getAddress(), fromPort);
|
||||
OutboundEstablishState getOutboundState(RemoteHostId from) {
|
||||
synchronized (_outboundStates) {
|
||||
OutboundEstablishState state = (OutboundEstablishState)_outboundStates.get(from);
|
||||
if ( (state == null) && (_log.shouldLog(Log.DEBUG)) )
|
||||
@ -121,12 +119,12 @@ public class EstablishmentManager {
|
||||
* Got a SessionRequest (initiates an inbound establishment)
|
||||
*
|
||||
*/
|
||||
void receiveSessionRequest(RemoteHostId from, InetAddress host, int port, UDPPacketReader reader) {
|
||||
void receiveSessionRequest(RemoteHostId from, UDPPacketReader reader) {
|
||||
InboundEstablishState state = null;
|
||||
synchronized (_inboundStates) {
|
||||
state = (InboundEstablishState)_inboundStates.get(from);
|
||||
if (state == null) {
|
||||
state = new InboundEstablishState(_context, host, port, _transport.getLocalPort());
|
||||
state = new InboundEstablishState(_context, from.getIP(), from.getPort(), _transport.getLocalPort());
|
||||
_inboundStates.put(from, state);
|
||||
}
|
||||
}
|
||||
|
@ -66,10 +66,10 @@ public class InboundEstablishState {
|
||||
/** we have completely received all of the confirmation packets */
|
||||
public static final int STATE_CONFIRMED_COMPLETELY = 4;
|
||||
|
||||
public InboundEstablishState(RouterContext ctx, InetAddress remoteHost, int remotePort, int localPort) {
|
||||
public InboundEstablishState(RouterContext ctx, byte remoteIP[], int remotePort, int localPort) {
|
||||
_context = ctx;
|
||||
_log = ctx.logManager().getLog(InboundEstablishState.class);
|
||||
_aliceIP = remoteHost.getAddress();
|
||||
_aliceIP = remoteIP;
|
||||
_alicePort = remotePort;
|
||||
_remoteHostId = new RemoteHostId(_aliceIP, _alicePort);
|
||||
_bobPort = localPort;
|
||||
@ -141,7 +141,8 @@ public class InboundEstablishState {
|
||||
* new relay tag + Bob's signed on time
|
||||
*/
|
||||
private void signSessionCreated() {
|
||||
byte signed[] = new byte[_aliceIP.length + 2
|
||||
byte signed[] = new byte[256 + 256 // X + Y
|
||||
+ _aliceIP.length + 2
|
||||
+ _bobIP.length + 2
|
||||
+ 4 // sent relay tag
|
||||
+ 4 // signed on time
|
||||
@ -149,6 +150,12 @@ public class InboundEstablishState {
|
||||
_sentSignedOnTime = _context.clock().now() / 1000;
|
||||
|
||||
int off = 0;
|
||||
System.arraycopy(_receivedX, 0, signed, off, _receivedX.length);
|
||||
off += _receivedX.length;
|
||||
if (_sentY == null)
|
||||
_sentY = getSentY();
|
||||
System.arraycopy(_sentY, 0, signed, off, _sentY.length);
|
||||
off += _sentY.length;
|
||||
System.arraycopy(_aliceIP, 0, signed, off, _aliceIP.length);
|
||||
off += _aliceIP.length;
|
||||
DataHelper.toLong(signed, off, 2, _alicePort);
|
||||
@ -166,6 +173,8 @@ public class InboundEstablishState {
|
||||
if (_log.shouldLog(Log.DEBUG)) {
|
||||
StringBuffer buf = new StringBuffer(128);
|
||||
buf.append("Signing sessionCreated:");
|
||||
buf.append(" ReceivedX: ").append(Base64.encode(_receivedX));
|
||||
buf.append(" SentY: ").append(Base64.encode(_sentY));
|
||||
buf.append(" AliceIP: ").append(Base64.encode(_aliceIP));
|
||||
buf.append(" AlicePort: ").append(_alicePort);
|
||||
buf.append(" BobIP: ").append(Base64.encode(_bobIP));
|
||||
@ -266,13 +275,18 @@ public class InboundEstablishState {
|
||||
try {
|
||||
peer.readBytes(in);
|
||||
|
||||
byte signed[] = new byte[_aliceIP.length + 2
|
||||
byte signed[] = new byte[256+256 // X + Y
|
||||
+ _aliceIP.length + 2
|
||||
+ _bobIP.length + 2
|
||||
+ 4 // Alice's relay key
|
||||
+ 4 // signed on time
|
||||
];
|
||||
|
||||
off = 0;
|
||||
System.arraycopy(_receivedX, 0, signed, off, _receivedX.length);
|
||||
off += _receivedX.length;
|
||||
System.arraycopy(_sentY, 0, signed, off, _sentY.length);
|
||||
off += _sentY.length;
|
||||
System.arraycopy(_aliceIP, 0, signed, off, _aliceIP.length);
|
||||
off += _aliceIP.length;
|
||||
DataHelper.toLong(signed, off, 2, _alicePort);
|
||||
|
@ -152,7 +152,8 @@ public class InboundMessageFragments /*implements UDPTransport.PartialACKSource
|
||||
_log.info("Message received completely! " + state);
|
||||
|
||||
_context.statManager().addRateData("udp.receivedCompleteTime", state.getLifetime(), state.getLifetime());
|
||||
_context.statManager().addRateData("udp.receivedCompleteFragments", state.getFragmentCount(), state.getLifetime());
|
||||
if (state.getFragmentCount() > 0)
|
||||
_context.statManager().addRateData("udp.receivedCompleteFragments", state.getFragmentCount(), state.getLifetime());
|
||||
} else if (messageExpired) {
|
||||
state.releaseResources();
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
|
@ -234,13 +234,18 @@ public class OutboundEstablishState {
|
||||
* new relay tag + Bob's signed on time
|
||||
*/
|
||||
private boolean verifySessionCreated() {
|
||||
byte signed[] = new byte[_aliceIP.length + 2
|
||||
byte signed[] = new byte[256+256 // X + Y
|
||||
+ _aliceIP.length + 2
|
||||
+ _bobIP.length + 2
|
||||
+ 4 // sent relay tag
|
||||
+ 4 // signed on time
|
||||
];
|
||||
|
||||
int off = 0;
|
||||
System.arraycopy(_sentX, 0, signed, off, _sentX.length);
|
||||
off += _sentX.length;
|
||||
System.arraycopy(_receivedY, 0, signed, off, _receivedY.length);
|
||||
off += _receivedY.length;
|
||||
System.arraycopy(_aliceIP, 0, signed, off, _aliceIP.length);
|
||||
off += _aliceIP.length;
|
||||
DataHelper.toLong(signed, off, 2, _alicePort);
|
||||
@ -287,7 +292,8 @@ public class OutboundEstablishState {
|
||||
public synchronized void prepareSessionConfirmed() {
|
||||
if (_sentSignedOnTime > 0)
|
||||
return;
|
||||
byte signed[] = new byte[_aliceIP.length + 2
|
||||
byte signed[] = new byte[256+256 // X + Y
|
||||
+ _aliceIP.length + 2
|
||||
+ _bobIP.length + 2
|
||||
+ 4 // Alice's relay key
|
||||
+ 4 // signed on time
|
||||
@ -296,6 +302,10 @@ public class OutboundEstablishState {
|
||||
_sentSignedOnTime = _context.clock().now() / 1000;
|
||||
|
||||
int off = 0;
|
||||
System.arraycopy(_sentX, 0, signed, off, _sentX.length);
|
||||
off += _sentX.length;
|
||||
System.arraycopy(_receivedY, 0, signed, off, _receivedY.length);
|
||||
off += _receivedY.length;
|
||||
System.arraycopy(_aliceIP, 0, signed, off, _aliceIP.length);
|
||||
off += _aliceIP.length;
|
||||
DataHelper.toLong(signed, off, 2, _alicePort);
|
||||
|
@ -35,7 +35,7 @@ public class OutboundMessageFragments {
|
||||
/** if we can handle more messages explicitly, set this to true */
|
||||
private boolean _allowExcess;
|
||||
|
||||
private static final int MAX_ACTIVE = 16;
|
||||
private static final int MAX_ACTIVE = 32;
|
||||
// don't send a packet more than 10 times
|
||||
static final int MAX_VOLLEYS = 10;
|
||||
|
||||
@ -414,8 +414,10 @@ public class OutboundMessageFragments {
|
||||
_log.info("Received ack of " + messageId + " by " + ackedBy.toBase64()
|
||||
+ " after " + state.getLifetime() + " and " + numSends + " sends");
|
||||
_context.statManager().addRateData("udp.sendConfirmTime", state.getLifetime(), state.getLifetime());
|
||||
_context.statManager().addRateData("udp.sendConfirmFragments", state.getFragmentCount(), state.getLifetime());
|
||||
_context.statManager().addRateData("udp.sendConfirmVolley", numSends, state.getFragmentCount());
|
||||
if (state.getFragmentCount() > 1)
|
||||
_context.statManager().addRateData("udp.sendConfirmFragments", state.getFragmentCount(), state.getLifetime());
|
||||
if (numSends > 1)
|
||||
_context.statManager().addRateData("udp.sendConfirmVolley", numSends, state.getFragmentCount());
|
||||
_transport.succeeded(state.getMessage());
|
||||
int numFragments = state.getFragmentCount();
|
||||
if (state.getPeer() != null) {
|
||||
@ -494,8 +496,10 @@ public class OutboundMessageFragments {
|
||||
|
||||
if (isComplete) {
|
||||
_context.statManager().addRateData("udp.sendConfirmTime", state.getLifetime(), state.getLifetime());
|
||||
_context.statManager().addRateData("udp.sendConfirmFragments", state.getFragmentCount(), state.getLifetime());
|
||||
_context.statManager().addRateData("udp.sendConfirmVolley", numSends, state.getFragmentCount());
|
||||
if (state.getFragmentCount() > 1)
|
||||
_context.statManager().addRateData("udp.sendConfirmFragments", state.getFragmentCount(), state.getLifetime());
|
||||
if (numSends > 1)
|
||||
_context.statManager().addRateData("udp.sendConfirmVolley", numSends, state.getFragmentCount());
|
||||
_transport.succeeded(state.getMessage());
|
||||
|
||||
if (state.getPeer() != null) {
|
||||
|
@ -225,10 +225,15 @@ public class OutboundMessageState {
|
||||
public boolean shouldSend(int fragmentNum) { return _fragmentSends[fragmentNum] >= (short)0; }
|
||||
public int fragmentSize(int fragmentNum) {
|
||||
if (_messageBuf == null) return -1;
|
||||
if (fragmentNum + 1 == _fragmentSends.length)
|
||||
return _messageBuf.getValid() % _fragmentSize;
|
||||
else
|
||||
if (fragmentNum + 1 == _fragmentSends.length) {
|
||||
int valid = _messageBuf.getValid();
|
||||
if (valid <= _fragmentSize)
|
||||
return valid;
|
||||
else
|
||||
return valid % _fragmentSize;
|
||||
} else {
|
||||
return _fragmentSize;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -241,10 +246,8 @@ public class OutboundMessageState {
|
||||
*/
|
||||
public int writeFragment(byte out[], int outOffset, int fragmentNum) {
|
||||
int start = _fragmentSize * fragmentNum;
|
||||
int end = start + _fragmentSize;
|
||||
int end = start + fragmentSize(fragmentNum);
|
||||
if (_messageBuf == null) return -1;
|
||||
if (end > _messageBuf.getValid())
|
||||
end = _messageBuf.getValid();
|
||||
int toSend = end - start;
|
||||
System.arraycopy(_messageBuf.getData(), start, out, outOffset, toSend);
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
|
@ -100,13 +100,12 @@ public class PacketHandler {
|
||||
private void handlePacket(UDPPacketReader reader, UDPPacket packet) {
|
||||
if (packet == null) return;
|
||||
|
||||
InetAddress remAddr = packet.getPacket().getAddress();
|
||||
int remPort = packet.getPacket().getPort();
|
||||
PeerState state = _transport.getPeerState(remAddr, remPort);
|
||||
RemoteHostId rem = packet.getRemoteHost();
|
||||
PeerState state = _transport.getPeerState(rem);
|
||||
if (state == null) {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Packet received is not for a connected peer");
|
||||
InboundEstablishState est = _establisher.getInboundState(remAddr, remPort);
|
||||
InboundEstablishState est = _establisher.getInboundState(rem);
|
||||
if (est != null) {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Packet received IS for an inbound establishment");
|
||||
@ -114,7 +113,7 @@ public class PacketHandler {
|
||||
} else {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Packet received is not for an inbound establishment");
|
||||
OutboundEstablishState oest = _establisher.getOutboundState(remAddr, remPort);
|
||||
OutboundEstablishState oest = _establisher.getOutboundState(rem);
|
||||
if (oest != null) {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Packet received IS for an outbound establishment");
|
||||
@ -152,9 +151,7 @@ public class PacketHandler {
|
||||
_log.info("Validation with existing con failed, but validation as reestablish/stray passed");
|
||||
packet.decrypt(_transport.getIntroKey());
|
||||
} else {
|
||||
InetAddress remAddr = packet.getPacket().getAddress();
|
||||
int remPort = packet.getPacket().getPort();
|
||||
InboundEstablishState est = _establisher.getInboundState(remAddr, remPort);
|
||||
InboundEstablishState est = _establisher.getInboundState(packet.getRemoteHost());
|
||||
if (est != null) {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Packet from an existing peer IS for an inbound establishment");
|
||||
@ -304,13 +301,14 @@ public class PacketHandler {
|
||||
|
||||
_context.statManager().addRateData("udp.receivePacketSkew", skew, packet.getLifetime());
|
||||
|
||||
InetAddress fromHost = packet.getPacket().getAddress();
|
||||
int fromPort = packet.getPacket().getPort();
|
||||
RemoteHostId from = new RemoteHostId(fromHost.getAddress(), fromPort);
|
||||
//InetAddress fromHost = packet.getPacket().getAddress();
|
||||
//int fromPort = packet.getPacket().getPort();
|
||||
//RemoteHostId from = new RemoteHostId(fromHost.getAddress(), fromPort);
|
||||
RemoteHostId from = packet.getRemoteHost();
|
||||
|
||||
switch (reader.readPayloadType()) {
|
||||
case UDPPacket.PAYLOAD_TYPE_SESSION_REQUEST:
|
||||
_establisher.receiveSessionRequest(from, fromHost, fromPort, reader);
|
||||
_establisher.receiveSessionRequest(from, reader);
|
||||
break;
|
||||
case UDPPacket.PAYLOAD_TYPE_SESSION_CONFIRMED:
|
||||
_establisher.receiveSessionConfirmed(from, reader);
|
||||
|
@ -541,10 +541,11 @@ public class PeerState {
|
||||
}
|
||||
}
|
||||
|
||||
_context.statManager().addRateData("udp.sendACKPartial", partialIncluded, rv.size() - partialIncluded);
|
||||
_lastACKSend = _context.clock().now();
|
||||
if (rv == null)
|
||||
rv = Collections.EMPTY_LIST;
|
||||
if (partialIncluded > 0)
|
||||
_context.statManager().addRateData("udp.sendACKPartial", partialIncluded, rv.size() - partialIncluded);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@ public class UDPEndpoint {
|
||||
_receiver.startup();
|
||||
} catch (SocketException se) {
|
||||
if (_log.shouldLog(Log.ERROR))
|
||||
_log.error("Unable to bind on " + _listenPort);
|
||||
_log.error("Unable to bind on " + _listenPort, se);
|
||||
}
|
||||
}
|
||||
|
||||
@ -45,11 +45,10 @@ public class UDPEndpoint {
|
||||
if (_sender != null) {
|
||||
_sender.shutdown();
|
||||
_receiver.shutdown();
|
||||
_sender = null;
|
||||
_receiver = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void setListenPort(int newPort) { _listenPort = newPort; }
|
||||
public void updateListenPort(int newPort) {
|
||||
if (newPort == _listenPort) return;
|
||||
try {
|
||||
|
@ -32,6 +32,7 @@ public class UDPPacket {
|
||||
private volatile byte[] _data;
|
||||
private volatile ByteArray _dataBuf;
|
||||
private volatile int _markedType;
|
||||
private volatile RemoteHostId _remoteHost;
|
||||
private volatile boolean _released;
|
||||
private volatile Exception _releasedBy;
|
||||
private volatile Exception _acquiredBy;
|
||||
@ -78,6 +79,7 @@ public class UDPPacket {
|
||||
_packet = new DatagramPacket(_data, MAX_PACKET_SIZE);
|
||||
_initializeTime = _context.clock().now();
|
||||
_markedType = -1;
|
||||
_remoteHost = null;
|
||||
}
|
||||
|
||||
public void initialize(int priority, long expiration, InetAddress host, int port) {
|
||||
@ -88,6 +90,7 @@ public class UDPPacket {
|
||||
//_packet.setLength(0);
|
||||
_packet.setAddress(host);
|
||||
_packet.setPort(port);
|
||||
_remoteHost = null;
|
||||
_released = false;
|
||||
_releasedBy = null;
|
||||
}
|
||||
@ -113,6 +116,12 @@ public class UDPPacket {
|
||||
*/
|
||||
public int getMarkedType() { verifyNotReleased(); return _markedType; }
|
||||
|
||||
public RemoteHostId getRemoteHost() {
|
||||
if (_remoteHost == null)
|
||||
_remoteHost = new RemoteHostId(_packet.getAddress().getAddress(), _packet.getPort());
|
||||
return _remoteHost;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the packet against the MAC specified, returning true if the
|
||||
* MAC matches, false otherwise.
|
||||
|
@ -75,7 +75,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
/** shared slow bid for unconnected peers when we want to prefer UDP */
|
||||
private TransportBid _slowPreferredBid;
|
||||
|
||||
public static final String STYLE = "SSUv1";
|
||||
public static final String STYLE = "SSU";
|
||||
public static final String PROP_INTERNAL_PORT = "i2np.udp.internalPort";
|
||||
|
||||
/** define this to explicitly set an external IP address */
|
||||
@ -85,11 +85,12 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
/**
|
||||
* If i2np.udp.alwaysPreferred is set, the UDP bids will always be under
|
||||
* the bid from the TCP transport - even if a TCP connection already
|
||||
* exists. The default is to prefer UDP unless no UDP session exists and
|
||||
* a TCP connection already exists.
|
||||
* exists. If this is true (the default), it will always prefer UDP, otherwise
|
||||
* it will prefer UDP unless no UDP session exists and a TCP connection
|
||||
* already exists.
|
||||
*/
|
||||
public static final String PROP_ALWAYS_PREFER_UDP = "i2np.udp.alwaysPreferred";
|
||||
|
||||
private static final String DEFAULT_ALWAYS_PREFER_UDP = "true";
|
||||
|
||||
/** how many relays offered to us will we use at a time? */
|
||||
public static final int PUBLIC_RELAY_COUNT = 3;
|
||||
@ -154,29 +155,35 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
|
||||
rebuildExternalAddress();
|
||||
|
||||
if (_endpoint == null) {
|
||||
int port = -1;
|
||||
if (_externalListenPort <= 0) {
|
||||
// no explicit external port, so lets try an internal one
|
||||
String portStr = _context.getProperty(PROP_INTERNAL_PORT);
|
||||
if (portStr != null) {
|
||||
try {
|
||||
port = Integer.parseInt(portStr);
|
||||
} catch (NumberFormatException nfe) {
|
||||
if (_log.shouldLog(Log.ERROR))
|
||||
_log.error("Invalid port specified [" + portStr + "]");
|
||||
}
|
||||
int port = -1;
|
||||
if (_externalListenPort <= 0) {
|
||||
// no explicit external port, so lets try an internal one
|
||||
String portStr = _context.getProperty(PROP_INTERNAL_PORT);
|
||||
if (portStr != null) {
|
||||
try {
|
||||
port = Integer.parseInt(portStr);
|
||||
} catch (NumberFormatException nfe) {
|
||||
if (_log.shouldLog(Log.ERROR))
|
||||
_log.error("Invalid port specified [" + portStr + "]");
|
||||
}
|
||||
if (port <= 0) {
|
||||
port = 1024 + _context.random().nextInt(31*1024);
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("Selecting a random port to bind to: " + port);
|
||||
}
|
||||
} else {
|
||||
port = _externalListenPort;
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("Binding to the explicitly specified external port: " + port);
|
||||
}
|
||||
if (port <= 0) {
|
||||
port = 8887;
|
||||
//port = 1024 + _context.random().nextInt(31*1024);
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("Selecting an arbitrary port to bind to: " + port);
|
||||
_context.router().setConfigSetting(PROP_INTERNAL_PORT, port+"");
|
||||
// attempt to use it as our external port - this will be overridden by
|
||||
// externalAddressReceived(...)
|
||||
_context.router().setConfigSetting(PROP_EXTERNAL_PORT, port+"");
|
||||
_context.router().saveConfig();
|
||||
}
|
||||
} else {
|
||||
port = _externalListenPort;
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("Binding to the explicitly specified external port: " + port);
|
||||
}
|
||||
if (_endpoint == null) {
|
||||
try {
|
||||
_endpoint = new UDPEndpoint(_context, port);
|
||||
} catch (SocketException se) {
|
||||
@ -184,6 +191,8 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
_log.log(Log.CRIT, "Unable to listen on the UDP port (" + port + ")", se);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
_endpoint.setListenPort(port);
|
||||
}
|
||||
|
||||
if (_establisher == null)
|
||||
@ -211,14 +220,14 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
if (_endpoint != null)
|
||||
_endpoint.shutdown();
|
||||
if (_flooder != null)
|
||||
_flooder.shutdown();
|
||||
if (_refiller != null)
|
||||
_refiller.shutdown();
|
||||
if (_handler != null)
|
||||
_handler.shutdown();
|
||||
if (_endpoint != null)
|
||||
_endpoint.shutdown();
|
||||
if (_fragments != null)
|
||||
_fragments.shutdown();
|
||||
if (_pusher != null)
|
||||
@ -268,6 +277,9 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
}
|
||||
}
|
||||
|
||||
_context.router().setConfigSetting(PROP_EXTERNAL_PORT, ourPort+"");
|
||||
_context.router().saveConfig();
|
||||
|
||||
if (updated)
|
||||
_context.router().rebuildRouterInfo();
|
||||
}
|
||||
@ -280,8 +292,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
* get the state for the peer at the given remote host/port, or null
|
||||
* if no state exists
|
||||
*/
|
||||
public PeerState getPeerState(InetAddress remoteHost, int remotePort) {
|
||||
RemoteHostId hostInfo = new RemoteHostId(remoteHost.getAddress(), remotePort);
|
||||
public PeerState getPeerState(RemoteHostId hostInfo) {
|
||||
synchronized (_peersByRemoteHost) {
|
||||
return (PeerState)_peersByRemoteHost.get(hostInfo);
|
||||
}
|
||||
@ -424,7 +435,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
}
|
||||
|
||||
private boolean alwaysPreferUDP() {
|
||||
String pref = _context.getProperty(PROP_ALWAYS_PREFER_UDP);
|
||||
String pref = _context.getProperty(PROP_ALWAYS_PREFER_UDP, DEFAULT_ALWAYS_PREFER_UDP);
|
||||
return (pref != null) && "true".equals(pref);
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,7 @@ public class HopProcessor {
|
||||
* and after using it at each hop so as to prevent a certain type of replay/confirmation
|
||||
* attack.
|
||||
*/
|
||||
static final boolean USE_DOUBLE_IV_ENCRYPTION = false;
|
||||
static final boolean USE_DOUBLE_IV_ENCRYPTION = true;
|
||||
static final int IV_LENGTH = 16;
|
||||
private static final ByteCache _cache = ByteCache.getInstance(128, IV_LENGTH);
|
||||
|
||||
|
Reference in New Issue
Block a user