{-# LANGUAGE RecordWildCards #-}
module Network.AMQP.Connection
( Connection
, SSL.SSLContext
, ConnectionParams(..)
, connectionClose
, connectTo
, connectionGet
, connectionPut
) where
import Network.Socket (PortNumber)
import qualified OpenSSL.Session as SSL
import qualified OpenSSL as SSL
import qualified System.IO.Streams as Streams
import qualified System.IO.Streams.SSL as Streams hiding (connect)
import System.IO.Streams (InputStream, OutputStream)
import qualified Network.Socket as N
import Network.AMQP.Prelude
data Connection = Connection
{ connClose :: IO ()
, connOS :: OutputStream ByteString
, connIS :: InputStream ByteString
}
data ConnectionParams = ConnectionParams
{ connectionHostname :: String
, connectionPort :: PortNumber
, connectionSecure :: Maybe SSL.SSLContext
}
connectionClose :: Connection -> IO ()
connectionClose = connClose
connectionPut :: Connection -> ByteString -> IO ()
connectionPut Connection{..} bs = do
Streams.write (Just bs) connOS
Streams.write (Just mempty) connOS
connectionGet :: Connection -> Int -> IO ByteString
connectionGet Connection{..} n = Streams.readExactly n connIS
connectTo :: ConnectionParams -> IO Connection
connectTo ConnectionParams{..} = do
ais <- N.getAddrInfo (Just N.defaultHints { N.addrFlags = [N.AI_ADDRCONFIG, N.AI_NUMERICSERV], N.addrSocketType = N.Stream })
(Just connectionHostname) (Just $ show connectionPort)
let addr = head ais
s <- N.socket (N.addrFamily addr) N.Stream N.defaultProtocol
N.connect s (N.addrAddress addr)
case connectionSecure of
Nothing -> do
(connIS,connOS) <- Streams.socketToStreams s
let connClose = N.close s
pure Connection {..}
Just ctx -> SSL.withOpenSSL $ do
ssl <- SSL.connection ctx s
SSL.setTlsextHostName ssl connectionHostname
SSL.connect ssl
(connIS,connOS) <- Streams.sslToStreams ssl
let connClose = do
SSL.shutdown ssl SSL.Unidirectional
N.close s
pure Connection {..}