packages feed

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 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