X-Git-Url: http://git.cielonegro.org/gitweb.cgi?p=haskell-dns.git;a=blobdiff_plain;f=Network%2FDNS%2FNamed%2FResponseBuilder.hs;fp=Network%2FDNS%2FNamed%2FResponseBuilder.hs;h=487a6786bd7240c9c933e8e1dcc309366f4b9781;hp=0000000000000000000000000000000000000000;hb=5015e5caa39e015e6ffa28a87fc5f189e7ba3c71;hpb=7a09a987b0369db0c013fb10272329c733ffc8a1 diff --git a/Network/DNS/Named/ResponseBuilder.hs b/Network/DNS/Named/ResponseBuilder.hs new file mode 100644 index 0000000..487a678 --- /dev/null +++ b/Network/DNS/Named/ResponseBuilder.hs @@ -0,0 +1,81 @@ +module Network.DNS.Named.ResponseBuilder + ( Builder + + , runBuilder + + , unauthorise + , addAnswer + , addAuthority + , addAdditional + ) + where + +import Control.Monad +import Network.DNS.Message + + +newtype Builder a = B { unB :: Message -> (a, Message) } + +instance Monad Builder where + return a = B $ \ s -> (a, s) + m >>= k = B $ \ s -> let (a, s') = unB m s + in + unB (k a) s' + fail err = B $ error err + + +runBuilder :: Message -> Builder () -> Message +runBuilder query builder + = let initialReply = query { + msgAnswers = [] + , msgAuthorities = [] + , msgAdditionals = [] + } + modHeader' = modifyHeader $ + \ h -> h { + hdMessageType = Response + , hdIsAuthoritativeAnswer = True + , hdIsTruncated = False + , hdIsRecursionAvailable = False + , hdResponseCode = NoError + } + (_, result) = unB (modHeader' >> builder) initialReply + in + result + +get :: (Message -> a) -> Builder a +get f = B $ \ s -> (f s, s) + +modify :: (Message -> Message) -> Builder () +modify f = B $ \ s -> ((), f s) + +modifyHeader :: (Header -> Header) -> Builder () +modifyHeader f + = modify $ \ s -> s { msgHeader = f (msgHeader s) } + +addAnswer :: SomeRR -> Builder () +addAnswer rr + = do anss <- get msgAnswers + unless (any (== rr) anss) + $ modify $ \ s -> + s { msgAnswers = msgAnswers s ++ [rr] } + +addAuthority :: SomeRR -> Builder () +addAuthority rr + = do anss <- get msgAnswers + aths <- get msgAuthorities + unless (any (== rr) anss || any (== rr) aths) + $ modify $ \ s -> + s { msgAuthorities = msgAuthorities s ++ [rr] } + +addAdditional :: SomeRR -> Builder () +addAdditional rr + = do anss <- get msgAnswers + aths <- get msgAuthorities + adds <- get msgAdditionals + unless (any (== rr) anss || any (== rr) aths || any (== rr) adds) + $ modify $ \ s -> + s { msgAdditionals = msgAdditionals s ++ [rr] } + +unauthorise :: Builder () +unauthorise = modifyHeader (\ h -> h { hdIsAuthoritativeAnswer = False })