From b69fd50df8ec24733cef44cb5772fea69cc1e511 Mon Sep 17 00:00:00 2001 From: Joe Crayne Date: Sun, 29 Dec 2019 03:32:37 -0500 Subject: readnodes.hs: Utility to write nodes in a binary format. --- dht/examples/readnodes.hs | 96 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 dht/examples/readnodes.hs diff --git a/dht/examples/readnodes.hs b/dht/examples/readnodes.hs new file mode 100644 index 00000000..e4a5b522 --- /dev/null +++ b/dht/examples/readnodes.hs @@ -0,0 +1,96 @@ +import Control.Monad +import qualified Data.ByteArray as BA +import Data.ByteString (hPutStr,pack) +import Data.Char +import Data.Function +import Data.Int +import Data.List +import Data.Maybe +import Data.Word +import Foreign.Ptr +import Foreign.Marshal.Utils +import Foreign.Storable +import Network.Tox.NodeId +import System.Environment +import System.IO (stdout) +import Text.Read + +-- struct bootstrap_node { +-- 8 char *address; +-- 2 bool ipv6; +-- 2 uint16_t port_udp; +-- 2 uint16_t port_tcp; +-- 32 uint8_t key[32]; +-- 2 +-- } bootstrap_nodes[] = { + + +int32_bytes :: Int32 -> IO [Word8] +int32_bytes = int_bytes + +int16_bytes :: Int16 -> IO [Word8] +int16_bytes i = int_bytes i + +int_bytes :: Storable a => a -> IO [Word8] +int_bytes i = with i $ \p0 -> + let p = castPtr p0 + in foldr (\g r -> g >>= \x -> fmap (x :) r) (return []) + $ peekElemOff p `map` [ 0 .. sizeOf i - 1 ] + + +node_bytes :: Int32 -> Int -> String -> NodeInfo -> IO [Word8] +node_bytes num_nodes a s n = do + -- amd64 8 + 2 + 2 + 2 + 32 + 2 = 48 + -- sizeof(bootstrap_node) = 48 + -- i386 4 + 2 + 2 + 2 + 32 + 2 = 44 + -- sizeof(bootstrap_node) = 44 + bigendian <- (==0) . head <$> int32_bytes 1 + let sz = sizeOf (0::Int) + 2 + 2 + 2 + 32 + 2 + base = fromIntegral num_nodes * sz + ip6 = case find (==':') s of + Just _ | bigendian -> [0,1] + | otherwise -> [1,0] + _ -> [0,0] + t = [0,0] -- TODO: TCP port + nid = nodeId n + adr <- int_bytes (base + a) + u <- int16_bytes $ fromIntegral $ nodePort n + return $ foldr (++) [] + [ adr -- char *address; + , ip6 -- bool ipv6; + , u -- uint16_t port_udp + , t -- uint16_t port_tcp + , BA.unpack (id2key nid) -- uint8_t key[32]; + , [0,0] -- padding + ] + +addressString :: NodeInfo -> String +addressString ni = case show (nodeAddr ni) of + '[':xs -> takeWhile (/=']') xs + xs -> takeWhile (/=':') xs + where + a = show (nodeAddr ni) + +main = do + args <- getArgs + let [ifilename] = args + ws <- words <$> readFile ifilename + let ns :: [ NodeInfo ] + ns = mapMaybe readMaybe ws + num_nodes :: Int32 + num_nodes = fromIntegral $ length ns + ptr_size :: Int32 + ptr_size = fromIntegral $ sizeOf (0 :: Int) + ss = map addressString ns + as = scanl (\i a -> length a + i + 1) 0 ss + let h = stdout + nbs <- int32_bytes num_nodes + pbs <- int32_bytes ptr_size + hPutStr h $ pack $ nbs ++ pbs + forM_ (zip3 as ss ns) $ \(a,s,n) -> do + bs <- node_bytes num_nodes a s n + hPutStr h $ pack bs + hPutStr h $ pack $ do + adr <- ss + map (fromIntegral . ord) adr ++ [0] + -- cgit v1.2.3