diff options
-rw-r--r-- | examples/dhtd.hs | 3 | ||||
-rw-r--r-- | src/Network/Tox/Crypto/Handlers.hs | 67 | ||||
-rw-r--r-- | src/Network/Tox/Crypto/Transport.hs | 12 |
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 #-} | ||
7 | module Network.Tox.Crypto.Handlers where | 8 | module Network.Tox.Crypto.Handlers where |
8 | 9 | ||
9 | import Network.Tox.NodeId | 10 | import 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 () | |||
778 | destroySession session = do | 792 | destroySession 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 @@ | |||
7 | module Network.Tox.Crypto.Transport | 7 | module 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 | ||
221 | data TypingStatus = NotTyping | Typing deriving (Show,Read,Eq,Ord,Enum) | 222 | data TypingStatus = NotTyping | Typing deriving (Show,Read,Eq,Ord,Enum) |
222 | 223 | ||
224 | unpadCryptoMsg :: CryptoMessage -> CryptoMessage | ||
225 | unpadCryptoMsg x@(TwoByte Padding (toEnum8 -> mid)) | ||
226 | | msgSizeParam mid == Just (True,0) = OneByte mid | ||
227 | unpadCryptoMsg 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 | ||
233 | unpadCryptoMsg x = x | ||
234 | |||
223 | data CryptoMessage | 235 | data CryptoMessage |
224 | = OneByte { msgID :: MessageID } | 236 | = OneByte { msgID :: MessageID } |
225 | | TwoByte { msgID :: MessageID, msgByte :: Word8 } | 237 | | TwoByte { msgID :: MessageID, msgByte :: Word8 } |