diff options
author | Joe Crayne <joe@jerkface.net> | 2018-09-04 22:55:39 -0400 |
---|---|---|
committer | Joe Crayne <joe@jerkface.net> | 2018-09-07 13:18:56 -0400 |
commit | 868b6c7f716d98bc458b4ca9d7365d8b02d49685 (patch) | |
tree | d299a1b80f577ac4fac5b132ad38a53133d038f4 | |
parent | 295590ccd3c65c04f9597767ad03a2c1dc5e139c (diff) |
tox: Avoid corrupting outbound buffer on nonsense ack.
-rw-r--r-- | src/Data/PacketQueue.hs | 42 |
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'. | ||
142 | dropPacketsLogic :: Word32 -> Word32 -> Word32 -> (Maybe Word32, Word32, [(Word32,Word32)]) | ||
143 | dropPacketsLogic 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. |
137 | dropPacketsBefore :: PacketQueue a -> Word32 -> STM () | 157 | dropPacketsBefore :: PacketQueue a -> Word32 -> STM () |
138 | dropPacketsBefore PacketQueue{ pktq, seqno, qsize, buffend } no0 = do | 158 | dropPacketsBefore 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 |