summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Mainline.hs23
-rw-r--r--examples/dhtd.hs65
2 files changed, 62 insertions, 26 deletions
diff --git a/Mainline.hs b/Mainline.hs
index 7c54a096..921bea0f 100644
--- a/Mainline.hs
+++ b/Mainline.hs
@@ -92,6 +92,13 @@ instance S.Serialize NodeId where
92instance FiniteBits NodeId where 92instance FiniteBits NodeId where
93 finiteBitSize _ = 160 93 finiteBitSize _ = 160
94 94
95instance Read NodeId where
96 readsPrec _ str
97 | (bs, xs) <- Base16.decode $ Char8.pack str
98 , B.length bs == 20
99 = [ (NodeId bs, drop 40 str) ]
100 | otherwise = []
101
95zeroID :: NodeId 102zeroID :: NodeId
96zeroID = NodeId $ B.replicate 20 0 103zeroID = NodeId $ B.replicate 20 0
97 104
@@ -465,7 +472,7 @@ traced (TableMethods ins del lkup)
465 472
466type MainlineClient = Client String Method TransactionId NodeInfo (Message BValue) 473type MainlineClient = Client String Method TransactionId NodeInfo (Message BValue)
467 474
468newClient :: SockAddr -> IO (MainlineClient, Routing) 475newClient :: SockAddr -> IO (MainlineClient, Routing, SwarmsDatabase)
469newClient addr = do 476newClient addr = do
470 udp <- udpTransport addr 477 udp <- udpTransport addr
471 nid <- NodeId <$> getRandomBytes 20 478 nid <- NodeId <$> getRandomBytes 20
@@ -564,7 +571,7 @@ newClient addr = do
564 (sched6 routing) 571 (sched6 routing)
565 (refreshBucket (nodeSearch client) (routing6 routing) (nodeId tenative_info)) 572 (refreshBucket (nodeSearch client) (routing6 routing) (nodeId tenative_info))
566 573
567 return (client, routing) 574 return (client, routing, swarms)
568 575
569-- | Modifies a purely random 'NodeId' to one that is related to a given 576-- | Modifies a purely random 'NodeId' to one that is related to a given
570-- routable address in accordance with BEP 42. 577-- routable address in accordance with BEP 42.
@@ -969,14 +976,14 @@ ping client addr =
969 976
970-- searchQuery :: ni -> IO (Maybe [ni], [r], tok)) 977-- searchQuery :: ni -> IO (Maybe [ni], [r], tok))
971getNodes :: MainlineClient -> NodeId -> NodeInfo -> IO (Maybe ([NodeInfo],[NodeInfo],())) 978getNodes :: MainlineClient -> NodeId -> NodeInfo -> IO (Maybe ([NodeInfo],[NodeInfo],()))
972getNodes = mainlineSend (Method "find_node") unwrap $ flip FindNode (Just Want_Both) 979getNodes = mainlineSend (Method "find_node") unwrapNodes $ flip FindNode (Just Want_Both)
973 where 980
974 unwrap (NodeFound ns4 ns6) = (ns4++ns6, ns4++ns6,()) 981unwrapNodes (NodeFound ns4 ns6) = (ns4++ns6, ns4++ns6,())
975 982
976getPeers :: MainlineClient -> NodeId -> NodeInfo -> IO (Maybe ([NodeInfo],[PeerAddr],Token)) 983getPeers :: MainlineClient -> NodeId -> NodeInfo -> IO (Maybe ([NodeInfo],[PeerAddr],Token))
977getPeers = mainlineSend (Method "get_peers") unwrap $ flip GetPeers (Just Want_Both) . coerce 984getPeers = mainlineSend (Method "get_peers") unwrapPeers $ flip GetPeers (Just Want_Both) . coerce
978 where 985
979 unwrap (GotPeers ps (NodeFound ns4 ns6) tok) = (ns4++ns6, ps, tok) 986unwrapPeers (GotPeers ps (NodeFound ns4 ns6) tok) = (ns4++ns6, ps, tok)
980 987
981data TriadSlot = SlotA | SlotB | SlotC 988data TriadSlot = SlotA | SlotB | SlotC
982 deriving (Eq,Ord,Enum,Show,Read) 989 deriving (Eq,Ord,Enum,Show,Read)
diff --git a/examples/dhtd.hs b/examples/dhtd.hs
index f98b05bd..67888eb4 100644
--- a/examples/dhtd.hs
+++ b/examples/dhtd.hs
@@ -39,6 +39,7 @@ import GHC.Conc (labelThread)
39#endif 39#endif
40 40
41import Network.Address hiding (NodeId, NodeInfo(..)) 41import Network.Address hiding (NodeId, NodeInfo(..))
42import Network.BitTorrent.DHT.Search
42import Network.QueryResponse 43import Network.QueryResponse
43import Network.StreamServer 44import Network.StreamServer
44import Kademlia 45import Kademlia
@@ -68,23 +69,31 @@ hPutClient h s = hPutStr h ('.' : marshalForClient s)
68hPutClientChunk :: Handle -> String -> IO () 69hPutClientChunk :: Handle -> String -> IO ()
69hPutClientChunk h s = hPutStr h (' ' : marshalForClient s) 70hPutClientChunk h s = hPutStr h (' ' : marshalForClient s)
70 71
71data DHT = forall ni. ( Show ni 72data DHTQuery nid ni = forall addr r tok. DHTQuery
72 , Read ni 73 { qsearch :: Search nid addr tok ni r
73 , ToJSON ni 74 , qhandler :: ni -> nid -> IO ([ni], [r], tok)
74 , FromJSON ni 75 , qshowR :: r -> String
75 ) => 76 , qshowTok :: tok -> Maybe String
77 }
78
79data DHT = forall nid ni. ( Show ni
80 , Read ni
81 , ToJSON ni
82 , FromJSON ni
83 ) =>
76 DHT 84 DHT
77 { dhtBuckets :: TVar (BucketList ni) 85 { dhtBuckets :: TVar (BucketList ni)
78 , dhtPing :: ni -> IO Bool 86 , dhtPing :: ni -> IO Bool
79 -- dhtClient :: Client err meth tid addr x 87 , dhtQuery :: Map.Map String (DHTQuery nid ni)
88 , dhtParseId :: String -> Either String nid
80 } 89 }
81 90
82nodesFileName :: String -> String 91nodesFileName :: String -> String
83nodesFileName netname = netname ++ "-nodes.json" 92nodesFileName netname = netname ++ "-nodes.json"
84 93
85saveNodes :: String -> DHT -> IO () 94saveNodes :: String -> DHT -> IO ()
86saveNodes netname (DHT var _) = do 95saveNodes netname DHT{dhtBuckets} = do
87 bkts <- atomically $ readTVar var 96 bkts <- atomically $ readTVar dhtBuckets
88 let ns = map fst $ concat $ R.toList bkts 97 let ns = map fst $ concat $ R.toList bkts
89 bs = J.encode ns 98 bs = J.encode ns
90 fname = nodesFileName netname 99 fname = nodesFileName netname
@@ -99,7 +108,7 @@ loadNodes netname = do
99 either (const $ return []) return attempt 108 either (const $ return []) return attempt
100 109
101pingNodes :: String -> DHT -> IO Bool 110pingNodes :: String -> DHT -> IO Bool
102pingNodes netname (DHT _ ping) = do 111pingNodes netname DHT{dhtPing} = do
103 let fname = nodesFileName netname 112 let fname = nodesFileName netname
104 attempt <- tryIOError $ do 113 attempt <- tryIOError $ do
105 J.decode <$> L.readFile fname 114 J.decode <$> L.readFile fname
@@ -110,7 +119,7 @@ pingNodes netname (DHT _ ping) = do
110 myThreadId >>= flip labelThread ("pinging."++fname) 119 myThreadId >>= flip labelThread ("pinging."++fname)
111 putStrLn $ "Forked "++show fname 120 putStrLn $ "Forked "++show fname
112 withTaskGroup 10 $ \g -> do 121 withTaskGroup 10 $ \g -> do
113 mapTasks_ g (map ping ns) 122 mapTasks_ g (map dhtPing ns)
114 putStrLn $ "Load finished "++show fname 123 putStrLn $ "Load finished "++show fname
115 return True 124 return True
116 125
@@ -189,9 +198,9 @@ clientSession s@Session{..} sock cnum h = do
189 _ -> hPutClient h "error." 198 _ -> hPutClient h "error."
190 199
191#endif 200#endif
192 ("ls", _) | Just (DHT var _) <- Map.lookup netname dhts 201 ("ls", _) | Just DHT{dhtBuckets} <- Map.lookup netname dhts
193 -> cmd0 $ do 202 -> cmd0 $ do
194 bkts <- atomically $ readTVar var 203 bkts <- atomically $ readTVar dhtBuckets
195 let r = reportTable bkts 204 let r = reportTable bkts
196 hPutClient h $ 205 hPutClient h $
197 showReport $ 206 showReport $
@@ -199,10 +208,10 @@ clientSession s@Session{..} sock cnum h = do
199 , ("node-id", show $ thisNode bkts) 208 , ("node-id", show $ thisNode bkts)
200 , ("network", netname) ] 209 , ("network", netname) ]
201 210
202 ("ping", s) | Just (DHT _ ping) <- Map.lookup netname dhts 211 ("ping", s) | Just DHT{dhtPing} <- Map.lookup netname dhts
203 -> cmd0 $ do 212 -> cmd0 $ do
204 case readEither s of 213 case readEither s of
205 Right addr -> do result <- ping addr 214 Right addr -> do result <- dhtPing addr
206 let rs = [" ", show result] 215 let rs = [" ", show result]
207 hPutClient h $ unlines rs 216 hPutClient h $ unlines rs
208 Left er -> hPutClient h er 217 Left er -> hPutClient h er
@@ -238,15 +247,35 @@ main = do
238 _ -> return defaultPort 247 _ -> return defaultPort
239 addr <- getBindAddress p True{- ipv6 -} 248 addr <- getBindAddress p True{- ipv6 -}
240 249
241 (bt,btR) <- Mainline.newClient addr 250 (bt,btR,swarms) <- Mainline.newClient addr
242 quitBt <- forkListener bt 251 quitBt <- forkListener bt
243 252
244 tox <- return $ error "TODO: Tox.newClient" 253 tox <- return $ error "TODO: Tox.newClient"
245 quitTox <- return $ return () -- TODO: forkListener tox 254 quitTox <- return $ return () -- TODO: forkListener tox
246 255
247 let dhts = Map.fromList 256 let mainlineDHT bkts = DHT
248 [ ("bt4", DHT (Mainline.routing4 btR) (Mainline.ping bt)) 257 { dhtBuckets = bkts btR
249 , ("bt6", DHT (Mainline.routing6 btR) (Mainline.ping bt)) 258 , dhtPing = Mainline.ping bt
259 , dhtQuery = Map.fromList
260 [ ("node", DHTQuery (Mainline.nodeSearch bt)
261 (\ni -> fmap Mainline.unwrapNodes
262 . Mainline.findNodeH btR ni
263 . flip Mainline.FindNode (Just Mainline.Want_Both))
264 show
265 (const Nothing))
266 , ("peer", DHTQuery (Mainline.peerSearch bt)
267 (\ni -> fmap Mainline.unwrapPeers
268 . Mainline.getPeersH btR swarms ni
269 . flip Mainline.GetPeers (Just Mainline.Want_Both)
270 . (read . show)) -- TODO: InfoHash -> NodeId
271 show
272 (Just . show))
273 ]
274 , dhtParseId = readEither :: String -> Either String Mainline.NodeId
275 }
276 dhts = Map.fromList
277 [ ("bt4", mainlineDHT Mainline.routing4)
278 , ("bt6", mainlineDHT Mainline.routing6)
250 ] 279 ]
251 280
252 waitForSignal <- do 281 waitForSignal <- do