diff options
author | Joe Crayne <joe@jerkface.net> | 2018-09-04 22:57:15 -0400 |
---|---|---|
committer | Joe Crayne <joe@jerkface.net> | 2018-09-07 13:18:56 -0400 |
commit | d133be0736d6ce366a41582bc59501e6eab81163 (patch) | |
tree | 5d87a0212db84a3ff1000b6fc020b928f214d9b9 /src/Data | |
parent | 868b6c7f716d98bc458b4ca9d7365d8b02d49685 (diff) |
PacketBuffer: compressSequenceNumbers utility (for tox PacketRequest).
Diffstat (limited to 'src/Data')
-rw-r--r-- | src/Data/PacketBuffer.hs | 55 |
1 files changed, 45 insertions, 10 deletions
diff --git a/src/Data/PacketBuffer.hs b/src/Data/PacketBuffer.hs index d2e96d11..343cb04e 100644 --- a/src/Data/PacketBuffer.hs +++ b/src/Data/PacketBuffer.hs | |||
@@ -13,9 +13,12 @@ module Data.PacketBuffer | |||
13 | , nextToSendSequenceNumber | 13 | , nextToSendSequenceNumber |
14 | , retrieveForResend | 14 | , retrieveForResend |
15 | , decompressSequenceNumbers | 15 | , decompressSequenceNumbers |
16 | , compressSequenceNumbers | ||
17 | , pbReport | ||
16 | ) where | 18 | ) where |
17 | 19 | ||
18 | import Data.PacketQueue as Q | 20 | import Data.PacketQueue as Q |
21 | import DPut | ||
19 | 22 | ||
20 | import Control.Concurrent.STM | 23 | import Control.Concurrent.STM |
21 | import Control.Monad | 24 | import Control.Monad |
@@ -24,8 +27,7 @@ import Data.Word | |||
24 | 27 | ||
25 | data PacketBuffer a b = PacketBuffer | 28 | data PacketBuffer a b = PacketBuffer |
26 | { inQueue :: PacketQueue a | 29 | { inQueue :: PacketQueue a |
27 | , outBuffer :: PacketQueue b | 30 | , outBuffer :: PacketQueue b } |
28 | } | ||
29 | 31 | ||
30 | -- | Initialize the packet buffers. Note, the capacity of the inbound packet | 32 | -- | Initialize the packet buffers. Note, the capacity of the inbound packet |
31 | -- queue is currently hardcoded to 200 packets and the capacity of the outbound | 33 | -- queue is currently hardcoded to 200 packets and the capacity of the outbound |
@@ -55,13 +57,13 @@ data PacketInboundEvent a | |||
55 | -- | Whenever a packet is received or sent (but not resent) from the network, | 57 | -- | Whenever a packet is received or sent (but not resent) from the network, |
56 | -- this function should be called to update the relevant buffers. | 58 | -- this function should be called to update the relevant buffers. |
57 | -- | 59 | -- |
58 | -- On outgoing packets, if the outbound buffer is full, this will block | 60 | -- On outgoing packets, if the outbound buffer is full, this will return |
59 | -- indefinitely until it is called in another thread with an inbound | 61 | -- True. In this case, the caller may retry to enable blocking until |
60 | -- acknowledgement. | 62 | -- 'grokInboundPacket' is called in another thread. |
61 | grokOutboundPacket :: PacketBuffer a b -> PacketOutboundEvent b -> STM () | 63 | grokOutboundPacket :: PacketBuffer a b -> PacketOutboundEvent b -> STM (Bool,(Word32,Word32)) |
62 | grokOutboundPacket (PacketBuffer _ outb) (PacketSent seqno a) | 64 | grokOutboundPacket (PacketBuffer _ outb) (PacketSent seqno a) |
63 | = do (n,_) <- Q.enqueue outb seqno a | 65 | = do (n,r) <- Q.enqueue outb seqno a |
64 | when (n/=0) retry | 66 | return (n/=0,(n,r)) |
65 | 67 | ||
66 | grokInboundPacket :: PacketBuffer a b -> PacketInboundEvent a -> STM () | 68 | grokInboundPacket :: PacketBuffer a b -> PacketInboundEvent a -> STM () |
67 | grokInboundPacket (PacketBuffer inb outb) (PacketReceived seqno a ack) | 69 | grokInboundPacket (PacketBuffer inb outb) (PacketReceived seqno a ack) |
@@ -100,13 +102,46 @@ retrieveForResend :: PacketBuffer a b -> [Word32] -> STM [(Word32,b)] | |||
100 | retrieveForResend (PacketBuffer _ outb) seqnos = | 102 | retrieveForResend (PacketBuffer _ outb) seqnos = |
101 | catMaybes <$> forM seqnos (\no -> fmap (no,) <$> Q.lookup outb no) | 103 | catMaybes <$> forM seqnos (\no -> fmap (no,) <$> Q.lookup outb no) |
102 | 104 | ||
103 | -- | Expand a compressed set of sequence numbers. The first squence number is | 105 | -- | Expand a compressed set of sequence numbers. The first sequence number is |
104 | -- given directly and the rest are computed using 8-bit offsets. This is | 106 | -- given directly and the rest are computed using 8-bit offsets. This is |
105 | -- normally used to obtain input for 'retrieveForResend'. | 107 | -- normally used to obtain input for 'retrieveForResend'. |
106 | decompressSequenceNumbers :: Word32 -> [Word8] -> [Word32] | 108 | decompressSequenceNumbers :: Word32 -> [Word8] -> [Word32] |
107 | decompressSequenceNumbers baseno ns = foldr doOne (const []) ns (baseno-1) | 109 | decompressSequenceNumbers baseno ns = foldr doOne (const []) ns (baseno-1) |
108 | where | 110 | where |
109 | doOne :: Word8 -> (Word32 -> [Word32]) -> Word32 -> [Word32] | 111 | doOne :: Word8 -> (Word32 -> [Word32]) -> Word32 -> [Word32] |
110 | doOne 0 f addend = f (addend+255) | 112 | doOne 0 f addend = f (addend + 255) |
111 | doOne x f addend = let y = fromIntegral x + addend | 113 | doOne x f addend = let y = fromIntegral x + addend |
112 | in y : f y | 114 | in y : f y |
115 | |||
116 | compressSequenceNumbers :: Word32 -> [Word32] -> [Word8] | ||
117 | compressSequenceNumbers baseno xs = foldr doOne (const []) xs (baseno-1) | ||
118 | where | ||
119 | doOne :: Word32 -> (Word32 -> [Word8]) -> Word32 -> [Word8] | ||
120 | doOne y f addend = case y - addend of | ||
121 | x | x < 255 -> fromIntegral x : f y | ||
122 | | otherwise -> 0 : doOne y f (addend + 255) | ||
123 | |||
124 | {- | ||
125 | compressSequenceNumbers :: Word32 -> [Word32] -> [Word8] | ||
126 | compressSequenceNumbers seqno xs = let r = map fromIntegral (reduceToSums ys >>= makeZeroes) | ||
127 | in dtrace XNetCrypto ("compressSequenceNumbers " ++ show seqno ++ show xs ++ " --> "++show r) r | ||
128 | where | ||
129 | ys = Prelude.map (subtract (seqno - 1)) xs | ||
130 | reduceToSums [] = [] | ||
131 | reduceToSums (x:xs) = x:(reduceToSums $ Prelude.map (subtract x) xs) | ||
132 | makeZeroes :: Word32 -> [Word32] | ||
133 | -- makeZeroes 0 = [] | ||
134 | makeZeroes x | ||
135 | = let (d,m)= x `divMod` 255 | ||
136 | zeros= Prelude.replicate (fromIntegral d) 0 | ||
137 | in zeros ++ [m] | ||
138 | -} | ||
139 | |||
140 | pbReport :: String -> PacketBuffer a b -> STM String | ||
141 | pbReport what (PacketBuffer inb outb) = do | ||
142 | inb_seqno <- getLastDequeuedPlus1 inb | ||
143 | inb_buffend <- getLastEnqueuedPlus1 inb | ||
144 | outb_seqno <- getLastDequeuedPlus1 outb | ||
145 | outb_bufend <- getLastEnqueuedPlus1 outb | ||
146 | return $ "PacketBuffer<"++what++"> Inbound" ++ show (inb_seqno, inb_buffend) | ||
147 | ++" Outbound" ++ show (outb_seqno, outb_bufend) | ||