summaryrefslogtreecommitdiff
path: root/src/Network/BitTorrent/DHT
diff options
context:
space:
mode:
Diffstat (limited to 'src/Network/BitTorrent/DHT')
-rw-r--r--src/Network/BitTorrent/DHT/Routing.hs51
1 files changed, 30 insertions, 21 deletions
diff --git a/src/Network/BitTorrent/DHT/Routing.hs b/src/Network/BitTorrent/DHT/Routing.hs
index b37f2613..64c7bbee 100644
--- a/src/Network/BitTorrent/DHT/Routing.hs
+++ b/src/Network/BitTorrent/DHT/Routing.hs
@@ -13,6 +13,11 @@ module Network.BitTorrent.DHT.Routing
13 ( -- * Routing table 13 ( -- * Routing table
14 Table 14 Table
15 15
16 -- * Table attributes
17 , BucketCount
18 , BucketSize
19 , NodeCount
20
16 -- * Routing 21 -- * Routing
17 , Timestamp 22 , Timestamp
18 , Routing 23 , Routing
@@ -20,6 +25,7 @@ module Network.BitTorrent.DHT.Routing
20 25
21 -- * Query 26 -- * Query
22 , thisId 27 , thisId
28 , shape
23 , Network.BitTorrent.DHT.Routing.size 29 , Network.BitTorrent.DHT.Routing.size
24 , Network.BitTorrent.DHT.Routing.depth 30 , Network.BitTorrent.DHT.Routing.depth
25 , K 31 , K
@@ -149,7 +155,7 @@ instance (Serialize k, Serialize v) => Serialize (Binding k v) where
149-- TODO instance Pretty where 155-- TODO instance Pretty where
150 156
151-- | Most clients use this value for maximum bucket size. 157-- | Most clients use this value for maximum bucket size.
152defaultBucketSize :: Int 158defaultBucketSize :: BucketSize
153defaultBucketSize = 20 159defaultBucketSize = 20
154 160
155-- | Bucket is also limited in its length — thus it's called k-bucket. 161-- | Bucket is also limited in its length — thus it's called k-bucket.
@@ -184,7 +190,7 @@ delta = 15 * 60
184-- | Max bucket size, in nodes. 190-- | Max bucket size, in nodes.
185type Alpha = Int 191type Alpha = Int
186 192
187defaultAlpha :: Int 193defaultAlpha :: Alpha
188defaultAlpha = 8 194defaultAlpha = 8
189 195
190insertBucket :: Eq ip => Timestamp -> NodeInfo ip -> Bucket ip 196insertBucket :: Eq ip => Timestamp -> NodeInfo ip -> Bucket ip
@@ -231,11 +237,11 @@ split i = (PSQ.fromList *** PSQ.fromList) . partition spanBit . PSQ.toList
231-- Table 237-- Table
232-----------------------------------------------------------------------} 238-----------------------------------------------------------------------}
233 239
234defaultBucketCount :: Int 240defaultBucketCount :: BucketCount
235defaultBucketCount = 20 241defaultBucketCount = 20
236 242
237data Table ip 243data Table ip
238 = Tip NodeId Int (Bucket ip) 244 = Tip NodeId BucketCount (Bucket ip)
239 | Zero (Table ip) (Bucket ip) 245 | Zero (Table ip) (Bucket ip)
240 | One (Bucket ip) (Table ip) 246 | One (Bucket ip) (Table ip)
241 deriving Generic 247 deriving Generic
@@ -249,35 +255,38 @@ instance Serialize NominalDiffTime where
249-- since it is included in routing table. 255-- since it is included in routing table.
250instance (Eq ip, Serialize ip) => Serialize (Table ip) 256instance (Eq ip, Serialize ip) => Serialize (Table ip)
251 257
258-- | Shape of the table.
252instance Pretty (Table ip) where 259instance Pretty (Table ip) where
253 pretty t = 260 pretty = hcat . punctuate "," . L.map PP.int . shape
254 "size = " <> PP.int (Network.BitTorrent.DHT.Routing.size t) <>
255 ", depth = " <> PP.int (depth t)
256
257 261
262-- | Empty table with specified /spine/ node id.
258nullTable :: Eq ip => NodeId -> Table ip 263nullTable :: Eq ip => NodeId -> Table ip
259nullTable nid = Tip nid defaultBucketCount PSQ.empty 264nullTable nid = Tip nid defaultBucketCount PSQ.empty
260 265
266-- | Get the /spine/ node id.
261thisId :: Table ip -> NodeId 267thisId :: Table ip -> NodeId
262thisId (Tip nid _ _) = nid 268thisId (Tip nid _ _) = nid
263thisId (Zero table _) = thisId table 269thisId (Zero table _) = thisId table
264thisId (One _ table) = thisId table 270thisId (One _ table) = thisId table
265 271
272type BucketSize = Int
273type BucketCount = Int
274type NodeCount = Int
275
276-- | Internally, routing table is similar to list of buckets or a
277-- /matrix/ of nodes. This function returns the shape of the matrix.
278shape :: Table ip -> [BucketSize]
279shape (Tip _ _ bucket) = [PSQ.size bucket]
280shape (Zero t bucket) = PSQ.size bucket : shape t
281shape (One bucket t ) = PSQ.size bucket : shape t
282
266-- | Get number of nodes in the table. 283-- | Get number of nodes in the table.
267size :: Table ip -> Int 284size :: Table ip -> NodeCount
268size = go 285size = L.sum . shape
269 where
270 go (Tip _ _ bucket) = PSQ.size bucket
271 go (Zero t bucket) = go t + PSQ.size bucket
272 go (One bucket t ) = PSQ.size bucket + go t
273 286
274-- | Get number of buckets in the table. 287-- | Get number of buckets in the table.
275depth :: Table ip -> Int 288depth :: Table ip -> BucketCount
276depth = go 289depth = L.length . shape
277 where
278 go (Tip _ _ _) = 1
279 go (Zero t _) = succ (go t)
280 go (One _ t) = succ (go t)
281 290
282lookupBucket :: NodeId -> Table ip -> Maybe (Bucket ip) 291lookupBucket :: NodeId -> Table ip -> Maybe (Bucket ip)
283lookupBucket nid = go 0 292lookupBucket nid = go 0
@@ -310,7 +319,7 @@ kclosestHash k nid t = kclosest k (coerseId nid) t
310-- Routing 319-- Routing
311-----------------------------------------------------------------------} 320-----------------------------------------------------------------------}
312 321
313splitTip :: Eq ip => NodeId -> Int -> BitIx -> Bucket ip -> Table ip 322splitTip :: Eq ip => NodeId -> BucketCount -> BitIx -> Bucket ip -> Table ip
314splitTip nid n i bucket 323splitTip nid n i bucket
315 | testIdBit nid i = (One zeros (Tip nid (pred n) ones)) 324 | testIdBit nid i = (One zeros (Tip nid (pred n) ones))
316 | otherwise = (Zero (Tip nid (pred n) zeros) ones) 325 | otherwise = (Zero (Tip nid (pred n) zeros) ones)