network-run 0.2.1 → 0.2.2
raw patch · 2 files changed
+39/−2 lines, 2 filesdep +bytestring
Dependencies added: bytestring
Files
- Network/Run/UDP.hs +37/−1
- network-run.cabal +2/−1
Network/Run/UDP.hs view
@@ -2,10 +2,15 @@ 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 @@ -19,8 +24,39 @@ let sockAddr = addrAddress addr E.bracket (openSocket addr) close $ \sock -> client sock sockAddr --- | Running a UDP server with an open socket.+-- | Running a UDP server with an open socket in a single Haskell thread. runUDPServer :: Maybe HostName -> ServiceName -> (Socket -> IO a) -> IO a runUDPServer mhost port server = withSocketsDo $ do addr <- resolve Datagram mhost port True E.bracket (openServerSocket addr) close server++-- | Running a UDP server with a connected socket in each Haskell thread.+-- The first request is given to the server.+-- Suppose that the server is serving on __addrS:portS__ and+-- a client connects to the service from __addrC:portC__.+-- A connected socket is created by binding to __*:portS__ and+-- connecting to __addrC:portC__,+-- resulting in __(UDP,addrS:portS,addrC:portC)__ where+-- __addrS__ is given magically.+-- This approach is fragile due to NAT rebidings.+runUDPServerFork :: [HostName] -> ServiceName -> (Socket -> ByteString -> IO ()) -> IO ()+runUDPServerFork [] _ _ = return ()+runUDPServerFork (h:hs) port server = do+ mapM_ (forkIO . run) hs+ run h+ where+ run host = runUDPServer (Just host) port $ \lsock -> forever $ do+ (bs0,peeraddr) <- recvFrom lsock 2048+ let family = case peeraddr of+ SockAddrInet{} -> AF_INET+ SockAddrInet6{} -> AF_INET6+ _ -> error "family"+ hints = defaultHints {+ addrSocketType = Datagram+ , addrFamily = family+ , addrFlags = [AI_PASSIVE]+ }+ addr <- head <$> getAddrInfo (Just hints) Nothing (Just port)+ s <- openServerSocket addr+ connect s peeraddr+ void $ forkFinally (server s bs0) (\_ -> close s)
network-run.cabal view
@@ -1,5 +1,5 @@ name: network-run-version: 0.2.1+version: 0.2.2 synopsis: Simple network runner library description: Simple functions to run network clients and servers. -- bug-reports:@@ -19,6 +19,7 @@ -- other-extensions: build-depends: base >= 4 && < 5 , network >= 3.1.0+ , bytestring -- hs-source-dirs: default-language: Haskell2010