From 9c31be66e6d7b6c3b3dbdc59e8bce3cd5cfc1347 Mon Sep 17 00:00:00 2001
From: zzz <zzz@i2pmail.org>
Date: Wed, 2 Mar 2022 10:47:47 -0500
Subject: [PATCH] SSU2: Data phase updates

Send immediate ack of Session Confirmed
Process I2NP messages and fragments in Session Confirmed
---
 .../transport/udp/InboundEstablishState2.java | 23 ++++++++++++++++---
 .../i2p/router/transport/udp/PeerState2.java  | 12 +++++++---
 2 files changed, 29 insertions(+), 6 deletions(-)

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 d6f7f04a50..01ae6eb7dc 100644
--- a/router/java/src/net/i2p/router/transport/udp/InboundEstablishState2.java
+++ b/router/java/src/net/i2p/router/transport/udp/InboundEstablishState2.java
@@ -178,6 +178,8 @@ class InboundEstablishState2 extends InboundEstablishState implements SSU2Payloa
         System.out.println("Got RI block: " + ri);
         if (isHandshake)
             throw new DataFormatException("RI in Sess Req");
+        if (_receivedUnconfirmedIdentity != null)
+            throw new DataFormatException("DUP RI in Sess Conf");
         _receivedUnconfirmedIdentity = ri.getIdentity();
         if (ri.getNetworkId() != _context.router().getNetworkID()) {
             // TODO ban
@@ -234,6 +236,7 @@ class InboundEstablishState2 extends InboundEstablishState implements SSU2Payloa
 
         _receivedConfirmedIdentity = _receivedUnconfirmedIdentity;
         _sendHeaderEncryptKey1 = ik;
+        createPeerState();
         //_sendHeaderEncryptKey2 calculated below
     }
 
@@ -271,6 +274,8 @@ class InboundEstablishState2 extends InboundEstablishState implements SSU2Payloa
             throw new IllegalStateException("I2NP in Sess Req");
         if (_receivedConfirmedIdentity == null)
             throw new IllegalStateException("RI must be first");
+        // pass to PeerState2
+        _pstate.gotI2NP(msg);
     }
 
     public void gotFragment(byte[] data, int off, int len, long messageID, int frag, boolean isLast) throws DataFormatException {
@@ -279,6 +284,8 @@ class InboundEstablishState2 extends InboundEstablishState implements SSU2Payloa
             throw new IllegalStateException("I2NP in Sess Req");
         if (_receivedConfirmedIdentity == null)
             throw new IllegalStateException("RI must be first");
+        // pass to PeerState2
+        _pstate.gotFragment(data, off, len, messageID, frag, isLast);
     }
 
     public void gotACK(long ackThru, int acks, byte[] ranges) {
@@ -443,6 +450,19 @@ class InboundEstablishState2 extends InboundEstablishState implements SSU2Payloa
         if (_receivedConfirmedIdentity == null)
             throw new GeneralSecurityException("No RI in Session Confirmed");
 
+        // createPeerState() called from gotRI()
+
+        _currentState = InboundState.IB_STATE_CONFIRMED_COMPLETELY;
+        packetReceived();
+        return _pstate;
+    }
+
+    /**
+     *  Creates the PeerState and stores in _pstate.
+     *  Called from gotRI() so that we can pass any I2NP messages
+     *  or fragments immediately to the PeerState.
+     */
+    private void createPeerState() {
         // split()
         // The CipherStates are from d_ab/d_ba,
         // not from k_ab/k_ba, so there's no use for
@@ -481,9 +501,6 @@ class InboundEstablishState2 extends InboundEstablishState implements SSU2Payloa
                                  true, _rtt, sender, rcvr,
                                  _sendConnID, _rcvConnID,
                                  _sendHeaderEncryptKey1, h_ba, h_ab);
-        _currentState = InboundState.IB_STATE_CONFIRMED_COMPLETELY;
-        packetReceived();
-        return _pstate;
     }
 
     /**
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 f5d69a6ab5..ebbb0dac71 100644
--- a/router/java/src/net/i2p/router/transport/udp/PeerState2.java
+++ b/router/java/src/net/i2p/router/transport/udp/PeerState2.java
@@ -78,9 +78,15 @@ public class PeerState2 extends PeerState implements SSU2Payload.PayloadCallback
         _rcvHeaderEncryptKey2 = rcvHdrKey2;
         _receivedMessages = new SSU2Bitfield(256, 0);
         _ackedMessages = new SSU2Bitfield(256, 0);
-        // For outbound, SessionConfirmed is packet 0
-        if (!isInbound)
+        if (isInbound) {
+            // Send immediate ack of Session Confirmed
+            _receivedMessages.set(0);
+            UDPPacket ack = transport.getBuilder2().buildACK(this);
+            transport.send(ack);
+        } else {
+            // For outbound, SessionConfirmed is packet 0
             _packetNumber.set(1);
+        }
     }
 
     // SSU 1 overrides
@@ -292,7 +298,7 @@ public class PeerState2 extends PeerState implements SSU2Payload.PayloadCallback
         _transport.messageReceived(msg, null, _remotePeer, 0, size);
     }
 
-    public void gotFragment(byte[] data, int off, int len, long messageId,int frag, boolean isLast) throws DataFormatException {
+    public void gotFragment(byte[] data, int off, int len, long messageId, int frag, boolean isLast) throws DataFormatException {
         InboundMessageState state;
         boolean messageComplete = false;
         boolean messageExpired = false;
-- 
GitLab