diff options
Diffstat (limited to 'src/Network')
-rw-r--r-- | src/Network/Tox/Crypto/Transport.hs | 65 |
1 files changed, 49 insertions, 16 deletions
diff --git a/src/Network/Tox/Crypto/Transport.hs b/src/Network/Tox/Crypto/Transport.hs index 2a0633f0..84929e63 100644 --- a/src/Network/Tox/Crypto/Transport.hs +++ b/src/Network/Tox/Crypto/Transport.hs | |||
@@ -10,6 +10,7 @@ module Network.Tox.Crypto.Transport | |||
10 | , parseCrypto | 10 | , parseCrypto |
11 | , encodeCrypto | 11 | , encodeCrypto |
12 | , unpadCryptoMsg | 12 | , unpadCryptoMsg |
13 | , decodeRawCryptoMsg | ||
13 | , createRequestPacket | 14 | , createRequestPacket |
14 | , parseHandshakes | 15 | , parseHandshakes |
15 | , encodeHandshakes | 16 | , encodeHandshakes |
@@ -59,6 +60,8 @@ module Network.Tox.Crypto.Transport | |||
59 | , msgSizeParam | 60 | , msgSizeParam |
60 | , NegotiationID(..) | 61 | , NegotiationID(..) |
61 | , NegotiationMsg(..) | 62 | , NegotiationMsg(..) |
63 | , getCryptoMessage | ||
64 | , putCryptoMessage | ||
62 | , module Data.Tox.Message | 65 | , module Data.Tox.Message |
63 | ) where | 66 | ) where |
64 | 67 | ||
@@ -70,21 +73,21 @@ import Network.Tox.NodeId | |||
70 | import Network.Socket | 73 | import Network.Socket |
71 | import Data.ByteArray | 74 | import Data.ByteArray |
72 | 75 | ||
76 | import Control.Monad | ||
73 | import Data.ByteString as B | 77 | import Data.ByteString as B |
78 | import Data.Function | ||
74 | import Data.Maybe | 79 | import Data.Maybe |
75 | import Data.Monoid | 80 | import Data.Monoid |
76 | import Data.Word | 81 | import Data.Word |
77 | import Data.Bits | 82 | import Data.Bits |
78 | import Crypto.Hash | 83 | import Crypto.Hash |
79 | import Control.Lens | 84 | import Control.Lens |
80 | import Control.Monad | ||
81 | import Data.Text as T | 85 | import Data.Text as T |
82 | import Data.Text.Encoding as T | 86 | import Data.Text.Encoding as T |
83 | import Data.Serialize as S | 87 | import Data.Serialize as S |
84 | import Control.Arrow | 88 | import Control.Arrow |
85 | import DPut | 89 | import DPut |
86 | import Data.PacketBuffer as PB | 90 | import Data.PacketBuffer as PB |
87 | import Data.Function | ||
88 | 91 | ||
89 | showCryptoMsg :: Word32 -> CryptoMessage -> [Char] | 92 | showCryptoMsg :: Word32 -> CryptoMessage -> [Char] |
90 | showCryptoMsg seqno (UpToN PacketRequest bytes) = "UpToN PacketRequest --> " | 93 | showCryptoMsg seqno (UpToN PacketRequest bytes) = "UpToN PacketRequest --> " |
@@ -234,8 +237,15 @@ One effect of this is that short messages will be padded to at least 5 bytes. | |||
234 | -} | 237 | -} |
235 | 238 | ||
236 | instance Serialize CryptoData where | 239 | instance Serialize CryptoData where |
237 | get = CryptoData <$> get <*> get <*> get | 240 | get = do |
238 | put (CryptoData start end dta) = put start >> put end >> put dta | 241 | ack <- get |
242 | seqno <- get | ||
243 | cm <- getCryptoMessage ack | ||
244 | return $ CryptoData ack seqno cm | ||
245 | put (CryptoData ack seqno dta) = do | ||
246 | put ack | ||
247 | put seqno | ||
248 | putCryptoMessage ack dta | ||
239 | 249 | ||
240 | -- The 'UserStatus' equivalent in Presence is: | 250 | -- The 'UserStatus' equivalent in Presence is: |
241 | -- | 251 | -- |
@@ -274,32 +284,55 @@ unpadCryptoMsg x@(UpToN mid0 (B.dropWhile (==0) -> B.uncons -> Just (toEnum8 -> | |||
274 | _ -> UpToN mid bytes | 284 | _ -> UpToN mid bytes |
275 | unpadCryptoMsg x = x | 285 | unpadCryptoMsg x = x |
276 | 286 | ||
287 | decodeRawCryptoMsg :: CryptoData -> CryptoMessage | ||
288 | decodeRawCryptoMsg (CryptoData ack seqno cm) = | ||
289 | let cm' = unpadCryptoMsg cm | ||
290 | in case msgID cm' of | ||
291 | PacketRequest -> RequestResend PacketRequest $ decompressSequenceNumbers ack $ msgByteList cm' | ||
292 | _ -> cm' | ||
293 | |||
277 | data CryptoMessage | 294 | data CryptoMessage |
278 | = OneByte { msgID :: MessageID } | 295 | = OneByte { msgID :: MessageID } |
279 | | TwoByte { msgID :: MessageID, msgByte :: Word8 } | 296 | | TwoByte { msgID :: MessageID, msgByte :: Word8 } |
280 | | UpToN { msgID :: MessageID, msgBytes :: ByteString } -- length < N | 297 | | UpToN { msgID :: MessageID, msgBytes :: ByteString } -- length < N |
298 | -- | TODO: The msgID field is redundant in this case and can be removed | ||
299 | -- after all uses are audited. | ||
300 | | RequestResend { msgID :: MessageID, requested :: [Word32] } | ||
281 | deriving (Eq,Show) | 301 | deriving (Eq,Show) |
282 | 302 | ||
303 | msgByteList :: CryptoMessage -> [Word8] | ||
304 | msgByteList (UpToN _ bs) = B.unpack bs | ||
305 | msgByteList (TwoByte _ b) = [b] | ||
306 | msgByteList (OneByte _) = [] | ||
307 | |||
283 | instance Sized CryptoMessage where | 308 | instance Sized CryptoMessage where |
284 | size = VarSize $ \case | 309 | size = VarSize $ \case |
285 | OneByte {} -> 1 | 310 | OneByte {} -> 1 |
286 | TwoByte {} -> 2 | 311 | TwoByte {} -> 2 |
287 | UpToN { msgBytes = bs } -> 1 + B.length bs | 312 | UpToN { msgBytes = bs } -> 1 + B.length bs |
313 | RequestResend { requested = ws } -> 1 + Prelude.length ws | ||
288 | 314 | ||
289 | instance Serialize CryptoMessage where | 315 | getCryptoMessage :: Word32 -> Get CryptoMessage |
290 | get = do | 316 | getCryptoMessage seqno = do |
291 | i <- get :: Get MessageID | 317 | i <- get :: Get MessageID |
292 | n <- remaining | 318 | n <- remaining |
293 | case msgSizeParam i of | 319 | pkt <- case msgSizeParam i of |
294 | Just (True,0) -> return $ OneByte i | 320 | Just (True,0) -> return $ OneByte i |
295 | Just (True,1) -> TwoByte i <$> get | 321 | Just (True,1) -> TwoByte i <$> get |
296 | _ -> UpToN i <$> getByteString n | 322 | _ -> UpToN i <$> getByteString n |
297 | 323 | return $ if msgID pkt == PacketRequest | |
298 | put (OneByte i) = putWord8 (fromIntegral . fromEnum $ i) | 324 | then RequestResend PacketRequest $ decompressSequenceNumbers seqno $ msgByteList pkt |
299 | put (TwoByte i b) = do putWord8 (fromIntegral . fromEnum $ i) | 325 | else pkt |
300 | putWord8 b | 326 | |
301 | put (UpToN i x) = do putWord8 (fromIntegral . fromEnum $ i) | 327 | putCryptoMessage :: Word32 -> CryptoMessage -> Put |
302 | putByteString x | 328 | putCryptoMessage seqno (OneByte i) = putWord8 (fromIntegral . fromEnum $ i) |
329 | putCryptoMessage seqno (TwoByte i b) = do putWord8 (fromIntegral . fromEnum $ i) | ||
330 | putWord8 b | ||
331 | putCryptoMessage seqno (UpToN i x) = do putWord8 (fromIntegral . fromEnum $ i) | ||
332 | putByteString x | ||
333 | putCryptoMessage seqno (RequestResend _ ws) = do | ||
334 | putWord8 (fromIntegral . fromEnum $ PacketRequest) | ||
335 | mapM_ putWord8 $ compressSequenceNumbers seqno ws | ||
303 | 336 | ||
304 | instance Serialize MessageID where | 337 | instance Serialize MessageID where |
305 | get = toEnum . fromIntegral <$> getWord8 | 338 | get = toEnum . fromIntegral <$> getWord8 |