forked from I2P_Developers/i2p.i2p
SSU2: Implement ack-immediate flag
Use a single ack timer for each session rather than creating a new one for every ack Log tweaks
This commit is contained in:
@@ -1,3 +1,12 @@
|
||||
2022-08-29 zzz
|
||||
* SSU2: Implement ack-immediate flag
|
||||
|
||||
2022-08-28 zzz
|
||||
* Console:
|
||||
- Add notification and summary bar info on deadlock
|
||||
- Linkify router hash even if not in netdb
|
||||
* Util: Add option to gzip router logs
|
||||
|
||||
2022-08-25 zzz
|
||||
* Router: Fix deadlock via rebuildRouterAddress() and UDPTransport
|
||||
* SSU2:
|
||||
|
||||
@@ -18,7 +18,7 @@ public class RouterVersion {
|
||||
/** deprecated */
|
||||
public final static String ID = "Git";
|
||||
public final static String VERSION = CoreVersion.VERSION;
|
||||
public final static long BUILD = 2;
|
||||
public final static long BUILD = 3;
|
||||
|
||||
/** for example "-test" */
|
||||
public final static String EXTRA = "";
|
||||
|
||||
@@ -275,6 +275,11 @@ class PacketBuilder2 {
|
||||
//if (_log.shouldDebug())
|
||||
// _log.debug("Packet " + pktNum + " before encryption:\n" + HexDump.dump(data, 0, off));
|
||||
|
||||
// ack immediate flag
|
||||
if (numFragments > 0) {
|
||||
data[SHORT_HEADER_FLAGS_OFFSET] = peer.getFlags();
|
||||
}
|
||||
|
||||
encryptDataPacket(packet, peer.getSendCipher(), pktNum, peer.getSendHeaderEncryptKey1(), peer.getSendHeaderEncryptKey2());
|
||||
setTo(packet, peer.getRemoteIPAddress(), peer.getRemotePort());
|
||||
//if (_log.shouldDebug())
|
||||
@@ -351,8 +356,8 @@ class PacketBuilder2 {
|
||||
* This will also include acks, a new token block, and padding.
|
||||
*/
|
||||
public UDPPacket buildSessionDestroyPacket(int reason, PeerState2 peer) {
|
||||
if (_log.shouldWarn())
|
||||
_log.warn("Sending termination " + reason + " to : " + peer);
|
||||
if (_log.shouldDebug())
|
||||
_log.debug("Sending termination " + reason + " to : " + peer);
|
||||
List<Block> blocks = new ArrayList<Block>(2);
|
||||
if (peer.getKeyEstablishedTime() - _context.clock().now() > EstablishmentManager.IB_TOKEN_EXPIRATION / 2 &&
|
||||
!_context.router().gracefulShutdownInProgress()) {
|
||||
|
||||
@@ -2214,6 +2214,17 @@ public class PeerState {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* SSU 2 only
|
||||
*
|
||||
* @since 0.9.56
|
||||
*/
|
||||
protected boolean shouldRequestImmediateAck() {
|
||||
synchronized(_sendWindowBytesRemainingLock) {
|
||||
return _sendWindowBytesRemaining < _sendWindowBytes / 3;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transfer the basic activity/state from the old peer to the current peer
|
||||
*
|
||||
|
||||
@@ -63,6 +63,8 @@ public class PeerState2 extends PeerState implements SSU2Payload.PayloadCallback
|
||||
*/
|
||||
private final SSU2Bitfield _ackedMessages;
|
||||
private final ConcurrentHashMap<Long, List<PacketBuilder.Fragment>> _sentMessages;
|
||||
private final ACKTimer _ackTimer;
|
||||
|
||||
private long _sentMessagesLastExpired;
|
||||
private byte[] _ourIP;
|
||||
private int _ourPort;
|
||||
@@ -140,6 +142,7 @@ public class PeerState2 extends PeerState implements SSU2Payload.PayloadCallback
|
||||
// For outbound, SessionConfirmed is packet 0
|
||||
_packetNumber.set(1);
|
||||
}
|
||||
_ackTimer = new ACKTimer();
|
||||
}
|
||||
|
||||
// SSU 1 overrides
|
||||
@@ -197,7 +200,7 @@ public class PeerState2 extends PeerState implements SSU2Payload.PayloadCallback
|
||||
protected synchronized void messagePartiallyReceived(long now) {
|
||||
if (_wantACKSendSince <= 0) {
|
||||
_wantACKSendSince = now;
|
||||
new ACKTimer();
|
||||
_ackTimer.schedule();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -490,6 +493,11 @@ public class PeerState2 extends PeerState implements SSU2Payload.PayloadCallback
|
||||
ECNReceived();
|
||||
} //// !_dead
|
||||
|
||||
boolean ackImmediate = (header.data[SHORT_HEADER_FLAGS_OFFSET] & 0x01) != 0 && _context.getBooleanProperty("ssu2.ackImmediate");
|
||||
if (ackImmediate) {
|
||||
_ackTimer.scheduleImmediate();
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
if (_log.shouldWarn())
|
||||
_log.warn("Bad encrypted packet on: " + this + '\n' + HexDump.dump(data, off, len), e);
|
||||
@@ -958,16 +966,50 @@ public class PeerState2 extends PeerState implements SSU2Payload.PayloadCallback
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flag byte to be sent in header
|
||||
*
|
||||
* @since 0.9.56
|
||||
*/
|
||||
byte getFlags() {
|
||||
return shouldRequestImmediateAck() ? (byte) 0x01 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* A timer to send an ack-only packet.
|
||||
*/
|
||||
private class ACKTimer extends SimpleTimer2.TimedEvent {
|
||||
|
||||
/**
|
||||
* Caller must schedule
|
||||
*/
|
||||
public ACKTimer() {
|
||||
super(_context.simpleTimer2());
|
||||
}
|
||||
|
||||
/**
|
||||
* Ack soon, based on the current RTT
|
||||
*
|
||||
* @since 0.9.56
|
||||
*/
|
||||
public void schedule() {
|
||||
long delta = Math.max(10, Math.min(_rtt/6, ACK_FREQUENCY));
|
||||
if (_log.shouldDebug())
|
||||
_log.debug("Sending delayed ack in " + delta + ": " + PeerState2.this);
|
||||
schedule(delta);
|
||||
reschedule(delta, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ack almost immediately
|
||||
*
|
||||
* @since 0.9.56
|
||||
*/
|
||||
public void scheduleImmediate() {
|
||||
_wantACKSendSince = _context.clock().now();
|
||||
long delta = Math.min(_rtt/16, 5);
|
||||
if (_log.shouldDebug())
|
||||
_log.debug("Sending immediate ack in " + delta + ": " + PeerState2.this);
|
||||
reschedule(delta, true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user