diff options
-rw-r--r-- | src/Network/BitTorrent/DHT.hs | 11 | ||||
-rw-r--r-- | src/Network/BitTorrent/DHT/Session.hs | 42 |
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 | ||
50 | import Prelude hiding (ioError) | ||
51 | |||
45 | import Control.Applicative | 52 | import Control.Applicative |
46 | import Control.Concurrent.STM | 53 | import Control.Concurrent.STM |
47 | import Control.Concurrent.Lifted | 54 | import Control.Concurrent.Lifted hiding (yield) |
48 | import Control.Exception.Lifted hiding (Handler) | 55 | import Control.Exception.Lifted hiding (Handler) |
49 | import Control.Monad.Base | 56 | import Control.Monad.Base |
50 | import Control.Monad.Logger | 57 | import Control.Monad.Logger |
51 | import Control.Monad.Reader | 58 | import Control.Monad.Reader |
52 | import Control.Monad.Trans.Control | 59 | import Control.Monad.Trans.Control |
53 | import Control.Monad.Trans.Resource | 60 | import Control.Monad.Trans.Resource |
61 | import Data.Conduit | ||
54 | import Data.Default | 62 | import Data.Default |
55 | import Data.Fixed | 63 | import Data.Fixed |
56 | import Data.Hashable | 64 | import Data.Hashable |
@@ -107,10 +115,10 @@ instance Default Options where | |||
107 | , optTimeout = 5 -- seconds | 115 | , optTimeout = 5 -- seconds |
108 | } | 116 | } |
109 | 117 | ||
110 | milliseconds :: NominalDiffTime -> Int | 118 | microseconds :: NominalDiffTime -> Int |
111 | milliseconds dt = fromEnum millis | 119 | microseconds 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 | |||
372 | type Iteration ip i o = i ip -> DHT ip (Either [i ip] [o ip]) | ||
373 | type Search ip i o = Conduit [i ip] (DHT ip) [o ip] | ||
374 | |||
375 | -- TODO: use all inputs | ||
376 | search :: Address ip => Iteration ip i o -> Search ip i o | ||
377 | search 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 | ||