packages feed

gbnet-hs 0.2.3.0 → 0.2.4.0

raw patch · 3 files changed

+56/−3 lines, 3 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

Files

CHANGELOG.md view
@@ -1,5 +1,11 @@ # Changelog +## 0.2.4.0++### Bug Fixes++- **Wire reliable channel retransmission**: `Channel.getRetransmitMessages` was implemented and exported but never called from the connection tick loop. Reliable messages that were lost on the wire were never retransmitted, causing silent data loss on any packet drop. Now called from `updateConnectedPure` after processing outgoing messages — expired unacked messages are re-queued as new Payload packets with fresh sequence numbers.+ ## 0.2.3.0  ### Bug Fixes
gbnet-hs.cabal view
@@ -1,6 +1,6 @@ cabal-version:      3.0 name:               gbnet-hs-version:            0.2.3.0+version:            0.2.4.0 synopsis:           Transport-level networking library with zero-copy Storable serialization description:   A transport-level networking library providing reliable UDP with
src/GBNet/Connection.hs view
@@ -548,9 +548,12 @@         | timeSinceSend > keepaliveMs = sendKeepalive conn2         | otherwise = conn2       -- Process channel outgoing messages-      conn4 = processChannelOutput now conn3+      afterOutput = processChannelOutput now conn3+      -- Retransmit unacked reliable messages past RTO+      currentRto = Rel.rtoMs (connReliability afterOutput)+      afterRetransmit = processRetransmissions now currentRto afterOutput       -- Update channels-      conn5 = conn4 & #connChannels %~ IntMap.map (Channel.channelUpdate now)+      conn5 = afterRetransmit & #connChannels %~ IntMap.map (Channel.channelUpdate now)       -- Send AckOnly if needed       conn6         | connPendingAck conn5 && not (connDataSentThisTick conn5) = sendAckOnly conn5@@ -655,6 +658,50 @@             .~ congestion             & #connCwnd             .~ cwnd+            & #connReliability+            .~ reliability+            & #connDataSentThisTick+            .~ True++-- | Retransmit unacked reliable messages that have exceeded the RTO.+-- Iterates all channels, calls 'getRetransmitMessages' to find expired+-- messages, and re-queues them as new Payload packets.+processRetransmissions :: MonoTime -> Double -> Connection -> Connection+processRetransmissions now rto conn =+  IntMap.foldlWithKey' retransmitChannel conn (connChannels conn)+  where+    retransmitChannel c chIdx channel =+      let (retransmits, updatedChannel) = Channel.getRetransmitMessages now rto channel+          channelUpdated = c & #connChannels %~ IntMap.insert chIdx updatedChannel+       in foldl' (emitRetransmit chIdx) channelUpdated retransmits++    emitRetransmit chIdx c msg =+      let msgSeqRaw = unSequenceNum (cmSequence msg)+          headerByte = fromIntegral chIdx .&. 0x07+          seqHi = fromIntegral (msgSeqRaw `shiftR` 8) :: Word8+          seqLo = fromIntegral (msgSeqRaw .&. 0xFF) :: Word8+          wireData = BS.cons headerByte $ BS.cons seqHi $ BS.cons seqLo (cmData msg)+          wireSize = BS.length wireData+          header = createHeaderInternal c+          pkt =+            OutgoingPacket+              { opHeader = header {packetType = Payload},+                opType = Payload,+                opPayload = wireData+              }+          reliability =+            Rel.onPacketSent+              (connLocalSeq c)+              now+              (ChannelId (fromIntegral chIdx))+              (cmSequence msg)+              wireSize+              (connReliability c)+       in c+            & #connSendQueue+            %~ (Seq.|> pkt)+            & #connLocalSeq+            %~ (+ 1)             & #connReliability             .~ reliability             & #connDataSentThisTick