diff --git a/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java b/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java index 7dacfe6bf19b6609e438d025b9fc19d9e895c454..cefb942c8f769eee61f9fdedce81d3a7b99588c5 100644 --- a/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java +++ b/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java @@ -51,7 +51,7 @@ class EstablishmentManager { // SSU 2 private final PacketBuilder2 _builder2; private final boolean _enableSSU2; - private final Map<Hash, Token> _outboundTokens; + private final Map<RemoteHostId, Token> _outboundTokens; private final Map<RemoteHostId, Token> _inboundTokens; /** map of RemoteHostId to InboundEstablishState */ @@ -168,7 +168,7 @@ class EstablishmentManager { _outboundByHash = new ConcurrentHashMap<Hash, OutboundEstablishState>(); if (_enableSSU2) { _inboundTokens = new LHMCache<RemoteHostId, Token>(MAX_TOKENS); - _outboundTokens = new LHMCache<Hash, Token>(MAX_TOKENS); + _outboundTokens = new LHMCache<RemoteHostId, Token>(MAX_TOKENS); } else { _inboundTokens = null; _outboundTokens = null; @@ -1800,7 +1800,7 @@ class EstablishmentManager { * @param token nonzero * @since 0.9.54 */ - public void addOutboundToken(Hash peer, long token, long expires) { + public void addOutboundToken(RemoteHostId peer, long token, long expires) { if (expires < _context.clock().now()) return; Token tok = new Token(token, expires); @@ -1815,7 +1815,7 @@ class EstablishmentManager { * @return 0 if none available * @since 0.9.54 */ - public long getOutboundToken(Hash peer) { + public long getOutboundToken(RemoteHostId peer) { Token tok; synchronized(_outboundTokens) { tok = _outboundTokens.remove(peer); @@ -1828,17 +1828,54 @@ class EstablishmentManager { } /** - * Remember a token that can be used later for the peer to connect to us + * Remove our outbound tokens for this length + * + * @since 0.9.54 + */ + public void ipChanged(boolean isIPv6) { + if (!_enableSSU2) + return; + int len = isIPv6 ? 16 : 4; + // expire while we're at it + long now = _context.clock().now(); + synchronized(_outboundTokens) { + for (Iterator<Map.Entry<RemoteHostId, Token>> iter = _outboundTokens.entrySet().iterator(); iter.hasNext(); ) { + Map.Entry<RemoteHostId, Token> e = iter.next(); + if (e.getKey().getIP().length == len || e.getValue().expires < now) + iter.remove(); + } + } + } + + /** + * Remove all outbound tokens + * + * @since 0.9.54 + */ + public void portChanged() { + if (!_enableSSU2) + return; + synchronized(_outboundTokens) { + _outboundTokens.clear(); + } + } + + /** + * Get a token that can be used later for the peer to connect to us * - * @param token nonzero * @since 0.9.54 */ - public void addInboundToken(RemoteHostId peer, long token) { + public Token getInboundToken(RemoteHostId peer) { + long token; + do { + token = _context.random().nextLong(); + } while (token == 0); long expires = _context.clock().now() + IB_TOKEN_EXPIRATION; Token tok = new Token(token, expires); synchronized(_inboundTokens) { _inboundTokens.put(peer, tok); } + return tok; } /** @@ -1862,7 +1899,7 @@ class EstablishmentManager { return tok.expires >= _context.clock().now(); } - private static class Token { + public static class Token { public final long token, expires; public Token(long tok, long exp) { token = tok; expires = exp; diff --git a/router/java/src/net/i2p/router/transport/udp/InboundEstablishState2.java b/router/java/src/net/i2p/router/transport/udp/InboundEstablishState2.java index 1a8b927d04c063dbebc144ee1e400bc5b7617634..c3beba3c86097da8ba552cec94888324109f219f 100644 --- a/router/java/src/net/i2p/router/transport/udp/InboundEstablishState2.java +++ b/router/java/src/net/i2p/router/transport/udp/InboundEstablishState2.java @@ -370,7 +370,7 @@ class InboundEstablishState2 extends InboundEstablishState implements SSU2Payloa public void gotToken(long token, long expires) { if (_receivedConfirmedIdentity == null) throw new IllegalStateException("RI must be first"); - _transport.getEstablisher().addOutboundToken(_receivedConfirmedIdentity.calculateHash(), token, expires); + _transport.getEstablisher().addOutboundToken(_remoteHostId, token, expires); } public void gotI2NP(I2NPMessage msg) { @@ -429,14 +429,8 @@ class InboundEstablishState2 extends InboundEstablishState implements SSU2Payloa public long getSendConnID() { return _sendConnID; } public long getRcvConnID() { return _rcvConnID; } public long getToken() { return _token; } - public long getNextToken() { - // generate on the fly, this will only be called once - long token; - do { - token = _context.random().nextLong(); - } while (token == 0); - _transport.getEstablisher().addInboundToken(_remoteHostId, token); - return token; + public EstablishmentManager.Token getNextToken() { + return _transport.getEstablisher().getInboundToken(_remoteHostId); } public HandshakeState getHandshakeState() { return _handshakeState; } public byte[] getSendHeaderEncryptKey1() { return _sendHeaderEncryptKey1; } @@ -720,6 +714,8 @@ class InboundEstablishState2 extends InboundEstablishState implements SSU2Payloa StringBuilder buf = new StringBuilder(128); buf.append("IES2 "); buf.append(Addresses.toString(_aliceIP, _alicePort)); + buf.append(" Rcv ID: ").append(_rcvConnID); + buf.append(" Send ID: ").append(_sendConnID); buf.append(" RelayTag: ").append(_sentRelayTag); buf.append(' ').append(_currentState); return buf.toString(); diff --git a/router/java/src/net/i2p/router/transport/udp/OutboundEstablishState2.java b/router/java/src/net/i2p/router/transport/udp/OutboundEstablishState2.java index 27bb6637067b55cf84c369b3a4579651f8c47a76..a430b03858593ccb64c7e6a91b35fd7a3892daee 100644 --- a/router/java/src/net/i2p/router/transport/udp/OutboundEstablishState2.java +++ b/router/java/src/net/i2p/router/transport/udp/OutboundEstablishState2.java @@ -127,7 +127,7 @@ class OutboundEstablishState2 extends OutboundEstablishState implements SSU2Payl } while (_sendConnID == rcid); _rcvConnID = rcid; - _token = _transport.getEstablisher().getOutboundToken(_remotePeer.calculateHash()); + _token = _transport.getEstablisher().getOutboundToken(_remoteHostId); _routerAddress = ra; if (_token != 0) createNewState(ra); @@ -247,7 +247,7 @@ class OutboundEstablishState2 extends OutboundEstablishState implements SSU2Payl } public void gotToken(long token, long expires) { - _transport.getEstablisher().addOutboundToken(_remotePeer.calculateHash(), token, expires); + _transport.getEstablisher().addOutboundToken(_remoteHostId, token, expires); } public void gotI2NP(I2NPMessage msg) { @@ -299,14 +299,8 @@ class OutboundEstablishState2 extends OutboundEstablishState implements SSU2Payl public long getSendConnID() { return _sendConnID; } public long getRcvConnID() { return _rcvConnID; } public long getToken() { return _token; } - public long getNextToken() { - // generate on the fly, this will only be called once - long token; - do { - token = _context.random().nextLong(); - } while (token == 0); - _transport.getEstablisher().addInboundToken(_remoteHostId, token); - return token; + public EstablishmentManager.Token getNextToken() { + return _transport.getEstablisher().getInboundToken(_remoteHostId); } public HandshakeState getHandshakeState() { return _handshakeState; } public byte[] getSendHeaderEncryptKey1() { return _sendHeaderEncryptKey1; } @@ -567,6 +561,9 @@ class OutboundEstablishState2 extends OutboundEstablishState implements SSU2Payl @Override public String toString() { - return "OES2 " + _remoteHostId + ' ' + _currentState; + return "OES2 " + _remoteHostId + + " Rcv ID: " + _rcvConnID + + " Send ID: " + _sendConnID + + ' ' + _currentState; } } diff --git a/router/java/src/net/i2p/router/transport/udp/PacketBuilder2.java b/router/java/src/net/i2p/router/transport/udp/PacketBuilder2.java index b8df75bcd6b8226be1d2bdef144c82211ad2fd97..662548b531724c868308c6cb367b5e99c0735ccc 100644 --- a/router/java/src/net/i2p/router/transport/udp/PacketBuilder2.java +++ b/router/java/src/net/i2p/router/transport/udp/PacketBuilder2.java @@ -73,9 +73,6 @@ class PacketBuilder2 { /** 80 */ public static final int MIN_IPV6_DATA_PACKET_OVERHEAD = IPV6_HEADER_SIZE + UDP_HEADER_SIZE + DATA_HEADER_SIZE + MAC_LEN; -/// FIXME - private static final int MAX_IDENTITY_FRAGMENT_SIZE = 1280 - (MIN_DATA_PACKET_OVERHEAD + KEY_LEN + MAC_LEN); - private static final int ABSOLUTE_MAX_ACK_RANGES = 512; /* Higher than all other OutNetMessage priorities, but still droppable, @@ -788,7 +785,8 @@ class PacketBuilder2 { * @param packet containing only 32 byte header */ private void encryptSessionCreated(UDPPacket packet, HandshakeState state, - byte[] hdrKey1, byte[] hdrKey2, long relayTag, long token, byte[] ip, int port) { + byte[] hdrKey1, byte[] hdrKey2, long relayTag, + EstablishmentManager.Token token, byte[] ip, int port) { DatagramPacket pkt = packet.getPacket(); byte data[] = pkt.getData(); int off = pkt.getOffset(); @@ -805,8 +803,8 @@ class PacketBuilder2 { len += block.getTotalLength(); blocks.add(block); } - if (token > 0) { - block = new SSU2Payload.NewTokenBlock(token, _context.clock().now() + EstablishmentManager.IB_TOKEN_EXPIRATION); + if (token != null) { + block = new SSU2Payload.NewTokenBlock(token.token, token.expires); len += block.getTotalLength(); blocks.add(block); } @@ -938,7 +936,7 @@ class PacketBuilder2 { */ private void encryptSessionConfirmed(UDPPacket packet, HandshakeState state, int mtu, boolean isIPv6, byte[] hdrKey1, byte[] hdrKey2, - SSU2Payload.RIBlock riblock, long token) { + SSU2Payload.RIBlock riblock, EstablishmentManager.Token token) { DatagramPacket pkt = packet.getPacket(); byte data[] = pkt.getData(); int off = pkt.getOffset(); @@ -949,8 +947,8 @@ class PacketBuilder2 { int len = riblock.getTotalLength(); blocks.add(riblock); // only if room - if (token > 0 && mtu - (SHORT_HEADER_SIZE + KEY_LEN + MAC_LEN + len + MAC_LEN) >= 15) { - Block block = new SSU2Payload.NewTokenBlock(token, _context.clock().now() + EstablishmentManager.IB_TOKEN_EXPIRATION); + if (token != null && mtu - (SHORT_HEADER_SIZE + KEY_LEN + MAC_LEN + len + MAC_LEN) >= 15) { + Block block = new SSU2Payload.NewTokenBlock(token.token, token.expires); len += block.getTotalLength(); blocks.add(block); } diff --git a/router/java/src/net/i2p/router/transport/udp/PacketHandler.java b/router/java/src/net/i2p/router/transport/udp/PacketHandler.java index be750dfdb797c7b2c241dcfe8dfb89fd48544bb2..be1c7ffc8fe585e3b202d320b8051900eefe7ee5 100644 --- a/router/java/src/net/i2p/router/transport/udp/PacketHandler.java +++ b/router/java/src/net/i2p/router/transport/udp/PacketHandler.java @@ -289,8 +289,8 @@ class PacketHandler { if (state.getNextMACKey() != null) isValid = validate(packet, state.getNextMACKey()); if (!isValid) { - if (_log.shouldLog(Log.INFO)) - _log.info("Failed validation with existing con, trying as new con: " + packet); + if (_log.shouldDebug()) + _log.debug("Failed validation with existing con, trying as new con: " + packet); isValid = validate(packet, _transport.getIntroKey()); if (isValid) { @@ -472,8 +472,8 @@ class PacketHandler { if (state.getMACKey() != null) { isValid = validate(packet, state.getMACKey()); if (isValid) { - if (_log.shouldLog(Log.INFO)) - _log.info("Valid introduction packet received for inbound con: " + packet); + if (_log.shouldDebug()) + _log.debug("Valid introduction packet received for inbound con: " + packet); packet.decrypt(state.getCipherKey()); handlePacket(reader, packet, null, null, null, AuthType.SESSION); @@ -513,8 +513,8 @@ class PacketHandler { isValid = validate(packet, state.getMACKey()); if (isValid) { // this should be the Session Confirmed packet - if (_log.shouldLog(Log.INFO)) - _log.info("Valid introduction packet received for outbound established con: " + packet); + if (_log.shouldDebug()) + _log.debug("Valid introduction packet received for outbound established con: " + packet); packet.decrypt(state.getCipherKey()); handlePacket(reader, packet, null, state, null, AuthType.SESSION); return; @@ -524,8 +524,8 @@ class PacketHandler { // keys not yet exchanged, lets try it with the peer's intro key isValid = validate(packet, state.getIntroKey()); if (isValid) { - if (_log.shouldLog(Log.INFO)) - _log.info("Valid packet received for " + state + " with Bob's intro key: " + packet); + if (_log.shouldDebug()) + _log.debug("Valid packet received for " + state + " with Bob's intro key: " + packet); packet.decrypt(state.getIntroKey()); // the only packet we should be getting with Bob's intro key is Session Created handlePacket(reader, packet, null, state, null, AuthType.BOBINTRO); @@ -721,8 +721,8 @@ class PacketHandler { _log.warn("Dropping type " + type + " auth " + auth + ": " + packet); break; } - if (_log.shouldLog(Log.INFO)) - _log.info("Received relay request packet: " + reader + " from " + from); + if (_log.shouldDebug()) + _log.debug("Received relay request packet: " + reader + " from " + from); _introManager.receiveRelayRequest(from, reader); break; case UDPPacket.PAYLOAD_TYPE_RELAY_INTRO: @@ -731,8 +731,8 @@ class PacketHandler { _log.warn("Dropping type " + type + " auth " + auth + ": " + packet); break; } - if (_log.shouldLog(Log.INFO)) - _log.info("Received relay intro packet: " + reader + " from " + from); + if (_log.shouldDebug()) + _log.debug("Received relay intro packet: " + reader + " from " + from); _introManager.receiveRelayIntro(from, reader); break; case UDPPacket.PAYLOAD_TYPE_RELAY_RESPONSE: @@ -741,8 +741,8 @@ class PacketHandler { _log.warn("Dropping type " + type + " auth " + auth + ": " + packet); break; } - if (_log.shouldLog(Log.INFO)) - _log.info("Received relay response packet: " + reader + " from " + from); + if (_log.shouldDebug()) + _log.debug("Received relay response packet: " + reader + " from " + from); _establisher.receiveRelayResponse(from, reader); break; case UDPPacket.PAYLOAD_TYPE_SESSION_DESTROY: diff --git a/router/java/src/net/i2p/router/transport/udp/PeerState2.java b/router/java/src/net/i2p/router/transport/udp/PeerState2.java index 6a467ad51a00547d559e8bbadc7770f6647a84f8..94fc7211f2ecea326f044023fc117a6b3ba1bb6b 100644 --- a/router/java/src/net/i2p/router/transport/udp/PeerState2.java +++ b/router/java/src/net/i2p/router/transport/udp/PeerState2.java @@ -427,7 +427,7 @@ public class PeerState2 extends PeerState implements SSU2Payload.PayloadCallback } public void gotToken(long token, long expires) { - _transport.getEstablisher().addOutboundToken(_remotePeer, token, expires); + _transport.getEstablisher().addOutboundToken(_remoteHostId, token, expires); } public void gotI2NP(I2NPMessage msg) { diff --git a/router/java/src/net/i2p/router/transport/udp/PeerTestManager.java b/router/java/src/net/i2p/router/transport/udp/PeerTestManager.java index 27d21c4955687143775a857c92341d6060469b71..fd4ad6836c3bb48ebb5e8df2d7e5a6a7d8678f75 100644 --- a/router/java/src/net/i2p/router/transport/udp/PeerTestManager.java +++ b/router/java/src/net/i2p/router/transport/udp/PeerTestManager.java @@ -184,7 +184,7 @@ class PeerTestManager { /** * The next few methods are for when we are Alice * - * @param bobIP IPv4 only + * @param bob IPv4 only */ public synchronized void runTest(PeerState bob) { if (_currentTest != null) {