summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Crayne <joe@jerkface.net>2018-10-03 14:37:17 -0400
committerJoe Crayne <joe@jerkface.net>2018-11-03 10:23:45 -0400
commit0c7768ba8eb62a6a74176f737a1c9c42308d5a8c (patch)
tree4c41e5cc4f6d0486466f2d74084b682c027aaf01
parent7ca3adad36ace11b523f7029fee4d43054f941ef (diff)
Use seqence number context when serializing CryptoMessage.
-rw-r--r--examples/atox.hs6
-rw-r--r--examples/dhtd.hs6
-rw-r--r--src/Network/Tox/Crypto/Transport.hs65
3 files changed, 55 insertions, 22 deletions
diff --git a/examples/atox.hs b/examples/atox.hs
index 7845d911..3bae5203 100644
--- a/examples/atox.hs
+++ b/examples/atox.hs
@@ -92,7 +92,7 @@ data SetCmd = SetME
92 deriving (Eq,Bounded,Ord,Enum,Show) 92 deriving (Eq,Bounded,Ord,Enum,Show)
93 93
94forkToxInputThread myRead = forkIO $ do 94forkToxInputThread myRead = forkIO $ do
95 let myconduit = Conduit.sourceHandle myRead .| conduitGet2 (S.get :: Get CryptoMessage) -- :: ConduitT i CryptoMessage IO () 95 let myconduit = Conduit.sourceHandle myRead .| conduitGet2 (getCryptoMessage 0 :: Get CryptoMessage) -- :: ConduitT i CryptoMessage IO ()
96 Conduit.runConduit (myconduit .| Conduit.awaitForever handle) 96 Conduit.runConduit (myconduit .| Conduit.awaitForever handle)
97 where 97 where
98 handle (UpToN IPC (B.uncons -> Just (ord -> toEnum -> i,arg))) = updateState i arg 98 handle (UpToN IPC (B.uncons -> Just (ord -> toEnum -> i,arg))) = updateState i arg
@@ -113,7 +113,7 @@ forkToxInputThread myRead = forkIO $ do
113 modifyTVar' sMap (Map.insert key view) 113 modifyTVar' sMap (Map.insert key view)
114 114
115 updateState AppendMsg arg 115 updateState AppendMsg arg
116 = case S.decode arg of 116 = case getCryptoMessage 0 `S.runGet` arg of
117 Left str -> puts (packUtf8 str) 117 Left str -> puts (packUtf8 str)
118 Right msg -> liftIO . atomically $ do 118 Right msg -> liftIO . atomically $ do
119 me <- readTVar sMe 119 me <- readTVar sMe
@@ -133,7 +133,7 @@ doit myReadFd myWriteFd = do
133 terminalInputLoop myWrite 133 terminalInputLoop myWrite
134 134
135hSend :: MonadIO m => Handle -> CryptoMessage -> m () 135hSend :: MonadIO m => Handle -> CryptoMessage -> m ()
136hSend h msg = liftIO $ B.hPutStrLn h (S.encode msg) 136hSend h msg = liftIO $ B.hPutStrLn h (S.runPut $ putCryptoMessage 0 msg)
137 137
138terminalInputLoop myWriteH = fix $ \loop -> do 138terminalInputLoop myWriteH = fix $ \loop -> do
139 line <- B.getLine 139 line <- B.getLine
diff --git a/examples/dhtd.hs b/examples/dhtd.hs
index 6161fbb4..5bc2b87a 100644
--- a/examples/dhtd.hs
+++ b/examples/dhtd.hs
@@ -99,7 +99,7 @@ import qualified Network.Tox.DHT.Transport as Tox
99import qualified Network.Tox.DHT.Handlers as Tox 99import qualified Network.Tox.DHT.Handlers as Tox
100import qualified Network.Tox.Onion.Transport as Tox 100import qualified Network.Tox.Onion.Transport as Tox
101import qualified Network.Tox.Onion.Handlers as Tox 101import qualified Network.Tox.Onion.Handlers as Tox
102import qualified Network.Tox.Crypto.Transport as Tox (CryptoMessage(..)) 102import qualified Network.Tox.Crypto.Transport as Tox (CryptoMessage(..),putCryptoMessage,getCryptoMessage)
103import qualified Network.Tox.Crypto.Handlers as Tox 103import qualified Network.Tox.Crypto.Handlers as Tox
104import Data.Typeable 104import Data.Typeable
105import Network.Tox.ContactInfo as Tox 105import Network.Tox.ContactInfo as Tox
@@ -1407,7 +1407,7 @@ netcrypto (Just (DHT {..})) (Just mypubkey) h roster (Just tox) exes paramStr =
1407 when (them /= their_pub) $ do 1407 when (them /= their_pub) $ do
1408 atomically $ writeTVar whoAreThey their_pub 1408 atomically $ writeTVar whoAreThey their_pub
1409 B.hPutStr myWrite ("\NUL\SOH" `B.append` S.encode (Tox.key2id their_pub)) 1409 B.hPutStr myWrite ("\NUL\SOH" `B.append` S.encode (Tox.key2id their_pub))
1410 B.hPutStr myWrite (S.encode msg) 1410 B.hPutStr myWrite (S.runPut $ Tox.putCryptoMessage 0 msg)
1411 return (Just id) 1411 return (Just id)
1412 addHooks currentHooks typs = forM_ typs $ \typ -> modifyTVar (Tox.ncHooks session) (Map.insert typ (currentHooks typ ++ [makeHook session typ])) 1412 addHooks currentHooks typs = forM_ typs $ \typ -> modifyTVar (Tox.ncHooks session) (Map.insert typ (currentHooks typ ++ [makeHook session typ]))
1413 case ranges of 1413 case ranges of
@@ -1426,7 +1426,7 @@ netcrypto (Just (DHT {..})) (Just mypubkey) h roster (Just tox) exes paramStr =
1426 tid <- myThreadId 1426 tid <- myThreadId
1427 let sidStr = printf "(%x)" (Tox.ncSessionId session) 1427 let sidStr = printf "(%x)" (Tox.ncSessionId session)
1428 labelThread tid (exekey ++ ".forward" ++ sidStr) 1428 labelThread tid (exekey ++ ".forward" ++ sidStr)
1429 let myconduit = Conduit.sourceHandle myRead .| conduitGet2 S.get -- :: ConduitT i CryptoMessage IO () 1429 let myconduit = Conduit.sourceHandle myRead .| conduitGet2 (Tox.getCryptoMessage 0) -- :: ConduitT i CryptoMessage IO ()
1430 Conduit.runConduit (myconduit .| awaitForever (\msg -> do 1430 Conduit.runConduit (myconduit .| awaitForever (\msg -> do
1431 let typ = toWord64 (getMessageType msg) 1431 let typ = toWord64 (getMessageType msg)
1432 mbSendIt <- liftIO $ atomically (lookupInRangeMap typ (Tox.ncOutHooks session)) 1432 mbSendIt <- liftIO $ atomically (lookupInRangeMap typ (Tox.ncOutHooks session))
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