summaryrefslogtreecommitdiff
path: root/src/Network/BitTorrent/DHT.hs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Network/BitTorrent/DHT.hs')
-rw-r--r--src/Network/BitTorrent/DHT.hs42
1 files changed, 27 insertions, 15 deletions
diff --git a/src/Network/BitTorrent/DHT.hs b/src/Network/BitTorrent/DHT.hs
index d9328cea..8bc423a3 100644
--- a/src/Network/BitTorrent/DHT.hs
+++ b/src/Network/BitTorrent/DHT.hs
@@ -15,9 +15,11 @@
15-- <http://www.bittorrent.org/beps/bep_0005.html> 15-- <http://www.bittorrent.org/beps/bep_0005.html>
16-- 16--
17{-# LANGUAGE FlexibleInstances #-} 17{-# LANGUAGE FlexibleInstances #-}
18{-# LANGUAGE FlexibleContexts #-}
18{-# LANGUAGE TemplateHaskell #-} 19{-# LANGUAGE TemplateHaskell #-}
19{-# LANGUAGE TypeOperators #-} 20{-# LANGUAGE TypeOperators #-}
20{-# LANGUAGE ScopedTypeVariables #-} 21{-# LANGUAGE ScopedTypeVariables #-}
22{-# LANGUAGE CPP #-}
21module Network.BitTorrent.DHT 23module Network.BitTorrent.DHT
22 ( -- * Distributed Hash Table 24 ( -- * Distributed Hash Table
23 DHT 25 DHT
@@ -37,7 +39,7 @@ module Network.BitTorrent.DHT
37 , snapshot 39 , snapshot
38 40
39 -- * Operations 41 -- * Operations
40 , Network.BitTorrent.DHT.lookup 42 -- , Network.BitTorrent.DHT.lookup
41 , Network.BitTorrent.DHT.insert 43 , Network.BitTorrent.DHT.insert
42 , Network.BitTorrent.DHT.delete 44 , Network.BitTorrent.DHT.delete
43 45
@@ -50,7 +52,7 @@ module Network.BitTorrent.DHT
50 , closeNode 52 , closeNode
51 53
52 -- ** Monad 54 -- ** Monad
53 , MonadDHT (..) 55 -- , MonadDHT (..)
54 , runDHT 56 , runDHT
55 ) where 57 ) where
56 58
@@ -81,11 +83,13 @@ import qualified Network.DatagramServer as KRPC (listen, Protocol(..))
81-- DHT types 83-- DHT types
82-----------------------------------------------------------------------} 84-----------------------------------------------------------------------}
83 85
86#if 0
84class MonadDHT m where 87class MonadDHT m where
85 liftDHT :: DHT IPv4 a -> m a 88 liftDHT :: DHT raw dht u IPv4 a -> m a
86 89
87instance MonadDHT (DHT IPv4) where 90instance MonadDHT (DHT raw dht u IPv4) where
88 liftDHT = id 91 liftDHT = id
92#endif
89 93
90-- | Convenience method. Pass this to 'dht' to enable full logging. 94-- | Convenience method. Pass this to 'dht' to enable full logging.
91fullLogging :: LogSource -> LogLevel -> Bool 95fullLogging :: LogSource -> LogLevel -> Bool
@@ -96,7 +100,7 @@ dht :: (Ord ip, Address ip)
96 => Options -- ^ normally you need to use 'Data.Default.def'; 100 => Options -- ^ normally you need to use 'Data.Default.def';
97 -> NodeAddr ip -- ^ address to bind this node; 101 -> NodeAddr ip -- ^ address to bind this node;
98 -> (LogSource -> LogLevel -> Bool) -- ^ use 'fullLogging' as a noisy default 102 -> (LogSource -> LogLevel -> Bool) -- ^ use 'fullLogging' as a noisy default
99 -> DHT ip a -- ^ actions to run: 'bootstrap', 'lookup', etc; 103 -> DHT raw dht u ip a -- ^ actions to run: 'bootstrap', 'lookup', etc;
100 -> IO a -- ^ result. 104 -> IO a -- ^ result.
101dht opts addr logfilter action = do 105dht opts addr logfilter action = do
102 runStderrLoggingT $ filterLogger logfilter $ LoggingT $ \ logger -> do 106 runStderrLoggingT $ filterLogger logfilter $ LoggingT $ \ logger -> do
@@ -175,7 +179,7 @@ resolveHostName NodeAddr {..} = do
175-- 179--
176-- This operation do block, use 180-- This operation do block, use
177-- 'Control.Concurrent.Async.Lifted.async' if needed. 181-- 'Control.Concurrent.Async.Lifted.async' if needed.
178bootstrap :: forall ip. Address ip => Maybe BS.ByteString -> [NodeAddr ip] -> DHT ip () 182bootstrap :: forall raw dht u ip. Address ip => Maybe BS.ByteString -> [NodeAddr ip] -> DHT raw dht u ip ()
179bootstrap mbs startNodes = do 183bootstrap mbs startNodes = do
180 restored <- 184 restored <-
181 case decode <$> mbs of 185 case decode <$> mbs of
@@ -187,8 +191,8 @@ bootstrap mbs startNodes = do
187 $(logInfoS) "bootstrap" "Start node bootstrapping" 191 $(logInfoS) "bootstrap" "Start node bootstrapping"
188 let searchAll aliveNodes = do 192 let searchAll aliveNodes = do
189 nid <- myNodeIdAccordingTo (error "FIXME") 193 nid <- myNodeIdAccordingTo (error "FIXME")
190 nss <- C.sourceList [aliveNodes] $= search nid (findNodeQ nid) $$ C.consume 194 ns <- bgsearch ioFindNodes nid
191 return ( nss :: [[NodeInfo KMessageOf ip ()]] ) 195 return ( ns :: [NodeInfo KMessageOf ip ()] )
192 input_nodes <- (restored ++) . T.toList <$> getTable 196 input_nodes <- (restored ++) . T.toList <$> getTable
193 -- Step 1: Use iterative searches to flesh out the table.. 197 -- Step 1: Use iterative searches to flesh out the table..
194 do let knowns = map (map $ nodeAddr . fst) input_nodes 198 do let knowns = map (map $ nodeAddr . fst) input_nodes
@@ -200,10 +204,10 @@ bootstrap mbs startNodes = do
200 -- If our cached nodes are alive and our IP address did not change, it's possible 204 -- If our cached nodes are alive and our IP address did not change, it's possible
201 -- we are already bootsrapped, so no need to do any searches. 205 -- we are already bootsrapped, so no need to do any searches.
202 when (not b) $ do 206 when (not b) $ do
203 nss <- searchAll $ take 2 alive_knowns 207 ns <- searchAll $ take 2 alive_knowns
204 -- We only use the supplied bootstrap nodes when we don't know of any 208 -- We only use the supplied bootstrap nodes when we don't know of any
205 -- others to try. 209 -- others to try.
206 when (null nss) $ do 210 when (null ns) $ do
207 -- TODO filter duplicated in startNodes list 211 -- TODO filter duplicated in startNodes list
208 -- TODO retransmissions for startNodes 212 -- TODO retransmissions for startNodes
209 (aliveNodes,_) <- unzip <$> queryParallel (pingQ <$> startNodes) 213 (aliveNodes,_) <- unzip <$> queryParallel (pingQ <$> startNodes)
@@ -243,7 +247,7 @@ bootstrap mbs startNodes = do
243-- 247--
244-- This operation do not block. 248-- This operation do not block.
245-- 249--
246isBootstrapped :: Eq ip => DHT ip Bool 250isBootstrapped :: Eq ip => DHT raw dht u ip Bool
247isBootstrapped = T.full <$> getTable 251isBootstrapped = T.full <$> getTable
248 252
249{----------------------------------------------------------------------- 253{-----------------------------------------------------------------------
@@ -254,7 +258,11 @@ isBootstrapped = T.full <$> getTable
254-- 258--
255-- This is blocking operation, use 259-- This is blocking operation, use
256-- 'Control.Concurrent.Async.Lifted.async' if needed. 260-- 'Control.Concurrent.Async.Lifted.async' if needed.
257snapshot :: Address ip => DHT ip BS.ByteString 261snapshot :: ( Address ip
262 , Ord (NodeId dht)
263 , Serialize u
264 , Serialize (NodeId dht)
265 ) => DHT raw dht u ip BS.ByteString
258snapshot = do 266snapshot = do
259 tbl <- getTable 267 tbl <- getTable
260 return $ encode tbl 268 return $ encode tbl
@@ -263,15 +271,19 @@ snapshot = do
263-- Operations 271-- Operations
264-----------------------------------------------------------------------} 272-----------------------------------------------------------------------}
265 273
274#if 0
275
266-- | Get list of peers which downloading this torrent. 276-- | Get list of peers which downloading this torrent.
267-- 277--
268-- This operation is incremental and do block. 278-- This operation is incremental and do block.
269-- 279--
270lookup :: Address ip => InfoHash -> DHT ip `C.Source` [PeerAddr ip] 280lookup :: Address ip => InfoHash -> DHT raw dht u ip `C.Source` [PeerAddr ip]
271lookup topic = do -- TODO retry getClosest if bucket is empty 281lookup topic = do -- TODO retry getClosest if bucket is empty
272 closest <- lift $ getClosest topic 282 closest <- lift $ getClosest topic
273 C.sourceList [closest] $= search topic (getPeersQ topic) 283 C.sourceList [closest] $= search topic (getPeersQ topic)
274 284
285#endif
286
275-- TODO do not republish if the topic is already in announceSet 287-- TODO do not republish if the topic is already in announceSet
276 288
277-- | Announce that /this/ peer may have some pieces of the specified 289-- | Announce that /this/ peer may have some pieces of the specified
@@ -281,7 +293,7 @@ lookup topic = do -- TODO retry getClosest if bucket is empty
281-- This operation is synchronous and do block, use 293-- This operation is synchronous and do block, use
282-- 'Control.Concurrent.Async.Lifted.async' if needed. 294-- 'Control.Concurrent.Async.Lifted.async' if needed.
283-- 295--
284insert :: Address ip => InfoHash -> PortNumber -> DHT ip () 296insert :: Address ip => InfoHash -> PortNumber -> DHT raw dht u ip ()
285insert ih p = do 297insert ih p = do
286 publish ih p 298 publish ih p
287 insertTopic ih p 299 insertTopic ih p
@@ -290,6 +302,6 @@ insert ih p = do
290-- 302--
291-- This operation is atomic and may block for a while. 303-- This operation is atomic and may block for a while.
292-- 304--
293delete :: InfoHash -> PortNumber -> DHT ip () 305delete :: InfoHash -> PortNumber -> DHT raw dht u ip ()
294delete = deleteTopic 306delete = deleteTopic
295{-# INLINE delete #-} 307{-# INLINE delete #-}