diff options
Diffstat (limited to 'src/Network/BitTorrent/DHT/Session.hs')
-rw-r--r-- | src/Network/BitTorrent/DHT/Session.hs | 91 |
1 files changed, 22 insertions, 69 deletions
diff --git a/src/Network/BitTorrent/DHT/Session.hs b/src/Network/BitTorrent/DHT/Session.hs index f96ba707..d94f028f 100644 --- a/src/Network/BitTorrent/DHT/Session.hs +++ b/src/Network/BitTorrent/DHT/Session.hs | |||
@@ -35,9 +35,10 @@ module Network.BitTorrent.DHT.Session | |||
35 | , routingInfo | 35 | , routingInfo |
36 | , routableAddress | 36 | , routableAddress |
37 | , getTimestamp | 37 | , getTimestamp |
38 | , SessionTokens | 38 | -- , SessionTokens |
39 | , sessionTokens | 39 | -- , sessionTokens |
40 | , contactInfo | 40 | -- , contactInfo |
41 | , dhtData | ||
41 | , PeerStore | 42 | , PeerStore |
42 | , manager | 43 | , manager |
43 | 44 | ||
@@ -55,8 +56,8 @@ module Network.BitTorrent.DHT.Session | |||
55 | , runDHT | 56 | , runDHT |
56 | 57 | ||
57 | -- ** Tokens | 58 | -- ** Tokens |
58 | , grantToken | 59 | -- , grantToken |
59 | , checkToken | 60 | -- , checkToken |
60 | 61 | ||
61 | -- ** Routing table | 62 | -- ** Routing table |
62 | , getTable | 63 | , getTable |
@@ -68,6 +69,7 @@ module Network.BitTorrent.DHT.Session | |||
68 | , insertPeer | 69 | , insertPeer |
69 | , getPeerList | 70 | , getPeerList |
70 | , getPeerList1 | 71 | , getPeerList1 |
72 | , lookupPeers | ||
71 | , insertTopic | 73 | , insertTopic |
72 | , deleteTopic | 74 | , deleteTopic |
73 | , getSwarms | 75 | , getSwarms |
@@ -113,6 +115,7 @@ import Data.Time.Clock.POSIX | |||
113 | import Data.Text as Text | 115 | import Data.Text as Text |
114 | import Text.PrettyPrint.HughesPJClass hiding ((<>),($$)) | 116 | import Text.PrettyPrint.HughesPJClass hiding ((<>),($$)) |
115 | import Data.Serialize as S | 117 | import Data.Serialize as S |
118 | import Network.DHT.Types | ||
116 | 119 | ||
117 | 120 | ||
118 | import Data.Torrent as Torrent | 121 | import Data.Torrent as Torrent |
@@ -228,33 +231,6 @@ instance Default Options where | |||
228 | 231 | ||
229 | seconds :: NominalDiffTime -> Int | 232 | seconds :: NominalDiffTime -> Int |
230 | seconds dt = fromEnum (realToFrac dt :: Uni) | 233 | seconds dt = fromEnum (realToFrac dt :: Uni) |
231 | |||
232 | {----------------------------------------------------------------------- | ||
233 | -- Tokens policy | ||
234 | -----------------------------------------------------------------------} | ||
235 | |||
236 | data SessionTokens = SessionTokens | ||
237 | { tokenMap :: !TokenMap | ||
238 | , lastUpdate :: !UTCTime | ||
239 | , maxInterval :: !NominalDiffTime | ||
240 | } | ||
241 | |||
242 | nullSessionTokens :: IO SessionTokens | ||
243 | nullSessionTokens = SessionTokens | ||
244 | <$> (tokens <$> liftIO randomIO) | ||
245 | <*> liftIO getCurrentTime | ||
246 | <*> pure defaultUpdateInterval | ||
247 | |||
248 | -- TODO invalidate *twice* if needed | ||
249 | invalidateTokens :: UTCTime -> SessionTokens -> SessionTokens | ||
250 | invalidateTokens curTime ts @ SessionTokens {..} | ||
251 | | curTime `diffUTCTime` lastUpdate > maxInterval = SessionTokens | ||
252 | { tokenMap = update tokenMap | ||
253 | , lastUpdate = curTime | ||
254 | , maxInterval = maxInterval | ||
255 | } | ||
256 | | otherwise = ts | ||
257 | |||
258 | {----------------------------------------------------------------------- | 234 | {----------------------------------------------------------------------- |
259 | -- Session | 235 | -- Session |
260 | -----------------------------------------------------------------------} | 236 | -----------------------------------------------------------------------} |
@@ -277,9 +253,8 @@ data Node raw dht u ip = Node | |||
277 | , resources :: !InternalState | 253 | , resources :: !InternalState |
278 | , manager :: !(Manager raw dht) -- ^ RPC manager; | 254 | , manager :: !(Manager raw dht) -- ^ RPC manager; |
279 | , routingInfo :: !(TVar (Maybe (R.Info dht ip u))) -- ^ search table; | 255 | , routingInfo :: !(TVar (Maybe (R.Info dht ip u))) -- ^ search table; |
280 | , contactInfo :: !(TVar (PeerStore ip )) -- ^ published by other nodes; | ||
281 | , announceInfo :: !(TVar AnnounceSet ) -- ^ to publish by this node; | 256 | , announceInfo :: !(TVar AnnounceSet ) -- ^ to publish by this node; |
282 | , sessionTokens :: !(TVar SessionTokens ) -- ^ query session IDs. | 257 | , dhtData :: DHTData dht ip |
283 | , loggerFun :: !LogFun | 258 | , loggerFun :: !LogFun |
284 | } | 259 | } |
285 | 260 | ||
@@ -371,6 +346,7 @@ locFromCS cs = case getCallStack cs of | |||
371 | newNode :: ( Address ip | 346 | newNode :: ( Address ip |
372 | , FiniteBits (NodeId dht) | 347 | , FiniteBits (NodeId dht) |
373 | , Serialize (NodeId dht) | 348 | , Serialize (NodeId dht) |
349 | , Kademlia dht | ||
374 | ) | 350 | ) |
375 | => -- [NodeHandler] -- ^ handlers to run on accepted queries; | 351 | => -- [NodeHandler] -- ^ handlers to run on accepted queries; |
376 | Options -- ^ various dht options; | 352 | Options -- ^ various dht options; |
@@ -389,12 +365,12 @@ newNode opts naddr logger mbid = do | |||
389 | s <- getInternalState | 365 | s <- getInternalState |
390 | (_, m) <- allocate (newManager rpcOpts (logt logger) nodeAddr []) closeManager | 366 | (_, m) <- allocate (newManager rpcOpts (logt logger) nodeAddr []) closeManager |
391 | liftIO $ do | 367 | liftIO $ do |
368 | dta <- initializeDHTData | ||
392 | myId <- maybe genNodeId return mbid | 369 | myId <- maybe genNodeId return mbid |
393 | node <- Node opts myId s m | 370 | node <- Node opts myId s m |
394 | <$> atomically (newTVar Nothing) | 371 | <$> atomically (newTVar Nothing) |
395 | <*> newTVarIO def | ||
396 | <*> newTVarIO S.empty | 372 | <*> newTVarIO S.empty |
397 | <*> (newTVarIO =<< nullSessionTokens) | 373 | <*> pure dta |
398 | <*> pure logger | 374 | <*> pure logger |
399 | return node | 375 | return node |
400 | 376 | ||
@@ -415,29 +391,6 @@ runDHT node action = runReaderT (unDHT action) node | |||
415 | -- /pick a random ID/ in the range of the bucket and perform a | 391 | -- /pick a random ID/ in the range of the bucket and perform a |
416 | -- find_nodes search on it. | 392 | -- find_nodes search on it. |
417 | 393 | ||
418 | {----------------------------------------------------------------------- | ||
419 | -- Tokens | ||
420 | -----------------------------------------------------------------------} | ||
421 | |||
422 | tryUpdateSecret :: TVar SessionTokens -> IO () | ||
423 | tryUpdateSecret toks = do | ||
424 | curTime <- liftIO getCurrentTime | ||
425 | liftIO $ atomically $ modifyTVar' toks (invalidateTokens curTime) | ||
426 | |||
427 | grantToken :: Hashable a => TVar SessionTokens -> NodeAddr a -> IO Token | ||
428 | grantToken sessionTokens addr = do | ||
429 | tryUpdateSecret sessionTokens | ||
430 | toks <- readTVarIO sessionTokens | ||
431 | return $ T.lookup addr $ tokenMap toks | ||
432 | |||
433 | -- | Throws 'HandlerError' if the token is invalid or already | ||
434 | -- expired. See 'TokenMap' for details. | ||
435 | checkToken :: Hashable a => TVar SessionTokens -> NodeAddr a -> Token -> IO Bool | ||
436 | checkToken sessionTokens addr questionableToken = do | ||
437 | tryUpdateSecret sessionTokens | ||
438 | toks <- readTVarIO sessionTokens | ||
439 | return $ T.member addr questionableToken (tokenMap toks) | ||
440 | |||
441 | 394 | ||
442 | {----------------------------------------------------------------------- | 395 | {----------------------------------------------------------------------- |
443 | -- Routing table | 396 | -- Routing table |
@@ -475,28 +428,28 @@ getTable = do | |||
475 | let nil = nullTable myId (optBucketCount opts) | 428 | let nil = nullTable myId (optBucketCount opts) |
476 | liftIO (maybe nil R.myBuckets <$> atomically (readTVar var)) | 429 | liftIO (maybe nil R.myBuckets <$> atomically (readTVar var)) |
477 | 430 | ||
478 | getSwarms :: Ord ip => DHT raw dht u ip [ (InfoHash, Int, Maybe ByteString) ] | 431 | getSwarms :: Ord ip => DHT raw KMessageOf u ip [ (InfoHash, Int, Maybe ByteString) ] |
479 | getSwarms = do | 432 | getSwarms = do |
480 | store <- asks contactInfo >>= liftIO . atomically . readTVar | 433 | store <- asks (contactInfo . dhtData) >>= liftIO . atomically . readTVar |
481 | return $ P.knownSwarms store | 434 | return $ P.knownSwarms store |
482 | 435 | ||
483 | savePeerStore :: (Ord ip, Address ip) => DHT raw dht u ip ByteString | 436 | savePeerStore :: (Ord ip, Address ip) => DHT raw KMessageOf u ip ByteString |
484 | savePeerStore = do | 437 | savePeerStore = do |
485 | var <- asks contactInfo | 438 | var <- asks (contactInfo . dhtData) |
486 | peers <- liftIO $ atomically $ readTVar var | 439 | peers <- liftIO $ atomically $ readTVar var |
487 | return $ S.encode peers | 440 | return $ S.encode peers |
488 | 441 | ||
489 | mergeSavedPeers :: (Ord ip, Address ip) => ByteString -> DHT raw dht u ip () | 442 | mergeSavedPeers :: (Ord ip, Address ip) => ByteString -> DHT raw KMessageOf u ip () |
490 | mergeSavedPeers bs = do | 443 | mergeSavedPeers bs = do |
491 | var <- asks contactInfo | 444 | var <- asks (contactInfo . dhtData) |
492 | case S.decode bs of | 445 | case S.decode bs of |
493 | Right newbies -> liftIO $ atomically $ modifyTVar' var (<> newbies) | 446 | Right newbies -> liftIO $ atomically $ modifyTVar' var (<> newbies) |
494 | Left _ -> return () | 447 | Left _ -> return () |
495 | 448 | ||
496 | 449 | ||
497 | allPeers :: Ord ip => InfoHash -> DHT raw dht u ip [ PeerAddr ip ] | 450 | allPeers :: Ord ip => InfoHash -> DHT raw KMessageOf u ip [ PeerAddr ip ] |
498 | allPeers ih = do | 451 | allPeers ih = do |
499 | store <- asks contactInfo >>= liftIO . atomically . readTVar | 452 | store <- asks (contactInfo . dhtData) >>= liftIO . atomically . readTVar |
500 | return $ P.lookup ih store | 453 | return $ P.lookup ih store |
501 | 454 | ||
502 | -- | Find a set of closest nodes from routing table of this node. (in | 455 | -- | Find a set of closest nodes from routing table of this node. (in |
@@ -566,7 +519,7 @@ getTimestamp = do | |||
566 | -- | 519 | -- |
567 | getPeerList :: Ord ip => InfoHash -> DHT raw KMessageOf () ip (PeerList ip) | 520 | getPeerList :: Ord ip => InfoHash -> DHT raw KMessageOf () ip (PeerList ip) |
568 | getPeerList ih = do | 521 | getPeerList ih = do |
569 | var <- asks contactInfo | 522 | var <- asks (contactInfo . dhtData) |
570 | ps <- liftIO $ lookupPeers var ih | 523 | ps <- liftIO $ lookupPeers var ih |
571 | if L.null ps | 524 | if L.null ps |
572 | then Left <$> getClosest ih | 525 | then Left <$> getClosest ih |
@@ -574,7 +527,7 @@ getPeerList ih = do | |||
574 | 527 | ||
575 | getPeerList1 :: Ord ip => DHT raw KMessageOf () ip (InfoHash -> IO (PeerList ip)) | 528 | getPeerList1 :: Ord ip => DHT raw KMessageOf () ip (InfoHash -> IO (PeerList ip)) |
576 | getPeerList1 = do | 529 | getPeerList1 = do |
577 | var <- asks contactInfo | 530 | var <- asks (contactInfo . dhtData) |
578 | getclosest <- getClosest1 | 531 | getclosest <- getClosest1 |
579 | return $ \ih -> do | 532 | return $ \ih -> do |
580 | ps <- lookupPeers var ih | 533 | ps <- lookupPeers var ih |