summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/dhtd.hs3
-rw-r--r--src/Network/Tox/Crypto/Handlers.hs67
-rw-r--r--src/Network/Tox/Crypto/Transport.hs12
3 files changed, 56 insertions, 26 deletions
diff --git a/examples/dhtd.hs b/examples/dhtd.hs
index 36a9fa68..f6c57130 100644
--- a/examples/dhtd.hs
+++ b/examples/dhtd.hs
@@ -1722,7 +1722,8 @@ main = runResourceT $ liftBaseWith $ \resT -> do
1722 let sockAddr = Tox.ncSockAddr netcrypto 1722 let sockAddr = Tox.ncSockAddr netcrypto
1723 pubKey = Tox.ncTheirPublicKey netcrypto 1723 pubKey = Tox.ncTheirPublicKey netcrypto
1724 tmchan <- atomically newTMChan 1724 tmchan <- atomically newTMChan
1725 let Just pingMachine = Tox.ncPingMachine netcrypto 1725 mbPingMaching <- atomically $ readTVar (Tox.ncPingMachine netcrypto)
1726 let Just pingMachine = mbPingMaching
1726 pingflag = readTVar (pingFlag pingMachine) 1727 pingflag = readTVar (pingFlag pingMachine)
1727 receiveCrypto = atomically $ readTMChan tmchan 1728 receiveCrypto = atomically $ readTMChan tmchan
1728 onEOF = return () -- TODO: Update toxContactInfo, not connected. 1729 onEOF = return () -- TODO: Update toxContactInfo, not connected.
diff --git a/src/Network/Tox/Crypto/Handlers.hs b/src/Network/Tox/Crypto/Handlers.hs
index d174b10c..f31a62e4 100644
--- a/src/Network/Tox/Crypto/Handlers.hs
+++ b/src/Network/Tox/Crypto/Handlers.hs
@@ -4,6 +4,7 @@
4{-# LANGUAGE PatternSynonyms #-} 4{-# LANGUAGE PatternSynonyms #-}
5{-# LANGUAGE TupleSections #-} 5{-# LANGUAGE TupleSections #-}
6{-# LANGUAGE TypeOperators #-} 6{-# LANGUAGE TypeOperators #-}
7{-# LANGUAGE ViewPatterns #-}
7module Network.Tox.Crypto.Handlers where 8module Network.Tox.Crypto.Handlers where
8 9
9import Network.Tox.NodeId 10import Network.Tox.NodeId
@@ -341,12 +342,15 @@ data NetCryptoSession = NCrypto
341 -- ^ a buffer in which incoming packets may be stored out of order 342 -- ^ a buffer in which incoming packets may be stored out of order
342 -- but from which they may be extracted in sequence, 343 -- but from which they may be extracted in sequence,
343 -- helps ensure lossless packets are processed in order 344 -- helps ensure lossless packets are processed in order
344 , ncDequeueThread :: Maybe ThreadId 345 , ncDequeueThread :: TVar (Maybe ThreadId)
345 -- ^ when the thread which dequeues from ncPacketQueue 346 -- ^ when the thread which dequeues from ncPacketQueue
346 -- is started, its ThreadId is stored here 347 -- is started, its ThreadId is stored here
347 , ncPingMachine :: Maybe PingMachine 348 , ncDequeueOutGoingThread :: TVar (Maybe ThreadId)
348 , ncPingThread :: Maybe ThreadId 349 -- ^ the thread which actually sends lossless packets
349 -- ^ when the ping thread is started, store it here 350 , ncPingMachine :: TVar (Maybe PingMachine)
351 -- ^ thread which triggers ping events
352 , ncPingThread :: TVar (Maybe ThreadId)
353 -- ^ thread which actually queues outgoing pings
350 , ncOutgoingQueue :: TVar 354 , ncOutgoingQueue :: TVar
351 (UponHandshake 355 (UponHandshake
352 (PQ.PacketOutQueue 356 (PQ.PacketOutQueue
@@ -599,6 +603,10 @@ freshCryptoSession sessions
599 dmsg $ "freshCryptoSession: Session ncTheirBaseNonce=" ++ show theirbasenonce 603 dmsg $ "freshCryptoSession: Session ncTheirBaseNonce=" ++ show theirbasenonce
600 dmsg $ "freshCryptoSession: My Session Public =" ++ show (key2id $ toPublic newsession) 604 dmsg $ "freshCryptoSession: My Session Public =" ++ show (key2id $ toPublic newsession)
601 ncTheirSessionPublic0 <- newTVar (frmMaybe mbtheirSessionKey) 605 ncTheirSessionPublic0 <- newTVar (frmMaybe mbtheirSessionKey)
606 ncDequeueThread0 <- newTVar Nothing
607 ncDequeueOutGoingThread0 <- newTVar Nothing
608 ncPingMachine0 <- newTVar Nothing
609 ncPingThread0 <- newTVar Nothing
602 let netCryptoSession0 = 610 let netCryptoSession0 =
603 NCrypto { ncState = ncState0 611 NCrypto { ncState = ncState0
604 , ncMyPublicKey = toPublic key 612 , ncMyPublicKey = toPublic key
@@ -621,9 +629,10 @@ freshCryptoSession sessions
621 , ncOutgoingIdMapEscapedLossless = losslessEscapeIdMap 629 , ncOutgoingIdMapEscapedLossless = losslessEscapeIdMap
622 , ncView = ncView0 630 , ncView = ncView0
623 , ncPacketQueue = pktq 631 , ncPacketQueue = pktq
624 , ncDequeueThread = Nothing -- error "you want the NetCrypto-Dequeue thread id, but is it started?" 632 , ncDequeueThread = ncDequeueThread0
625 , ncPingMachine = Nothing -- error "you want the NetCrypto-PingMachine, but is it started?" 633 , ncDequeueOutGoingThread = ncDequeueOutGoingThread0
626 , ncPingThread = Nothing -- error "you want the NetCrypto-PingSender, but is it started?" 634 , ncPingMachine = ncPingMachine0
635 , ncPingThread = ncPingThread0
627 , ncOutgoingQueue = mbpktoqVar 636 , ncOutgoingQueue = mbpktoqVar
628 , ncLastNMsgs = lastNQ 637 , ncLastNMsgs = lastNQ
629 , ncListeners = listeners 638 , ncListeners = listeners
@@ -713,33 +722,40 @@ runUponHandshake netCryptoSession0 addr pktoq = do
713 crypto = transportCrypto sessions 722 crypto = transportCrypto sessions
714 allsessions = netCryptoSessions sessions 723 allsessions = netCryptoSessions sessions
715 allsessionsByKey = netCryptoSessionsByKey sessions 724 allsessionsByKey = netCryptoSessionsByKey sessions
725 sidStr = printf "(%x)" (ncSessionId netCryptoSession0)
716 -- launch dequeue thread 726 -- launch dequeue thread
717 -- (In terms of data dependency, this thread could be launched prior to handshake) 727 -- (In terms of data dependency, this thread could be launched prior to handshake)
718 threadid <- forkIO $ do 728 threadid <- forkIO $ do
719 tid <- myThreadId 729 tid <- myThreadId
720 labelThread tid ("NetCryptoDequeue." ++ show (key2id remotePublicKey)) 730 atomically $ writeTVar (ncDequeueThread netCryptoSession0) (Just tid)
731 labelThread tid ("NetCryptoDequeue." ++ show (key2id remotePublicKey) ++ sidStr)
721 fix $ \loop -> do 732 fix $ \loop -> do
722 cd <- atomically $ PQ.dequeue pktq 733 cd <- atomically $ PQ.dequeue pktq
723 _ <- runCryptoHook (netCryptoSession0 {ncDequeueThread=Just tid}) (bufferData cd) 734 dput XNetCrypto $ "Dequeued::" ++ show (bufferData cd) ++ " now running hook..."
735 _ <- runCryptoHook netCryptoSession0 (bufferData cd)
724 loop 736 loop
725 dput XNetCrypto $ "runUponHandshake: " ++ show threadid ++ " = NetCryptoDequeue." ++ show (key2id remotePublicKey) 737 dput XNetCrypto $ "runUponHandshake: " ++ show threadid ++ " = NetCryptoDequeue." ++ show (key2id remotePublicKey) ++ sidStr
726 -- launch dequeueOutgoing thread 738 -- launch dequeueOutgoing thread
727 threadidOutgoing <- forkIO $ do 739 threadidOutgoing <- forkIO $ do
728 tid <- myThreadId 740 tid <- myThreadId
729 labelThread tid ("NetCryptoDequeueOutgoing." ++ show (key2id remotePublicKey)) 741 atomically $ writeTVar (ncDequeueOutGoingThread netCryptoSession0) (Just tid)
742 labelThread tid ("NetCryptoDequeueOutgoing." ++ show (key2id remotePublicKey) ++ sidStr)
730 fix $ \loop -> do 743 fix $ \loop -> do
731 (_,pkt) <- atomically $ PQ.dequeueOutgoing pktoq 744 (_,pkt) <- atomically $ PQ.dequeueOutgoing pktoq
732 dput XNetCrypto "NetCryptoDequeueOutgoing thread... Sending encrypted Packet" 745 dput XNetCrypto "NetCryptoDequeueOutgoing thread... Sending encrypted Packet"
733 sendSessionPacket sessions addr pkt 746 sendSessionPacket sessions addr pkt
734 loop 747 loop
735 dput XNetCrypto $ "runUponHandshake: " ++ show threadidOutgoing ++ " = NetCryptoDequeueOutgoing." ++ show (key2id remotePublicKey) 748 dput XNetCrypto $ "runUponHandshake: " ++ show threadidOutgoing ++ " = NetCryptoDequeueOutgoing." ++ show (key2id remotePublicKey) ++ sidStr
736 -- launch ping Machine thread 749 -- launch ping Machine thread
737 fuzz <- return 0 -- randomRIO (0,2000) -- Fuzz to prevent simultaneous ping/pong exchanges. 750 fuzz <- return 0 -- randomRIO (0,2000) -- Fuzz to prevent simultaneous ping/pong exchanges.
738 -- Disabled because tox has no pong event. 751 -- Disabled because tox has no pong event.
739 pingMachine <- forkPingMachine ("NetCrypto." ++ show (key2id remotePublicKey)) (8000 + fuzz) 4000 752 pingMachine <- forkPingMachine ("NetCrypto." ++ show (key2id remotePublicKey) ++ sidStr) (8000 + fuzz) 4000
753 atomically $ writeTVar (ncPingMachine netCryptoSession0) (Just pingMachine)
754 -- launch ping thread
740 pingThreadId <- forkIO $ do 755 pingThreadId <- forkIO $ do
741 tid <- myThreadId 756 tid <- myThreadId
742 labelThread tid ("NetCryptoPingSender." ++ show (key2id remotePublicKey) ++ "." ++ show (ncSessionId netCryptoSession0)) 757 atomically $ writeTVar (ncPingThread netCryptoSession0) (Just tid)
758 labelThread tid ("NetCryptoPingSender." ++ show (key2id remotePublicKey) ++ sidStr)
743 event <- atomically $ pingWait pingMachine 759 event <- atomically $ pingWait pingMachine
744 case event of 760 case event of
745 PingIdle -> do 761 PingIdle -> do
@@ -756,9 +772,7 @@ runUponHandshake netCryptoSession0 addr pktoq = do
756 Right _ -> return () 772 Right _ -> return ()
757 PingTimeOut -> dput XNetCrypto $ "(pingThread session: " ++ show (ncSessionId netCryptoSession0) ++ ") PingTimeOut TODO" 773 PingTimeOut -> dput XNetCrypto $ "(pingThread session: " ++ show (ncSessionId netCryptoSession0) ++ ") PingTimeOut TODO"
758 -- update session with thread ids 774 -- update session with thread ids
759 let netCryptoSession = netCryptoSession0 { ncDequeueThread=Just threadid 775 let netCryptoSession = netCryptoSession0
760 , ncPingMachine=Just pingMachine
761 , ncPingThread=Just pingThreadId}
762 -- add this session to the lookup maps 776 -- add this session to the lookup maps
763 -- atomically $ addSessionToMapIfNotThere sessions addr netCryptoSession 777 -- atomically $ addSessionToMapIfNotThere sessions addr netCryptoSession
764 -- run announceNewSessionHooks 778 -- run announceNewSessionHooks
@@ -778,10 +792,10 @@ destroySession :: NetCryptoSession -> IO ()
778destroySession session = do 792destroySession session = do
779 let allsessions = ncAllSessions session 793 let allsessions = ncAllSessions session
780 sid = ncSessionId session 794 sid = ncSessionId session
781 stopThread :: Maybe ThreadId -> IO () 795 stopThread :: TVar (Maybe ThreadId) -> IO ()
782 stopThread x = maybe (return ()) killThread x 796 stopThread x = atomically (readTVar x) >>= maybe (return ()) killThread
783 stopMachine :: Maybe PingMachine -> IO () 797 stopMachine :: TVar (Maybe PingMachine) -> IO ()
784 stopMachine x = maybe (return ()) pingCancel x 798 stopMachine x = atomically (readTVar x) >>= maybe (return ()) pingCancel
785 atomically $ do 799 atomically $ do
786 modifyTVar (netCryptoSessionsByKey allsessions) 800 modifyTVar (netCryptoSessionsByKey allsessions)
787 $ Map.map (filter ((/=sid) . ncSessionId)) 801 $ Map.map (filter ((/=sid) . ncSessionId))
@@ -790,6 +804,7 @@ destroySession session = do
790 stopThread (ncPingThread session) 804 stopThread (ncPingThread session)
791 stopMachine (ncPingMachine session) 805 stopMachine (ncPingMachine session)
792 stopThread (ncDequeueThread session) 806 stopThread (ncDequeueThread session)
807 stopThread (ncDequeueOutGoingThread session)
793 808
794-- | Called when we get a handshake, but there's already a session entry. 809-- | Called when we get a handshake, but there's already a session entry.
795-- 810--
@@ -960,7 +975,8 @@ sessionPacketH sessions addrRaw (CryptoPacket nonce16 encrypted) = do
960 Left s -> do 975 Left s -> do
961 dput XNetCrypto $ "(NetCrypto)sessionPacketH: " ++ s 976 dput XNetCrypto $ "(NetCrypto)sessionPacketH: " ++ s
962 return Nothing -- decryption failed, ignore packet 977 return Nothing -- decryption failed, ignore packet
963 Right cd@(CryptoData {bufferStart, bufferEnd, bufferData=cm}) -> do -- decryption succeeded, 978 Right cd'@(CryptoData {bufferStart, bufferEnd, bufferData=(unpadCryptoMsg -> cm)}) -> do -- decryption succeeded,
979 let cd = cd' { bufferData= cm }
964 -- TODO: Why do I need bufferStart & bufferEnd? 980 -- TODO: Why do I need bufferStart & bufferEnd?
965 -- 981 --
966 -- buffer_start = highest packet number handled + 1 982 -- buffer_start = highest packet number handled + 1
@@ -978,7 +994,8 @@ sessionPacketH sessions addrRaw (CryptoPacket nonce16 encrypted) = do
978 -- then set session confirmed, 994 -- then set session confirmed,
979 atomically $ writeTVar ncState {-Confirmed-}Established 995 atomically $ writeTVar ncState {-Confirmed-}Established
980 -- bump ping machine 996 -- bump ping machine
981 case ncPingMachine of 997 ncPingMachine0 <- atomically $ readTVar ncPingMachine
998 case ncPingMachine0 of
982 Just pingMachine -> -- Normally, we would bump the PingMachine to mark the connection 999 Just pingMachine -> -- Normally, we would bump the PingMachine to mark the connection
983 -- as non-idle so that we don't need to send a ping message. 1000 -- as non-idle so that we don't need to send a ping message.
984 -- Because tox has no pong message, we need to send a ping every 1001 -- Because tox has no pong message, we need to send a ping every
@@ -995,10 +1012,10 @@ sessionPacketH sessions addrRaw (CryptoPacket nonce16 encrypted) = do
995 isLossy (Msg mid) | lossyness mid == Lossy = True 1012 isLossy (Msg mid) | lossyness mid == Lossy = True
996 isLossy _ = False 1013 isLossy _ = False
997 if isLossy msgTypMapped 1014 if isLossy msgTypMapped
998 then do dput XNetCrypto "enqueue ncPacketQueue Lossy" 1015 then do dput XNetCrypto $ "enqueue ncPacketQueue Lossy " ++ show cm
999 atomically $ PQ.observeOutOfBand ncPacketQueue bufferEnd 1016 atomically $ PQ.observeOutOfBand ncPacketQueue bufferEnd
1000 runCryptoHook session (bufferData cd) 1017 runCryptoHook session (bufferData cd)
1001 else do dput XNetCrypto "enqueue ncPacketQueue Lossless" 1018 else do dput XNetCrypto $ "enqueue ncPacketQueue Lossless " ++ show cm
1002 when (msgID cm == PING) $ 1019 when (msgID cm == PING) $
1003 dput XNetCrypto $ "NetCrypto Recieved PING (session " ++ show ncSessionId ++")" 1020 dput XNetCrypto $ "NetCrypto Recieved PING (session " ++ show ncSessionId ++")"
1004 atomically $ PQ.enqueue ncPacketQueue bufferEnd cd 1021 atomically $ PQ.enqueue ncPacketQueue bufferEnd cd
diff --git a/src/Network/Tox/Crypto/Transport.hs b/src/Network/Tox/Crypto/Transport.hs
index ce3bafee..fab0f3e2 100644
--- a/src/Network/Tox/Crypto/Transport.hs
+++ b/src/Network/Tox/Crypto/Transport.hs
@@ -7,6 +7,7 @@
7module Network.Tox.Crypto.Transport 7module Network.Tox.Crypto.Transport
8 ( parseCrypto 8 ( parseCrypto
9 , encodeCrypto 9 , encodeCrypto
10 , unpadCryptoMsg
10 , parseHandshakes 11 , parseHandshakes
11 , encodeHandshakes 12 , encodeHandshakes
12 , CryptoData(..) 13 , CryptoData(..)
@@ -220,6 +221,17 @@ data UserStatus = Online | Away | Busy deriving (Show,Read,Eq,Ord,Enum)
220 221
221data TypingStatus = NotTyping | Typing deriving (Show,Read,Eq,Ord,Enum) 222data TypingStatus = NotTyping | Typing deriving (Show,Read,Eq,Ord,Enum)
222 223
224unpadCryptoMsg :: CryptoMessage -> CryptoMessage
225unpadCryptoMsg x@(TwoByte Padding (toEnum8 -> mid))
226 | msgSizeParam mid == Just (True,0) = OneByte mid
227unpadCryptoMsg x@(UpToN mid0 (B.dropWhile (==0) -> B.uncons -> Just (toEnum8 -> mid,bytes)))
228 | mid0 == Padding
229 = case msgSizeParam mid of
230 Just (True,0) -> OneByte mid
231 Just (True,1) -> TwoByte mid (B.head bytes)
232 _ -> UpToN mid bytes
233unpadCryptoMsg x = x
234
223data CryptoMessage 235data CryptoMessage
224 = OneByte { msgID :: MessageID } 236 = OneByte { msgID :: MessageID }
225 | TwoByte { msgID :: MessageID, msgByte :: Word8 } 237 | TwoByte { msgID :: MessageID, msgByte :: Word8 }