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 f3fccd13b4bd32b693902710f14cd0d479c7243d..93992cacdbc9327c4ccd118ec34b48f705f6c9eb 100644 --- a/router/java/src/net/i2p/router/transport/udp/PacketBuilder2.java +++ b/router/java/src/net/i2p/router/transport/udp/PacketBuilder2.java @@ -58,14 +58,14 @@ class PacketBuilder2 { static final int TYPE_CREAT = 73; /** IPv4 only */ - public static final int IP_HEADER_SIZE = 20; + public static final int IP_HEADER_SIZE = PacketBuilder.IP_HEADER_SIZE; /** Same for IPv4 and IPv6 */ - public static final int UDP_HEADER_SIZE = 8; + public static final int UDP_HEADER_SIZE = PacketBuilder.UDP_HEADER_SIZE; /** 74 */ public static final int MIN_DATA_PACKET_OVERHEAD = IP_HEADER_SIZE + UDP_HEADER_SIZE + DATA_HEADER_SIZE + MAC_LEN; - public static final int IPV6_HEADER_SIZE = 40; + public static final int IPV6_HEADER_SIZE = PacketBuilder.IPV6_HEADER_SIZE; /** 94 */ public static final int MIN_IPV6_DATA_PACKET_OVERHEAD = IPV6_HEADER_SIZE + UDP_HEADER_SIZE + DATA_HEADER_SIZE + MAC_LEN; @@ -135,7 +135,7 @@ class PacketBuilder2 { // calculate data size int numFragments = fragments.size(); int dataSize = 0; - int priority = 0; + int priority = PRIORITY_LOW; for (int i = 0; i < numFragments; i++) { Fragment frag = fragments.get(i); OutboundMessageState state = frag.state; @@ -176,7 +176,7 @@ class PacketBuilder2 { // add the acks if (availableForAcks >= SSU2Payload.BLOCK_HEADER_SIZE + 5) { - int maxRanges = (availableForAcks - (SSU2Payload.BLOCK_HEADER_SIZE + 5)) / 2; + int maxRanges = Math.min((availableForAcks - (SSU2Payload.BLOCK_HEADER_SIZE + 5)) / 2, ABSOLUTE_MAX_ACK_RANGES); Block block = peer.getReceivedMessages().toAckBlock(maxRanges); if (block != null) { blocks.add(block); @@ -255,7 +255,7 @@ class PacketBuilder2 { pkt.setLength(off); encryptDataPacket(packet, peer.getSendCipher(), pktNum, peer.getSendHeaderEncryptKey1(), peer.getSendHeaderEncryptKey2()); setTo(packet, peer.getRemoteIPAddress(), peer.getRemotePort()); - packet.setPriority(0); + packet.setPriority(PRIORITY_LOW); return packet; } diff --git a/router/java/src/net/i2p/router/transport/udp/PeerState.java b/router/java/src/net/i2p/router/transport/udp/PeerState.java index fd716c55f8836f6ec7dc127e49d6af76b43c9e43..23ba705327e245a0c562efa5b14686212cf7d396 100644 --- a/router/java/src/net/i2p/router/transport/udp/PeerState.java +++ b/router/java/src/net/i2p/router/transport/udp/PeerState.java @@ -137,7 +137,7 @@ public class PeerState { */ private volatile int _slowStartThreshold; /** what IP is the peer sending and receiving packets on? */ - private final byte[] _remoteIP; + protected final byte[] _remoteIP; /** cached IP address */ private volatile InetAddress _remoteIPAddress; /** what port is the peer sending and receiving packets on? */ @@ -160,7 +160,7 @@ public class PeerState { */ private long _theyRelayToUsAs; /** what is the largest packet we can currently send to the peer? */ - private int _mtu; + protected int _mtu; private int _mtuReceive; /** what is the largest packet we will ever send to the peer? */ private int _largeMTU; @@ -394,8 +394,6 @@ public class PeerState { _keyEstablishedTime = now; _lastSendTime = now; _lastReceiveTime = now; - _currentACKs = new ConcurrentHashSet<Long>(); - _currentACKsResend = new LinkedBlockingQueue<ResendACK>(); _slowStartThreshold = MAX_SEND_WINDOW_BYTES/2; _receivePeriodBegin = now; _remoteIP = addr.getAddress().getAddress(); @@ -428,11 +426,14 @@ public class PeerState { _inboundMessages = new HashMap<Long, InboundMessageState>(8); _outboundMessages = new CachedIteratorCollection<OutboundMessageState>(); _outboundQueue = new PriBlockingQueue<OutboundMessageState>(ctx, "UDP-PeerState", 32); - _ackedMessages = new AckedMessages(); _remotePeer = remotePeer; _isInbound = isInbound; _remoteHostId = new RemoteHostId(_remoteIP, _remotePort); _bwEstimator = new SimpleBandwidthEstimator(ctx, this); + // Unused in SSU2 + _currentACKs = null; + _currentACKsResend = null; + _ackedMessages = null; } /** 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 8519a245093bb3ec5f9e5d34dbc056b2bd0d7c00..b05bf0de5420c38ba11ad4a117fdcfaaba1df5d8 100644 --- a/router/java/src/net/i2p/router/transport/udp/PeerState2.java +++ b/router/java/src/net/i2p/router/transport/udp/PeerState2.java @@ -3,6 +3,7 @@ package net.i2p.router.transport.udp; import java.net.DatagramPacket; import java.net.InetSocketAddress; import java.security.GeneralSecurityException; +import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import com.southernstorm.noise.protocol.CipherState; @@ -66,8 +67,59 @@ public class PeerState2 extends PeerState implements SSU2Payload.PayloadCallback _sentMessages = new SSU2Bitfield(256, 0); } + // SSU 1 overrides + @Override public int getVersion() { return 2; } + + /** + * how much payload data can we shove in there? + * Does NOT leave any room for acks, we'll fit them in when we can. + * This is 5 bytes too low for first or only fragment. + * + * @return MTU - 68 (IPv4), MTU - 88 (IPv6) + */ + @Override + int fragmentSize() { + // 20 + 8 + 16 + 3 + 5 + 16 = 68 (IPv4) + // 40 + 8 + 16 + 3 + 5 + 16 = 88 (IPv6) + return _mtu - + (_remoteIP.length == 4 ? PacketBuilder2.MIN_DATA_PACKET_OVERHEAD : PacketBuilder2.MIN_IPV6_DATA_PACKET_OVERHEAD) - + DATA_FOLLOWON_EXTRA_SIZE; // Followon fragment block overhead (5) + } + + /** + * Packet overhead + * Does NOT leave any room for acks, we'll fit them in when we can. + * This is 5 bytes too high for first or only fragment. + * + * @return 68 (IPv4), 88 (IPv6) + */ + @Override + int fragmentOverhead() { + // 20 + 8 + 16 + 3 + 5 + 16 = 68 (IPv4) + // 40 + 8 + 16 + 3 + 5 + 16 = 88 (IPv6) + return (_remoteIP.length == 4 ? PacketBuilder2.MIN_DATA_PACKET_OVERHEAD : PacketBuilder2.MIN_IPV6_DATA_PACKET_OVERHEAD) + + DATA_FOLLOWON_EXTRA_SIZE; // Followon fragment block overhead (5) + } + + // SSU 1 unsupported things + + @Override + void setCurrentMACKey(SessionKey key) { throw new UnsupportedOperationException(); } + @Override + void setCurrentCipherKey(SessionKey key) { throw new UnsupportedOperationException(); } + @Override + List<Long> getCurrentFullACKs() { throw new UnsupportedOperationException(); } + @Override + List<Long> getCurrentResendACKs() { throw new UnsupportedOperationException(); } + @Override + void removeACKMessage(Long messageId) { throw new UnsupportedOperationException(); } + @Override + void fetchPartialACKs(List<ACKBitfield> rv) { throw new UnsupportedOperationException(); } + + // SSU 2 things + long getNextPacketNumber() { return _packetNumber.incrementAndGet(); } long getSendConnID() { return _sendConnID; } long getRcvConnID() { return _rcvConnID; } diff --git a/router/java/src/net/i2p/router/transport/udp/SSU2Util.java b/router/java/src/net/i2p/router/transport/udp/SSU2Util.java index aa4370815196845d1e90c60ce71cde1b00106365..8563ecc11b704e2a7b0b09e201eef7854d2346fa 100644 --- a/router/java/src/net/i2p/router/transport/udp/SSU2Util.java +++ b/router/java/src/net/i2p/router/transport/udp/SSU2Util.java @@ -55,17 +55,22 @@ final class SSU2Util { public static final int MIN_HANDSHAKE_DATA_LEN = SESSION_HEADER_SIZE + TOTAL_PROT_SAMPLE_LEN; - /** 3 byte block header + 9 byte I2NP header = 12 */ - public static final int FULL_I2NP_HEADER_SIZE = SSU2Payload.BLOCK_HEADER_SIZE + 9; + /** 3 byte block header */ + public static final int FULL_I2NP_HEADER_SIZE = SSU2Payload.BLOCK_HEADER_SIZE; - /** 3 byte block header + 9 byte I2NP header = 12 */ - public static final int FIRST_FRAGMENT_HEADER_SIZE = SSU2Payload.BLOCK_HEADER_SIZE + 9; + /** 3 byte block header */ + public static final int FIRST_FRAGMENT_HEADER_SIZE = SSU2Payload.BLOCK_HEADER_SIZE; + + /** + * 5 for flag and msg number in followon block + */ + public static final int DATA_FOLLOWON_EXTRA_SIZE = 5; /** 3 byte block header + 4 byte msg ID + 1 byte fragment info = 8 */ - public static final int FOLLOWON_FRAGMENT_HEADER_SIZE = SSU2Payload.BLOCK_HEADER_SIZE + 5; + public static final int FOLLOWON_FRAGMENT_HEADER_SIZE = SSU2Payload.BLOCK_HEADER_SIZE + DATA_FOLLOWON_EXTRA_SIZE; - /** 16 byte block header + 2 + 12 = 30 */ - public static final int DATA_HEADER_SIZE = SHORT_HEADER_SIZE + 2 + FULL_I2NP_HEADER_SIZE; + /** 16 byte short header + 3 = 19 */ + public static final int DATA_HEADER_SIZE = SHORT_HEADER_SIZE + FULL_I2NP_HEADER_SIZE; /** * The message types, 0-10, as bytes