summaryrefslogtreecommitdiff
path: root/src/Network/DHT/Routing.hs
diff options
context:
space:
mode:
authorjoe <joe@jerkface.net>2017-07-14 23:52:05 -0400
committerjoe <joe@jerkface.net>2017-07-14 23:52:05 -0400
commit29f369311408b5ed7823c9858257d1c948e24d28 (patch)
tree460c7b68c5eadc6f67ddd8ed9eca49715924c631 /src/Network/DHT/Routing.hs
parentf5186fa528bf9c79533d4c4ee1a3846eab4fc6be (diff)
DHT rewrite: kclosest
Diffstat (limited to 'src/Network/DHT/Routing.hs')
-rw-r--r--src/Network/DHT/Routing.hs46
1 files changed, 36 insertions, 10 deletions
diff --git a/src/Network/DHT/Routing.hs b/src/Network/DHT/Routing.hs
index 34d8385f..bfaaf022 100644
--- a/src/Network/DHT/Routing.hs
+++ b/src/Network/DHT/Routing.hs
@@ -62,6 +62,7 @@ module Network.DHT.Routing
62 62
63 -- * Routing 63 -- * Routing
64 , Timestamp 64 , Timestamp
65 , getTimestamp
65 ) -} where 66 ) -} where
66 67
67import Control.Applicative as A 68import Control.Applicative as A
@@ -83,6 +84,7 @@ import Text.PrettyPrint as PP hiding ((<>))
83import Text.PrettyPrint.HughesPJClass (pPrint,Pretty) 84import Text.PrettyPrint.HughesPJClass (pPrint,Pretty)
84import qualified Data.ByteString as BS 85import qualified Data.ByteString as BS
85import Data.Bits 86import Data.Bits
87import Data.Ord
86 88
87import Network.Address 89import Network.Address
88 90
@@ -103,6 +105,11 @@ import Network.Address
103-- 105--
104type Timestamp = POSIXTime 106type Timestamp = POSIXTime
105 107
108getTimestamp :: IO Timestamp
109getTimestamp = do
110 utcTime <- getCurrentTime
111 return $ utcTimeToPOSIXSeconds utcTime
112
106 113
107 114
108{----------------------------------------------------------------------- 115{-----------------------------------------------------------------------
@@ -435,8 +442,11 @@ size = L.sum . shape
435depth :: Table -> BucketCount 442depth :: Table -> BucketCount
436depth = L.length . shape 443depth = L.length . shape
437 444
438lookupBucket :: ( FiniteBits (NodeId) 445#endif
439 ) => NodeId -> Table -> [Bucket] 446
447lookupBucket :: ( FiniteBits nid
448 , Ord nid
449 ) => nid -> Table ni nid -> [Bucket ni]
440lookupBucket nid = go 0 [] 450lookupBucket nid = go 0 []
441 where 451 where
442 go i bs (Zero table bucket) 452 go i bs (Zero table bucket)
@@ -447,7 +457,6 @@ lookupBucket nid = go 0 []
447 | otherwise = bucket : toBucketList table ++ bs 457 | otherwise = bucket : toBucketList table ++ bs
448 go _ bs (Tip _ _ bucket) = bucket : bs 458 go _ bs (Tip _ _ bucket) = bucket : bs
449 459
450#endif
451 460
452compatibleNodeId :: forall ni nid. 461compatibleNodeId :: forall ni nid.
453 ( Serialize nid, FiniteBits nid) => 462 ( Serialize nid, FiniteBits nid) =>
@@ -498,14 +507,31 @@ class TableKey dht k where
498instance TableKey dht (NodeId) where 507instance TableKey dht (NodeId) where
499 toNodeId = id 508 toNodeId = id
500 509
510#endif
511
512-- | In Kademlia, the distance metric is XOR and the result is
513-- interpreted as an unsigned integer.
514newtype NodeDistance nodeid = NodeDistance nodeid
515 deriving (Eq, Ord)
516
517-- | distance(A,B) = |A xor B| Smaller values are closer.
518distance :: Bits nid => nid -> nid -> NodeDistance nid
519distance a b = NodeDistance $ xor a b
520
521-- | Order by closeness: nearest nodes first.
522rank :: ( FiniteBits nid
523 , Ord nid
524 ) => (x -> nid) -> nid -> [x] -> [x]
525rank f nid = L.sortBy (comparing (distance nid . f))
526
527
501-- | Get a list of /K/ closest nodes using XOR metric. Used in 528-- | Get a list of /K/ closest nodes using XOR metric. Used in
502-- 'find_node' and 'get_peers' queries. 529-- 'find_node' and 'get_peers' queries.
503kclosest :: ( Eq ip 530kclosest :: ( FiniteBits nid
504 , Ord (NodeId) 531 , Ord nid
505 , FiniteBits (NodeId) 532 ) => (ni -> nid) -> Int -> nid -> Table ni nid -> [ni]
506 ) => TableKey dht a => K -> a -> Table -> [NodeInfo] 533kclosest nodeId k nid tbl = take k $ rank nodeId nid (L.concat bucket)
507kclosest k (toNodeId -> nid) tbl = take k $ rank nodeId nid (L.concat bucket) 534 ++ rank nodeId nid (L.concat everyone)
508 ++ rank nodeId nid (L.concat everyone)
509 where 535 where
510 (bucket,everyone) = 536 (bucket,everyone) =
511 L.splitAt 1 537 L.splitAt 1
@@ -513,7 +539,7 @@ kclosest k (toNodeId -> nid) tbl = take k $ rank nodeId nid (L.concat bucket)
513 . lookupBucket nid 539 . lookupBucket nid
514 $ tbl 540 $ tbl
515 541
516#endif 542
517 543
518{----------------------------------------------------------------------- 544{-----------------------------------------------------------------------
519-- Routing 545-- Routing