-- | Decoders for DNS.
module Network.DNS.Decode (
    -- * Decoder
    decode
  , decodeMany
    -- ** Decoder for Each Part
  , decodeResourceRecord
  , decodeDNSHeader
  , decodeDNSFlags
  , decodeDomain
  , decodeMailbox
  ) where

import Network.DNS.Decode.Internal
import Network.DNS.Imports
import Network.DNS.StateBinary
import Network.DNS.Types

----------------------------------------------------------------

-- | Decoding DNS query or response.

decode :: ByteString -> Either DNSError DNSMessage
decode :: ByteString -> Either DNSError DNSMessage
decode ByteString
bs = (DNSMessage, PState) -> DNSMessage
forall a b. (a, b) -> a
fst ((DNSMessage, PState) -> DNSMessage)
-> Either DNSError (DNSMessage, PState)
-> Either DNSError DNSMessage
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> SGet DNSMessage
-> ByteString -> Either DNSError (DNSMessage, PState)
forall a. SGet a -> ByteString -> Either DNSError (a, PState)
runSGet SGet DNSMessage
getResponse ByteString
bs

-- | Parse many length-encoded DNS records, for example, from TCP traffic.

decodeMany :: ByteString -> Either DNSError ([DNSMessage], ByteString)
decodeMany :: ByteString -> Either DNSError ([DNSMessage], ByteString)
decodeMany ByteString
bs = do
    (([ByteString]
bss, PState
_), ByteString
leftovers) <- SGet [ByteString]
-> ByteString
-> Either DNSError (([ByteString], PState), ByteString)
forall a.
SGet a -> ByteString -> Either DNSError ((a, PState), ByteString)
runSGetWithLeftovers SGet [ByteString]
lengthEncoded ByteString
bs
    [DNSMessage]
msgs <- (ByteString -> Either DNSError DNSMessage)
-> [ByteString] -> Either DNSError [DNSMessage]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM ByteString -> Either DNSError DNSMessage
decode [ByteString]
bss
    ([DNSMessage], ByteString)
-> Either DNSError ([DNSMessage], ByteString)
forall (m :: * -> *) a. Monad m => a -> m a
return ([DNSMessage]
msgs, ByteString
leftovers)
  where
    -- Read a list of length-encoded lazy bytestrings
    lengthEncoded :: SGet [ByteString]
    lengthEncoded :: SGet [ByteString]
lengthEncoded = StateT PState (Parser ByteString) ByteString -> SGet [ByteString]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many (StateT PState (Parser ByteString) ByteString -> SGet [ByteString])
-> StateT PState (Parser ByteString) ByteString
-> SGet [ByteString]
forall a b. (a -> b) -> a -> b
$ do
      Int
len <- SGet Int
getInt16
      Int -> StateT PState (Parser ByteString) ByteString
getNByteString Int
len

-- | Decoding DNS flags.
decodeDNSFlags :: ByteString -> Either DNSError DNSFlags
decodeDNSFlags :: ByteString -> Either DNSError DNSFlags
decodeDNSFlags ByteString
bs = (DNSFlags, PState) -> DNSFlags
forall a b. (a, b) -> a
fst ((DNSFlags, PState) -> DNSFlags)
-> Either DNSError (DNSFlags, PState) -> Either DNSError DNSFlags
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> SGet DNSFlags -> ByteString -> Either DNSError (DNSFlags, PState)
forall a. SGet a -> ByteString -> Either DNSError (a, PState)
runSGet SGet DNSFlags
getDNSFlags ByteString
bs

-- | Decoding DNS header.
decodeDNSHeader :: ByteString -> Either DNSError DNSHeader
decodeDNSHeader :: ByteString -> Either DNSError DNSHeader
decodeDNSHeader ByteString
bs = (DNSHeader, PState) -> DNSHeader
forall a b. (a, b) -> a
fst ((DNSHeader, PState) -> DNSHeader)
-> Either DNSError (DNSHeader, PState) -> Either DNSError DNSHeader
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> SGet DNSHeader -> ByteString -> Either DNSError (DNSHeader, PState)
forall a. SGet a -> ByteString -> Either DNSError (a, PState)
runSGet SGet DNSHeader
getHeader ByteString
bs

-- | Decoding domain.
decodeDomain :: ByteString -> Either DNSError Domain
decodeDomain :: ByteString -> Either DNSError ByteString
decodeDomain ByteString
bs = (ByteString, PState) -> ByteString
forall a b. (a, b) -> a
fst ((ByteString, PState) -> ByteString)
-> Either DNSError (ByteString, PState)
-> Either DNSError ByteString
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> StateT PState (Parser ByteString) ByteString
-> ByteString -> Either DNSError (ByteString, PState)
forall a. SGet a -> ByteString -> Either DNSError (a, PState)
runSGet StateT PState (Parser ByteString) ByteString
getDomain ByteString
bs

-- | Decoding mailbox.
decodeMailbox :: ByteString -> Either DNSError Mailbox
decodeMailbox :: ByteString -> Either DNSError ByteString
decodeMailbox ByteString
bs = (ByteString, PState) -> ByteString
forall a b. (a, b) -> a
fst ((ByteString, PState) -> ByteString)
-> Either DNSError (ByteString, PState)
-> Either DNSError ByteString
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> StateT PState (Parser ByteString) ByteString
-> ByteString -> Either DNSError (ByteString, PState)
forall a. SGet a -> ByteString -> Either DNSError (a, PState)
runSGet StateT PState (Parser ByteString) ByteString
getMailbox ByteString
bs

-- | Decoding resource record.
decodeResourceRecord :: ByteString -> Either DNSError ResourceRecord
decodeResourceRecord :: ByteString -> Either DNSError ResourceRecord
decodeResourceRecord ByteString
bs = (ResourceRecord, PState) -> ResourceRecord
forall a b. (a, b) -> a
fst ((ResourceRecord, PState) -> ResourceRecord)
-> Either DNSError (ResourceRecord, PState)
-> Either DNSError ResourceRecord
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> SGet ResourceRecord
-> ByteString -> Either DNSError (ResourceRecord, PState)
forall a. SGet a -> ByteString -> Either DNSError (a, PState)
runSGet SGet ResourceRecord
getResourceRecord ByteString
bs