summaryrefslogtreecommitdiff
path: root/src/Network
diff options
context:
space:
mode:
Diffstat (limited to 'src/Network')
-rw-r--r--src/Network/Tox/Crypto/Handlers.hs144
1 files changed, 91 insertions, 53 deletions
diff --git a/src/Network/Tox/Crypto/Handlers.hs b/src/Network/Tox/Crypto/Handlers.hs
index bde286fe..0027e414 100644
--- a/src/Network/Tox/Crypto/Handlers.hs
+++ b/src/Network/Tox/Crypto/Handlers.hs
@@ -225,7 +225,7 @@ data NetCryptoSession = NCrypto
225 , ncHandShake :: TVar (UponHandshake (Handshake Encrypted)) 225 , ncHandShake :: TVar (UponHandshake (Handshake Encrypted))
226 , ncCookie :: TVar (UponCookie Cookie) -- ^ Cookie issued by remote peer 226 , ncCookie :: TVar (UponCookie Cookie) -- ^ Cookie issued by remote peer
227 , ncTheirDHTKey :: UponDHTKey PublicKey 227 , ncTheirDHTKey :: UponDHTKey PublicKey
228 , ncTheirSessionPublic :: UponHandshake PublicKey 228 , ncTheirSessionPublic :: TVar (UponHandshake PublicKey)
229 , ncSessionSecret :: SecretKey 229 , ncSessionSecret :: SecretKey
230 , ncSockAddr :: UponDHTKey SockAddr 230 , ncSockAddr :: UponDHTKey SockAddr
231 -- The remaining fields correspond to implementation specific state -- 231 -- The remaining fields correspond to implementation specific state --
@@ -550,22 +550,14 @@ freshCryptoSession sessions
550 mbpktoq 550 mbpktoq
551 <- case mbtheirSessionKey of 551 <- case mbtheirSessionKey of
552 Nothing -> return NeedHandshake 552 Nothing -> return NeedHandshake
553 Just theirSessionKey -> do 553 Just theirSessionKey -> createNetCryptoOutQueue sessions newsession theirSessionKey pktq ncMyPacketNonce0 ncOutgoingIdMap0
554 let toWireIO = do
555 f <- lookupNonceFunction crypto newsession theirSessionKey
556 atomically $ do
557 n24 <- readTVar ncMyPacketNonce0
558 let n24plus1 = incrementNonce24 n24
559 trace ("ncMyPacketNonce+1=" ++ show n24plus1) $ writeTVar ncMyPacketNonce0 n24plus1
560 return (return (f n24, n24, ncOutgoingIdMap0))
561 pktoq <- atomically $ PQ.newOutGoing pktq ncToWire toWireIO 0 (outboundQueueCapacity sessions) 0
562 return (HaveHandshake pktoq)
563 lastNQ <- atomically (CB.new 10 0 :: STM (CyclicBuffer (Bool,(ViewSnapshot,InOrOut CryptoMessage)))) 554 lastNQ <- atomically (CB.new 10 0 :: STM (CyclicBuffer (Bool,(ViewSnapshot,InOrOut CryptoMessage))))
564 listeners <- atomically $ newTVar IntMap.empty 555 listeners <- atomically $ newTVar IntMap.empty
565 msgNum <- atomically $ newTVar 0 556 msgNum <- atomically $ newTVar 0
566 dropNum <- atomically $ newTVar 0 557 dropNum <- atomically $ newTVar 0
567 theirbasenonce <- atomically $ readTVar ncTheirBaseNonce0 558 theirbasenonce <- atomically $ readTVar ncTheirBaseNonce0
568 dput XNetCrypto $ "freshCryptoSession: Session ncTheirBaseNonce=" ++ show theirbasenonce 559 dput XNetCrypto $ "freshCryptoSession: Session ncTheirBaseNonce=" ++ show theirbasenonce
560 ncTheirSessionPublic0 <- atomically $ newTVar (frmMaybe mbtheirSessionKey)
569 let netCryptoSession0 = 561 let netCryptoSession0 =
570 NCrypto { ncState = ncState0 562 NCrypto { ncState = ncState0
571 , ncMyPublicKey = toPublic key 563 , ncMyPublicKey = toPublic key
@@ -576,7 +568,7 @@ freshCryptoSession sessions
576 , ncHandShake = ncHandShake0 568 , ncHandShake = ncHandShake0
577 , ncCookie = cookie0 569 , ncCookie = cookie0
578 , ncTheirDHTKey = HaveDHTKey remoteDhtPublicKey 570 , ncTheirDHTKey = HaveDHTKey remoteDhtPublicKey
579 , ncTheirSessionPublic = frmMaybe mbtheirSessionKey 571 , ncTheirSessionPublic = ncTheirSessionPublic0
580 , ncSessionSecret = newsession 572 , ncSessionSecret = newsession
581 , ncSockAddr = HaveDHTKey addr 573 , ncSockAddr = HaveDHTKey addr
582 , ncHooks = ncHooks0 574 , ncHooks = ncHooks0
@@ -594,7 +586,40 @@ freshCryptoSession sessions
594 , ncLastNMsgs = lastNQ 586 , ncLastNMsgs = lastNQ
595 , ncListeners = listeners 587 , ncListeners = listeners
596 } 588 }
589 case mbpktoq of
590 NeedHandshake -> return ()
591 HaveHandshake pktoq -> runUponHandshake netCryptoSession0 addr pktoq
592
593type NetCryptoOutQueue = PQ.PacketOutQueue (State,Nonce24,RangeMap TArray Word8 TVar)
594 CryptoMessage
595 (CryptoPacket Encrypted)
596 CryptoData
597
598createNetCryptoOutQueue :: NetCryptoSessions -> SecretKey -> PublicKey -> PacketQueue CryptoData
599 -> TVar Nonce24 -> RangeMap TArray Word8 TVar -> IO (UponHandshake NetCryptoOutQueue)
600createNetCryptoOutQueue sessions newsession theirSessionKey pktq ncMyPacketNonce0 ncOutgoingIdMap0 = do
601 let crypto = transportCrypto sessions
602 let toWireIO = do
603 f <- lookupNonceFunction crypto newsession theirSessionKey
604 atomically $ do
605 n24 <- readTVar ncMyPacketNonce0
606 let n24plus1 = incrementNonce24 n24
607 trace ("ncMyPacketNonce+1=" ++ show n24plus1) $ writeTVar ncMyPacketNonce0 n24plus1
608 return (return (f n24, n24, ncOutgoingIdMap0))
609 pktoq <- atomically $ PQ.newOutGoing pktq ncToWire toWireIO 0 (outboundQueueCapacity sessions) 0
610 return (HaveHandshake pktoq)
611
612
613runUponHandshake :: NetCryptoSession -> SockAddr -> NetCryptoOutQueue -> IO ()
614runUponHandshake netCryptoSession0 addr pktoq = do
615 let sessions = ncAllSessions netCryptoSession0
616 pktq = ncPacketQueue netCryptoSession0
617 remotePublicKey = ncTheirPublicKey netCryptoSession0
618 crypto = transportCrypto sessions
619 allsessions = netCryptoSessions sessions
620 allsessionsByKey = netCryptoSessionsByKey sessions
597 -- launch dequeue thread 621 -- launch dequeue thread
622 -- (In terms of data dependency, this thread could be launched prior to handshake)
598 threadid <- forkIO $ do 623 threadid <- forkIO $ do
599 tid <- myThreadId 624 tid <- myThreadId
600 labelThread tid ("NetCryptoDequeue." ++ show (key2id remotePublicKey)) 625 labelThread tid ("NetCryptoDequeue." ++ show (key2id remotePublicKey))
@@ -602,44 +627,41 @@ freshCryptoSession sessions
602 cd <- atomically $ PQ.dequeue pktq 627 cd <- atomically $ PQ.dequeue pktq
603 _ <- runCryptoHook (netCryptoSession0 {ncDequeueThread=Just tid}) (bufferData cd) 628 _ <- runCryptoHook (netCryptoSession0 {ncDequeueThread=Just tid}) (bufferData cd)
604 loop 629 loop
605 case mbpktoq of 630 -- launch dequeueOutgoing thread
606 NeedHandshake -> return () 631 threadidOutgoing <- forkIO $ do
607 HaveHandshake pktoq -> do 632 tid <- myThreadId
608 -- launch dequeueOutgoing thread 633 labelThread tid ("NetCryptoDequeueOutgoing." ++ show (key2id remotePublicKey))
609 threadidOutgoing <- forkIO $ do 634 fix $ \loop -> do
610 tid <- myThreadId 635 (_,pkt) <- atomically $ PQ.dequeueOutgoing pktoq
611 labelThread tid ("NetCryptoDequeueOutgoing." ++ show (key2id remotePublicKey)) 636 dput XNetCrypto "NetCryptoDequeueOutgoing thread... Sending encrypted Packet"
612 fix $ \loop -> do 637 sendMessage (sessionTransport sessions) addr (NetCrypto pkt)
613 (_,pkt) <- atomically $ PQ.dequeueOutgoing pktoq 638 loop
614 dput XNetCrypto "NetCryptoDequeueOutgoing thread... Sending encrypted Packet" 639 -- launch ping thread
615 sendMessage (sessionTransport sessions) addr (NetCrypto pkt) 640 fuzz <- randomRIO (0,2000)
616 loop 641 pingMachine <- forkPingMachine ("NetCrypto." ++ show (key2id remotePublicKey)) (15000 + fuzz) 2000
617 -- launch ping thread 642 -- update session with thread ids
618 fuzz <- randomRIO (0,2000) 643 let netCryptoSession = netCryptoSession0 {ncDequeueThread=Just threadid, ncPingMachine=Just pingMachine}
619 pingMachine <- forkPingMachine ("NetCrypto." ++ show (key2id remotePublicKey)) (15000 + fuzz) 2000 644 -- add this session to the lookup maps
620 -- update session with thread ids 645 atomically $ do
621 let netCryptoSession = netCryptoSession0 {ncDequeueThread=Just threadid, ncPingMachine=Just pingMachine} 646 modifyTVar allsessions (Map.insert addr netCryptoSession)
622 -- add this session to the lookup maps 647 byKeyResult <- readTVar allsessionsByKey >>= return . Map.lookup remotePublicKey
623 atomically $ do 648 case byKeyResult of
624 modifyTVar allsessions (Map.insert addr netCryptoSession) 649 Nothing -> modifyTVar allsessionsByKey (Map.insert remotePublicKey [netCryptoSession])
625 byKeyResult <- readTVar allsessionsByKey >>= return . Map.lookup remotePublicKey 650 Just xs -> modifyTVar allsessionsByKey (Map.insert remotePublicKey (netCryptoSession:xs))
626 case byKeyResult of 651 -- run announceNewSessionHooks
627 Nothing -> modifyTVar allsessionsByKey (Map.insert remotePublicKey [netCryptoSession]) 652 hooks <- atomically $ readTVar (announceNewSessionHooks sessions)
628 Just xs -> modifyTVar allsessionsByKey (Map.insert remotePublicKey (netCryptoSession:xs)) 653 flip fix (hooks,netCryptoSession) $ \loop (hooks,session) ->
629 -- run announceNewSessionHooks 654 case hooks of
630 hooks <- atomically $ readTVar (announceNewSessionHooks sessions) 655 [] -> return ()
631 flip fix (hooks,netCryptoSession) $ \loop (hooks,session) -> 656 (h:hs) -> do
632 case hooks of 657 r <- h Nothing session
633 [] -> return () 658 case r of
634 (h:hs) -> do 659 Just f -> loop (hs, f session)
635 r <- h Nothing session 660 Nothing -> return ()
636 case r of
637 Just f -> loop (hs, f session)
638 Nothing -> return ()
639 661
640-- | Called when we get a handshake, but there's already a session entry. 662-- | Called when we get a handshake, but there's already a session entry.
641updateCryptoSession :: NetCryptoSessions -> SockAddr -> HandshakeParams -> NetCryptoSession -> IO () 663updateCryptoSession :: NetCryptoSessions -> SockAddr -> HandshakeParams -> NetCryptoSession -> Handshake Encrypted -> IO ()
642updateCryptoSession sessions addr hp session = do 664updateCryptoSession sessions addr hp session handshake = do
643 ncState0 <- atomically $ readTVar (ncState session) 665 ncState0 <- atomically $ readTVar (ncState session)
644 ncTheirBaseNonce0 <- atomically $ readTVar (ncTheirBaseNonce session) 666 ncTheirBaseNonce0 <- atomically $ readTVar (ncTheirBaseNonce session)
645 if (ncState0 >= {-Accepted-}InProgress AwaitingSessionPacket) 667 if (ncState0 >= {-Accepted-}InProgress AwaitingSessionPacket)
@@ -656,10 +678,25 @@ updateCryptoSession sessions addr hp session = do
656 dput XNetCrypto (" ncTheirDHTKey=" ++ show (ncTheirDHTKey session) 678 dput XNetCrypto (" ncTheirDHTKey=" ++ show (ncTheirDHTKey session)
657 ++ bool "{/=}" "{==}" (ncTheirDHTKey session == HaveDHTKey (hpCookieRemoteDhtkey hp)) 679 ++ bool "{/=}" "{==}" (ncTheirDHTKey session == HaveDHTKey (hpCookieRemoteDhtkey hp))
658 ++ "hpCookieRemoteDhtkey=" ++ show (hpCookieRemoteDhtkey hp)) 680 ++ "hpCookieRemoteDhtkey=" ++ show (hpCookieRemoteDhtkey hp))
659 when ( -- Just ncTheirBaseNonce0 /= hpTheirBaseNonce hp -- XXX: Do we really want to compare base nonce here? 681 if ( -- Just ncTheirBaseNonce0 /= hpTheirBaseNonce hp -- XXX: Do we really want to compare base nonce here?
660 -- || 682 -- ||
661 ncTheirDHTKey session /= HaveDHTKey (hpCookieRemoteDhtkey hp) 683 ncTheirDHTKey session /= HaveDHTKey (hpCookieRemoteDhtkey hp)
662 ) $ freshCryptoSession sessions addr hp 684 ) then freshCryptoSession sessions addr hp
685 else do
686 atomically $ do
687 writeTVar (ncTheirBaseNonce session) (frmMaybe (hpTheirBaseNonce hp))
688 writeTVar (ncTheirSessionPublic session) (frmMaybe (hpTheirSessionKeyPublic hp))
689 writeTVar (ncHandShake session) (HaveHandshake handshake)
690 case ncOutgoingQueue session of
691 NeedHandshake -> do
692 case hpTheirSessionKeyPublic hp of
693 Just sessionpubkey -> do
694 pktoq <- createNetCryptoOutQueue sessions (ncSessionSecret session) sessionpubkey
695 (ncPacketQueue session) (ncMyPacketNonce session) (ncOutgoingIdMap session)
696 case pktoq of
697 NeedHandshake -> dput XNetCrypto "Unexpectedly missing ncOutgoingQueue"
698 HaveHandshake pktoq -> runUponHandshake session addr pktoq
699 HaveHandshake pktoq -> runUponHandshake session addr pktoq
663 else do 700 else do
664 dput XNetCrypto "updateCryptoSession else clause" 701 dput XNetCrypto "updateCryptoSession else clause"
665 dput XNetCrypto (" ncTheirBaseNonce0=" ++ show ncTheirBaseNonce0 702 dput XNetCrypto (" ncTheirBaseNonce0=" ++ show ncTheirBaseNonce0
@@ -674,7 +711,7 @@ cryptoNetHandler sessions addr (NetHandshake hs) = handshakeH sessions addr
674cryptoNetHandler sessions addr (NetCrypto pkt) = sessionPacketH sessions addr pkt 711cryptoNetHandler sessions addr (NetCrypto pkt) = sessionPacketH sessions addr pkt
675 712
676handshakeH :: NetCryptoSessions -> SockAddr -> Handshake Encrypted -> IO (Maybe a) 713handshakeH :: NetCryptoSessions -> SockAddr -> Handshake Encrypted -> IO (Maybe a)
677handshakeH sessions addr (Handshake (Cookie n24 ecookie) nonce24 encrypted) = do 714handshakeH sessions addr hshake@(Handshake (Cookie n24 ecookie) nonce24 encrypted) = do
678 dput XNetCrypto ("RECIEVED HANDSHAKE from " ++ show addr) 715 dput XNetCrypto ("RECIEVED HANDSHAKE from " ++ show addr)
679 -- Handle Handshake Message 716 -- Handle Handshake Message
680 let crypto = transportCrypto sessions 717 let crypto = transportCrypto sessions
@@ -746,7 +783,7 @@ handshakeH sessions addr (Handshake (Cookie n24 ecookie) nonce24 encrypted) = do
746 freshCryptoSession sessions addr hp -- create new session 783 freshCryptoSession sessions addr hp -- create new session
747 Just session -> do 784 Just session -> do
748 dput XNetCrypto "sockaddr ALREADY in session map, so updateCryptoSession" 785 dput XNetCrypto "sockaddr ALREADY in session map, so updateCryptoSession"
749 updateCryptoSession sessions addr hp session -- update existing session 786 updateCryptoSession sessions addr hp session hshake -- update existing session
750 return Nothing 787 return Nothing
751 788
752sessionPacketH :: NetCryptoSessions -> SockAddr -> CryptoPacket Encrypted -> IO (Maybe (x -> x)) 789sessionPacketH :: NetCryptoSessions -> SockAddr -> CryptoPacket Encrypted -> IO (Maybe (x -> x))
@@ -771,8 +808,9 @@ sessionPacketH sessions addr (CryptoPacket nonce16 encrypted) = do
771 let diff :: Word16 808 let diff :: Word16
772 diff = nonce16 - (last2Bytes theirBaseNonce) -- truncating to Word16 809 diff = nonce16 - (last2Bytes theirBaseNonce) -- truncating to Word16
773 tempNonce = addtoNonce24 theirBaseNonce (fromIntegral diff) -- expanding to Word 810 tempNonce = addtoNonce24 theirBaseNonce (fromIntegral diff) -- expanding to Word
811 mbpublickey <- atomically (readTVar ncTheirSessionPublic)
774 lr <- fmap join $ sequence $ do -- Either Monad -- 812 lr <- fmap join $ sequence $ do -- Either Monad --
775 pubkey <- maybeToEither ncTheirSessionPublic 813 pubkey <- maybeToEither mbpublickey
776 Right $ do -- IO Monad 814 Right $ do -- IO Monad
777 dput XNetCrypto $ "cryptoNetHandler: pubkey = " ++ show (key2id $ pubkey) 815 dput XNetCrypto $ "cryptoNetHandler: pubkey = " ++ show (key2id $ pubkey)
778 dput XNetCrypto $ "cryptoNetHandler: theirBaseNonce = " ++ show theirBaseNonce 816 dput XNetCrypto $ "cryptoNetHandler: theirBaseNonce = " ++ show theirBaseNonce