module Main where
---import Control.Applicative
+import System.IO
import Control.Monad
-import qualified Data.ByteString.Char8 as C (pack, unpack)
-import qualified Data.ByteString.Lazy.Char8 as L (pack, unpack)
-import Data.ByteString.Lazy as BS hiding (reverse, putStrLn)
-import Data.ConfigFile
-import Data.Either.Utils
+import Data.ByteString.Lazy hiding (reverse, putStr, putStrLn)
+import qualified Data.ByteString.Char8 as C (pack)
+import qualified Data.ByteString.Lazy.Char8 as L (pack)
+import qualified Data.Text as T (pack)
import Data.List.Split
import Data.Aeson (encode, decode, Value(..))
import Network.HTTP.Types
import Data.Conduit
import Network.HTTP.Conduit
-import Data.JsonRpcClient
+
+import JsonRpcClient
+import Config
import PowerDns
-import NmcJson
+import NmcRpc
+import NmcDom
confFile = "/etc/namecoin.conf"
--- Config file handling
-
-data Config = Config { rpcuser :: String
- , rpcpassword :: String
- , rpchost :: String
- , rpcport :: Int
- } deriving (Show)
-
-readConfig :: String -> IO Config
-readConfig f = do
- cp <- return . forceEither =<< readfile emptyCP f
- return (Config { rpcuser = getSetting cp "rpcuser" ""
- , rpcpassword = getSetting cp "rpcpassword" ""
- , rpchost = getSetting cp "rpchost" "localhost"
- , rpcport = getSetting cp "rpcport" 8336
- })
- where
- getSetting cp x dfl = case get cp "DEFAULT" x of
- Left _ -> dfl
- Right x -> x
-
-- HTTP/JsonRpc interface
-qReq :: Config -> ByteString -> ByteString -> Request m
+qReq :: Config -> String -> String -> Request m
qReq cf q id = applyBasicAuth (C.pack (rpcuser cf)) (C.pack (rpcpassword cf))
$ def { host = (C.pack (rpchost cf))
, port = (rpcport cf)
, requestBody = RequestBodyLBS $ encode $
JsonRpcRequest JsonRpcV1
"name_show"
- [q]
- (String "pdns-nmc")
+ [L.pack q]
+ (String (T.pack id))
, checkStatus = \_ _ _ -> Nothing
}
-qRsp :: Response ByteString -> Either String NmcDom
+qRsp :: Response ByteString -> Either String ByteString
qRsp rsp =
case parseJsonRpc (responseBody rsp) :: Either JsonRpcError NmcRes of
- Left jerr -> Left $ "Unparseable response: " ++ (show (responseBody rsp))
- Right jrsp ->
- case decode (resValue jrsp) :: Maybe NmcDom of
- Nothing -> Left $ "Unparseable value: " ++ (show (resValue jrsp))
- Just dom -> Right dom
+ Left jerr ->
+ case (jrpcErrCode jerr) of
+ -4 -> Right "{}" -- this is how non-existent entry is returned
+ _ -> Left $ "JsonRpc error response: " ++ (show jerr)
+ Right jrsp -> Right $ resValue jrsp
-- NMC interface
-queryNmc :: Manager -> Config -> String -> RRType -> String
+queryNmc :: Manager -> Config -> String -> String
-> IO (Either String NmcDom)
-queryNmc mgr cfg fqdn qtype qid = do
+queryNmc mgr cfg qid fqdn =
case reverse (splitOn "." fqdn) of
"bit":dn:xs -> do
- rsp <- runResourceT $
- httpLbs (qReq cfg (L.pack ("d/" ++ dn)) (L.pack qid)) mgr
- return $ qRsp rsp
+ dom <- mergeImport queryOp $
+ emptyNmcDom { domImport = Just ("d/" ++ dn)}
+ case dom of
+ Left err -> return $ Left err
+ Right dom' -> return $ Right $ descendNmcDom xs dom'
_ ->
return $ Left "Only \".bit\" domain is supported"
+ where
+ queryOp key = do
+ rsp <- runResourceT $ httpLbs (qReq cfg key qid) mgr
+ -- print $ qRsp rsp
+ return $ qRsp rsp
-- Main entry
cfg <- readConfig confFile
+ hSetBuffering stdin LineBuffering
+ hSetBuffering stdout LineBuffering
ver <- do
let
loopErr e = forever $ do
putStrLn $ "OK\tDnsNmc ready to serve, protocol v." ++ (show ver)
mgr <- newManager def
-
- print $ qReq cfg "d/nosuchdomain" "query-nmc"
- rsp <- runResourceT $ httpLbs (qReq cfg "d/nosuchdomain" "query-nmc") mgr
- print $ (statusCode . responseStatus) rsp
- putStrLn "===== complete response is:"
- print rsp
- let rbody = responseBody rsp
- putStrLn "===== response body is:"
- print rbody
- let result = parseJsonRpc rbody :: Either JsonRpcError NmcRes
- putStrLn "===== parsed response is:"
- print result
--- print $ parseJsonRpc (responseBody rsp)
-
- --forever $ getLine >>= (pdnsOut uri) . (pdnsParse ver)
+ forever $ do
+ l <- getLine
+ case pdnsParse ver l of
+ Left e -> putStr $ pdnsReport e
+ Right preq -> do
+ case preq of
+ PdnsRequestQ qname qtype id _ _ _ ->
+ queryNmc mgr cfg id qname >>= putStr . (pdnsOut ver id qname qtype)
+ PdnsRequestAXFR xfrreq ->
+ putStr $ pdnsReport ("No support for AXFR " ++ xfrreq)
+ PdnsRequestPing -> putStrLn "END"
+
+-- for testing
+
+ask str = do
+ cfg <- readConfig confFile
+ mgr <- newManager def
+ queryNmc mgr cfg "askid" str >>= putStr . (pdnsOut 1 "askid" str RRTypeANY)