module Network where
import Control.Exception.Extensible as E
import Control.Monad (forever, unless)
import Control.Monad.Trans (MonadIO(..), lift)
import Control.Proxy (Consumer, Producer, Proxy, request, respond, runIdentityP)
import Data.ByteString as B (ByteString, null)
import Network.BSD (getProtocolNumber)
import Network.Socket (Family(AF_INET), Socket, SockAddr(..), SocketOption(ReuseAddr), SocketType(Stream), bindSocket, iNADDR_ANY, sClose, maxListenQueue, listen, socket, setSocketOption)
import Network.Socket.ByteString (sendAll, recv)
listenOn :: Int
-> IO Socket
listenOn portm = do
proto <- getProtocolNumber "tcp"
E.bracketOnError
(socket AF_INET Stream proto)
(sClose)
(\sock -> do
setSocketOption sock ReuseAddr 1
bindSocket sock (SockAddrInet (fromIntegral portm) iNADDR_ANY)
listen sock (max 1024 maxListenQueue)
return sock
)
socketReader :: (Proxy p, MonadIO m) =>
Socket
-> (() -> Producer p ByteString m ())
socketReader sock () = runIdentityP go
where
go = do
bs <- lift (liftIO $ recv sock 4096)
unless (B.null bs) $
respond bs >> go
socketWriter :: (Proxy p, MonadIO m) =>
Socket
-> (() -> Consumer p ByteString m ())
socketWriter sock () =
runIdentityP $
forever $
do bs <- request ()
lift $ liftIO (sendAll sock bs)