diff options
Diffstat (limited to 'src/Network/BitTorrent/DHT.hs')
-rw-r--r-- | src/Network/BitTorrent/DHT.hs | 42 |
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 #-} | ||
21 | module Network.BitTorrent.DHT | 23 | module 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 | ||
84 | class MonadDHT m where | 87 | class MonadDHT m where |
85 | liftDHT :: DHT IPv4 a -> m a | 88 | liftDHT :: DHT raw dht u IPv4 a -> m a |
86 | 89 | ||
87 | instance MonadDHT (DHT IPv4) where | 90 | instance 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. |
91 | fullLogging :: LogSource -> LogLevel -> Bool | 95 | fullLogging :: 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. |
101 | dht opts addr logfilter action = do | 105 | dht 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. |
178 | bootstrap :: forall ip. Address ip => Maybe BS.ByteString -> [NodeAddr ip] -> DHT ip () | 182 | bootstrap :: forall raw dht u ip. Address ip => Maybe BS.ByteString -> [NodeAddr ip] -> DHT raw dht u ip () |
179 | bootstrap mbs startNodes = do | 183 | bootstrap 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 | -- |
246 | isBootstrapped :: Eq ip => DHT ip Bool | 250 | isBootstrapped :: Eq ip => DHT raw dht u ip Bool |
247 | isBootstrapped = T.full <$> getTable | 251 | isBootstrapped = 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. |
257 | snapshot :: Address ip => DHT ip BS.ByteString | 261 | snapshot :: ( Address ip |
262 | , Ord (NodeId dht) | ||
263 | , Serialize u | ||
264 | , Serialize (NodeId dht) | ||
265 | ) => DHT raw dht u ip BS.ByteString | ||
258 | snapshot = do | 266 | snapshot = 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 | -- |
270 | lookup :: Address ip => InfoHash -> DHT ip `C.Source` [PeerAddr ip] | 280 | lookup :: Address ip => InfoHash -> DHT raw dht u ip `C.Source` [PeerAddr ip] |
271 | lookup topic = do -- TODO retry getClosest if bucket is empty | 281 | lookup 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 | -- |
284 | insert :: Address ip => InfoHash -> PortNumber -> DHT ip () | 296 | insert :: Address ip => InfoHash -> PortNumber -> DHT raw dht u ip () |
285 | insert ih p = do | 297 | insert 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 | -- |
293 | delete :: InfoHash -> PortNumber -> DHT ip () | 305 | delete :: InfoHash -> PortNumber -> DHT raw dht u ip () |
294 | delete = deleteTopic | 306 | delete = deleteTopic |
295 | {-# INLINE delete #-} | 307 | {-# INLINE delete #-} |