diff options
Diffstat (limited to 'src/Network/BitTorrent/DHT')
-rw-r--r-- | src/Network/BitTorrent/DHT/Session.hs | 42 |
1 files changed, 34 insertions, 8 deletions
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 | ||