{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE RankNTypes #-}
module Tox.Conduit.Network where
import Control.Monad (void)
import Control.Monad.IO.Class (MonadIO, liftIO)
import Data.Binary (Binary)
import qualified Data.ByteString as BS
import Data.Conduit (ConduitT, await, yield)
import qualified Data.Conduit.List as CL
import qualified Network.Socket as Socket
import qualified Network.Socket.ByteString as SocketBS
import Tox.Network.Core.HostAddress (HostAddress (..))
import Tox.Network.Core.NodeInfo (NodeInfo (..))
import Tox.Network.Core.Packet (Packet (..))
import Tox.Network.Core.PortNumber (PortNumber (..))
import Tox.Network.Core.SocketAddress (SocketAddress (..))
import Tox.Network.Core.TransportProtocol (TransportProtocol (..))
toSockAddr :: SocketAddress -> Socket.SockAddr
toSockAddr :: SocketAddress -> SockAddr
toSockAddr (SocketAddress (IPv4 HostAddress
addr) (PortNumber Word16
port)) =
PortNumber -> HostAddress -> SockAddr
Socket.SockAddrInet (Word16 -> PortNumber
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word16
port) HostAddress
addr
toSockAddr (SocketAddress (IPv6 HostAddress6
addr) (PortNumber Word16
port)) =
PortNumber
-> HostAddress -> HostAddress6 -> HostAddress -> SockAddr
Socket.SockAddrInet6 (Word16 -> PortNumber
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word16
port) HostAddress
0 HostAddress6
addr HostAddress
0
fromSockAddr :: Socket.SockAddr -> Maybe SocketAddress
fromSockAddr :: SockAddr -> Maybe SocketAddress
fromSockAddr (Socket.SockAddrInet PortNumber
port HostAddress
addr) =
SocketAddress -> Maybe SocketAddress
forall a. a -> Maybe a
Just (SocketAddress -> Maybe SocketAddress)
-> SocketAddress -> Maybe SocketAddress
forall a b. (a -> b) -> a -> b
$ HostAddress -> PortNumber -> SocketAddress
SocketAddress (HostAddress -> HostAddress
IPv4 HostAddress
addr) (PortNumber -> PortNumber
forall a b. (Integral a, Num b) => a -> b
fromIntegral PortNumber
port)
fromSockAddr (Socket.SockAddrInet6 PortNumber
port HostAddress
_ HostAddress6
addr HostAddress
_) =
SocketAddress -> Maybe SocketAddress
forall a. a -> Maybe a
Just (SocketAddress -> Maybe SocketAddress)
-> SocketAddress -> Maybe SocketAddress
forall a b. (a -> b) -> a -> b
$ HostAddress -> PortNumber -> SocketAddress
SocketAddress (HostAddress6 -> HostAddress
IPv6 HostAddress6
addr) (PortNumber -> PortNumber
forall a b. (Integral a, Num b) => a -> b
fromIntegral PortNumber
port)
fromSockAddr SockAddr
_ = Maybe SocketAddress
forall a. Maybe a
Nothing
udpSource :: MonadIO m => Socket.Socket -> ConduitT i (Socket.SockAddr, BS.ByteString) m ()
udpSource :: Socket -> ConduitT i (SockAddr, ByteString) m ()
udpSource Socket
sock = do
(ByteString
bs, SockAddr
addr) <- IO (ByteString, SockAddr)
-> ConduitT i (SockAddr, ByteString) m (ByteString, SockAddr)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (ByteString, SockAddr)
-> ConduitT i (SockAddr, ByteString) m (ByteString, SockAddr))
-> IO (ByteString, SockAddr)
-> ConduitT i (SockAddr, ByteString) m (ByteString, SockAddr)
forall a b. (a -> b) -> a -> b
$ Socket -> Int -> IO (ByteString, SockAddr)
SocketBS.recvFrom Socket
sock Int
4096
(SockAddr, ByteString) -> ConduitT i (SockAddr, ByteString) m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
yield (SockAddr
addr, ByteString
bs)
Socket -> ConduitT i (SockAddr, ByteString) m ()
forall (m :: * -> *) i.
MonadIO m =>
Socket -> ConduitT i (SockAddr, ByteString) m ()
udpSource Socket
sock
udpSink :: MonadIO m => Socket.Socket -> ConduitT (Socket.SockAddr, BS.ByteString) o m ()
udpSink :: Socket -> ConduitT (SockAddr, ByteString) o m ()
udpSink Socket
sock = ((SockAddr, ByteString) -> m ())
-> ConduitT (SockAddr, ByteString) o m ()
forall (m :: * -> *) a o.
Monad m =>
(a -> m ()) -> ConduitT a o m ()
CL.mapM_ (((SockAddr, ByteString) -> m ())
-> ConduitT (SockAddr, ByteString) o m ())
-> ((SockAddr, ByteString) -> m ())
-> ConduitT (SockAddr, ByteString) o m ()
forall a b. (a -> b) -> a -> b
$ \(SockAddr
addr, ByteString
bs) ->
IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ IO Int -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (IO Int -> IO ()) -> IO Int -> IO ()
forall a b. (a -> b) -> a -> b
$ Socket -> ByteString -> SockAddr -> IO Int
SocketBS.sendTo Socket
sock ByteString
bs SockAddr
addr