X-Git-Url: http://www.average.org/gitweb/?p=pdns-pipe-nmc.git;a=blobdiff_plain;f=pdns-pipe-nmc.hs;h=4bd87582d8a31d1467b4b96cfbd816445a242eea;hp=f61d7baecf5ae61faa20d39adeb62a0e208e7699;hb=f05929457a786046899b21db566ae0428411d690;hpb=e8fbbca8429c42f84bab9e1ab14bb1ff52c5e4cd diff --git a/pdns-pipe-nmc.hs b/pdns-pipe-nmc.hs index f61d7ba..4bd8758 100644 --- a/pdns-pipe-nmc.hs +++ b/pdns-pipe-nmc.hs @@ -2,11 +2,20 @@ module Main where +import Prelude hiding (readFile) +import System.Environment +import System.IO hiding (readFile) +import System.IO.Error +import Control.Exception +import Text.Show.Pretty hiding (String) 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 Control.Monad.State +import Data.ByteString.Lazy hiding (reverse, putStr, putStrLn, head, empty) +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.Map.Lazy (Map, empty, insert, delete, size) import Data.Aeson (encode, decode, Value(..)) import Network.HTTP.Types import Data.Conduit @@ -15,13 +24,15 @@ import Network.HTTP.Conduit import JsonRpcClient import Config import PowerDns -import NmcJson +import NmcRpc +import NmcDom +import NmcTransform confFile = "/etc/namecoin.conf" -- 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) @@ -33,39 +44,41 @@ qReq cf q id = applyBasicAuth (C.pack (rpcuser cf)) (C.pack (rpcpassword 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 - -> IO (Either String NmcDom) -queryNmc mgr cfg fqdn qtype qid = do +queryOpNmc cfg mgr qid key = + runResourceT (httpLbs (qReq cfg key qid) mgr) >>= return . qRsp + +queryOpFile key = catch (readFile key >>= return . Right) + (\e -> return (Left (show (e :: IOException)))) + +queryDom queryOp 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 - _ -> - return $ Left "Only \".bit\" domain is supported" + "bit":dn:xs -> descendNmcDom queryOp xs $ seedNmcDom dn + _ -> return $ Left "Only \".bit\" domain is supported" --- Main entry +-- Main entries -main = do +mainPdnsNmc = do cfg <- readConfig confFile + hSetBuffering stdin LineBuffering + hSetBuffering stdout LineBuffering ver <- do let loopErr e = forever $ do @@ -83,18 +96,52 @@ main = do putStrLn $ "OK\tDnsNmc ready to serve, protocol v." ++ (show ver) mgr <- newManager def + let + newcache count name = (insert count name) . (delete (count - 10)) + io = liftIO + mainloop = forever $ do + l <- io getLine + (count, cache) <- get + case pdnsParse ver l of + Left e -> io $ putStr $ pdnsReport e + Right preq -> do + case preq of + PdnsRequestQ qname qtype id _ _ _ -> do + io $ queryDom (queryOpNmc cfg mgr id) qname + >>= putStr . (pdnsOut ver (show count) qname qtype) + io $ putStrLn $ "LOG\tRequest number " ++ (show count) + ++ " id: " ++ id + ++ " qname: " ++ qname + ++ " qtype: " ++ (show qtype) + ++ " cache size: " ++ (show (size cache)) + put (count + 1, newcache count qname cache) + PdnsRequestAXFR xfrreq -> + io $ putStr $ pdnsReport ("No support for AXFR " ++ xfrreq) + PdnsRequestPing -> io $ putStrLn "END" + runStateT mainloop (0, empty) >> return () + +-- query by key from Namecoin + +mainOne key = do + cfg <- readConfig confFile + mgr <- newManager def + dom <- queryDom (queryOpNmc cfg mgr "_") key + putStrLn $ ppShow dom + putStr $ pdnsOut 1 "_" key RRTypeANY dom - 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) +-- using file backend for testing json domain data + +mainFile key = do + dom <- queryDom queryOpFile key + putStrLn $ ppShow dom + putStr $ pdnsOut 1 "+" key RRTypeANY dom + +-- Entry point + +main = do + args <- getArgs + case args of + [] -> mainPdnsNmc + [key] -> mainOne key + ["-f",key] -> mainFile key + _ -> error $ "usage: empty args, or \"[-f] \""