summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Crayne <joe@jerkface.net>2018-09-04 22:55:39 -0400
committerJoe Crayne <joe@jerkface.net>2018-09-07 13:18:56 -0400
commit868b6c7f716d98bc458b4ca9d7365d8b02d49685 (patch)
treed299a1b80f577ac4fac5b132ad38a53133d038f4
parent295590ccd3c65c04f9597767ad03a2c1dc5e139c (diff)
tox: Avoid corrupting outbound buffer on nonsense ack.
-rw-r--r--src/Data/PacketQueue.hs42
1 files changed, 25 insertions, 17 deletions
diff --git a/src/Data/PacketQueue.hs b/src/Data/PacketQueue.hs
index c5d5ac09..aa51426b 100644
--- a/src/Data/PacketQueue.hs
+++ b/src/Data/PacketQueue.hs
@@ -10,6 +10,7 @@ module Data.PacketQueue
10 , getLastEnqueuedPlus1 10 , getLastEnqueuedPlus1
11 , new 11 , new
12 , dequeue 12 , dequeue
13 , dropPacketsLogic
13 , dropPacketsBefore 14 , dropPacketsBefore
14 , getMissing 15 , getMissing
15 -- , dequeueOrGetMissing 16 -- , dequeueOrGetMissing
@@ -33,6 +34,10 @@ data PacketQueue a = PacketQueue
33 , qsize :: Word32 34 , qsize :: Word32
34 , buffend :: TVar Word32 -- on incoming, next packet they'll send + 1 35 , buffend :: TVar Word32 -- on incoming, next packet they'll send + 1
35 -- i.e. one more than the largest seen sequence number. 36 -- i.e. one more than the largest seen sequence number.
37 -- Written by:
38 -- observeOutOfBand
39 -- dropPacketsBefore
40 -- enqueue
36 } 41 }
37 42
38-- | Obtain a list of non-empty slots in the 'PacketQueue'. The numeric value 43-- | Obtain a list of non-empty slots in the 'PacketQueue'. The numeric value
@@ -133,27 +138,30 @@ dequeue PacketQueue { pktq, seqno, qsize } = do
133 modifyTVar' seqno succ 138 modifyTVar' seqno succ
134 return x 139 return x
135 140
141-- | Helper to 'dropPacketsBefore'.
142dropPacketsLogic :: Word32 -> Word32 -> Word32 -> (Maybe Word32, Word32, [(Word32,Word32)])
143dropPacketsLogic qsize low no0 =
144 let no = no0 - 1 -- Unsigned: could overflow
145 proj = no - low -- Unsigned: could overflow
146 in if proj < qsize
147 then
148 let ilow = low `mod` qsize
149 i = no `mod` qsize
150 ranges = if ilow <= i then [(ilow, i)]
151 else [(0,i),(ilow,qsize-1)]
152 in (Nothing,no0,ranges) -- Clear some, but not all, slots.
153 else (Nothing,low,[]) -- out of bounds, do nothing -- (Just no0, no0, [(0,qsize - 1)]) -- Reset to empty queue.
154
155
136-- | Drop all packets preceding the given packet number. 156-- | Drop all packets preceding the given packet number.
137dropPacketsBefore :: PacketQueue a -> Word32 -> STM () 157dropPacketsBefore :: PacketQueue a -> Word32 -> STM ()
138dropPacketsBefore PacketQueue{ pktq, seqno, qsize, buffend } no0 = do 158dropPacketsBefore PacketQueue{ pktq, seqno, qsize, buffend } no0 = do
139 low <- readTVar seqno 159 low <- readTVar seqno
140 let no = no0 - 1 -- possibly negative 160 let (mbuffend, no, ranges) = dropPacketsLogic qsize low no0
141 proj = no - low -- possibly negative 161 mapM_ (writeTVar buffend) mbuffend
142 if (proj < qsize) 162 writeTVar seqno no
143 then do 163 forM_ ranges $ \(lo,hi) -> forM_ [lo .. hi] $ \i -> writeArray pktq i Nothing
144 -- Clear some, but not all, slots. 164
145 let ilow = low `mod` qsize
146 i = no `mod` qsize
147 ranges = if ilow <= i then [[ilow .. i]]
148 else [[0 .. i],[ilow .. qsize-1]]
149 writeTVar seqno no
150 forM_ ranges $ mapM_ $ \i -> writeArray pktq i Nothing
151 else do
152 -- Reset to empty queue.
153 writeTVar seqno no
154 writeTVar buffend no
155 (z,n) <- getBounds pktq
156 forM_ [z .. n] $ \i -> writeArray pktq i Nothing
157 165
158-- -- | Like dequeue, but marks as viewed rather than removing 166-- -- | Like dequeue, but marks as viewed rather than removing
159-- markButNotDequeue :: PacketQueue (Bool,a) -> STM a 167-- markButNotDequeue :: PacketQueue (Bool,a) -> STM a