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.hs33
1 files changed, 22 insertions, 11 deletions
diff --git a/src/Network/BitTorrent/DHT/Routing.hs b/src/Network/BitTorrent/DHT/Routing.hs
index 984a61cc..af10513d 100644
--- a/src/Network/BitTorrent/DHT/Routing.hs
+++ b/src/Network/BitTorrent/DHT/Routing.hs
@@ -37,13 +37,12 @@ module Network.BitTorrent.DHT.Routing
37 , Network.BitTorrent.DHT.Routing.insert 37 , Network.BitTorrent.DHT.Routing.insert
38 ) where 38 ) where
39 39
40import Control.Applicative hiding (empty) 40import Control.Applicative as A
41import Control.Arrow 41import Control.Arrow
42import Control.Monad 42import Control.Monad
43import Data.Function 43import Data.Function
44import Data.List as L hiding (insert) 44import Data.List as L hiding (insert)
45import Data.Maybe 45import Data.Maybe
46import Data.Monoid
47import Data.PSQueue as PSQ 46import Data.PSQueue as PSQ
48import Data.Serialize as S hiding (Result, Done) 47import Data.Serialize as S hiding (Result, Done)
49import Data.Time 48import Data.Time
@@ -101,12 +100,14 @@ insert ping (k, v) = go 0
101type Timestamp = POSIXTime 100type Timestamp = POSIXTime
102 101
103data Routing ip result 102data Routing ip result
104 = Done result 103 = Full
104 | Done result
105 | GetTime ( Timestamp -> Routing ip result) 105 | GetTime ( Timestamp -> Routing ip result)
106 | NeedPing (NodeAddr ip) ( Bool -> Routing ip result) 106 | NeedPing (NodeAddr ip) ( Bool -> Routing ip result)
107 | Refresh NodeId ([NodeInfo ip] -> Routing ip result) 107 | Refresh NodeId ([NodeInfo ip] -> Routing ip result)
108 108
109instance Functor (Routing ip) where 109instance Functor (Routing ip) where
110 fmap _ Full = Full
110 fmap f (Done r) = Done ( f r) 111 fmap f (Done r) = Done ( f r)
111 fmap f (GetTime g) = GetTime (fmap f . g) 112 fmap f (GetTime g) = GetTime (fmap f . g)
112 fmap f (NeedPing addr g) = NeedPing addr (fmap f . g) 113 fmap f (NeedPing addr g) = NeedPing addr (fmap f . g)
@@ -115,20 +116,31 @@ instance Functor (Routing ip) where
115instance Monad (Routing ip) where 116instance Monad (Routing ip) where
116 return = Done 117 return = Done
117 118
119 Full >>= _ = Full
118 Done r >>= m = m r 120 Done r >>= m = m r
119 GetTime f >>= m = GetTime $ \ t -> f t >>= m 121 GetTime f >>= m = GetTime $ \ t -> f t >>= m
120 NeedPing a f >>= m = NeedPing a $ \ p -> f p >>= m 122 NeedPing a f >>= m = NeedPing a $ \ p -> f p >>= m
121 Refresh n f >>= m = Refresh n $ \ i -> f i >>= m 123 Refresh n f >>= m = Refresh n $ \ i -> f i >>= m
122 124
125instance Applicative (Routing ip) where
126 pure = return
127 (<*>) = ap
128
129instance Alternative (Routing ip) where
130 empty = Full
131 Full <|> m = m
132 m <|> _ = m
133
123runRouting :: (Monad m, Eq ip) 134runRouting :: (Monad m, Eq ip)
124 => (NodeAddr ip -> m Bool) -- ^ ping_node 135 => (NodeAddr ip -> m Bool) -- ^ ping_node
125 -> (NodeId -> m [NodeInfo ip]) -- ^ find_nodes 136 -> (NodeId -> m [NodeInfo ip]) -- ^ find_nodes
126 -> m Timestamp -- ^ timestamper 137 -> m Timestamp -- ^ timestamper
127 -> Routing ip f -- ^ action 138 -> Routing ip f -- ^ action
128 -> m f -- ^ result 139 -> m (Maybe f) -- ^ result
129runRouting ping_node find_nodes timestamper = go 140runRouting ping_node find_nodes timestamper = go
130 where 141 where
131 go (Done r) = return r 142 go Full = return (Nothing)
143 go (Done r) = return (Just r)
132 go (GetTime f) = do 144 go (GetTime f) = do
133 t <- timestamper 145 t <- timestamper
134 go (f t) 146 go (f t)
@@ -231,7 +243,7 @@ insertBucket curTime info bucket
231 return $ PSQ.insert info curTime bucket 243 return $ PSQ.insert info curTime bucket
232 244
233 -- bucket is full of good nodes => ignore new node 245 -- bucket is full of good nodes => ignore new node
234 | otherwise = return bucket 246 | otherwise = A.empty
235 247
236insertNode :: Eq ip => NodeInfo ip -> Bucket ip -> ip `Routing` Bucket ip 248insertNode :: Eq ip => NodeInfo ip -> Bucket ip -> ip `Routing` Bucket ip
237insertNode info bucket = do 249insertNode info bucket = do
@@ -348,8 +360,7 @@ insert info @ NodeInfo {..} = go (0 :: BitIx)
348 go i (One bucket table ) 360 go i (One bucket table )
349 | testIdBit nodeId i = One bucket <$> go (succ i) table 361 | testIdBit nodeId i = One bucket <$> go (succ i) table
350 | otherwise = (`One` table) <$> insertNode info bucket 362 | otherwise = (`One` table) <$> insertNode info bucket
351 go i (Tip nid n bucket) = case insertNode info bucket of 363 go i (Tip nid n bucket)
352 Done kbucket 364 | n == 0 = Tip nid n <$> insertNode info bucket
353 | n == 0 -> Tip nid n <$> Done kbucket 365 | otherwise = Tip nid n <$> insertNode info bucket
354 | otherwise -> go (succ i) (splitTip nid n i kbucket) 366 <|> go (succ i) (splitTip nid n i bucket)
355 result -> Tip nid n <$> result