network-run 0.0.1 → 0.1.0
raw patch · 4 files changed
+85/−32 lines, 4 files
Files
- Network/Run/Core.hs +48/−0
- Network/Run/TCP.hs +11/−30
- Network/Run/UDP.hs +23/−0
- network-run.cabal +3/−2
+ Network/Run/Core.hs view
@@ -0,0 +1,48 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE CPP #-}++module Network.Run.Core (+ runClient+ , resolve+ , openServerSocket+ ) where++import qualified Control.Exception as E+import Control.Monad (when)+import Network.Socket++runClient :: SocketType -> String -> String -> (Socket -> SockAddr -> IO a) -> IO a+runClient socketType host port client = withSocketsDo $ do+ addr <- resolve socketType (Just host) port False+ let sockAddr = addrAddress addr+#if MIN_VERSION_network(3,1,1)+ E.bracket (open addr) (\sock -> gracefulClose sock 5000)+ (\sock -> client sock sockAddr)+#else+ E.bracket (open addr) close $ \sock -> client sock sockAddr+#endif+ where+ open addr = do+ sock <- openSocket addr+ when (socketType == Stream) $ connect sock $ addrAddress addr+ return sock++resolve :: SocketType -> Maybe HostName -> ServiceName -> Bool -> IO AddrInfo+resolve socketType mhost port passive =+ head <$> getAddrInfo (Just hints) mhost (Just port)+ where+ hints = defaultHints {+ addrSocketType = socketType+ , addrFlags = if passive then [AI_PASSIVE] else []+ }++openSocket :: AddrInfo -> IO Socket+openSocket addr = socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr)++openServerSocket :: AddrInfo -> IO Socket+openServerSocket addr = do+ sock <- openSocket addr+ setSocketOption sock ReuseAddr 1+ withFdSocket sock $ setCloseOnExecIfNeeded+ bind sock $ addrAddress addr+ return sock
Network/Run/TCP.hs view
@@ -12,47 +12,28 @@ import Control.Monad (forever, void) import Network.Socket +import Network.Run.Core+ -- | Running a TCP client with a connected socket.-runTCPClient :: HostName -> ServiceName -> (Socket -> IO a) -> IO a-runTCPClient host port client = withSocketsDo $ do- addr <- resolve-#if MIN_VERSION_network(3,1,1)- E.bracket (open addr) (\sock -> gracefulClose sock 5000) client-#else- E.bracket (open addr) close client-#endif+runTCPClient :: String -> String -> (Socket -> IO a) -> IO a+runTCPClient host port client = runClient Stream host port client' where- resolve = do- let hints = defaultHints { addrSocketType = Stream }- head <$> getAddrInfo (Just hints) (Just host) (Just port)- open addr = do- sock <- socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr)- connect sock $ addrAddress addr- return sock+ client' sock _peer = client sock -- | Running a TCP server with an accepted socket and its peer name.-runTCPServer :: Maybe HostName -> ServiceName -> (Socket -> SockAddr -> IO a) -> IO a+runTCPServer :: Maybe HostName -> ServiceName -> (Socket -> IO a) -> IO a runTCPServer mhost port server = withSocketsDo $ do- addr <- resolve+ addr <- resolve Stream mhost port True E.bracket (open addr) close loop where- resolve = do- let hints = defaultHints {- addrFlags = [AI_PASSIVE]- , addrSocketType = Stream- }- head <$> getAddrInfo (Just hints) mhost (Just port) open addr = do- sock <- socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr)- setSocketOption sock ReuseAddr 1- withFdSocket sock $ setCloseOnExecIfNeeded- bind sock $ addrAddress addr+ sock <- openServerSocket addr listen sock 1024 return sock loop sock = forever $ do- (conn, peer) <- accept sock+ (conn, _peer) <- accept sock #if MIN_VERSION_network(3,1,1)- void $ forkFinally (server conn peer) (const $ gracefulClose conn 5000)+ void $ forkFinally (server conn) (const $ gracefulClose conn 5000) #else- void $ forkFinally (server conn peer) (const $ close conn)+ void $ forkFinally (server conn) (const $ close conn) #endif
+ Network/Run/UDP.hs view
@@ -0,0 +1,23 @@+-- | Simple functions to run UDP clients and servers.+module Network.Run.UDP (+ runUDPClient+ , runUDPServer+ ) where++import qualified Control.Exception as E+import Network.Socket++import Network.Run.Core++-- | Running a UDP client with a socket.+-- The client action takes a socket and+-- server's socket address.+-- They should be used with 'sendTo'.+runUDPClient :: String -> String -> (Socket -> SockAddr -> IO a) -> IO a+runUDPClient = runClient Datagram++-- | Running a UDP server with an open socket.+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
network-run.cabal view
@@ -1,5 +1,5 @@ name: network-run-version: 0.0.1+version: 0.1.0 synopsis: Simple network runner library description: Simple functions to run network clients and servers. -- bug-reports:@@ -14,7 +14,8 @@ library exposed-modules: Network.Run.TCP- -- other-modules:+ Network.Run.UDP+ other-modules: Network.Run.Core -- other-extensions: build-depends: base >= 4 && < 5 , network >= 3.1.0