module Data.Conduit.Network.UDP
(
Message (..)
, sourceSocket
, sinkSocket
, sinkAllSocket
, sinkToSocket
, sinkAllToSocket
, HostPreference (..)
, bindPort
, getSocket
) where
import Data.Conduit
import Network.Socket (AddrInfo, SockAddr, Socket)
import qualified Network.Socket as NS
import Network.Socket.ByteString (recvFrom, send, sendAll, sendTo, sendAllTo)
import Data.ByteString (ByteString)
import Control.Monad.IO.Class (MonadIO (liftIO))
import Control.Monad (void)
import Control.Monad.Trans.Class (lift)
import Data.Conduit.Network.Utils (HostPreference)
import qualified Data.Conduit.Network.Utils as Utils
data Message = Message { msgData :: !ByteString
, msgSender :: !SockAddr
}
sourceSocket :: MonadIO m => Socket -> Int -> Producer m Message
sourceSocket socket len = loop
where
loop = do
(bs, addr) <- lift $ liftIO $ recvFrom socket len
yield (Message bs addr) >> loop
sinkSocket :: MonadIO m => Socket -> Consumer ByteString m ()
sinkSocket = sinkSocketHelper (\sock bs -> void $ send sock bs)
sinkAllSocket :: MonadIO m => Socket -> Consumer ByteString m ()
sinkAllSocket = sinkSocketHelper sendAll
sinkToSocket :: MonadIO m => Socket -> Consumer Message m ()
sinkToSocket = sinkSocketHelper (\sock (Message bs addr) -> void $ sendTo sock bs addr)
sinkAllToSocket :: MonadIO m => Socket -> Consumer Message m ()
sinkAllToSocket = sinkSocketHelper (\sock (Message bs addr) -> sendAllTo sock bs addr)
getSocket :: String -> Int -> IO (Socket, AddrInfo)
getSocket host' port' = Utils.getSocket host' port' NS.Datagram
bindPort :: Int -> HostPreference -> IO Socket
bindPort p s = Utils.bindPort p s NS.Datagram
sinkSocketHelper :: MonadIO m => (Socket -> a -> IO ())
-> Socket
-> Consumer a m ()
sinkSocketHelper act socket = loop
where
loop = await >>= maybe
(return ())
(\a -> lift (liftIO $ act socket a) >> loop)