diff options
author | joe <joe@jerkface.net> | 2017-07-14 23:52:05 -0400 |
---|---|---|
committer | joe <joe@jerkface.net> | 2017-07-14 23:52:05 -0400 |
commit | 29f369311408b5ed7823c9858257d1c948e24d28 (patch) | |
tree | 460c7b68c5eadc6f67ddd8ed9eca49715924c631 /src/Network/DHT/Routing.hs | |
parent | f5186fa528bf9c79533d4c4ee1a3846eab4fc6be (diff) |
DHT rewrite: kclosest
Diffstat (limited to 'src/Network/DHT/Routing.hs')
-rw-r--r-- | src/Network/DHT/Routing.hs | 46 |
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 | ||
67 | import Control.Applicative as A | 68 | import Control.Applicative as A |
@@ -83,6 +84,7 @@ import Text.PrettyPrint as PP hiding ((<>)) | |||
83 | import Text.PrettyPrint.HughesPJClass (pPrint,Pretty) | 84 | import Text.PrettyPrint.HughesPJClass (pPrint,Pretty) |
84 | import qualified Data.ByteString as BS | 85 | import qualified Data.ByteString as BS |
85 | import Data.Bits | 86 | import Data.Bits |
87 | import Data.Ord | ||
86 | 88 | ||
87 | import Network.Address | 89 | import Network.Address |
88 | 90 | ||
@@ -103,6 +105,11 @@ import Network.Address | |||
103 | -- | 105 | -- |
104 | type Timestamp = POSIXTime | 106 | type Timestamp = POSIXTime |
105 | 107 | ||
108 | getTimestamp :: IO Timestamp | ||
109 | getTimestamp = do | ||
110 | utcTime <- getCurrentTime | ||
111 | return $ utcTimeToPOSIXSeconds utcTime | ||
112 | |||
106 | 113 | ||
107 | 114 | ||
108 | {----------------------------------------------------------------------- | 115 | {----------------------------------------------------------------------- |
@@ -435,8 +442,11 @@ size = L.sum . shape | |||
435 | depth :: Table -> BucketCount | 442 | depth :: Table -> BucketCount |
436 | depth = L.length . shape | 443 | depth = L.length . shape |
437 | 444 | ||
438 | lookupBucket :: ( FiniteBits (NodeId) | 445 | #endif |
439 | ) => NodeId -> Table -> [Bucket] | 446 | |
447 | lookupBucket :: ( FiniteBits nid | ||
448 | , Ord nid | ||
449 | ) => nid -> Table ni nid -> [Bucket ni] | ||
440 | lookupBucket nid = go 0 [] | 450 | lookupBucket 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 | ||
452 | compatibleNodeId :: forall ni nid. | 461 | compatibleNodeId :: forall ni nid. |
453 | ( Serialize nid, FiniteBits nid) => | 462 | ( Serialize nid, FiniteBits nid) => |
@@ -498,14 +507,31 @@ class TableKey dht k where | |||
498 | instance TableKey dht (NodeId) where | 507 | instance 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. | ||
514 | newtype NodeDistance nodeid = NodeDistance nodeid | ||
515 | deriving (Eq, Ord) | ||
516 | |||
517 | -- | distance(A,B) = |A xor B| Smaller values are closer. | ||
518 | distance :: Bits nid => nid -> nid -> NodeDistance nid | ||
519 | distance a b = NodeDistance $ xor a b | ||
520 | |||
521 | -- | Order by closeness: nearest nodes first. | ||
522 | rank :: ( FiniteBits nid | ||
523 | , Ord nid | ||
524 | ) => (x -> nid) -> nid -> [x] -> [x] | ||
525 | rank 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. |
503 | kclosest :: ( Eq ip | 530 | kclosest :: ( 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] | 533 | kclosest nodeId k nid tbl = take k $ rank nodeId nid (L.concat bucket) |
507 | kclosest 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 |