Skip to content

Commit

Permalink
withResolver'.
Browse files Browse the repository at this point in the history
  • Loading branch information
kazu-yamamoto committed Feb 16, 2014
1 parent 7ef7c4c commit e872445
Showing 1 changed file with 43 additions and 20 deletions.
63 changes: 43 additions & 20 deletions Network/DNS/Resolver.hs
Expand Up @@ -8,7 +8,7 @@ module Network.DNS.Resolver (
-- ** Intermediate data type for resolver -- ** Intermediate data type for resolver
, ResolvSeed, makeResolvSeed , ResolvSeed, makeResolvSeed
-- ** Type and function for resolver -- ** Type and function for resolver
, Resolver(..), withResolver , Resolver(..), withResolver, withResolvers
-- ** Looking up functions -- ** Looking up functions
, lookup, lookupAuth, lookupRaw , lookup, lookupAuth, lookupRaw
) where ) where
Expand Down Expand Up @@ -142,18 +142,37 @@ makeAddrInfo addr = do
-- argument. 'withResolver' should be passed to 'forkIO'. For -- argument. 'withResolver' should be passed to 'forkIO'. For
-- examples, see "Network.DNS.Lookup". -- examples, see "Network.DNS.Lookup".
withResolver :: ResolvSeed -> (Resolver -> IO a) -> IO a withResolver :: ResolvSeed -> (Resolver -> IO a) -> IO a
withResolver seed func = do withResolver seed func = bracket (openSocket seed) sClose $ \sock -> do
let ai = addrInfo seed connectSocket sock seed
sock <- socket (addrFamily ai) (addrSocketType ai) (addrProtocol ai) func $ makeResolver seed sock
connect sock (addrAddress ai)
let resolv = Resolver { withResolvers :: [ResolvSeed] -> ([Resolver] -> IO a) -> IO a
genId = getRandom withResolvers seeds func = bracket openSockets closeSockets $ \socks -> do
, dnsSock = sock mapM_ (uncurry connectSocket) $ zip socks seeds
, dnsTimeout = rsTimeout seed let resolvs = map (uncurry makeResolver) $ zip seeds socks
, dnsRetry = rsRetry seed func resolvs
, dnsBufsize = rsBufsize seed where
} openSockets = mapM openSocket seeds
func resolv `finally` sClose sock closeSockets = mapM sClose

openSocket :: ResolvSeed -> IO Socket
openSocket seed = socket (addrFamily ai) (addrSocketType ai) (addrProtocol ai)
where
ai = addrInfo seed

connectSocket :: Socket -> ResolvSeed -> IO ()
connectSocket sock seed = connect sock (addrAddress ai)
where
ai = addrInfo seed

makeResolver :: ResolvSeed -> Socket -> Resolver
makeResolver seed sock = Resolver {
genId = getRandom
, dnsSock = sock
, dnsTimeout = rsTimeout seed
, dnsRetry = rsRetry seed
, dnsBufsize = rsBufsize seed
}


getRandom :: IO Int getRandom :: IO Int
getRandom = getStdRandom (randomR (0,65535)) getRandom = getStdRandom (randomR (0,65535))
Expand Down Expand Up @@ -244,20 +263,24 @@ lookupRaw rlv dom typ = do
seqno <- genId rlv seqno <- genId rlv
let query = composeQuery seqno [q] let query = composeQuery seqno [q]
checkSeqno = check seqno checkSeqno = check seqno
loop query checkSeqno 0 loop query checkSeqno 0 False
where where
loop query checkSeqno cnt loop query checkSeqno cnt mismatch
| cnt == retry = return $ Left TimeoutExpired | cnt == retry = do
let ret | mismatch = SequenceNumberMismatch
| otherwise = TimeoutExpired
return $ Left ret
| otherwise = do | otherwise = do
sendAll sock query sendAll sock query
response <- timeout tm (receive sock) response <- timeout tm (receive sock)
case response of case response of
Nothing -> loop query checkSeqno (cnt + 1) Nothing -> loop query checkSeqno (cnt + 1) False
Just res -> do Just res -> do
let valid = checkSeqno res let valid = checkSeqno res
ret | valid = Right res if valid then
| otherwise = Left SequenceNumberMismatch return $ Right res
return ret else
loop query checkSeqno (cnt + 1) False
sock = dnsSock rlv sock = dnsSock rlv
tm = dnsTimeout rlv tm = dnsTimeout rlv
retry = dnsRetry rlv retry = dnsRetry rlv
Expand Down

0 comments on commit e872445

Please sign in to comment.