1 {-# LANGUAGE OverloadedStrings #-}
5 import Prelude hiding (readFile)
6 import System.Environment
7 import System.IO hiding (readFile)
9 import Control.Exception
10 import Text.Show.Pretty hiding (String)
12 import Data.ByteString.Lazy hiding (reverse, putStr, putStrLn, head)
13 import qualified Data.ByteString.Char8 as C (pack)
14 import qualified Data.ByteString.Lazy.Char8 as L (pack)
15 import qualified Data.Text as T (pack)
16 import Data.List.Split
17 import Data.Aeson (encode, decode, Value(..))
18 import Network.HTTP.Types
20 import Network.HTTP.Conduit
29 confFile = "/etc/namecoin.conf"
31 -- HTTP/JsonRpc interface
33 qReq :: Config -> String -> String -> Request m
34 qReq cf q id = applyBasicAuth (C.pack (rpcuser cf)) (C.pack (rpcpassword cf))
35 $ def { host = (C.pack (rpchost cf))
38 , requestHeaders = [ (hAccept, "application/json")
39 , (hContentType, "application/json")
40 , (hConnection, "Keep-Alive")
42 , requestBody = RequestBodyLBS $ encode $
43 JsonRpcRequest JsonRpcV1
47 , checkStatus = \_ _ _ -> Nothing
50 qRsp :: Response ByteString -> Either String ByteString
52 case parseJsonRpc (responseBody rsp) :: Either JsonRpcError NmcRes of
54 case (jrpcErrCode jerr) of
55 -4 -> Right "{}" -- this is how non-existent entry is returned
56 _ -> Left $ "JsonRpc error response: " ++ (show jerr)
57 Right jrsp -> Right $ resValue jrsp
61 queryNmc :: Manager -> Config -> String -> String
62 -> IO (Either String NmcDom)
63 queryNmc mgr cfg qid fqdn =
64 case reverse (splitOn "." fqdn) of
65 "bit":dn:xs -> descendNmcDom queryOp xs $ seedNmcDom dn
66 _ -> return $ Left "Only \".bit\" domain is supported"
69 rsp <- runResourceT $ httpLbs (qReq cfg key qid) mgr
77 cfg <- readConfig confFile
79 hSetBuffering stdin LineBuffering
80 hSetBuffering stdout LineBuffering
83 loopErr e = forever $ do
84 putStrLn $ "FAIL\t" ++ e
89 ["HELO", "1"] -> return 1
90 ["HELO", "2"] -> return 2
91 ["HELO", "3"] -> return 3
92 ["HELO", x ] -> loopErr $ "unsupported ABI version " ++ (show x)
93 _ -> loopErr $ "bad HELO " ++ (show s)
95 putStrLn $ "OK\tDnsNmc ready to serve, protocol v." ++ (show ver)
100 case pdnsParse ver l of
101 Left e -> putStr $ pdnsReport e
104 PdnsRequestQ qname qtype id _ _ _ ->
105 queryNmc mgr cfg id qname >>= putStr . (pdnsOut ver id qname qtype)
106 PdnsRequestAXFR xfrreq ->
107 putStr $ pdnsReport ("No support for AXFR " ++ xfrreq)
108 PdnsRequestPing -> putStrLn "END"
110 -- query by key from Namecoin
113 cfg <- readConfig confFile
114 mgr <- newManager def
115 dom <- queryNmc mgr cfg "+" key
116 putStrLn $ ppShow dom
117 putStr $ pdnsOut 1 "+" key RRTypeANY dom
119 -- using file backend for testing json domain data
121 queryFile :: String -> IO (Either String ByteString)
122 queryFile key = catch (readFile key >>= return . Right)
123 (\e -> return (Left (show (e :: IOException))))
126 dom <- descendNmcDom queryFile [] (seedNmcDom key)
127 putStrLn $ ppShow dom
128 putStr $ pdnsOut 1 "+" key RRTypeANY dom
137 ["-f",key] -> mainFile key
138 _ -> error $ "usage: empty args, or \"<key>\", or \"-f <key>\""