summaryrefslogtreecommitdiff
path: root/src/Network/DHT/Mainline.hs
diff options
context:
space:
mode:
authorjoe <joe@jerkface.net>2017-06-30 13:21:29 -0400
committerjoe <joe@jerkface.net>2017-06-30 13:21:29 -0400
commite1b2fc9c7a5efd828a8c66f3e3a1d0a547397080 (patch)
treeea85593b4400fbd03118d032bd89fef53e5b1dc0 /src/Network/DHT/Mainline.hs
parent3195c0877b443e5ccd4d489f03944fc059d4d7aa (diff)
It builds!
Diffstat (limited to 'src/Network/DHT/Mainline.hs')
-rw-r--r--src/Network/DHT/Mainline.hs76
1 files changed, 75 insertions, 1 deletions
diff --git a/src/Network/DHT/Mainline.hs b/src/Network/DHT/Mainline.hs
index 29d4231d..aefd7742 100644
--- a/src/Network/DHT/Mainline.hs
+++ b/src/Network/DHT/Mainline.hs
@@ -88,6 +88,10 @@ module Network.DHT.Mainline
88 , Announce (..) 88 , Announce (..)
89 , Announced (..) 89 , Announced (..)
90#endif 90#endif
91 , DHTData(..)
92 , SessionTokens(..)
93 , grantToken
94 , checkToken
91 ) where 95 ) where
92 96
93import Control.Applicative 97import Control.Applicative
@@ -118,13 +122,19 @@ import Network.DatagramServer.Mainline
118import Data.Maybe 122import Data.Maybe
119 123
120import Data.Torrent (InfoHash) 124import Data.Torrent (InfoHash)
121import Network.BitTorrent.DHT.Token 125import Network.BitTorrent.DHT.Token as T
126import Network.BitTorrent.DHT.ContactInfo
122#ifdef VERSION_bencoding 127#ifdef VERSION_bencoding
123import Network.DatagramServer () 128import Network.DatagramServer ()
124#endif 129#endif
125import Network.DatagramServer.Types hiding (Query,Response) 130import Network.DatagramServer.Types hiding (Query,Response)
126import Network.DHT.Types 131import Network.DHT.Types
127import Network.DHT.Routing 132import Network.DHT.Routing
133import Data.Time
134import Control.Concurrent.STM
135import System.Random
136import Data.Hashable
137
128 138
129{----------------------------------------------------------------------- 139{-----------------------------------------------------------------------
130-- envelopes 140-- envelopes
@@ -472,6 +482,59 @@ bep42 addr (NodeId r)
472 where msk | BS.length ip == 4 = ip4mask 482 where msk | BS.length ip == 4 = ip4mask
473 | otherwise = ip6mask 483 | otherwise = ip6mask
474 484
485{-----------------------------------------------------------------------
486-- Tokens policy
487-----------------------------------------------------------------------}
488
489data SessionTokens = SessionTokens
490 { tokenMap :: !TokenMap
491 , lastUpdate :: !UTCTime
492 , maxInterval :: !NominalDiffTime
493 }
494
495nullSessionTokens :: IO SessionTokens
496nullSessionTokens = SessionTokens
497 <$> (tokens <$> randomIO)
498 <*> getCurrentTime
499 <*> pure defaultUpdateInterval
500
501-- TODO invalidate *twice* if needed
502invalidateTokens :: UTCTime -> SessionTokens -> SessionTokens
503invalidateTokens curTime ts @ SessionTokens {..}
504 | curTime `diffUTCTime` lastUpdate > maxInterval = SessionTokens
505 { tokenMap = update tokenMap
506 , lastUpdate = curTime
507 , maxInterval = maxInterval
508 }
509 | otherwise = ts
510
511{-----------------------------------------------------------------------
512-- Tokens
513-----------------------------------------------------------------------}
514
515tryUpdateSecret :: TVar SessionTokens -> IO ()
516tryUpdateSecret toks = do
517 curTime <- getCurrentTime
518 atomically $ modifyTVar' toks (invalidateTokens curTime)
519
520grantToken :: Hashable a => TVar SessionTokens -> NodeAddr a -> IO Token
521grantToken sessionTokens addr = do
522 tryUpdateSecret sessionTokens
523 toks <- readTVarIO sessionTokens
524 return $ T.lookup addr $ tokenMap toks
525
526-- | Throws 'HandlerError' if the token is invalid or already
527-- expired. See 'TokenMap' for details.
528checkToken :: Hashable a => TVar SessionTokens -> NodeAddr a -> Token -> IO Bool
529checkToken sessionTokens addr questionableToken = do
530 tryUpdateSecret sessionTokens
531 toks <- readTVarIO sessionTokens
532 return $ T.member addr questionableToken (tokenMap toks)
533
534
535--------------------------
536
537
475instance Kademlia KMessageOf where 538instance Kademlia KMessageOf where
476 data Ping KMessageOf = Ping 539 data Ping KMessageOf = Ping
477 deriving (Show, Eq, Typeable) 540 deriving (Show, Eq, Typeable)
@@ -479,10 +542,17 @@ instance Kademlia KMessageOf where
479 deriving (Show, Eq, Typeable) 542 deriving (Show, Eq, Typeable)
480 newtype NodeFound KMessageOf ip = NodeFound [NodeInfo KMessageOf ip ()] 543 newtype NodeFound KMessageOf ip = NodeFound [NodeInfo KMessageOf ip ()]
481 deriving (Show, Eq, Typeable) 544 deriving (Show, Eq, Typeable)
545 data DHTData KMessageOf ip = TorrentData
546 { contactInfo :: !(TVar (PeerStore ip )) -- ^ published by other nodes;
547 , sessionTokens :: !(TVar SessionTokens ) -- ^ query session IDs.
548 }
549
482 pingMessage _ = Ping 550 pingMessage _ = Ping
483 pongMessage _ = Ping 551 pongMessage _ = Ping
484 findNodeMessage _ k = FindNode (toNodeId k) 552 findNodeMessage _ k = FindNode (toNodeId k)
553 findWho (FindNode nid) = nid
485 foundNodes (NodeFound ns) = ns 554 foundNodes (NodeFound ns) = ns
555 foundNodesMessage ns = NodeFound ns
486 556
487 dhtAdjustID _ fallback ip0 arrival 557 dhtAdjustID _ fallback ip0 arrival
488 = fromMaybe fallback $ do 558 = fromMaybe fallback $ do
@@ -494,3 +564,7 @@ instance Kademlia KMessageOf where
494 564
495 namePing _ = "ping" 565 namePing _ = "ping"
496 nameFindNodes _ = "find-nodes" 566 nameFindNodes _ = "find-nodes"
567
568 initializeDHTData = TorrentData
569 <$> newTVarIO def
570 <*> (newTVarIO =<< nullSessionTokens)