{-# LANGUAGE OverloadedStrings #-}
module System.ZMQ4.Endpoint (
parseAttoEndpoint
, parseAttoTCPEndpoint
, parseAttoUDPEndpoint
, pTransport
, pEndpoint
, endpointAddr
, endpointPort
, endpointTransport
, newEndpoint
, newEndpointPort
, newEndpointAddrInfo
, newEndpointPortAddrInfo
, newTCPEndpoint
, newTCPEndpointAddrInfo
, newUDPEndpoint
, toAddrInfo
, Port
, Address
, Transport(..)
, Endpoint(..)) where
import Control.Applicative
import Data.Attoparsec.ByteString.Char8 as A
import qualified Data.ByteString.Char8 as B
import Data.Char (toLower)
import Network.Socket
import Network.SockAddr (showSockAddrBS)
type Port = Int
type Address = B.ByteString
data Transport = TCP | UDP | IPC | InProc | PGM | EPGM
deriving (Show, Eq, Ord)
data Endpoint = Endpoint Transport Address (Maybe Port)
deriving (Show, Eq, Ord)
pTransport :: Show a => a -> B.ByteString
pTransport x = B.pack $ map toLower $ show x
pEndpoint :: Endpoint -> B.ByteString
pEndpoint (Endpoint t a Nothing) = B.concat [pTransport t, "://" , a]
pEndpoint (Endpoint t a (Just p)) = B.concat [pTransport t, "://" , a, ":", B.pack $ show p]
newEndpoint :: Transport -> Address -> Endpoint
newEndpoint transport addr = newEndpointPort' transport addr Nothing
newEndpointAddrInfo :: Transport -> AddrInfo -> Endpoint
newEndpointAddrInfo transport addr = newEndpointPortAddrInfo' transport addr Nothing
newEndpointPort' :: Transport -> Address -> Maybe Port -> Endpoint
newEndpointPort' transport addr port = Endpoint transport addr port
newEndpointPortAddrInfo' :: Transport -> AddrInfo -> Maybe Port -> Endpoint
newEndpointPortAddrInfo' transport addr port = newEndpointPort' transport (showSockAddrBS $ addrAddress addr) port
newEndpointPort :: Transport -> Address -> Port -> Endpoint
newEndpointPort transport addr port = newEndpointPort' transport addr (Just port)
newEndpointPortAddrInfo :: Transport -> AddrInfo -> Port -> Endpoint
newEndpointPortAddrInfo transport addr port = newEndpointPortAddrInfo' transport addr (Just port)
newTCPEndpoint :: Address -> Port -> Endpoint
newTCPEndpoint addr port = newEndpointPort TCP addr port
newUDPEndpoint :: Address -> Port -> Endpoint
newUDPEndpoint addr port = newEndpointPort UDP addr port
newTCPEndpointAddrInfo :: AddrInfo -> Port -> Endpoint
newTCPEndpointAddrInfo addr port = newEndpointPortAddrInfo TCP addr port
toAddrInfo :: Endpoint -> IO [AddrInfo]
toAddrInfo (Endpoint _ a (Just p)) = getAddrInfo Nothing (Just $ B.unpack a) (Just $ show p)
toAddrInfo (Endpoint _ a _) = getAddrInfo Nothing (Just $ B.unpack a) Nothing
parseTransport :: Parser Transport
parseTransport = do
t <- A.takeWhile (/=':')
_ <- string "://"
r <- case t of
"tcp" -> pure TCP
"ipc" -> pure IPC
"inproc" -> pure InProc
"pgm" -> pure PGM
"epgm" -> pure EPGM
_ -> fail $ "Unknown transport" ++ (B.unpack t)
return r
parseAddress :: Parser Address
parseAddress = A.takeWhile(/=':')
parsePort :: Parser Port
parsePort = do
_ <- char ':'
d <- decimal
return d
parseEndpoint :: Parser Endpoint
parseEndpoint = Endpoint <$> parseTransport <*> parseAddress <*> optional parsePort
parseTCPEndpoint :: Parser Endpoint
parseTCPEndpoint = Endpoint <$> pure TCP <*> parseAddress <*> optional parsePort
parseUDPEndpoint :: Parser Endpoint
parseUDPEndpoint = Endpoint <$> pure UDP <*> parseAddress <*> optional parsePort
parseAttoEndpoint :: B.ByteString -> Either String Endpoint
parseAttoEndpoint = A.parseOnly parseEndpoint
parseAttoTCPEndpoint :: B.ByteString -> Either String Endpoint
parseAttoTCPEndpoint = A.parseOnly parseTCPEndpoint
parseAttoUDPEndpoint :: B.ByteString -> Either String Endpoint
parseAttoUDPEndpoint = A.parseOnly parseUDPEndpoint
endpointAddr :: Endpoint -> Address
endpointAddr (Endpoint _ a _) = a
endpointPort :: Endpoint -> Maybe Port
endpointPort (Endpoint _ _ p) = p
endpointTransport :: Endpoint -> Transport
endpointTransport (Endpoint t _ _) = t