summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Crayne <joe@jerkface.net>2019-12-29 03:32:37 -0500
committerJoe Crayne <joe@jerkface.net>2020-01-03 17:26:06 -0500
commitb69fd50df8ec24733cef44cb5772fea69cc1e511 (patch)
treeb9bf4ac9effa5c6a2a923b2a92cc674e8f958770
parentf37cd8aa9134142d6a23156fc4fd0c6cb5a308dd (diff)
readnodes.hs: Utility to write nodes in a binary format.
-rw-r--r--dht/examples/readnodes.hs96
1 files changed, 96 insertions, 0 deletions
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 @@
1import Control.Monad
2import qualified Data.ByteArray as BA
3import Data.ByteString (hPutStr,pack)
4import Data.Char
5import Data.Function
6import Data.Int
7import Data.List
8import Data.Maybe
9import Data.Word
10import Foreign.Ptr
11import Foreign.Marshal.Utils
12import Foreign.Storable
13import Network.Tox.NodeId
14import System.Environment
15import System.IO (stdout)
16import Text.Read
17
18-- struct bootstrap_node {
19-- 8 char *address;
20-- 2 bool ipv6;
21-- 2 uint16_t port_udp;
22-- 2 uint16_t port_tcp;
23-- 32 uint8_t key[32];
24-- 2
25-- } bootstrap_nodes[] = {
26
27
28int32_bytes :: Int32 -> IO [Word8]
29int32_bytes = int_bytes
30
31int16_bytes :: Int16 -> IO [Word8]
32int16_bytes i = int_bytes i
33
34int_bytes :: Storable a => a -> IO [Word8]
35int_bytes i = with i $ \p0 ->
36 let p = castPtr p0
37 in foldr (\g r -> g >>= \x -> fmap (x :) r) (return [])
38 $ peekElemOff p `map` [ 0 .. sizeOf i - 1 ]
39
40
41node_bytes :: Int32 -> Int -> String -> NodeInfo -> IO [Word8]
42node_bytes num_nodes a s n = do
43 -- amd64 8 + 2 + 2 + 2 + 32 + 2 = 48
44 -- sizeof(bootstrap_node) = 48
45 -- i386 4 + 2 + 2 + 2 + 32 + 2 = 44
46 -- sizeof(bootstrap_node) = 44
47 bigendian <- (==0) . head <$> int32_bytes 1
48 let sz = sizeOf (0::Int) + 2 + 2 + 2 + 32 + 2
49 base = fromIntegral num_nodes * sz
50 ip6 = case find (==':') s of
51 Just _ | bigendian -> [0,1]
52 | otherwise -> [1,0]
53 _ -> [0,0]
54 t = [0,0] -- TODO: TCP port
55 nid = nodeId n
56 adr <- int_bytes (base + a)
57 u <- int16_bytes $ fromIntegral $ nodePort n
58 return $ foldr (++) []
59 [ adr -- char *address;
60 , ip6 -- bool ipv6;
61 , u -- uint16_t port_udp
62 , t -- uint16_t port_tcp
63 , BA.unpack (id2key nid) -- uint8_t key[32];
64 , [0,0] -- padding
65 ]
66
67addressString :: NodeInfo -> String
68addressString ni = case show (nodeAddr ni) of
69 '[':xs -> takeWhile (/=']') xs
70 xs -> takeWhile (/=':') xs
71 where
72 a = show (nodeAddr ni)
73
74main = do
75 args <- getArgs
76 let [ifilename] = args
77 ws <- words <$> readFile ifilename
78 let ns :: [ NodeInfo ]
79 ns = mapMaybe readMaybe ws
80 num_nodes :: Int32
81 num_nodes = fromIntegral $ length ns
82 ptr_size :: Int32
83 ptr_size = fromIntegral $ sizeOf (0 :: Int)
84 ss = map addressString ns
85 as = scanl (\i a -> length a + i + 1) 0 ss
86 let h = stdout
87 nbs <- int32_bytes num_nodes
88 pbs <- int32_bytes ptr_size
89 hPutStr h $ pack $ nbs ++ pbs
90 forM_ (zip3 as ss ns) $ \(a,s,n) -> do
91 bs <- node_bytes num_nodes a s n
92 hPutStr h $ pack bs
93 hPutStr h $ pack $ do
94 adr <- ss
95 map (fromIntegral . ord) adr ++ [0]
96