summaryrefslogtreecommitdiff
path: root/src/Network/Tox
diff options
context:
space:
mode:
Diffstat (limited to 'src/Network/Tox')
-rw-r--r--src/Network/Tox/Crypto/Transport.hs65
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
70import Network.Socket 73import Network.Socket
71import Data.ByteArray 74import Data.ByteArray
72 75
76import Control.Monad
73import Data.ByteString as B 77import Data.ByteString as B
78import Data.Function
74import Data.Maybe 79import Data.Maybe
75import Data.Monoid 80import Data.Monoid
76import Data.Word 81import Data.Word
77import Data.Bits 82import Data.Bits
78import Crypto.Hash 83import Crypto.Hash
79import Control.Lens 84import Control.Lens
80import Control.Monad
81import Data.Text as T 85import Data.Text as T
82import Data.Text.Encoding as T 86import Data.Text.Encoding as T
83import Data.Serialize as S 87import Data.Serialize as S
84import Control.Arrow 88import Control.Arrow
85import DPut 89import DPut
86import Data.PacketBuffer as PB 90import Data.PacketBuffer as PB
87import Data.Function
88 91
89showCryptoMsg :: Word32 -> CryptoMessage -> [Char] 92showCryptoMsg :: Word32 -> CryptoMessage -> [Char]
90showCryptoMsg seqno (UpToN PacketRequest bytes) = "UpToN PacketRequest --> " 93showCryptoMsg 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
236instance Serialize CryptoData where 239instance 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
275unpadCryptoMsg x = x 285unpadCryptoMsg x = x
276 286
287decodeRawCryptoMsg :: CryptoData -> CryptoMessage
288decodeRawCryptoMsg (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
277data CryptoMessage 294data 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
303msgByteList :: CryptoMessage -> [Word8]
304msgByteList (UpToN _ bs) = B.unpack bs
305msgByteList (TwoByte _ b) = [b]
306msgByteList (OneByte _) = []
307
283instance Sized CryptoMessage where 308instance 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
289instance Serialize CryptoMessage where 315getCryptoMessage :: Word32 -> Get CryptoMessage
290 get = do 316getCryptoMessage 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) 327putCryptoMessage :: Word32 -> CryptoMessage -> Put
302 putByteString x 328putCryptoMessage seqno (OneByte i) = putWord8 (fromIntegral . fromEnum $ i)
329putCryptoMessage seqno (TwoByte i b) = do putWord8 (fromIntegral . fromEnum $ i)
330 putWord8 b
331putCryptoMessage seqno (UpToN i x) = do putWord8 (fromIntegral . fromEnum $ i)
332 putByteString x
333putCryptoMessage seqno (RequestResend _ ws) = do
334 putWord8 (fromIntegral . fromEnum $ PacketRequest)
335 mapM_ putWord8 $ compressSequenceNumbers seqno ws
303 336
304instance Serialize MessageID where 337instance Serialize MessageID where
305 get = toEnum . fromIntegral <$> getWord8 338 get = toEnum . fromIntegral <$> getWord8