@@ -84,38 +84,19 @@ private const val HEARTBEAT_POLL_MS = 250L
8484/* * Minimum ms between re-requesting the same missing sequence number. */
8585private const val MISSING_SEQ_RETRY_MS = 1_000L
8686
87- /* * Size in bytes of an encoded replay-request payload (big-endian uint32). */
88- private const val REPLAY_REQUEST_BYTES = 4
89-
9087/* * Maximum configurable flush window in milliseconds. */
9188private const val MAX_FLUSH_WINDOW_MS = 5_000L
9289
93- /* * Size in bytes of a heartbeat-status payload (two big-endian uint32s). */
94- private const val HEARTBEAT_STATUS_BYTES = 8
95-
9690// ---------------------------------------------------------------------------
9791// Helpers
9892// ---------------------------------------------------------------------------
9993
100- private fun encodeUint32BE (value : Int ): ByteArray = Buffer ().apply { writeInt(value) }.readByteArray()
101-
10294/* * Size in bytes of an encoded uint32 (big-endian). */
10395private const val UINT32_BYTES = 4
10496
10597private fun decodeUint32BE (bytes : ByteArray , offset : Int = 0): Int =
10698 Buffer ().apply { write(bytes, offset, UINT32_BYTES ) }.readInt()
10799
108- private fun encodeHeartbeatStatus (lastTxSeq : Int , lastRxSeq : Int ): ByteArray = Buffer ()
109- .apply {
110- writeInt(lastTxSeq)
111- writeInt(lastRxSeq)
112- }
113- .readByteArray()
114-
115- private fun decodeHeartbeatStatus (bytes : ByteArray ): Pair <Int , Int >? = bytes
116- .takeIf { it.size >= HEARTBEAT_STATUS_BYTES }
117- ?.let { Buffer ().apply { write(it) }.let { buf -> buf.readInt() to buf.readInt() } }
118-
119100// ---------------------------------------------------------------------------
120101// Sent-frame record for retransmission history
121102// ---------------------------------------------------------------------------
@@ -128,6 +109,9 @@ private data class SentFrame(
128109 val payload : ByteString ,
129110 val cols : Int ,
130111 val rows : Int ,
112+ val flags : Int = 0 ,
113+ val lastTxSeq : Int = 0 ,
114+ val lastRxSeq : Int = 0 ,
131115)
132116
133117// ---------------------------------------------------------------------------
@@ -237,6 +221,9 @@ class RemoteShellViewModel(
237221 payload = frame.payload,
238222 cols = frame.cols,
239223 rows = frame.rows,
224+ flags = frame.flags,
225+ last_tx_seq = frame.lastTxSeq,
226+ last_rx_seq = frame.lastRxSeq,
240227 ),
241228 remember = false ,
242229 )
@@ -547,7 +534,8 @@ class RemoteShellViewModel(
547534 session_id = sessionId.value,
548535 seq = allocSeq(),
549536 ack_seq = currentAckSeq(),
550- payload = encodeHeartbeatStatus(highestSentSeq(), currentAckSeq()).toByteString(),
537+ last_tx_seq = highestSentSeq(),
538+ last_rx_seq = currentAckSeq(),
551539 ),
552540 isHeartbeat = true ,
553541 )
@@ -576,9 +564,8 @@ class RemoteShellViewModel(
576564 pruneSentFrames(frame.ack_seq)
577565
578566 if (frame.op == RemoteShell .OpCode .ACK ) {
579- val payload = frame.payload.toByteArray()
580- if (payload.size >= REPLAY_REQUEST_BYTES ) {
581- replayFrom(decodeUint32BE(payload))
567+ if (frame.last_rx_seq > 0 ) {
568+ replayFrom(frame.last_rx_seq + 1 )
582569 }
583570 return
584571 }
@@ -640,11 +627,10 @@ class RemoteShellViewModel(
640627 _sessionState .update { SessionState .CLOSED }
641628 }
642629 RemoteShell .OpCode .PONG -> {
643- val payload = frame.payload.toByteArray()
644- if (payload.isEmpty()) return
645- val (peerLastTxSeq, peerLastRxSeq) = decodeHeartbeatStatus(payload) ? : return
630+ val peerLastTxSeq = frame.last_tx_seq
631+ val peerLastRxSeq = frame.last_rx_seq
646632 val ourHighestTx = highestSentSeq()
647- if (peerLastRxSeq < ourHighestTx) {
633+ if (peerLastRxSeq in 1 .. < ourHighestTx) {
648634 replayFrom(peerLastRxSeq + 1 )
649635 }
650636 if (peerLastTxSeq > currentAckSeq()) {
@@ -661,14 +647,13 @@ class RemoteShellViewModel(
661647 // region --- Frame dispatch ---
662648
663649 private suspend fun sendAck (replayFrom : Int? = null) {
664- val payload = replayFrom?.let { encodeUint32BE(it).toByteString() } ? : ByteString .EMPTY
665650 sendFrame(
666651 RemoteShell (
667652 op = RemoteShell .OpCode .ACK ,
668653 session_id = sessionId.value,
669654 seq = 0 ,
670655 ack_seq = currentAckSeq(),
671- payload = payload ,
656+ last_rx_seq = replayFrom?. let { it - 1 } ? : 0 ,
672657 ),
673658 remember = false ,
674659 )
@@ -685,6 +670,9 @@ class RemoteShellViewModel(
685670 payload = frame.payload,
686671 cols = frame.cols,
687672 rows = frame.rows,
673+ flags = frame.flags,
674+ lastTxSeq = frame.last_tx_seq,
675+ lastRxSeq = frame.last_rx_seq,
688676 ),
689677 )
690678 }
0 commit comments