* 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:
jrandom
2005-07-27 19:03:43 +00:00
committed by zzz
parent aeb8f02269
commit a8a866b5f6
45 changed files with 325 additions and 827 deletions

View File

@ -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);

View File

@ -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");

View File

@ -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();

View File

@ -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;
}

View File

@ -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);

View File

@ -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());

View File

@ -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());

View File

@ -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;

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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))

View File

@ -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);

View File

@ -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) {

View File

@ -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))

View File

@ -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);

View File

@ -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;
}

View File

@ -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 {

View File

@ -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.

View File

@ -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);
}

View File

@ -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);