diff options
-rw-r--r-- | Mainline.hs | 23 | ||||
-rw-r--r-- | examples/dhtd.hs | 65 |
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 | |||
92 | instance FiniteBits NodeId where | 92 | instance FiniteBits NodeId where |
93 | finiteBitSize _ = 160 | 93 | finiteBitSize _ = 160 |
94 | 94 | ||
95 | instance 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 | |||
95 | zeroID :: NodeId | 102 | zeroID :: NodeId |
96 | zeroID = NodeId $ B.replicate 20 0 | 103 | zeroID = NodeId $ B.replicate 20 0 |
97 | 104 | ||
@@ -465,7 +472,7 @@ traced (TableMethods ins del lkup) | |||
465 | 472 | ||
466 | type MainlineClient = Client String Method TransactionId NodeInfo (Message BValue) | 473 | type MainlineClient = Client String Method TransactionId NodeInfo (Message BValue) |
467 | 474 | ||
468 | newClient :: SockAddr -> IO (MainlineClient, Routing) | 475 | newClient :: SockAddr -> IO (MainlineClient, Routing, SwarmsDatabase) |
469 | newClient addr = do | 476 | newClient 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)) |
971 | getNodes :: MainlineClient -> NodeId -> NodeInfo -> IO (Maybe ([NodeInfo],[NodeInfo],())) | 978 | getNodes :: MainlineClient -> NodeId -> NodeInfo -> IO (Maybe ([NodeInfo],[NodeInfo],())) |
972 | getNodes = mainlineSend (Method "find_node") unwrap $ flip FindNode (Just Want_Both) | 979 | getNodes = mainlineSend (Method "find_node") unwrapNodes $ flip FindNode (Just Want_Both) |
973 | where | 980 | |
974 | unwrap (NodeFound ns4 ns6) = (ns4++ns6, ns4++ns6,()) | 981 | unwrapNodes (NodeFound ns4 ns6) = (ns4++ns6, ns4++ns6,()) |
975 | 982 | ||
976 | getPeers :: MainlineClient -> NodeId -> NodeInfo -> IO (Maybe ([NodeInfo],[PeerAddr],Token)) | 983 | getPeers :: MainlineClient -> NodeId -> NodeInfo -> IO (Maybe ([NodeInfo],[PeerAddr],Token)) |
977 | getPeers = mainlineSend (Method "get_peers") unwrap $ flip GetPeers (Just Want_Both) . coerce | 984 | getPeers = 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) | 986 | unwrapPeers (GotPeers ps (NodeFound ns4 ns6) tok) = (ns4++ns6, ps, tok) |
980 | 987 | ||
981 | data TriadSlot = SlotA | SlotB | SlotC | 988 | data 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 | ||
41 | import Network.Address hiding (NodeId, NodeInfo(..)) | 41 | import Network.Address hiding (NodeId, NodeInfo(..)) |
42 | import Network.BitTorrent.DHT.Search | ||
42 | import Network.QueryResponse | 43 | import Network.QueryResponse |
43 | import Network.StreamServer | 44 | import Network.StreamServer |
44 | import Kademlia | 45 | import Kademlia |
@@ -68,23 +69,31 @@ hPutClient h s = hPutStr h ('.' : marshalForClient s) | |||
68 | hPutClientChunk :: Handle -> String -> IO () | 69 | hPutClientChunk :: Handle -> String -> IO () |
69 | hPutClientChunk h s = hPutStr h (' ' : marshalForClient s) | 70 | hPutClientChunk h s = hPutStr h (' ' : marshalForClient s) |
70 | 71 | ||
71 | data DHT = forall ni. ( Show ni | 72 | data 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 | |||
79 | data 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 | ||
82 | nodesFileName :: String -> String | 91 | nodesFileName :: String -> String |
83 | nodesFileName netname = netname ++ "-nodes.json" | 92 | nodesFileName netname = netname ++ "-nodes.json" |
84 | 93 | ||
85 | saveNodes :: String -> DHT -> IO () | 94 | saveNodes :: String -> DHT -> IO () |
86 | saveNodes netname (DHT var _) = do | 95 | saveNodes 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 | ||
101 | pingNodes :: String -> DHT -> IO Bool | 110 | pingNodes :: String -> DHT -> IO Bool |
102 | pingNodes netname (DHT _ ping) = do | 111 | pingNodes 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 |