summaryrefslogtreecommitdiff
path: root/src/Network/BitTorrent
diff options
context:
space:
mode:
authorSam Truzjan <pxqr.sta@gmail.com>2014-01-23 02:47:42 +0400
committerSam Truzjan <pxqr.sta@gmail.com>2014-01-23 02:47:42 +0400
commit7e61a78b975e586cde5c7f2729e5943d7a44699a (patch)
treed20037d9bc41bcbce9e3d4bf4b93058fbcb19e57 /src/Network/BitTorrent
parent5d5c52d5a558b49fb8db814198315627d1c119e5 (diff)
Add class MonadDHT
Diffstat (limited to 'src/Network/BitTorrent')
-rw-r--r--src/Network/BitTorrent/DHT.hs32
-rw-r--r--src/Network/BitTorrent/DHT/Session.hs59
2 files changed, 69 insertions, 22 deletions
diff --git a/src/Network/BitTorrent/DHT.hs b/src/Network/BitTorrent/DHT.hs
index 77bb9da9..a97ebcf7 100644
--- a/src/Network/BitTorrent/DHT.hs
+++ b/src/Network/BitTorrent/DHT.hs
@@ -20,6 +20,7 @@
20module Network.BitTorrent.DHT 20module Network.BitTorrent.DHT
21 ( -- * Distributed Hash Table 21 ( -- * Distributed Hash Table
22 DHT 22 DHT
23 , MonadDHT (..)
23 , dht 24 , dht
24 25
25 -- * Initialization 26 -- * Initialization
@@ -31,6 +32,14 @@ module Network.BitTorrent.DHT
31 , Network.BitTorrent.DHT.lookup 32 , Network.BitTorrent.DHT.lookup
32 , Network.BitTorrent.DHT.insert 33 , Network.BitTorrent.DHT.insert
33 , Network.BitTorrent.DHT.delete 34 , Network.BitTorrent.DHT.delete
35
36 -- * Internal
37 -- | Can be used to implement instance of 'MonadDHT'.
38 , LogFun
39 , Node
40 , handlers
41 , startNode
42 , runDHT
34 ) where 43 ) where
35 44
36import Control.Applicative 45import Control.Applicative
@@ -45,6 +54,15 @@ import Data.Torrent.InfoHash
45import Network.BitTorrent.Core 54import Network.BitTorrent.Core
46import Network.BitTorrent.DHT.Session 55import Network.BitTorrent.DHT.Session
47 56
57{-----------------------------------------------------------------------
58-- DHT types
59-----------------------------------------------------------------------}
60
61class MonadDHT m where
62 liftDHT :: DHT IPv4 a -> m a
63
64instance MonadDHT (DHT IPv4) where
65 liftDHT = id
48 66
49-- | Run DHT on specified port. <add note about resources> 67-- | Run DHT on specified port. <add note about resources>
50dht :: Address ip 68dht :: Address ip
@@ -52,9 +70,17 @@ dht :: Address ip
52 -> NodeAddr ip -- ^ address to bind this node; 70 -> NodeAddr ip -- ^ address to bind this node;
53 -> DHT ip a -- ^ actions to run: 'bootstrap', 'lookup', etc; 71 -> DHT ip a -- ^ actions to run: 'bootstrap', 'lookup', etc;
54 -> IO a -- ^ result. 72 -> IO a -- ^ result.
55dht = runDHT handlers 73dht opts addr action = do
74 runResourceT $ do
75 runStderrLoggingT $ LoggingT $ \ logger -> do
76 node <- startNode handlers opts addr logger
77 runDHT node action
56{-# INLINE dht #-} 78{-# INLINE dht #-}
57 79
80{-----------------------------------------------------------------------
81-- Initialization
82-----------------------------------------------------------------------}
83
58-- | One good node may be sufficient. The list of bootstrapping nodes 84-- | One good node may be sufficient. The list of bootstrapping nodes
59-- usually obtained from 'Data.Torrent.tNodes' field. Bootstrapping 85-- usually obtained from 'Data.Torrent.tNodes' field. Bootstrapping
60-- process can take up to 5 minutes. 86-- process can take up to 5 minutes.
@@ -87,6 +113,10 @@ restore = error "DHT.restore: not implemented"
87snapshot :: DHT ip ByteString 113snapshot :: DHT ip ByteString
88snapshot = error "DHT.snapshot: not implemented" 114snapshot = error "DHT.snapshot: not implemented"
89 115
116{-----------------------------------------------------------------------
117-- Operations
118-----------------------------------------------------------------------}
119
90-- | Get list of peers which downloading this torrent. 120-- | Get list of peers which downloading this torrent.
91-- 121--
92-- This operation is incremental and do block. 122-- This operation is incremental and do block.
diff --git a/src/Network/BitTorrent/DHT/Session.hs b/src/Network/BitTorrent/DHT/Session.hs
index 9455c465..50ca6db3 100644
--- a/src/Network/BitTorrent/DHT/Session.hs
+++ b/src/Network/BitTorrent/DHT/Session.hs
@@ -1,3 +1,10 @@
1-- |
2-- Copyright : (c) Sam Truzjan 2013
3-- License : BSD3
4-- Maintainer : pxqr.sta@gmail.com
5-- Stability : experimental
6-- Portability : portable
7--
1{-# LANGUAGE RecordWildCards #-} 8{-# LANGUAGE RecordWildCards #-}
2{-# LANGUAGE FlexibleContexts #-} 9{-# LANGUAGE FlexibleContexts #-}
3{-# LANGUAGE FlexibleInstances #-} 10{-# LANGUAGE FlexibleInstances #-}
@@ -14,6 +21,11 @@ module Network.BitTorrent.DHT.Session
14 , defaultK 21 , defaultK
15 , Options (..) 22 , Options (..)
16 23
24 -- * Node
25 , LogFun
26 , Node
27 , startNode
28
17 -- * Session 29 -- * Session
18 , DHT 30 , DHT
19 , runDHT 31 , runDHT
@@ -233,7 +245,7 @@ invalidateTokens curTime ts @ SessionTokens {..}
233type AnnounceSet = Set (InfoHash, PortNumber) 245type AnnounceSet = Set (InfoHash, PortNumber)
234 246
235-- | Logger function. 247-- | Logger function.
236type Logger = Loc -> LogSource -> LogLevel -> LogStr -> IO () 248type LogFun = Loc -> LogSource -> LogLevel -> LogStr -> IO ()
237 249
238-- | DHT session keep track state of /this/ node. 250-- | DHT session keep track state of /this/ node.
239data Node ip = Node 251data Node ip = Node
@@ -244,7 +256,7 @@ data Node ip = Node
244 , contactInfo :: !(TVar (PeerStore ip)) -- ^ published by other nodes; 256 , contactInfo :: !(TVar (PeerStore ip)) -- ^ published by other nodes;
245 , announceInfo :: !(TVar AnnounceSet ) -- ^ to publish by this node; 257 , announceInfo :: !(TVar AnnounceSet ) -- ^ to publish by this node;
246 , sessionTokens :: !(TVar SessionTokens) -- ^ query session IDs. 258 , sessionTokens :: !(TVar SessionTokens) -- ^ query session IDs.
247 , loggerFun :: !Logger 259 , loggerFun :: !LogFun
248 } 260 }
249 261
250-- | DHT keep track current session and proper resource allocation for 262-- | DHT keep track current session and proper resource allocation for
@@ -274,28 +286,35 @@ instance MonadLogger (DHT ip) where
274 logger <- asks loggerFun 286 logger <- asks loggerFun
275 liftIO $ logger loc src lvl (toLogStr msg) 287 liftIO $ logger loc src lvl (toLogStr msg)
276 288
289type NodeHandler ip = Handler (DHT ip)
290
277-- | Run DHT session. Some resources like listener thread may live for 291-- | Run DHT session. Some resources like listener thread may live for
278-- some short period of time right after this DHT session closed. 292-- some short period of time right after this DHT session closed.
279runDHT :: forall ip a. Address ip 293startNode :: Address ip
280 => [Handler (DHT ip)] -- ^ handlers to run on accepted queries; 294 => [NodeHandler ip] -- ^ handlers to run on accepted queries;
281 -> Options -- ^ various dht options; 295 -> Options -- ^ various dht options;
282 -> NodeAddr ip -- ^ node address to bind; 296 -> NodeAddr ip -- ^ node address to bind;
283 -> DHT ip a -- ^ DHT action to run; 297 -> LogFun -- ^
284 -> IO a -- ^ result. 298 -> ResIO (Node ip) -- ^ a new DHT node running at given address.
285runDHT hs opts naddr action = runResourceT $ do 299startNode hs opts naddr logger = do
286 runStderrLoggingT $ LoggingT $ \ logger -> do 300-- (_, m) <- allocate (newManager rpcOpts nodeAddr hs) closeManager
287 let rpcOpts = KRPC.def { optQueryTimeout = seconds (optTimeout opts) } 301 m <- liftIO $ newManager rpcOpts nodeAddr hs
288 let nodeAddr = toSockAddr naddr
289 (_, m) <- allocate (newManager rpcOpts nodeAddr hs) closeManager
290 myId <- liftIO genNodeId 302 myId <- liftIO genNodeId
291 node <- liftIO $ Node opts myId m 303 node <- liftIO $ Node opts myId m
292 <$> newMVar (nullTable myId (optBucketCount opts)) 304 <$> newMVar (nullTable myId (optBucketCount opts))
293 <*> newTVarIO def 305 <*> newTVarIO def
294 <*> newTVarIO S.empty 306 <*> newTVarIO S.empty
295 <*> (newTVarIO =<< nullSessionTokens) 307 <*> (newTVarIO =<< nullSessionTokens)
296 <*> pure logger 308 <*> pure logger
297 runReaderT (unDHT (listen >> action)) node 309 runReaderT (unDHT listen) node
310 return node
311 where
312 rpcOpts = KRPC.def { optQueryTimeout = seconds (optTimeout opts) }
313 nodeAddr = toSockAddr naddr
298 314
315runDHT :: Node ip -> DHT ip a -> ResIO a
316runDHT node action = runReaderT (unDHT action) node
317{-# INLINE runDHT #-}
299 318
300askOption :: (Options -> a) -> DHT ip a 319askOption :: (Options -> a) -> DHT ip a
301askOption f = asks (f . options) 320askOption f = asks (f . options)
@@ -475,8 +494,6 @@ ping addr = do
475 (nid, Ping) <- queryNode addr Ping 494 (nid, Ping) <- queryNode addr Ping
476 return (NodeInfo nid addr) 495 return (NodeInfo nid addr)
477 496
478type NodeHandler ip = Handler (DHT ip)
479
480nodeHandler :: Address ip => KRPC (Query a) (Response b) 497nodeHandler :: Address ip => KRPC (Query a) (Response b)
481 => (NodeAddr ip -> a -> DHT ip b) -> NodeHandler ip 498 => (NodeAddr ip -> a -> DHT ip b) -> NodeHandler ip
482nodeHandler action = handler $ \ sockAddr (Query remoteId q) -> do 499nodeHandler action = handler $ \ sockAddr (Query remoteId q) -> do