1 module Network.DNS.Named.ResponseBuilder
16 import Network.DNS.Message
19 newtype Builder a = B { unB :: Message -> (a, Message) }
21 instance Monad Builder where
22 return a = B $ \ s -> (a, s)
23 m >>= k = B $ \ s -> let (a, s') = unB m s
26 fail err = B $ error err
29 runBuilder :: Message -> Builder () -> Message
30 runBuilder query builder
31 = let initialReply = query {
36 modHeader' = modifyHeader $
38 hdMessageType = Response
39 , hdIsAuthoritativeAnswer = True
40 , hdIsTruncated = False
41 , hdIsRecursionAvailable = False
42 , hdResponseCode = NoError
44 setNameError = do aa <- get (hdIsRecursionAvailable . msgHeader)
45 rc <- get (hdResponseCode . msgHeader)
46 anss <- get msgAnswers
48 when (aa && rc == NoError && null anss)
49 $ setResponseCode NameError
51 (_, result) = unB (modHeader' >> builder >> setNameError) initialReply
55 get :: (Message -> a) -> Builder a
56 get f = B $ \ s -> (f s, s)
58 modify :: (Message -> Message) -> Builder ()
59 modify f = B $ \ s -> ((), f s)
61 modifyHeader :: (Header -> Header) -> Builder ()
63 = modify $ \ s -> s { msgHeader = f (msgHeader s) }
65 addAnswer :: SomeRR -> Builder ()
67 = do anss <- get msgAnswers
68 unless (any (== rr) anss)
70 s { msgAnswers = msgAnswers s ++ [rr] }
72 addAnswerNonuniquely :: SomeRR -> Builder ()
73 addAnswerNonuniquely rr
75 s { msgAnswers = msgAnswers s ++ [rr] }
77 addAuthority :: SomeRR -> Builder ()
79 = do anss <- get msgAnswers
80 aths <- get msgAuthorities
81 unless (any (== rr) anss || any (== rr) aths)
83 s { msgAuthorities = msgAuthorities s ++ [rr] }
85 addAdditional :: SomeRR -> Builder ()
87 = do anss <- get msgAnswers
88 aths <- get msgAuthorities
89 adds <- get msgAdditionals
90 unless (any (== rr) anss || any (== rr) aths || any (== rr) adds)
92 s { msgAdditionals = msgAdditionals s ++ [rr] }
94 unauthorise :: Builder ()
95 unauthorise = modifyHeader (\ h -> h { hdIsAuthoritativeAnswer = False })
97 setResponseCode :: ResponseCode -> Builder ()
99 = modifyHeader (\ h -> h { hdResponseCode = code })