module Network.Run.UDP (
runUDPClient
, runUDPServer
, runUDPServerFork
) where
import Control.Concurrent (forkIO, forkFinally)
import qualified Control.Exception as E
import Control.Monad (forever, void)
import Data.ByteString (ByteString)
import Network.Socket
import Network.Socket.ByteString
import Network.Run.Core
runUDPClient :: HostName -> ServiceName -> (Socket -> SockAddr -> IO a) -> IO a
runUDPClient :: forall a.
HostName -> HostName -> (Socket -> SockAddr -> IO a) -> IO a
runUDPClient HostName
host HostName
port Socket -> SockAddr -> IO a
client = forall a. IO a -> IO a
withSocketsDo forall a b. (a -> b) -> a -> b
$ do
AddrInfo
addr <- SocketType -> Maybe HostName -> HostName -> Bool -> IO AddrInfo
resolve SocketType
Datagram (forall a. a -> Maybe a
Just HostName
host) HostName
port Bool
False
let sockAddr :: SockAddr
sockAddr = AddrInfo -> SockAddr
addrAddress AddrInfo
addr
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
E.bracket (AddrInfo -> IO Socket
openSocket AddrInfo
addr) Socket -> IO ()
close forall a b. (a -> b) -> a -> b
$ \Socket
sock -> Socket -> SockAddr -> IO a
client Socket
sock SockAddr
sockAddr
runUDPServer :: Maybe HostName -> ServiceName -> (Socket -> IO a) -> IO a
runUDPServer :: forall a. Maybe HostName -> HostName -> (Socket -> IO a) -> IO a
runUDPServer Maybe HostName
mhost HostName
port Socket -> IO a
server = forall a. IO a -> IO a
withSocketsDo forall a b. (a -> b) -> a -> b
$ do
AddrInfo
addr <- SocketType -> Maybe HostName -> HostName -> Bool -> IO AddrInfo
resolve SocketType
Datagram Maybe HostName
mhost HostName
port Bool
True
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
E.bracket (AddrInfo -> IO Socket
openServerSocket AddrInfo
addr) Socket -> IO ()
close Socket -> IO a
server
runUDPServerFork :: [HostName] -> ServiceName -> (Socket -> ByteString -> IO ()) -> IO ()
runUDPServerFork :: [HostName] -> HostName -> (Socket -> ByteString -> IO ()) -> IO ()
runUDPServerFork [] HostName
_ Socket -> ByteString -> IO ()
_ = forall (m :: * -> *) a. Monad m => a -> m a
return ()
runUDPServerFork (HostName
h:[HostName]
hs) HostName
port Socket -> ByteString -> IO ()
server = do
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (IO () -> IO ThreadId
forkIO forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall {a}. HostName -> IO a
run) [HostName]
hs
forall {a}. HostName -> IO a
run HostName
h
where
run :: HostName -> IO a
run HostName
host = forall a. Maybe HostName -> HostName -> (Socket -> IO a) -> IO a
runUDPServer (forall a. a -> Maybe a
Just HostName
host) HostName
port forall a b. (a -> b) -> a -> b
$ \Socket
lsock -> forall (f :: * -> *) a b. Applicative f => f a -> f b
forever forall a b. (a -> b) -> a -> b
$ do
(ByteString
bs0,SockAddr
peeraddr) <- Socket -> Int -> IO (ByteString, SockAddr)
recvFrom Socket
lsock Int
2048
let family :: Family
family = case SockAddr
peeraddr of
SockAddrInet{} -> Family
AF_INET
SockAddrInet6{} -> Family
AF_INET6
SockAddr
_ -> forall a. HasCallStack => HostName -> a
error HostName
"family"
hints :: AddrInfo
hints = AddrInfo
defaultHints {
addrSocketType :: SocketType
addrSocketType = SocketType
Datagram
, addrFamily :: Family
addrFamily = Family
family
, addrFlags :: [AddrInfoFlag]
addrFlags = [AddrInfoFlag
AI_PASSIVE]
}
AddrInfo
addr <- forall a. [a] -> a
head forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe AddrInfo -> Maybe HostName -> Maybe HostName -> IO [AddrInfo]
getAddrInfo (forall a. a -> Maybe a
Just AddrInfo
hints) forall a. Maybe a
Nothing (forall a. a -> Maybe a
Just HostName
port)
Socket
s <- AddrInfo -> IO Socket
openServerSocket AddrInfo
addr
Socket -> SockAddr -> IO ()
connect Socket
s SockAddr
peeraddr
forall (f :: * -> *) a. Functor f => f a -> f ()
void forall a b. (a -> b) -> a -> b
$ forall a. IO a -> (Either SomeException a -> IO ()) -> IO ThreadId
forkFinally (Socket -> ByteString -> IO ()
server Socket
s ByteString
bs0) (\Either SomeException ()
_ -> Socket -> IO ()
close Socket
s)