packages feed

dns 0.1.2 → 0.2.0

raw patch · 10 files changed

+169/−148 lines, 10 filesdep +attoparsecdep +attoparsec-enumeratordep +blaze-builderdep −haskell98PVP ok

version bump matches the API change (PVP)

Dependencies added: attoparsec, attoparsec-enumerator, blaze-builder, enumerator, network-enumerator, random

Dependencies removed: haskell98

API changes (from Hackage documentation)

- Network.DNS.Resolver: ResolvConf :: FileOrNumericHost -> Int -> Int64 -> ResolvConf
+ Network.DNS.Resolver: ResolvConf :: FileOrNumericHost -> Int -> Integer -> ResolvConf
- Network.DNS.Resolver: resolvBufsize :: ResolvConf -> Int64
+ Network.DNS.Resolver: resolvBufsize :: ResolvConf -> Integer
- Network.DNS.Types: type Domain = String
+ Network.DNS.Types: type Domain = ByteString

Files

Network/DNS.hs view
@@ -2,8 +2,7 @@   Thread-safe DNS library written in Haskell.    Currently, only resolver side is supported. This code is written in-  Haskell, not using FFI. So, the \"-threaded\" option for GHC is not-  necessary.+  Haskell, not using FFI.    Sample code: 
Network/DNS/Internal.hs view
@@ -1,6 +1,7 @@ module Network.DNS.Internal where -import qualified Data.ByteString.Lazy.Char8 as L+import Data.ByteString (ByteString)+import qualified Data.ByteString.Char8 as BS import Data.Char import Data.IP import Data.Maybe@@ -10,7 +11,7 @@ {-|   Type for domain. -}-type Domain = String+type Domain = ByteString  ---------------------------------------------------------------- @@ -126,17 +127,17 @@ -} data RDATA = RD_NS Domain | RD_CNAME Domain | RD_MX Int Domain            | RD_SOA Domain Domain Int Int Int Int Int-           | RD_A IPv4 | RD_AAAA IPv6 | RD_TXT L.ByteString+           | RD_A IPv4 | RD_AAAA IPv6 | RD_TXT ByteString            | RD_OTH [Int] deriving (Eq)  instance Show RDATA where-  show (RD_NS dom) = dom-  show (RD_MX prf dom) = dom ++ " " ++ show prf-  show (RD_CNAME dom) = dom+  show (RD_NS dom) = BS.unpack dom+  show (RD_MX prf dom) = BS.unpack dom ++ " " ++ show prf+  show (RD_CNAME dom) = BS.unpack dom   show (RD_A a) = show a   show (RD_AAAA aaaa) = show aaaa-  show (RD_TXT txt) = L.unpack txt-  show (RD_SOA mn _ _ _ _ _ mi) = mn ++ " " ++ show mi+  show (RD_TXT txt) = BS.unpack txt+  show (RD_SOA mn _ _ _ _ _ mi) = BS.unpack mn ++ " " ++ show mi   show (RD_OTH is) = show is  ----------------------------------------------------------------
Network/DNS/Lookup.hs view
@@ -9,7 +9,7 @@   ) where  import Control.Applicative-import qualified Data.ByteString.Lazy.Char8 as L+import Data.ByteString (ByteString) import Data.IP import Data.Maybe import Network.DNS.Resolver as DNS@@ -61,23 +61,22 @@ lookupAAAAviaMX :: Resolver -> Domain -> IO (Maybe [IPv6]) lookupAAAAviaMX rlv dom = lookupXviaMX rlv dom (lookupAAAA rlv) -lookupXviaMX :: Resolver -> Domain -> (Domain -> IO (Maybe [a])) -> IO (Maybe [a])+lookupXviaMX :: Show a => Resolver -> Domain -> (Domain -> IO (Maybe [a])) -> IO (Maybe [a]) lookupXviaMX rlv dom func = do     mdps <- lookupMX rlv dom     maybe (return Nothing) lookup' mdps   where-    lookup' dps = do-        as <- catMaybes <$> mapM (func . fst) dps-        case as of-          []  -> return Nothing-          ass -> return $ Just (concat ass)+    lookup' dps = check . catMaybes <$> mapM (func . fst) dps+    check as = case as of+        []  -> Nothing+        ass -> Just (concat ass)  ----------------------------------------------------------------  {-|   Resolving 'String' by 'TXT'. -}-lookupTXT :: Resolver -> Domain -> IO (Maybe [L.ByteString])+lookupTXT :: Resolver -> Domain -> IO (Maybe [ByteString]) lookupTXT rlv dom = toTXT <$> DNS.lookup rlv dom TXT   where     toTXT = maybe Nothing (Just . map unTag)
Network/DNS/Query.hs view
@@ -1,13 +1,18 @@ module Network.DNS.Query (composeQuery) where -import qualified Data.ByteString.Lazy.Char8 as L-import Data.Char+import qualified Data.ByteString.Lazy.Char8 as BL (ByteString)+import qualified Data.ByteString  as BS (unpack)+import qualified Data.ByteString.Char8 as BS (length, split, null) import Network.DNS.StateBinary import Network.DNS.Internal+import Data.Monoid +(+++) :: Monoid a => a -> a -> a+(+++) = mappend+ ---------------------------------------------------------------- -composeQuery :: Int -> [Question] -> L.ByteString+composeQuery :: Int -> [Question] -> BL.ByteString composeQuery idt qs = runSPut (encodeQuery qry)   where     hdr = header defaultQuery@@ -22,21 +27,19 @@ ----------------------------------------------------------------  encodeQuery :: DNSFormat -> SPut-encodeQuery fmt = do-  let hdr = header fmt-      qs = question fmt-  encodeHeader hdr-  encodeQuestion qs-  return ()+encodeQuery fmt = encodeHeader hdr+              +++ encodeQuestion qs+  where+    hdr = header fmt+    qs = question fmt  encodeHeader :: DNSHeader -> SPut-encodeHeader hdr = do-    encodeIdentifier $ identifier hdr-    encodeFlags $ flags hdr-    decodeQdCount $ qdCount hdr-    decodeAnCount $ anCount hdr-    decodeNsCount $ nsCount hdr-    decodeArCount $ arCount hdr+encodeHeader hdr = encodeIdentifier (identifier hdr)+               +++ encodeFlags (flags hdr)+               +++ decodeQdCount (qdCount hdr)+               +++ decodeAnCount (anCount hdr)+               +++ decodeNsCount (nsCount hdr)+               +++ decodeArCount (arCount hdr)   where     encodeIdentifier = putInt16     decodeQdCount = putInt16@@ -48,31 +51,24 @@ encodeFlags _ = put16 0x0100 -- xxx  encodeQuestion :: [Question] -> SPut-encodeQuestion qs = do-  let q = head qs-      dom = qname q-      typ = qtype q-  encodeDomain dom-  putInt16 . typeToInt $ typ-  put16 1+encodeQuestion qs = encodeDomain dom+                +++ putInt16 (typeToInt typ)+                +++ put16 1+  where+    q = head qs+    dom = qname q+    typ = qtype q  ----------------------------------------------------------------  encodeDomain :: Domain -> SPut-encodeDomain dom = do-    let ss = split '.' dom-        ls = map length ss-    mapM_ encodeSubDomain $ zip ls ss-    put8 0+encodeDomain dom = foldr ((+++) . encodeSubDomain) (put8 0) $ zip ls ss   where-    encodeSubDomain (len,sub) = do-      putInt8 len-      mapM_ (putInt8 . ord) sub+    ss = filter (not . BS.null) $ BS.split '.' dom+    ls = map BS.length ss -split :: Char -> String -> [String]-split _ "" = []-split c cs-  | null rest = s : split c rest-  | otherwise = s : split c (tail rest)+encodeSubDomain :: (Int, Domain) -> SPut+encodeSubDomain (len,sub) = putInt8 len+                        +++ foldr ((+++) . put8) mempty ss   where-    (s,rest) = break (c ==) cs+    ss = BS.unpack sub
Network/DNS/Resolver.hs view
@@ -38,8 +38,9 @@ import Network.Socket hiding (send, sendTo, recv, recvFrom) import Network.Socket.ByteString.Lazy import Prelude hiding (lookup)-import Random+import System.Random import System.Timeout+import Network.Socket.Enumerator  ---------------------------------------------------------------- @@ -55,7 +56,7 @@ data ResolvConf = ResolvConf {     resolvInfo :: FileOrNumericHost   , resolvTimeout :: Int-  , resolvBufsize :: Int64+  , resolvBufsize :: Integer }  {-|@@ -79,7 +80,7 @@ data ResolvSeed = ResolvSeed {     addrInfo :: AddrInfo   , rsTimeout :: Int-  , rsBufsize :: Int64+  , rsBufsize :: Integer }  {-|@@ -89,7 +90,7 @@     genId   :: IO Int   , dnsSock :: Socket   , dnsTimeout :: Int-  , dnsBufsize :: Int64+  , dnsBufsize :: Integer }  ----------------------------------------------------------------@@ -169,7 +170,8 @@ lookupRaw rlv dom typ = do     seqno <- genId rlv     sendAll sock (composeQuery seqno [q])-    (>>= check seqno) <$> timeout tm (parseResponse <$> recv sock bufsize)+    let responseEnum = enumSocket bufsize sock+    (>>= check seqno) <$> timeout tm (parseResponse responseEnum responseIter)   where     sock = dnsSock rlv     bufsize = dnsBufsize rlv
Network/DNS/Response.hs view
@@ -1,18 +1,25 @@-module Network.DNS.Response (parseResponse) where+{-# LANGUAGE OverloadedStrings #-} +module Network.DNS.Response (responseIter, parseResponse) where++import Control.Applicative import Control.Monad import Data.Bits-import qualified Data.ByteString.Lazy.Char8 as L-import Data.Char+import qualified Data.ByteString.Char8 as BS import Data.IP import Data.Maybe import Network.DNS.Internal import Network.DNS.StateBinary+import Data.Enumerator (Enumerator, Iteratee, run_, ($$))+import Data.ByteString (ByteString) -----------------------------------------------------------------+responseIter :: Iteratee ByteString IO (DNSFormat, PState)+responseIter = runSGet decodeResponse -parseResponse :: L.ByteString -> DNSFormat-parseResponse = runSGet decodeResponse+parseResponse :: Enumerator ByteString IO (a,b)+              -> Iteratee ByteString IO (a,b)+              -> IO a+parseResponse enum iter = fst <$> run_ (enum $$ iter)  ---------------------------------------------------------------- @@ -27,16 +34,15 @@ ----------------------------------------------------------------  decodeFlags :: SGet DNSFlags-decodeFlags = do-  flgs <- get16-  return $ DNSFlags (getQorR flgs)-                    (getOpcode flgs)-                    (getAuthAnswer flgs)-                    (getTrunCation flgs)-                    (getRecDesired flgs)-                    (getRecAvailable flgs)-                    (getRcode flgs)+decodeFlags = toFlags <$> get16   where+    toFlags flgs = DNSFlags (getQorR flgs)+                            (getOpcode flgs)+                            (getAuthAnswer flgs)+                            (getTrunCation flgs)+                            (getRecDesired flgs)+                            (getRecAvailable flgs)+                            (getRcode flgs)     getQorR w = if testBit w 15 then QR_Response else QR_Query     getOpcode w = toEnum $ fromIntegral $ shiftR w 11 .&. 0x0f     getAuthAnswer w = testBit w 10@@ -100,7 +106,7 @@ decodeRData CNAME _ = RD_CNAME <$> decodeDomain decodeRData TXT len = (RD_TXT . ignoreLength) <$> getNByteString len   where-    ignoreLength = L.tail+    ignoreLength = BS.tail decodeRData A len  = (RD_A . toIPv4) <$> getNBytes len decodeRData AAAA len  = (RD_AAAA . toIPv6 . combine) <$> getNBytes len   where@@ -139,17 +145,14 @@             let offset = n * 256 + d             fromMaybe (error $ "decodeDomain: " ++ show offset) <$> pop offset           else do-            hs <- decodeString n+            hs <- getNByteString n             ds <- decodeDomain-            let dom = hs ++ "." ++ ds+            let dom = hs `BS.append` "." `BS.append` ds             push pos dom             return dom   where     getValue c = c .&. 0x3f     isPointer c = testBit c 7 && testBit c 6--decodeString :: Int -> SGet String-decodeString n = map chr <$> getNBytes n  ignoreClass :: SGet () ignoreClass = () <$ get16
Network/DNS/StateBinary.hs view
@@ -1,71 +1,94 @@ module Network.DNS.StateBinary where +import Blaze.ByteString.Builder+import Control.Applicative import Control.Monad.State-import Data.Binary.Get-import Data.Binary.Put-import qualified Data.ByteString.Lazy.Char8 as L-import Data.Char+import Data.Attoparsec+import Data.Attoparsec.Enumerator+import Data.ByteString (ByteString)+import qualified Data.ByteString as BS (unpack)+import qualified Data.ByteString.Lazy as BL (ByteString)+import Data.Enumerator (Iteratee)+import Data.Int import Data.IntMap (IntMap) import qualified Data.IntMap as IM (insert, lookup, empty) import Data.Word import Network.DNS.Types-import Prelude hiding (lookup)+import Prelude hiding (lookup, take)  ---------------------------------------------------------------- -type SGet = StateT PState Get+type SPut = Write -type PState = IntMap Domain+put8 :: Word8 -> SPut+put8  = writeWord8 -----------------------------------------------------------------+put16 :: Word16 -> SPut+put16 = writeWord16be -(<$>) :: (Monad m) => (a -> b) -> m a -> m b-(<$>) = liftM+put32 :: Word32 -> SPut+put32 = writeWord32be -(<$) :: (Monad m) => b -> m a -> m b-x <$ y = y >> return x+putInt8 :: Int -> SPut+putInt8  = writeInt8 . fromIntegral -(<*>) :: (Monad m) => m (a -> b) -> m a -> m b-(<*>) = ap+putInt16 :: Int -> SPut+putInt16 = writeInt16be . fromIntegral -(<*) :: (Monad m) => m a -> m b -> m a-(<*) ma mb = do-    a <- ma-    mb-    return a+putInt32 :: Int -> SPut+putInt32 = writeInt32be . fromIntegral  ---------------------------------------------------------------- -type SPut = Put+type SGet = StateT PState Parser -put8 :: Word8 -> SPut-put8  = putWord8+data PState = PState {+    psDomain :: IntMap Domain+  , psPosition :: Int+  } -put16 :: Word16 -> SPut-put16 = putWord16be+---------------------------------------------------------------- -put32 :: Word32 -> SPut-put32 = putWord32be+getPosition :: SGet Int+getPosition = psPosition <$> get -putInt8 :: Int -> SPut-putInt8  = put8  . fromIntegral+addPosition :: Int -> SGet ()+addPosition n = do+    PState dom pos <- get+    put $ PState dom (pos + n) -putInt16 :: Int -> SPut-putInt16 = put16 . fromIntegral+push :: Int -> Domain -> SGet ()+push n d = do+    PState dom pos <- get+    put $ PState (IM.insert n d dom) pos -putInt32 :: Int -> SPut-putInt32 = put32 . fromIntegral+pop :: Int -> SGet (Maybe Domain)+pop n = IM.lookup n . psDomain <$> get  ----------------------------------------------------------------  get8 :: SGet Word8-get8  = lift getWord8+get8  = lift anyWord8 <* addPosition 1  get16 :: SGet Word16-get16 = lift getWord16be+get16 = lift getWord16be <* addPosition 2+  where+    word8' = fromIntegral <$> anyWord8+    getWord16be = do+        a <- word8'+        b <- word8'+        return $ a * 256 + b  get32 :: SGet Word32-get32 = lift getWord32be+get32 = lift getWord32be <* addPosition 4+  where+    word8' = fromIntegral <$> anyWord8+    getWord32be = do+        a <- word8'+        b <- word8'+        c <- word8'+        d <- word8'+        return $ a * 1677721 + b * 65536 + c * 256 + d  getInt8 :: SGet Int getInt8 = fromIntegral <$> get8@@ -78,32 +101,21 @@  ---------------------------------------------------------------- -getPosition :: SGet Int-getPosition = fromIntegral <$> lift bytesRead- getNBytes :: Int -> SGet [Int] getNBytes len = toInts <$> getNByteString len   where-    toInts = map ord . L.unpack--getNByteString :: Int -> SGet L.ByteString-getNByteString len = lift . getLazyByteString . fromIntegral $ len--------------------------------------------------------------------push :: Int -> Domain -> SGet ()-push n d = modify (IM.insert n d)+    toInts = map fromIntegral . BS.unpack -pop :: Int -> SGet (Maybe Domain)-pop n = IM.lookup n <$> get+getNByteString :: Int -> SGet ByteString+getNByteString n = lift (take n) <* addPosition n  ---------------------------------------------------------------- -initialState :: IntMap Domain-initialState = IM.empty+initialState :: PState+initialState = PState IM.empty 0 -runSGet :: SGet DNSFormat -> L.ByteString -> DNSFormat-runSGet res bs = fst $ runGet (runStateT res initialState) bs+runSGet :: SGet a -> Iteratee ByteString IO (a, PState)+runSGet parser = iterParser (runStateT parser initialState) -runSPut :: Put -> L.ByteString-runSPut = runPut+runSPut :: SPut -> BL.ByteString+runSPut = toLazyByteString . fromWrite
Network/DNS/Types.hs view
@@ -3,11 +3,17 @@ -}  module Network.DNS.Types (+  -- * Domain     Domain+  -- * TYPE   , TYPE (..), intToType, typeToInt, toType+  -- * DNS Format   , DNSFormat, header, question, answer, authority, additional+  -- * DNS Header   , DNSHeader, identifier, flags, qdCount, anCount, nsCount, arCount+  -- * DNS Flags   , DNSFlags, qOrR, opcode, authAnswer, trunCation, recDesired, recAvailable, rcode+  -- * DNS Body   , QorR (..)   , OPCODE (..)   , RCODE (..)
Test.hs view
@@ -2,7 +2,6 @@  module Test where -import Data.IP import Data.List import Network.DNS as DNS import Test.Framework (defaultMain, testGroup, Test)@@ -27,7 +26,7 @@ test_lookupA = do     rs <- makeResolvSeed defaultResolvConf     withResolver rs $ \resolver ->-        DNS.lookupA resolver "www.mew.org" ?= Just [toIPv4 [202,232,15,101]]+        DNS.lookupA resolver "www.mew.org" ?= Just ["202.232.15.101"]  (??=) :: (Ord a, Show a) => IO (Maybe [a]) -> [a] -> IO () a ??= bs = do@@ -41,7 +40,7 @@     rs <- makeResolvSeed defaultResolvConf     withResolver rs $ \resolver -> do         DNS.lookupAAAA resolver "mew.org" ?= Nothing-        DNS.lookupAAAA resolver "www.mew.org" ?= Just [read "2001:240:11e:c00::101"]+        DNS.lookupAAAA resolver "www.mew.org" ?= Just ["2001:240:11e:c00::101"]  test_lookupTXT :: IO () test_lookupTXT = do@@ -53,13 +52,13 @@ test_lookupAviaMX = do     rs <- makeResolvSeed defaultResolvConf     withResolver rs $ \resolver ->-        DNS.lookupAviaMX resolver "mixi.jp" ??= [read "202.32.29.4", read "202.32.29.5"]+        DNS.lookupAviaMX resolver "mixi.jp" ??= ["202.32.29.4", "202.32.29.5"]  test_lookupAviaCNAME :: IO () test_lookupAviaCNAME = do     rs <- makeResolvSeed defaultResolvConf     withResolver rs $ \resolver ->-        DNS.lookupA resolver "foundry1.hongo.wide.ad.jp" ??= [read "203.178.135.1", read "203.178.138.230"]+        DNS.lookupA resolver "ghs.google.com" ??= ["72.14.203.121"]  main :: IO () main = defaultMain tests
dns.cabal view
@@ -1,5 +1,5 @@ Name:                   dns-Version:                0.1.2+Version:                0.2.0 Author:                 Kazu Yamamoto <kazu@iij.ad.jp> Maintainer:             Kazu Yamamoto <kazu@iij.ad.jp> License:                BSD3@@ -27,15 +27,19 @@                         Network.DNS.Query                         Network.DNS.Response   if impl(ghc >= 7)-    Build-Depends:      base >= 4 && < 5, haskell98,+    Build-Depends:      base >= 4 && < 5,                         binary, iproute,-                        containers, mtl, bytestring,-                        network >= 2.3+                        containers, mtl, bytestring, random,+                        network >= 2.3, blaze-builder,+                        attoparsec, enumerator, attoparsec-enumerator,+                        network-enumerator   else-    Build-Depends:      base >= 4 && < 5, haskell98,+    Build-Depends:      base >= 4 && < 5,                         binary, iproute,-                        containers, mtl, bytestring,-                        network, network-bytestring+                        containers, mtl, bytestring, random,+                        network, network-bytestring, blaze-builder,+                        attoparsec, enumerator, attoparsec-enumerator,+                        network-enumerator Source-Repository head   Type:                 git   Location:             git://github.com/kazu-yamamoto/dns.git