summaryrefslogtreecommitdiff
path: root/src/Network/BitTorrent/DHT/Routing.hs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Network/BitTorrent/DHT/Routing.hs')
-rw-r--r--src/Network/BitTorrent/DHT/Routing.hs36
1 files changed, 22 insertions, 14 deletions
diff --git a/src/Network/BitTorrent/DHT/Routing.hs b/src/Network/BitTorrent/DHT/Routing.hs
index cf4a4de3..6cf7f122 100644
--- a/src/Network/BitTorrent/DHT/Routing.hs
+++ b/src/Network/BitTorrent/DHT/Routing.hs
@@ -83,8 +83,10 @@ import Text.PrettyPrint.HughesPJClass (pPrint,Pretty)
83import qualified Data.ByteString as BS 83import qualified Data.ByteString as BS
84import Data.Bits 84import Data.Bits
85 85
86import Network.KRPC.Message (KMessageOf)
86import Data.Torrent 87import Data.Torrent
87import Network.BitTorrent.Address 88import Network.BitTorrent.Address
89import Network.DHT.Mainline
88 90
89{----------------------------------------------------------------------- 91{-----------------------------------------------------------------------
90-- Routing monad 92-- Routing monad
@@ -180,7 +182,7 @@ runRouting ping_node find_nodes timestamper = go
180-- other words: new nodes are used only when older nodes disappear. 182-- other words: new nodes are used only when older nodes disappear.
181 183
182-- | Timestamp - last time this node is pinged. 184-- | Timestamp - last time this node is pinged.
183type NodeEntry ip = Binding (NodeInfo ip) Timestamp 185type NodeEntry ip = Binding (NodeInfo KMessageOf ip ()) Timestamp
184 186
185-- TODO instance Pretty where 187-- TODO instance Pretty where
186 188
@@ -211,7 +213,7 @@ fromQ embed project QueueMethods{..} =
211 } 213 }
212-} 214-}
213 215
214seqQ :: QueueMethods Identity (NodeInfo ip) (Seq.Seq (NodeInfo ip)) 216seqQ :: QueueMethods Identity (NodeInfo KMessageOf ip ()) (Seq.Seq (NodeInfo KMessageOf ip ()))
215seqQ = QueueMethods 217seqQ = QueueMethods
216 { pushBack = \e fifo -> pure (fifo Seq.|> e) 218 { pushBack = \e fifo -> pure (fifo Seq.|> e)
217 , popFront = \fifo -> case Seq.viewl fifo of 219 , popFront = \fifo -> case Seq.viewl fifo of
@@ -220,9 +222,9 @@ seqQ = QueueMethods
220 , emptyQueue = pure Seq.empty 222 , emptyQueue = pure Seq.empty
221 } 223 }
222 224
223type BucketQueue ip = Seq.Seq (NodeInfo ip) 225type BucketQueue ip = Seq.Seq (NodeInfo KMessageOf ip ())
224 226
225bucketQ :: QueueMethods Identity (NodeInfo ip) (BucketQueue ip) 227bucketQ :: QueueMethods Identity (NodeInfo KMessageOf ip ()) (BucketQueue ip)
226bucketQ = seqQ 228bucketQ = seqQ
227 229
228-- | Bucket is also limited in its length — thus it's called k-bucket. 230-- | Bucket is also limited in its length — thus it's called k-bucket.
@@ -232,7 +234,7 @@ bucketQ = seqQ
232-- very unlikely that all nodes in bucket fail within an hour of 234-- very unlikely that all nodes in bucket fail within an hour of
233-- each other. 235-- each other.
234-- 236--
235data Bucket ip = Bucket { bktNodes :: !(PSQ (NodeInfo ip) Timestamp) 237data Bucket ip = Bucket { bktNodes :: !(PSQ (NodeInfo KMessageOf ip ()) Timestamp)
236 , bktQ :: !(BucketQueue ip) 238 , bktQ :: !(BucketQueue ip)
237 } deriving (Show,Generic) 239 } deriving (Show,Generic)
238 240
@@ -303,7 +305,7 @@ insertBucket curTime (PingResult bad_node got_response) bucket
303 pure $ PSQ.insert info curTime nodes' 305 pure $ PSQ.insert info curTime nodes'
304 | otherwise = id 306 | otherwise = id
305 307
306updateStamps :: Eq ip => Timestamp -> [NodeInfo ip] -> PSQ (NodeInfo ip) Timestamp -> PSQ (NodeInfo ip) Timestamp 308updateStamps :: Eq ip => Timestamp -> [NodeInfo KMessageOf ip ()] -> PSQ (NodeInfo KMessageOf ip ()) Timestamp -> PSQ (NodeInfo KMessageOf ip ()) Timestamp
307updateStamps curTime stales nodes = foldl' (\q n -> PSQ.insert n curTime q) nodes stales 309updateStamps curTime stales nodes = foldl' (\q n -> PSQ.insert n curTime q) nodes stales
308 310
309 311
@@ -330,6 +332,12 @@ split i b = (Bucket ns qs, Bucket ms rs)
330 where 332 where
331 (ns,ms) = (PSQ.fromList *** PSQ.fromList) . partition (spanBit . key) . PSQ.toList $ bktNodes b 333 (ns,ms) = (PSQ.fromList *** PSQ.fromList) . partition (spanBit . key) . PSQ.toList $ bktNodes b
332 (qs,rs) = runIdentity $ partitionQ bucketQ spanBit $ bktQ b 334 (qs,rs) = runIdentity $ partitionQ bucketQ spanBit $ bktQ b
335 {-
336 spanBit :: forall (dht :: * -> *) addr u.
337 FiniteBits (Network.RPC.NodeId dht) =>
338 NodeInfo dht addr u -> Bool
339 -}
340 spanBit :: NodeInfo KMessageOf addr () -> Bool
333 spanBit entry = testIdBit (nodeId entry) i 341 spanBit entry = testIdBit (nodeId entry) i
334 342
335{----------------------------------------------------------------------- 343{-----------------------------------------------------------------------
@@ -458,7 +466,7 @@ compatibleNodeId tbl = genBucketSample prefix br
458 where 466 where
459 br = bucketRange (L.length (shape tbl) - 1) True 467 br = bucketRange (L.length (shape tbl) - 1) True
460 bs = BS.pack $ take nodeIdSize $ tablePrefix tbl ++ repeat 0 468 bs = BS.pack $ take nodeIdSize $ tablePrefix tbl ++ repeat 0
461 prefix = asNodeId bs 469 prefix = either error id $ S.decode bs
462 470
463tablePrefix :: Table ip -> [Word8] 471tablePrefix :: Table ip -> [Word8]
464tablePrefix = map (packByte . take 8 . (++repeat False)) 472tablePrefix = map (packByte . take 8 . (++repeat False))
@@ -503,7 +511,7 @@ instance TableKey InfoHash where
503 511
504-- | Get a list of /K/ closest nodes using XOR metric. Used in 512-- | Get a list of /K/ closest nodes using XOR metric. Used in
505-- 'find_node' and 'get_peers' queries. 513-- 'find_node' and 'get_peers' queries.
506kclosest :: Eq ip => TableKey a => K -> a -> Table ip -> [NodeInfo ip] 514kclosest :: Eq ip => TableKey a => K -> a -> Table ip -> [NodeInfo KMessageOf ip ()]
507kclosest k (toNodeId -> nid) tbl = take k $ rank nodeId nid (L.concat bucket) 515kclosest k (toNodeId -> nid) tbl = take k $ rank nodeId nid (L.concat bucket)
508 ++ rank nodeId nid (L.concat everyone) 516 ++ rank nodeId nid (L.concat everyone)
509 where 517 where
@@ -547,19 +555,19 @@ modifyBucket nodeId f = go (0 :: BitIx)
547 <|> go i (splitTip nid n i bucket) 555 <|> go i (splitTip nid n i bucket)
548 556
549-- | Triggering event for atomic table update 557-- | Triggering event for atomic table update
550data Event ip = TryInsert { foreignNode :: NodeInfo ip } 558data Event ip = TryInsert { foreignNode :: NodeInfo KMessageOf ip () }
551 | PingResult { foreignNode :: NodeInfo ip 559 | PingResult { foreignNode :: NodeInfo KMessageOf ip ()
552 , ponged :: Bool 560 , ponged :: Bool
553 } 561 }
554 deriving (Eq,Ord,Show) 562 deriving (Eq,Show) -- Ord
555 563
556eventId :: Event ip -> NodeId 564eventId :: Event ip -> NodeId
557eventId (TryInsert NodeInfo{..}) = nodeId 565eventId (TryInsert NodeInfo{..}) = nodeId
558eventId (PingResult NodeInfo{..} _) = nodeId 566eventId (PingResult NodeInfo{..} _) = nodeId
559 567
560-- | Actions requested by atomic table update 568-- | Actions requested by atomic table update
561data CheckPing ip = CheckPing [NodeInfo ip] 569data CheckPing ip = CheckPing [NodeInfo KMessageOf ip ()]
562 deriving (Eq,Ord,Show) 570 deriving (Eq,Show) -- Ord
563 571
564 572
565-- | Atomic 'Table' update 573-- | Atomic 'Table' update
@@ -571,7 +579,7 @@ insert tm event tbl = pure $ fromMaybe ([],tbl) $ modifyBucket (eventId event) (
571-- Conversion 579-- Conversion
572-----------------------------------------------------------------------} 580-----------------------------------------------------------------------}
573 581
574type TableEntry ip = (NodeInfo ip, Timestamp) 582type TableEntry ip = (NodeInfo KMessageOf ip (), Timestamp)
575 583
576tableEntry :: NodeEntry ip -> TableEntry ip 584tableEntry :: NodeEntry ip -> TableEntry ip
577tableEntry (a :-> b) = (a, b) 585tableEntry (a :-> b) = (a, b)