pipes-network 0.5.0.0 → 0.5.1.0
raw patch · 5 files changed
+133/−92 lines, 5 filesdep ~network-simplePVP ok
version bump matches the API change (PVP)
Dependency ranges changed: network-simple
API changes (from Hackage documentation)
+ Control.Proxy.TCP: instance Data Timeout
+ Control.Proxy.TCP: instance Eq Timeout
+ Control.Proxy.TCP: instance Exception Timeout
+ Control.Proxy.TCP: instance Show Timeout
+ Control.Proxy.TCP: instance Typeable Timeout
+ Control.Proxy.TCP: withSocketsDo :: IO a -> IO a
+ Control.Proxy.TCP.Safe: withSocketsDo :: IO a -> IO a
Files
- NEWS +8/−1
- pipes-network.cabal +8/−10
- src/Control/Proxy/Network/Internal.hs +0/−46
- src/Control/Proxy/TCP.hs +64/−18
- src/Control/Proxy/TCP/Safe.hs +53/−17
NEWS view
@@ -1,6 +1,13 @@+# Version 0.5.1.0++* Re-export `Network.Socket.withSocketsDo`.++* Use TCP `send` and `recv` as eported by network-simple-0.2.1.0.++ # Version 0.5.0.0 - * Removed `Control.Proxy.TCP.Sync` and `Control.Proxy.TCP.Safe.Sync`.+* Removed `Control.Proxy.TCP.Sync` and `Control.Proxy.TCP.Safe.Sync`. # Version 0.4.0.1
pipes-network.cabal view
@@ -1,5 +1,5 @@ name: pipes-network-version: 0.5.0.0+version: 0.5.1.0 license: BSD3 license-file: LICENSE copyright: Copyright (c) Renzo Carbonara 2012-2013, Paolo Capriotti 2012-2012.@@ -19,13 +19,13 @@ . This package is organized using the following namespaces: .- * "Control.Proxy.TCP" exports @pipes@ proxies and functions to deal with TCP- connections. Such proxies don't acquire nor release new resources within a- proxy pipeline.+ * "Control.Proxy.TCP" exports 'Control.Proxy.Proxy's and functions for+ establishing and using TCP connections. .- * "Control.Proxy.TCP.Safe" exports @pipes-safe@ proxies and functions to deal- with TCP connections. Such proxies may safely acquire and release resources- within a pipeline, using the facilities provided by the @pipes-safe@ package.+ * "Control.Proxy.TCP.Safe" is similar to "Control.Proxy.TCP", except+ the exported 'Control.Proxy.Proxy's themselves can obtain new network+ resources safely by using the facilities providied by the @pipes-safe@+ package. . See the @NEWS@ file in the source distribution to learn about any important changes between version.@@ -40,15 +40,13 @@ base (==4.*), bytestring (>=0.9.2.1), network,- network-simple (>=0.2.0.1 && <0.3),+ network-simple (>=0.2.1 && <0.3), pipes (>=3.2 && <3.4), pipes-safe (>=1.1 && <1.3), transformers (>=0.2 && <0.4) exposed-modules: Control.Proxy.TCP Control.Proxy.TCP.Safe- other-modules:- Control.Proxy.Network.Internal ghc-options: -Wall -fno-warn-unused-do-bind test-suite simple
− src/Control/Proxy/Network/Internal.hs
@@ -1,46 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# OPTIONS_HADDOCK hide #-}---- | This module doesn't belong to this namespace, but really, I don't--- know where it belongs. Suggestions welcome.------ There's a @data-timeout@ package, maybe we should depend on that.--module Control.Proxy.Network.Internal (- Timeout(..)- , recv- , send- ) where--import qualified Data.ByteString as B-import qualified Control.Exception as E-import Data.Typeable (Typeable)-import qualified Network.Socket as NS-import qualified Network.Socket.ByteString----- |Exception thrown when a timeout has elapsed.-data Timeout- = Timeout String -- ^Timeouted with an additional explanatory message.- deriving (Eq, Show, Typeable)--instance E.Exception Timeout where--------------------------------------------------------------------------------------- | Read up to a limited number of bytes from a socket.------ Returns `Nothing` if the remote end closed the connection or EOF was reached.-recv :: NS.Socket -> Int -> IO (Maybe B.ByteString)-recv sock nbytes = do- bs <- Network.Socket.ByteString.recv sock nbytes- if B.null bs- then return Nothing- else return (Just bs)-{-# INLINE recv #-}---- | Writes the given bytes to the socket.-send :: NS.Socket -> B.ByteString -> IO ()-send = Network.Socket.ByteString.sendAll-{-# INLINE send #-}
src/Control/Proxy/TCP.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE DeriveDataTypeable #-}+ -- | This module exports functions that allow you to safely use 'NS.Socket' -- resources acquired and released outside a 'P.Proxy' pipeline. --@@ -35,32 +37,67 @@ , nsocketReadTimeoutS , socketWriteTimeoutD - -- * Exports+ -- * Note to Windows users+ -- $windows-users+ , NS.withSocketsDo++ -- * Types , S.HostPreference(..) , Timeout(..) ) where +import qualified Control.Exception as E import Control.Monad.Trans.Class import qualified Control.Proxy as P import qualified Control.Proxy.Trans.Either as PE-import Control.Proxy.Network.Internal import qualified Data.ByteString as B+import Data.Data (Data,Typeable) import Data.Monoid import qualified Network.Socket as NS import qualified Network.Simple.TCP as S import System.Timeout (timeout) + -------------------------------------------------------------------------------- +-- $windows-users+--+-- If you are running Windows, then you /must/ call 'NS.withSocketsDo', just+-- once, right at the beginning of your program. That is, change your program's+-- 'main' function from:+--+-- @+-- main = do+-- print \"Hello world\"+-- -- rest of the program...+-- @+--+-- To:+--+-- @+-- main = 'NS.withSocketsDo' $ do+-- print \"Hello world\"+-- -- rest of the program...+-- @+--+-- If you don't do this, your networking code won't work and you will get many+-- unexpected errors at runtime. If you use an operating system other than+-- Windows then you don't need to do this, but it is harmless to do it, so it's+-- recommended that you do for portability reasons.++--------------------------------------------------------------------------------+ -- $client-side -- -- Here's how you could run a TCP client: ----- > connect "www.example.org" "80" $ \(connectionSocket, remoteAddr) -> do--- > putStrLn $ "Connection established to " ++ show remoteAddr--- > -- now you may use connectionSocket as you please within this scope.--- > -- possibly with any of the socketReadS, nsocketReadS or socketWriteD--- > -- proxies explained below.+-- @+-- 'S.connect' \"www.example.org\" \"80\" $ \(connectionSocket, remoteAddr) -> do+-- putStrLn $ \"Connection established to \" ++ show remoteAddr+-- -- Now you may use connectionSocket as you please within this scope,+-- -- possibly using 'socketReadS', 'socketWriteD' or similar proxies+-- -- explained below.+-- @ -------------------------------------------------------------------------------- @@ -69,11 +106,13 @@ -- Here's how you can run a TCP server that handles in different threads each -- incoming connection to port @8000@ at IPv4 address @127.0.0.1@: ----- > serve (Host "127.0.0.1") "8000" $ \(connectionSocket, remoteAddr) -> do--- > putStrLn $ "TCP connection established from " ++ show remoteAddr--- > -- now you may use connectionSocket as you please within this scope.--- > -- possibly with any of the socketReadS, nsocketReadS or socketWriteD--- > -- proxies explained below.+-- @+-- 'S.serve' ('S.Host' \"127.0.0.1\") \"8000\" $ \(connectionSocket, remoteAddr) -> do+-- putStrLn $ \"TCP connection established from \" ++ show remoteAddr+-- -- Now you may use connectionSocket as you please within this scope,+-- -- possibly using 'socketReadS', 'socketWriteD' or similar proxies+-- -- explained below.+-- @ -- -- If you need more control on the way your server runs, then you can use more -- advanced functions such as 'listen', 'accept' and 'acceptFork'.@@ -101,7 +140,7 @@ -> () -> P.Producer p B.ByteString IO () socketReadS nbytes sock () = P.runIdentityP loop where loop = do- mbs <- lift (recv sock nbytes)+ mbs <- lift (S.recv sock nbytes) case mbs of Just bs -> P.respond bs >> loop Nothing -> return ()@@ -115,7 +154,7 @@ -> Int -> P.Server p Int B.ByteString IO () nsocketReadS sock = P.runIdentityK loop where loop nbytes = do- mbs <- lift (recv sock nbytes)+ mbs <- lift (S.recv sock nbytes) case mbs of Just bs -> P.respond bs >>= loop Nothing -> return ()@@ -132,7 +171,7 @@ socketWriteD sock = P.runIdentityK loop where loop x = do a <- P.request x- lift (send sock a)+ lift (S.send sock a) P.respond a >>= loop {-# INLINABLE socketWriteD #-} @@ -157,7 +196,7 @@ -> () -> P.Producer (PE.EitherP Timeout p) B.ByteString IO () socketReadTimeoutS wait nbytes sock () = loop where loop = do- mmbs <- lift (timeout wait (recv sock nbytes))+ mmbs <- lift (timeout wait (S.recv sock nbytes)) case mmbs of Just (Just bs) -> P.respond bs >> loop Just Nothing -> return ()@@ -175,7 +214,7 @@ -> Int -> P.Server (PE.EitherP Timeout p) Int B.ByteString IO () nsocketReadTimeoutS wait sock = loop where loop nbytes = do- mmbs <- lift (timeout wait (recv sock nbytes))+ mmbs <- lift (timeout wait (S.recv sock nbytes)) case mmbs of Just (Just bs) -> P.respond bs >>= loop Just Nothing -> return ()@@ -194,11 +233,18 @@ socketWriteTimeoutD wait sock = loop where loop x = do a <- P.request x- m <- lift (timeout wait (send sock a))+ m <- lift (timeout wait (S.send sock a)) case m of Just () -> P.respond a >>= loop Nothing -> PE.throw ex ex = Timeout $ "socketWriteTimeoutD: " <> show wait <> " microseconds." {-# INLINABLE socketWriteTimeoutD #-} +-------------------------------------------------------------------------------- +-- |Exception thrown when a time limit has elapsed.+data Timeout+ = Timeout String -- ^Timeouted with an additional explanatory message.+ deriving (Eq, Show, Data, Typeable)++instance E.Exception Timeout where
src/Control/Proxy/TCP/Safe.hs view
@@ -37,6 +37,11 @@ nsocketReadS, socketWriteD, + -- * Note to Windows users+ -- $windows-users+ NS.withSocketsDo,++ -- * Exports S.HostPreference(..), Timeout(..)@@ -45,8 +50,8 @@ import Control.Concurrent (ThreadId) import Control.Monad import qualified Control.Proxy as P-import Control.Proxy.Network.Internal import qualified Control.Proxy.Safe as P+import Control.Proxy.TCP (Timeout(..)) import qualified Data.ByteString as B import Data.Monoid import qualified Network.Socket as NS@@ -55,15 +60,44 @@ -------------------------------------------------------------------------------- +-- $windows-users+--+-- If you are running Windows, then you /must/ call 'NS.withSocketsDo', just+-- once, right at the beginning of your program. That is, change your program's+-- 'main' function from:+--+-- @+-- main = do+-- print \"Hello world\"+-- -- rest of the program...+-- @+--+-- To:+--+-- @+-- main = 'NS.withSocketsDo' $ do+-- print \"Hello world\"+-- -- rest of the program...+-- @+--+-- If you don't do this, your networking code won't work and you will get many+-- unexpected errors at runtime. If you use an operating system other than+-- Windows then you don't need to do this, but it is harmless to do it, so it's+-- recommended that you do for portability reasons.++--------------------------------------------------------------------------------+ -- $client-side -- -- Here's how you could run a TCP client: ----- > connect "www.example.org" "80" $ \(connectionSocket, remoteAddr) -> do--- > tryIO . putStrLn $ "Connection established to " ++ show remoteAddr--- > -- now you may use connectionSocket as you please within this scope.--- > -- possibly with any of the socketReadS, nsocketReadS or socketWriteD--- > -- proxies explained below.+-- @+-- 'connect' \"www.example.org\" \"80\" $ \(connectionSocket, remoteAddr) -> do+-- putStrLn $ \"Connection established to \" ++ show remoteAddr+-- -- Now you may use connectionSocket as you please within this scope,+-- -- possibly using 'socketReadS', 'socketWriteD' or similar proxies+-- -- explained below.+-- @ -- -- You might instead prefer the simpler but less general solutions offered by -- 'connectReadS' and 'connectWriteD', so check those too.@@ -160,11 +194,13 @@ -- Here's how you can run a TCP server that handles in different threads each -- incoming connection to port @8000@ at IPv4 address @127.0.0.1@: ----- > serve (Host "127.0.0.1") "8000" $ \(connectionSocket, remoteAddr) -> do--- > tryIO . putStrLn $ "TCP connection established from " ++ show remoteAddr--- > -- now you may use connectionSocket as you please within this scope.--- > -- possibly with any of the socketReadS, nsocketReadS or socketWriteD--- > -- proxies explained below.+-- @+-- 'serve' ('Host' \"127.0.0.1\") \"8000\" $ \(connectionSocket, remoteAddr) -> do+-- putStrLn $ \"TCP connection established from \" ++ show remoteAddr+-- -- Now you may use connectionSocket as you please within this scope,+-- -- possibly using 'socketReadS', 'socketWriteD' or similar proxies+-- -- explained below.+-- @ -- -- You might instead prefer the simpler but less general solutions offered by -- 'serveReadS' and 'serveWriteD', so check those too. On the other hand,@@ -364,13 +400,13 @@ -> () -> P.Producer (P.ExceptionP p) B.ByteString P.SafeIO () socketReadS Nothing nbytes sock () = loop where loop = do- mbs <- P.tryIO (recv sock nbytes)+ mbs <- P.tryIO (S.recv sock nbytes) case mbs of Just bs -> P.respond bs >> loop Nothing -> return () socketReadS (Just wait) nbytes sock () = loop where loop = do- mmbs <- P.tryIO (timeout wait (recv sock nbytes))+ mmbs <- P.tryIO (timeout wait (S.recv sock nbytes)) case mmbs of Just (Just bs) -> P.respond bs >> loop Just Nothing -> return ()@@ -387,13 +423,13 @@ -> Int -> P.Server (P.ExceptionP p) Int B.ByteString P.SafeIO () nsocketReadS Nothing sock = loop where loop nbytes = do- mbs <- P.tryIO (recv sock nbytes)+ mbs <- P.tryIO (S.recv sock nbytes) case mbs of Just bs -> P.respond bs >>= loop Nothing -> return () nsocketReadS (Just wait) sock = loop where loop nbytes = do- mbs <- P.tryIO (timeout wait (recv sock nbytes))+ mbs <- P.tryIO (timeout wait (S.recv sock nbytes)) case mbs of Just (Just bs) -> P.respond bs >>= loop Just Nothing -> return ()@@ -417,12 +453,12 @@ socketWriteD Nothing sock = loop where loop x = do a <- P.request x- P.tryIO (send sock a)+ P.tryIO (S.send sock a) P.respond a >>= loop socketWriteD (Just wait) sock = loop where loop x = do a <- P.request x- m <- P.tryIO (timeout wait (send sock a))+ m <- P.tryIO (timeout wait (S.send sock a)) case m of Just () -> P.respond a >>= loop Nothing -> P.throw ex