module Network.CoAP.Internal ( createEndpoint , createOpts ) where import Network.DNS.Lookup import Network.DNS.Resolver import Data.ByteString.Char8 import Network.URI import Data.IP import Network.Socket import Network.CoAP.Types createIPv4Endpoint :: [IPv4] -> PortNumber -> Endpoint createIPv4Endpoint (addr:_) port = SockAddrInet port (toHostAddress addr) createIPv6Endpoint :: [IPv6] -> PortNumber -> Endpoint createIPv6Endpoint (addr:_) port = SockAddrInet6 port 0 (toHostAddress6 addr) 0 stripBrackets :: String -> String stripBrackets [] = [] stripBrackets [']'] = [] stripBrackets ('[':rest) = stripBrackets rest stripBrackets (h:t) = h:stripBrackets t parsePort :: String -> Int parsePort [] = 5683 parsePort (':':rest) = parsePort rest parsePort s = read s createEndpoint :: URI -> IO Endpoint createEndpoint uri = do let (Just auth) = uriAuthority uri hname = stripBrackets (uriRegName auth) port = fromIntegral (parsePort (uriPort auth)) if isIPv6address hname then return (createIPv6Endpoint [read hname :: IPv6] port) else if isIPv4address hname then return (createIPv4Endpoint [read hname :: IPv4] port) else resolveEndpoint hname port resolveEndpoint :: String -> PortNumber -> IO Endpoint resolveEndpoint hostName port = do let hname = pack hostName rs <- makeResolvSeed defaultResolvConf ipv6Addr <- withResolver rs (`lookupAAAA` hname) case ipv6Addr of Left _ -> do ipv4Addr <- withResolver rs (`lookupA` hname) case ipv4Addr of Left _ -> error "Unable to resolve hostname" Right addr -> return (createIPv4Endpoint addr port) Right addr -> return (createIPv6Endpoint addr port) parsePath :: String -> String parsePath [] = [] parsePath ('/':rest) = rest parsePath any = any createOpts :: URI -> [Option] createOpts uri = let (Just auth) = uriAuthority uri path = parsePath (uriPath uri) port = parsePort (uriPort auth) in [UriPath (pack path), UriPort port]