From c17a9373053cf74967f53570cb21c074fe00587a Mon Sep 17 00:00:00 2001 From: joe Date: Mon, 24 Jul 2017 20:06:42 -0400 Subject: Bootstrap nodes for Mainline rewrite. --- Mainline.hs | 46 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/Mainline.hs b/Mainline.hs index 29f1df80..76e914b3 100644 --- a/Mainline.hs +++ b/Mainline.hs @@ -54,6 +54,8 @@ import qualified Network.DHT.Routing as R ;import Network.DHT.Routing (Info, Timestamp, getTimestamp) import Network.QueryResponse import Network.Socket +import System.IO.Error +import System.IO.Unsafe (unsafeInterleaveIO) newtype NodeId = NodeId ByteString deriving (Eq,Ord,Show,ByteArrayAccess, BEncode, Bits, Hashable) @@ -344,7 +346,7 @@ data Routing = Routing type MainlineClient = Client String Method TransactionId NodeInfo (Message BValue) -newClient :: SockAddr -> IO MainlineClient +newClient :: SockAddr -> IO (MainlineClient, Routing) newClient addr = do udp <- udpTransport addr nid <- NodeId <$> getRandomBytes 20 @@ -414,7 +416,7 @@ newClient addr = do , clientResponseId = return } - return client + return (client, routing) defaultHandler :: ByteString -> Handler defaultHandler meth = MethodHandler decodePayload errorPayload returnError @@ -840,3 +842,43 @@ nodeSearch = Search , searchNodeAddress = nodeIP &&& nodePort , searchQuery = error "searchQuery" } + +-- | List of bootstrap nodes maintained by different bittorrent +-- software authors. +bootstrapNodes :: WantIP -> IO [NodeInfo] +bootstrapNodes want = unsafeInterleaveIO $ do + let wellknowns = + [ "router.bittorrent.com:6881" -- by BitTorrent Inc. + + -- doesn't work at the moment (use git blame) of commit + , "dht.transmissionbt.com:6881" -- by Transmission project + + , "router.utorrent.com:6881" + ] + nss <- forM wellknowns $ \hostAndPort -> do + e <- resolve want hostAndPort + case e of + Left _ -> return [] + Right sockaddr -> either (const $ return []) + (return . (: [])) + $ nodeInfo zeroID sockaddr + return $ concat nss + +-- | Resolve either a numeric network address or a hostname to a +-- numeric IP address of the node. +resolve :: WantIP -> String -> IO (Either IOError SockAddr) +resolve want hostAndPort = do + let hints = defaultHints { addrSocketType = Datagram + , addrFamily = case want of + Want_IP4 -> AF_INET + _ -> AF_INET6 + } + (rport,rhost) = span (/= ':') $ reverse hostAndPort + (host,port) = case rhost of + [] -> (hostAndPort, Nothing) + (_:hs) -> (reverse hs, Just (reverse rport)) + tryIOError $ do + -- getAddrInfo throws exception on empty list, so this + -- pattern matching never fails. + info : _ <- getAddrInfo (Just hints) (Just host) port + return $ addrAddress info -- cgit v1.2.3