{-# LANGUAGE ScopedTypeVariables #-}
module Control.Pipe.Socket (
socketReader, socketWriter,
Handler, runSocketServer, runSocketClient
) where
import Control.Concurrent ( forkIO )
import qualified Control.Exception as CE
import Control.Monad ( forever, unless )
import Control.Monad.IO.Class ( MonadIO(..) )
import Control.Monad.Trans.Class ( lift )
import Data.ByteString.Char8 ( ByteString )
import qualified Data.ByteString.Char8 as B
import Network.Socket ( Socket )
import qualified Network.Socket as NS
import Network.Socket.ByteString ( sendAll, recv )
import Pipes ( Consumer, Producer, await, yield )
socketReader :: (MonadIO m) => Socket -> Producer ByteString m ()
socketReader socket = do
bin <- lift . liftIO $ recv socket 4096
unless (B.null bin) $ do
yield bin
socketReader socket
socketWriter :: (MonadIO m) => Socket -> Consumer ByteString m ()
socketWriter socket = forever $ do
bin <- await
lift . liftIO $ sendAll socket bin
type Handler r = Producer ByteString IO ()
-> Consumer ByteString IO ()
-> IO r
runSocketServer :: (MonadIO m) => Socket -> Handler () -> m ()
runSocketServer lsocket handler = liftIO $ forever $ do
(socket, _addr) <- NS.accept lsocket
_ <- forkIO $ CE.finally
(handler (socketReader socket) (socketWriter socket))
(NS.close socket)
return ()
runSocketClient :: (MonadIO m) => Socket -> Handler r -> m r
runSocketClient socket handler = liftIO $ do
handler (socketReader socket) (socketWriter socket)