summaryrefslogtreecommitdiff
path: root/src/Data
diff options
context:
space:
mode:
authorJoe Crayne <joe@jerkface.net>2018-09-04 22:57:15 -0400
committerJoe Crayne <joe@jerkface.net>2018-09-07 13:18:56 -0400
commitd133be0736d6ce366a41582bc59501e6eab81163 (patch)
tree5d87a0212db84a3ff1000b6fc020b928f214d9b9 /src/Data
parent868b6c7f716d98bc458b4ca9d7365d8b02d49685 (diff)
PacketBuffer: compressSequenceNumbers utility (for tox PacketRequest).
Diffstat (limited to 'src/Data')
-rw-r--r--src/Data/PacketBuffer.hs55
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
18import Data.PacketQueue as Q 20import Data.PacketQueue as Q
21import DPut
19 22
20import Control.Concurrent.STM 23import Control.Concurrent.STM
21import Control.Monad 24import Control.Monad
@@ -24,8 +27,7 @@ import Data.Word
24 27
25data PacketBuffer a b = PacketBuffer 28data 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.
61grokOutboundPacket :: PacketBuffer a b -> PacketOutboundEvent b -> STM () 63grokOutboundPacket :: PacketBuffer a b -> PacketOutboundEvent b -> STM (Bool,(Word32,Word32))
62grokOutboundPacket (PacketBuffer _ outb) (PacketSent seqno a) 64grokOutboundPacket (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
66grokInboundPacket :: PacketBuffer a b -> PacketInboundEvent a -> STM () 68grokInboundPacket :: PacketBuffer a b -> PacketInboundEvent a -> STM ()
67grokInboundPacket (PacketBuffer inb outb) (PacketReceived seqno a ack) 69grokInboundPacket (PacketBuffer inb outb) (PacketReceived seqno a ack)
@@ -100,13 +102,46 @@ retrieveForResend :: PacketBuffer a b -> [Word32] -> STM [(Word32,b)]
100retrieveForResend (PacketBuffer _ outb) seqnos = 102retrieveForResend (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'.
106decompressSequenceNumbers :: Word32 -> [Word8] -> [Word32] 108decompressSequenceNumbers :: Word32 -> [Word8] -> [Word32]
107decompressSequenceNumbers baseno ns = foldr doOne (const []) ns (baseno-1) 109decompressSequenceNumbers 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
116compressSequenceNumbers :: Word32 -> [Word32] -> [Word8]
117compressSequenceNumbers 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{-
125compressSequenceNumbers :: Word32 -> [Word32] -> [Word8]
126compressSequenceNumbers 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
140pbReport :: String -> PacketBuffer a b -> STM String
141pbReport 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)