diff options
author | Andrew Cady <d@jerkface.net> | 2018-06-09 01:34:43 -0400 |
---|---|---|
committer | Andrew Cady <d@jerkface.net> | 2018-06-09 01:34:43 -0400 |
commit | 626820b99b76b4e4fa0b36e8e92e05d8176c4f43 (patch) | |
tree | 5ced91907da9ff6b9d391ca013533912366ae29c /src/Network/Tox | |
parent | 031d0e35f0532e4573497926a692ced50ba2f4b0 (diff) | |
parent | fb0c6758ec415c5cda5cc7c182e1f83906f365fb (diff) |
Merge branch 'dht-presence' of blackbird:bittorrent
Diffstat (limited to 'src/Network/Tox')
-rw-r--r-- | src/Network/Tox/Crypto/Handlers.hs | 19 | ||||
-rw-r--r-- | src/Network/Tox/NodeId.hs | 11 | ||||
-rw-r--r-- | src/Network/Tox/Onion/Handlers.hs | 33 |
3 files changed, 53 insertions, 10 deletions
diff --git a/src/Network/Tox/Crypto/Handlers.hs b/src/Network/Tox/Crypto/Handlers.hs index 5316acc8..e22388a3 100644 --- a/src/Network/Tox/Crypto/Handlers.hs +++ b/src/Network/Tox/Crypto/Handlers.hs | |||
@@ -2,6 +2,7 @@ | |||
2 | {-# LANGUAGE TupleSections #-} | 2 | {-# LANGUAGE TupleSections #-} |
3 | {-# LANGUAGE TypeOperators #-} | 3 | {-# LANGUAGE TypeOperators #-} |
4 | {-# LANGUAGE DeriveFunctor #-} | 4 | {-# LANGUAGE DeriveFunctor #-} |
5 | {-# LANGUAGE CPP #-} | ||
5 | module Network.Tox.Crypto.Handlers where | 6 | module Network.Tox.Crypto.Handlers where |
6 | 7 | ||
7 | import Network.Tox.NodeId | 8 | import Network.Tox.NodeId |
@@ -40,8 +41,12 @@ import System.IO.Temp | |||
40 | import System.Environment | 41 | import System.Environment |
41 | import System.Directory | 42 | import System.Directory |
42 | import System.Random -- for ping fuzz | 43 | import System.Random -- for ping fuzz |
44 | #ifdef THREAD_DEBUG | ||
45 | import Control.Concurrent.Lifted.Instrument | ||
46 | #else | ||
43 | import Control.Concurrent | 47 | import Control.Concurrent |
44 | import GHC.Conc (labelThread) | 48 | import GHC.Conc (labelThread) |
49 | #endif | ||
45 | import PingMachine | 50 | import PingMachine |
46 | import qualified Data.IntMap.Strict as IntMap | 51 | import qualified Data.IntMap.Strict as IntMap |
47 | import Control.Concurrent.Supply | 52 | import Control.Concurrent.Supply |
@@ -719,8 +724,8 @@ updateCryptoSession sessions addr newsession timestamp hp session handshake = do | |||
719 | dmsg (" ncTheirDHTKey=" ++ show (ncTheirDHTKey session) | 724 | dmsg (" ncTheirDHTKey=" ++ show (ncTheirDHTKey session) |
720 | ++ bool "{/=}" "{==}" (ncTheirDHTKey session == HaveDHTKey (hpCookieRemoteDhtkey hp)) | 725 | ++ bool "{/=}" "{==}" (ncTheirDHTKey session == HaveDHTKey (hpCookieRemoteDhtkey hp)) |
721 | ++ "hpCookieRemoteDhtkey=" ++ show (hpCookieRemoteDhtkey hp)) | 726 | ++ "hpCookieRemoteDhtkey=" ++ show (hpCookieRemoteDhtkey hp)) |
722 | if ( -- Just ncTheirBaseNonce0 /= hpTheirBaseNonce hp -- XXX: Do we really want to compare base nonce here? | 727 | if ( toMaybe ncTheirBaseNonce0 /= hpTheirBaseNonce hp |
723 | -- || | 728 | || |
724 | ncTheirDHTKey session /= HaveDHTKey (hpCookieRemoteDhtkey hp) | 729 | ncTheirDHTKey session /= HaveDHTKey (hpCookieRemoteDhtkey hp) |
725 | ) | 730 | ) |
726 | then freshCryptoSession sessions addr newsession timestamp hp | 731 | then freshCryptoSession sessions addr newsession timestamp hp |
@@ -1042,10 +1047,16 @@ sendCrypto crypto session updateLocal cm = do | |||
1042 | PQ.OGEncodeFail -> return (Left "Failed to encode outgoing packet") | 1047 | PQ.OGEncodeFail -> return (Left "Failed to encode outgoing packet") |
1043 | 1048 | ||
1044 | sendOnline :: TransportCrypto -> NetCryptoSession -> IO (Either String ()) | 1049 | sendOnline :: TransportCrypto -> NetCryptoSession -> IO (Either String ()) |
1045 | sendOnline crypto session = sendCrypto crypto session (return ()) (OneByte ONLINE) | 1050 | sendOnline crypto session = do |
1051 | let cm=OneByte ONLINE | ||
1052 | addMsgToLastN False (cm ^. messageType) session (Out cm) | ||
1053 | sendCrypto crypto session (return ()) (OneByte ONLINE) | ||
1046 | 1054 | ||
1047 | sendOffline :: TransportCrypto -> NetCryptoSession -> IO (Either String ()) | 1055 | sendOffline :: TransportCrypto -> NetCryptoSession -> IO (Either String ()) |
1048 | sendOffline crypto session = sendCrypto crypto session (return ()) (OneByte OFFLINE) | 1056 | sendOffline crypto session = do |
1057 | let cm=OneByte OFFLINE | ||
1058 | addMsgToLastN False (cm ^. messageType) session (Out cm) | ||
1059 | sendCrypto crypto session (return ()) (OneByte OFFLINE) | ||
1049 | 1060 | ||
1050 | 1061 | ||
1051 | sendKill :: TransportCrypto -> NetCryptoSession -> IO (Either String ()) | 1062 | sendKill :: TransportCrypto -> NetCryptoSession -> IO (Either String ()) |
diff --git a/src/Network/Tox/NodeId.hs b/src/Network/Tox/NodeId.hs index 74239710..dab1b14a 100644 --- a/src/Network/Tox/NodeId.hs +++ b/src/Network/Tox/NodeId.hs | |||
@@ -555,8 +555,14 @@ parseNoSpamJID jid = do | |||
555 | _ -> Left "Hostname should be 43 base64 digits followed by .tox." | 555 | _ -> Left "Hostname should be 43 base64 digits followed by .tox." |
556 | pub <- id2key <$> readEither base64 | 556 | pub <- id2key <$> readEither base64 |
557 | let ustr = Text.unpack u | 557 | let ustr = Text.unpack u |
558 | '$' : b64digits <- Right ustr -- TODO: support 0x prefix also. | 558 | case ustr of |
559 | NoSpam nospam (Just x) <- readEither $ map (\case; '?' -> '0'; c -> c) ustr | 559 | '$' : b64digits -> solveBase64NoSpamID b64digits pub |
560 | '0' : 'x' : hexdigits -> do nospam <- readEither ('0':'x':hexdigits) | ||
561 | return $ NoSpamId nospam pub | ||
562 | |||
563 | solveBase64NoSpamID :: String -> PublicKey -> Either String NoSpamId | ||
564 | solveBase64NoSpamID b64digits pub = do | ||
565 | NoSpam nospam (Just x) <- readEither $ '$' : map (\case; '?' -> '0'; c -> c) b64digits | ||
560 | let nlo = fromIntegral (0x0FFFF .&. nospam) :: Word16 | 566 | let nlo = fromIntegral (0x0FFFF .&. nospam) :: Word16 |
561 | nhi = fromIntegral (0x0FFFF .&. (nospam `shiftR` 16)) :: Word16 | 567 | nhi = fromIntegral (0x0FFFF .&. (nospam `shiftR` 16)) :: Word16 |
562 | sum = x `xor` nlo `xor` nhi `xor` xorsum pub | 568 | sum = x `xor` nlo `xor` nhi `xor` xorsum pub |
@@ -583,7 +589,6 @@ parseNoSpamJID jid = do | |||
583 | let bitpos = q * 6 + p * 2 | 589 | let bitpos = q * 6 + p * 2 |
584 | ac' = ac `xor` shiftR (fromIntegral b `shiftL` 48) bitpos | 590 | ac' = ac `xor` shiftR (fromIntegral b `shiftL` 48) bitpos |
585 | solve ns ac' | 591 | solve ns ac' |
586 | |||
587 | n64' <- solve ns n64 | 592 | n64' <- solve ns n64 |
588 | let nospam' = fromIntegral (n64' `shiftR` 32) | 593 | let nospam' = fromIntegral (n64' `shiftR` 32) |
589 | cksum' = fromIntegral (n64' `shiftR` 16) | 594 | cksum' = fromIntegral (n64' `shiftR` 16) |
diff --git a/src/Network/Tox/Onion/Handlers.hs b/src/Network/Tox/Onion/Handlers.hs index 99ef3c69..263d60bd 100644 --- a/src/Network/Tox/Onion/Handlers.hs +++ b/src/Network/Tox/Onion/Handlers.hs | |||
@@ -11,7 +11,7 @@ import Network.QueryResponse as QR hiding (Client) | |||
11 | import qualified Network.QueryResponse as QR (Client) | 11 | import qualified Network.QueryResponse as QR (Client) |
12 | import Crypto.Tox | 12 | import Crypto.Tox |
13 | import qualified Data.Wrapper.PSQ as PSQ | 13 | import qualified Data.Wrapper.PSQ as PSQ |
14 | ;import Data.Wrapper.PSQ (PSQ) | 14 | ;import Data.Wrapper.PSQ (PSQ,pattern (:->)) |
15 | #ifdef CRYPTONITE_BACKPORT | 15 | #ifdef CRYPTONITE_BACKPORT |
16 | import Crypto.Error.Types (CryptoFailable (..), | 16 | import Crypto.Error.Types (CryptoFailable (..), |
17 | throwCryptoError) | 17 | throwCryptoError) |
@@ -35,6 +35,12 @@ import Network.BitTorrent.DHT.Token as Token | |||
35 | 35 | ||
36 | import Control.Exception hiding (Handler) | 36 | import Control.Exception hiding (Handler) |
37 | import Control.Monad | 37 | import Control.Monad |
38 | #ifdef THREAD_DEBUG | ||
39 | import Control.Concurrent.Lifted.Instrument | ||
40 | #else | ||
41 | import Control.Concurrent | ||
42 | import GHC.Conc (labelThread) | ||
43 | #endif | ||
38 | import Control.Concurrent.STM | 44 | import Control.Concurrent.STM |
39 | import Data.Time.Clock.POSIX (POSIXTime, getPOSIXTime) | 45 | import Data.Time.Clock.POSIX (POSIXTime, getPOSIXTime) |
40 | import Network.Socket | 46 | import Network.Socket |
@@ -159,7 +165,7 @@ toOnionDestination (AnnouncedRoute ni rpath) = OnionToOwner ni rpath | |||
159 | -- structure. | 165 | -- structure. |
160 | -- | 166 | -- |
161 | data AnnouncedKeys = AnnouncedKeys | 167 | data AnnouncedKeys = AnnouncedKeys |
162 | { keyByAge :: !(PSQ NodeId (Down POSIXTime{-Time at which they announced to you-})) -- TODO: timeout of 300 seconds | 168 | { keyByAge :: !(PSQ NodeId (POSIXTime{-Time at which they announced to you-})) |
163 | , keyAssoc :: !(MinMaxPSQ' NodeId NodeDistance (Int{-count of route usage-},AnnouncedRoute)) | 169 | , keyAssoc :: !(MinMaxPSQ' NodeId NodeDistance (Int{-count of route usage-},AnnouncedRoute)) |
164 | -- ^ PSQ using NodeId(user/public key) as Key | 170 | -- ^ PSQ using NodeId(user/public key) as Key |
165 | -- and using 'NodeDistance' as priority. | 171 | -- and using 'NodeDistance' as priority. |
@@ -172,12 +178,33 @@ data AnnouncedKeys = AnnouncedKeys | |||
172 | 178 | ||
173 | insertKey :: POSIXTime -> NodeId -> AnnouncedRoute -> NodeDistance -> AnnouncedKeys -> AnnouncedKeys | 179 | insertKey :: POSIXTime -> NodeId -> AnnouncedRoute -> NodeDistance -> AnnouncedKeys -> AnnouncedKeys |
174 | insertKey tm pub toxpath d keydb = AnnouncedKeys | 180 | insertKey tm pub toxpath d keydb = AnnouncedKeys |
175 | { keyByAge = PSQ.insert pub (Down tm) (keyByAge keydb) | 181 | { keyByAge = PSQ.insert pub tm (keyByAge keydb) |
176 | , keyAssoc = case MinMaxPSQ.lookup' pub (keyAssoc keydb) of | 182 | , keyAssoc = case MinMaxPSQ.lookup' pub (keyAssoc keydb) of |
177 | Just (_,(cnt,_)) -> MinMaxPSQ.insert' pub (cnt,toxpath) d (keyAssoc keydb) | 183 | Just (_,(cnt,_)) -> MinMaxPSQ.insert' pub (cnt,toxpath) d (keyAssoc keydb) |
178 | Nothing -> MinMaxPSQ.insert' pub (0 ,toxpath) d (keyAssoc keydb) | 184 | Nothing -> MinMaxPSQ.insert' pub (0 ,toxpath) d (keyAssoc keydb) |
179 | } | 185 | } |
180 | 186 | ||
187 | -- | Forks a thread to garbage-collect old key announcements. Keys may be | ||
188 | -- discarded after 5 minutes. | ||
189 | forkAnnouncedKeysGC :: TVar AnnouncedKeys -> IO ThreadId | ||
190 | forkAnnouncedKeysGC db = forkIO $ do | ||
191 | myThreadId >>= flip labelThread "gc:toxids" | ||
192 | fix $ \loop -> do | ||
193 | cutoff <- getPOSIXTime | ||
194 | threadDelay 300000000 -- 300 seconds | ||
195 | join $ atomically $ do | ||
196 | fix $ \gc -> do | ||
197 | keys <- readTVar db | ||
198 | case PSQ.minView (keyByAge keys) of | ||
199 | Nothing -> return loop | ||
200 | Just (pub :-> tm,kba') | ||
201 | | tm > cutoff -> return loop | ||
202 | | otherwise -> do writeTVar db keys | ||
203 | { keyByAge = kba' | ||
204 | , keyAssoc = MinMaxPSQ.delete pub (keyAssoc keys) | ||
205 | } | ||
206 | gc | ||
207 | |||
181 | areq :: Message -> Either String AnnounceRequest | 208 | areq :: Message -> Either String AnnounceRequest |
182 | areq (OnionAnnounce asymm) = Right $ fst $ runIdentity $ asymmData asymm | 209 | areq (OnionAnnounce asymm) = Right $ fst $ runIdentity $ asymmData asymm |
183 | areq _ = Left "Unexpected non-announce OnionMessage" | 210 | areq _ = Left "Unexpected non-announce OnionMessage" |