summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Network/BitTorrent/DHT.hs11
-rw-r--r--src/Network/BitTorrent/DHT/Session.hs42
2 files changed, 40 insertions, 13 deletions
diff --git a/src/Network/BitTorrent/DHT.hs b/src/Network/BitTorrent/DHT.hs
index 5517e20f..a098d339 100644
--- a/src/Network/BitTorrent/DHT.hs
+++ b/src/Network/BitTorrent/DHT.hs
@@ -91,7 +91,8 @@ dht = runDHT handlers
91{-# INLINE dht #-} 91{-# INLINE dht #-}
92 92
93-- | One good node may be sufficient. The list of bootstrapping nodes 93-- | One good node may be sufficient. The list of bootstrapping nodes
94-- usually obtained from 'Data.Torrent.tNodes' field. 94-- usually obtained from 'Data.Torrent.tNodes' field. Bootstrapping
95-- process can take up to 5 minutes.
95-- 96--
96-- (TODO) This operation is asynchronous and do not block. 97-- (TODO) This operation is asynchronous and do not block.
97-- 98--
@@ -109,12 +110,12 @@ bootstrap startNodes = do
109 $(logWarnS) "bootstrap" $ T.pack $ show (e :: IOError) 110 $(logWarnS) "bootstrap" $ T.pack $ show (e :: IOError)
110 111
111 Right (NodeFound closest) -> do 112 Right (NodeFound closest) -> do
112 $(logDebug) ("Get a list of closest nodes: " <> 113 $(logDebug) $ "Get a list of closest nodes: " <>
113 T.pack (PP.render (pretty closest))) 114 T.pack (PP.render (pretty closest))
114 forM_ (L.take 2 closest) $ \ info @ NodeInfo {..} -> do 115 forM_ closest $ \ info @ NodeInfo {..} -> do
115 let prettyAddr = T.pack (show (pretty nodeAddr)) 116 let prettyAddr = T.pack (show (pretty nodeAddr))
116 $(logInfoS) "bootstrap" $ "table detalization" <> prettyAddr 117 $(logInfoS) "bootstrap" $ "table detalization" <> prettyAddr
117 fork $ insertClosest nodeAddr 118 insertClosest nodeAddr
118 119
119-- | Get list of peers which downloading this torrent. 120-- | Get list of peers which downloading this torrent.
120-- 121--
diff --git a/src/Network/BitTorrent/DHT/Session.hs b/src/Network/BitTorrent/DHT/Session.hs
index a6c56d70..55e66a7e 100644
--- a/src/Network/BitTorrent/DHT/Session.hs
+++ b/src/Network/BitTorrent/DHT/Session.hs
@@ -40,17 +40,25 @@ module Network.BitTorrent.DHT.Session
40 -- ** Accept 40 -- ** Accept
41 , NodeHandler 41 , NodeHandler
42 , nodeHandler 42 , nodeHandler
43
44 -- ** Iterate
45 , Iteration
46 , Search
47 , search
43 ) where 48 ) where
44 49
50import Prelude hiding (ioError)
51
45import Control.Applicative 52import Control.Applicative
46import Control.Concurrent.STM 53import Control.Concurrent.STM
47import Control.Concurrent.Lifted 54import Control.Concurrent.Lifted hiding (yield)
48import Control.Exception.Lifted hiding (Handler) 55import Control.Exception.Lifted hiding (Handler)
49import Control.Monad.Base 56import Control.Monad.Base
50import Control.Monad.Logger 57import Control.Monad.Logger
51import Control.Monad.Reader 58import Control.Monad.Reader
52import Control.Monad.Trans.Control 59import Control.Monad.Trans.Control
53import Control.Monad.Trans.Resource 60import Control.Monad.Trans.Resource
61import Data.Conduit
54import Data.Default 62import Data.Default
55import Data.Fixed 63import Data.Fixed
56import Data.Hashable 64import Data.Hashable
@@ -107,10 +115,10 @@ instance Default Options where
107 , optTimeout = 5 -- seconds 115 , optTimeout = 5 -- seconds
108 } 116 }
109 117
110milliseconds :: NominalDiffTime -> Int 118microseconds :: NominalDiffTime -> Int
111milliseconds dt = fromEnum millis 119microseconds dt = fromEnum millis
112 where 120 where
113 millis = realToFrac dt :: Milli 121 millis = realToFrac dt :: Micro
114 122
115{----------------------------------------------------------------------- 123{-----------------------------------------------------------------------
116-- Tokens policy 124-- Tokens policy
@@ -325,13 +333,15 @@ queryNode addr q = do
325 let signature = T.decodeUtf8 name <> " @ " <> T.pack (render (pretty addr)) 333 let signature = T.decodeUtf8 name <> " @ " <> T.pack (render (pretty addr))
326 $(logDebugS) "queryNode" $ "Query sent | " <> signature 334 $(logDebugS) "queryNode" $ "Query sent | " <> signature
327 335
328 interval <- asks (milliseconds . optTimeout . options) 336 interval <- asks (optTimeout . options)
329 result <- timeout interval $ query (toSockAddr addr) (Query nid q) 337 result <- timeout (microseconds interval) $ do
338 query (toSockAddr addr) (Query nid q)
330 case result of 339 case result of
331 Nothing -> do 340 Nothing -> do
332 $(logWarnS) "queryNode" $ "not responding @ " 341 $(logWarnS) "queryNode" $ "not responding @ "
333 <> T.pack (show (pretty addr)) 342 <> T.pack (show (pretty addr)) <> " for "
334 throwIO $ KError GenericError "timeout expired" "" 343 <> T.pack (show interval)
344 ioError $ userError "timeout expired"
335 345
336 Just (Response remoteId r) -> do 346 Just (Response remoteId r) -> do
337 $(logDebugS) "queryNode" $ "Query recv | " <> signature 347 $(logDebugS) "queryNode" $ "Query recv | " <> signature
@@ -354,3 +364,19 @@ nodeHandler action = handler $ \ sockAddr (Query remoteId q) -> do
354 Just naddr -> do 364 Just naddr -> do
355 insertNode (NodeInfo remoteId naddr) 365 insertNode (NodeInfo remoteId naddr)
356 Response <$> getNodeId <*> action naddr q 366 Response <$> getNodeId <*> action naddr q
367
368{-----------------------------------------------------------------------
369-- Search
370-----------------------------------------------------------------------}
371
372type Iteration ip i o = i ip -> DHT ip (Either [i ip] [o ip])
373type Search ip i o = Conduit [i ip] (DHT ip) [o ip]
374
375-- TODO: use all inputs
376search :: Address ip => Iteration ip i o -> Search ip i o
377search action = do
378 alpha <- lift $ asks (optAlpha . options)
379 awaitForever $ \ inputs -> do
380 forM_ (L.take alpha inputs) $ \ input -> do
381 result <- lift $ action input
382 either leftover yield result