diff options
Diffstat (limited to 'src/Network/BitTorrent/DHT')
-rw-r--r-- | src/Network/BitTorrent/DHT/Routing.hs | 37 | ||||
-rw-r--r-- | src/Network/BitTorrent/DHT/Session.hs | 24 |
2 files changed, 28 insertions, 33 deletions
diff --git a/src/Network/BitTorrent/DHT/Routing.hs b/src/Network/BitTorrent/DHT/Routing.hs index 293d58ab..73fe358a 100644 --- a/src/Network/BitTorrent/DHT/Routing.hs +++ b/src/Network/BitTorrent/DHT/Routing.hs | |||
@@ -14,6 +14,7 @@ | |||
14 | -- <http://www.bittorrent.org/beps/bep_0005.html#routing-table> | 14 | -- <http://www.bittorrent.org/beps/bep_0005.html#routing-table> |
15 | -- | 15 | -- |
16 | {-# LANGUAGE RecordWildCards #-} | 16 | {-# LANGUAGE RecordWildCards #-} |
17 | {-# LANGUAGE ViewPatterns #-} | ||
17 | {-# LANGUAGE TypeOperators #-} | 18 | {-# LANGUAGE TypeOperators #-} |
18 | {-# LANGUAGE DeriveGeneric #-} | 19 | {-# LANGUAGE DeriveGeneric #-} |
19 | {-# OPTIONS_GHC -fno-warn-orphans #-} | 20 | {-# OPTIONS_GHC -fno-warn-orphans #-} |
@@ -39,8 +40,8 @@ module Network.BitTorrent.DHT.Routing | |||
39 | -- * Lookup | 40 | -- * Lookup |
40 | , K | 41 | , K |
41 | , defaultK | 42 | , defaultK |
42 | , Network.BitTorrent.DHT.Routing.kclosest | 43 | , TableKey (..) |
43 | , Network.BitTorrent.DHT.Routing.kclosestHash | 44 | , kclosest |
44 | 45 | ||
45 | -- * Construction | 46 | -- * Construction |
46 | , Network.BitTorrent.DHT.Routing.nullTable | 47 | , Network.BitTorrent.DHT.Routing.nullTable |
@@ -383,22 +384,24 @@ type K = Int | |||
383 | defaultK :: K | 384 | defaultK :: K |
384 | defaultK = 8 | 385 | defaultK = 8 |
385 | 386 | ||
386 | -- | Get a list of /K/ closest nodes using XOR metric. Used in | 387 | class TableKey k where |
387 | -- 'find_node' queries. | 388 | toNodeId :: k -> NodeId |
388 | kclosest :: Eq ip => K -> NodeId -> Table ip -> [NodeInfo ip] | 389 | |
389 | kclosest k nid = L.take k . rank nid | 390 | instance TableKey NodeId where |
390 | . L.map key . PSQ.toList . fromMaybe PSQ.empty | 391 | toNodeId = id |
391 | . lookupBucket nid | ||
392 | |||
393 | coerceId :: (Serialize a, Serialize b) => a -> b | ||
394 | coerceId = either (error msg) id . S.decode . S.encode | ||
395 | where | ||
396 | msg = "coerceId: impossible" | ||
397 | 392 | ||
398 | -- | Get a list of /K/ nodes with node id closest to the specific | 393 | instance TableKey InfoHash where |
399 | -- infohash. Used in 'get_peers' queries. | 394 | toNodeId = either (error msg) id . S.decode . S.encode |
400 | kclosestHash :: Eq a => K -> InfoHash -> Table a -> [NodeInfo a] | 395 | where -- TODO unsafe coerse? |
401 | kclosestHash k nid t = kclosest k (coerceId nid) t | 396 | msg = "tableKey: impossible" |
397 | |||
398 | -- | Get a list of /K/ closest nodes using XOR metric. Used in | ||
399 | -- 'find_node' and 'get_peers' queries. | ||
400 | kclosest :: Eq ip => TableKey a => K -> a -> Table ip -> [NodeInfo ip] | ||
401 | kclosest k (toNodeId -> nid) | ||
402 | = L.take k . rank nid | ||
403 | . L.map PSQ.key . PSQ.toList . fromMaybe PSQ.empty | ||
404 | . lookupBucket nid | ||
402 | 405 | ||
403 | {----------------------------------------------------------------------- | 406 | {----------------------------------------------------------------------- |
404 | -- Routing | 407 | -- Routing |
diff --git a/src/Network/BitTorrent/DHT/Session.hs b/src/Network/BitTorrent/DHT/Session.hs index 149b7dd2..5ceca4a3 100644 --- a/src/Network/BitTorrent/DHT/Session.hs +++ b/src/Network/BitTorrent/DHT/Session.hs | |||
@@ -26,7 +26,6 @@ module Network.BitTorrent.DHT.Session | |||
26 | , getTable | 26 | , getTable |
27 | , getNodeId | 27 | , getNodeId |
28 | , getClosest | 28 | , getClosest |
29 | , getClosestHash | ||
30 | , insertNode | 29 | , insertNode |
31 | 30 | ||
32 | -- * Peer storage | 31 | -- * Peer storage |
@@ -327,21 +326,10 @@ getNodeId = asks thisNodeId | |||
327 | -- | 326 | -- |
328 | -- This operation used for 'find_nodes' query. | 327 | -- This operation used for 'find_nodes' query. |
329 | -- | 328 | -- |
330 | getClosest :: Eq ip => NodeId -> DHT ip [NodeInfo ip] | 329 | getClosest :: Eq ip => TableKey k => k -> DHT ip [NodeInfo ip] |
331 | getClosest nid = do | 330 | getClosest node = do |
332 | k <- asks (optK . options) | 331 | k <- asks (optK . options) |
333 | kclosest k nid <$> getTable | 332 | kclosest k node <$> getTable |
334 | |||
335 | -- | Find a set of closest nodes from routing table of this node. (in | ||
336 | -- no particular order) | ||
337 | -- | ||
338 | -- This operation used as failback in 'get_peers' query, see | ||
339 | -- 'getPeerList'. | ||
340 | -- | ||
341 | getClosestHash :: Eq ip => InfoHash -> DHT ip [NodeInfo ip] | ||
342 | getClosestHash ih = do | ||
343 | k <- asks (optK . options) | ||
344 | kclosestHash k ih <$> getTable | ||
345 | 333 | ||
346 | -- | This operation do not block but acquire exclusive access to | 334 | -- | This operation do not block but acquire exclusive access to |
347 | -- routing table. | 335 | -- routing table. |
@@ -378,11 +366,15 @@ lookupPeers ih = do | |||
378 | 366 | ||
379 | type PeerList ip = Either [NodeInfo ip] [PeerAddr ip] | 367 | type PeerList ip = Either [NodeInfo ip] [PeerAddr ip] |
380 | 368 | ||
369 | -- | | ||
370 | -- | ||
371 | -- This operation used 'getClosest' as failback. | ||
372 | -- | ||
381 | getPeerList :: Eq ip => InfoHash -> DHT ip (PeerList ip) | 373 | getPeerList :: Eq ip => InfoHash -> DHT ip (PeerList ip) |
382 | getPeerList ih = do | 374 | getPeerList ih = do |
383 | ps <- lookupPeers ih | 375 | ps <- lookupPeers ih |
384 | if L.null ps | 376 | if L.null ps |
385 | then Left <$> getClosestHash ih | 377 | then Left <$> getClosest ih |
386 | else return (Right ps) | 378 | else return (Right ps) |
387 | 379 | ||
388 | {----------------------------------------------------------------------- | 380 | {----------------------------------------------------------------------- |