Skip to content

Instantly share code, notes, and snippets.

@chrisdone
Created February 5, 2020 15:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chrisdone/8b3622539bef18c24ed7fcb595b5d7db to your computer and use it in GitHub Desktop.
Save chrisdone/8b3622539bef18c24ed7fcb595b5d7db to your computer and use it in GitHub Desktop.
{-# LANGUAGE ScopedTypeVariables #-}
-- | A ResourceT-based way to use connections with conduit.
module Data.Conduit.Network.Resource where
import qualified Network.Socket as NS
import Control.Exception
import Control.Monad.IO.Class
import Control.Monad.Trans.Resource
import Data.Streaming.Network
import Data.Streaming.Network.Internal
import Network.Socket.ByteString (sendAll)
-- | Allocate a TCP client that will be close automatically by the
-- resource monad.
allocateTCPClient ::
(MonadIO m, MonadResource m)
=> ClientSettings
-> m (Either IOException (ReleaseKey, AppData))
allocateTCPClient (ClientSettings port host addrFamily readBufferSize) = do
result <- allocate (try allocator) freer
case result of
(releaseKey, Right appData) -> pure (Right (releaseKey, appData))
(_, Left ioexception) -> pure (Left ioexception)
where
allocator = do
(s, address) <- liftIO (getSocketFamilyTCP host port addrFamily)
pure
AppData
{ appRead' = safeRecv s readBufferSize
, appWrite' = sendAll s
, appSockAddr' = address
, appLocalAddr' = Nothing
, appCloseConnection' = NS.close s
, appRawSocket' = Just s
}
freer :: Either IOException AppData -> IO ()
freer = either (const (pure ())) appCloseConnection'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment