-- |
-- Copyright: (C) 2014 EURL Tweag
--
{-# LANGUAGE OverloadedStrings #-}
module Network.Transport.ZMQ.Internal
( bindRandomPort
, authManager
, closeZeroLinger
)
where
import Control.Monad ( forever )
import Control.Monad.Catch
( mask
, finally
)
import Control.Concurrent.Async
import Data.ByteString ( ByteString )
import Data.List.NonEmpty ( NonEmpty(..) )
import System.ZMQ4
-- | Bind socket to the random port.
bindRandomPort :: Socket t
-> String -- ^ Address
-> IO Int
bindRandomPort sock addr = do
bind sock $ addr++":0"
fmap (read . last . split (/=':')) $ lastEndpoint sock
-- | One possible password authentification
authManager :: Context -> ByteString -> ByteString -> IO (Async ())
authManager ctx user pass = do
req <- socket ctx Rep
bind req "inproc://zeromq.zap.01"
mask $ \restore ->
async $ (restore $ forever $ do
("1.0":requestId:_domain:_ipAddress:_identity:mech:xs) <- receiveMulti req
case mech of
"PLAIN" -> case xs of
(pass':user':_)
| user == user' && pass == pass' -> do
sendMulti req $ "1.0" :| [requestId, "200", "OK", "", ""]
| otherwise -> sendMulti req $ "1.0" :| [requestId, "400", "Credentials are not implemented", "", ""]
_ -> sendMulti req $ "1.0" :| [requestId, "500", "Method not implemented", "", ""]
_ -> sendMulti req $ "1.0" :| [requestId, "500", "Method not implemented", "", ""])
`finally` (close req)
-- | Close socket immideately.
closeZeroLinger :: Socket a -> IO ()
closeZeroLinger sock = do
setLinger (restrict (0::Int)) sock
close sock
split :: (Char -> Bool) -> String -> [String]
split f = go
where
go [] = []
go s = case span f s of
(p,[]) -> [p]
(p,_:ss) -> p:go ss