packages feed

pipes-network 0.2.0.0 → 0.3.0.0

raw patch · 7 files changed

+202/−109 lines, 7 filesdep ~pipes-safePVP ok

version bump matches the API change (PVP)

Dependency ranges changed: pipes-safe

API changes (from Hackage documentation)

- Control.Proxy.TCP: socketWriteD :: Proxy p => Socket -> x -> p x ByteString x ByteString IO r
+ Control.Proxy.TCP: socketWriteD :: Proxy p => Socket -> x -> p x ByteString x ByteString IO ()
- Control.Proxy.TCP: socketWriteTimeoutD :: Proxy p => Int -> Socket -> x -> (EitherP Timeout p) x ByteString x ByteString IO r
+ Control.Proxy.TCP: socketWriteTimeoutD :: Proxy p => Int -> Socket -> x -> (EitherP Timeout p) x ByteString x ByteString IO ()
- Control.Proxy.TCP.Safe: socketWriteD :: Proxy p => Maybe Int -> Socket -> x -> (ExceptionP p) x ByteString x ByteString SafeIO r
+ Control.Proxy.TCP.Safe: socketWriteD :: Proxy p => Maybe Int -> Socket -> x -> (ExceptionP p) x ByteString x ByteString SafeIO ()

Files

NEWS view
@@ -1,3 +1,14 @@+# Version 0.3.0.0++* Quietly stop writing or reading bytes from a TCP socket if a+  “Broken Pipe” error happens, indicating that the remote end+  already closed the connection. Previously, a `ResourceVanished`+  exception was thrown.++* All the `*Write*D` proxies now return `()` if the remote end+  closed the connection.++ # Version 0.2.0.0  * Depend on network-simple 0.2@@ -12,6 +23,7 @@ * Split many of the non-pipes-related TCP utilities to the own   `network-simple` package. * Depend on `network-simple` and re-export its functions.+  # Version 0.1.0.1 
pipes-network.cabal view
@@ -1,5 +1,5 @@ name:               pipes-network-version:            0.2.0.0+version:            0.3.0.0 license:            BSD3 license-file:       LICENSE copyright:          Copyright (c) Renzo Carbonara 2012-2013, Paolo Capriotti 2012-2012.@@ -42,7 +42,7 @@         network,         network-simple (>=0.2 && <0.3),         pipes          (>=3.1 && <3.3),-        pipes-safe     (>=1.0),+        pipes-safe     (>=1.1 && <1.2),         transformers   (>=0.2 && <0.4)     exposed-modules:         Control.Proxy.TCP
src/Control/Proxy/Network/Internal.hs view
@@ -7,11 +7,17 @@ -- There's a @data-timeout@ package, maybe we should depend on that.  module Control.Proxy.Network.Internal (-  Timeout(..)+    Timeout(..)+  , recv+  , send   ) where +import qualified Data.ByteString               as B import qualified Control.Exception             as E import           Data.Typeable                 (Typeable)+import qualified GHC.IO.Exception              as Eg+import qualified Network.Socket                as NS+import qualified Network.Socket.ByteString   -- |Exception thrown when a timeout has elapsed.@@ -20,3 +26,29 @@   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 (“Broken Pipe”) or+-- EOF was reached.+recv :: NS.Socket -> Int -> IO (Maybe B.ByteString)+recv sock nbytes =+    E.handle (\Eg.IOError{Eg.ioe_type=Eg.ResourceVanished} -> return Nothing)+             (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.+--+-- Returns `False` if the remote end closed the connection (“Broken Pipe”),+-- otherwise `True`.+send :: NS.Socket -> B.ByteString -> IO Bool+send sock bs =+    E.handle (\Eg.IOError{Eg.ioe_type=Eg.ResourceVanished} -> return False)+             (do Network.Socket.ByteString.sendAll sock bs+                 return True)+{-# INLINE send #-}
src/Control/Proxy/TCP.hs view
@@ -48,7 +48,6 @@ import qualified Data.ByteString                as B import           Data.Monoid import qualified Network.Socket                 as NS-import           Network.Socket.ByteString      (recv, sendAll) import qualified Network.Simple.TCP             as S import           System.Timeout                 (timeout) @@ -94,13 +93,18 @@ -- If the remote peer closes its side of the connection, this proxy returns. socketReadS   :: P.Proxy p-  => Int                -- ^Maximum number of bytes to receive at once.+  => Int                -- ^Maximum number of bytes to receive and send+                        -- dowstream at once. Any positive value is fine, the+                        -- optimal value depends on how you deal with the+                        -- received data. Try using @4096@ if you don't care.   -> NS.Socket          -- ^Connected socket.   -> () -> P.Producer p B.ByteString IO () socketReadS nbytes sock () = P.runIdentityP loop where     loop = do-      bs <- lift $ recv sock nbytes-      unless (B.null bs) $ P.respond bs >> loop+      mbs <- lift (recv sock nbytes)+      case mbs of+        Just bs -> P.respond bs >> loop+        Nothing -> return () {-# INLINABLE socketReadS #-}  -- | Just like 'socketReadS', except each request from downstream specifies the@@ -111,23 +115,27 @@   -> Int -> P.Server p Int B.ByteString IO () nsocketReadS sock = P.runIdentityK loop where     loop nbytes = do-      bs <- lift $ recv sock nbytes-      unless (B.null bs) $ P.respond bs >>= loop+      mbs <- lift (recv sock nbytes)+      case mbs of+        Just bs -> P.respond bs >>= loop+        Nothing -> return () {-# INLINABLE nsocketReadS #-}  -- | Sends to the remote end the bytes received from upstream, then forwards -- such same bytes downstream. -- -- Requests from downstream are forwarded upstream.+--+-- If the remote peer closes its side of the connection, this proxy returns. socketWriteD   :: P.Proxy p   => NS.Socket          -- ^Connected socket.-  -> x -> p x B.ByteString x B.ByteString IO r+  -> x -> p x B.ByteString x B.ByteString IO () socketWriteD sock = P.runIdentityK loop where     loop x = do       a <- P.request x-      lift $ sendAll sock a-      P.respond a >>= loop+      ok <- lift (send sock a)+      when ok (P.respond a >>= loop) {-# INLINABLE socketWriteD #-}  --------------------------------------------------------------------------------@@ -143,16 +151,20 @@ socketReadTimeoutS   :: P.Proxy p   => Int                -- ^Timeout in microseconds (1/10^6 seconds).-  -> Int                -- ^Maximum number of bytes to receive at once.+  -> Int                -- ^Maximum number of bytes to receive and send+                        -- dowstream at once. Any positive value is fine, the+                        -- optimal value depends on how you deal with the+                        -- received data. Try using @4096@ if you don't care.   -> NS.Socket          -- ^Connected socket.   -> () -> P.Producer (PE.EitherP Timeout p) B.ByteString IO () socketReadTimeoutS wait nbytes sock () = loop where     loop = do-      mbs <- lift . timeout wait $ recv sock nbytes-      case mbs of-        Nothing -> PE.throw ex-        Just bs -> unless (B.null bs) $ P.respond bs >> loop-    ex = Timeout $ "recv: " <> show wait <> " microseconds."+      mmbs <- lift (timeout wait (recv sock nbytes))+      case mmbs of+        Just (Just bs) -> P.respond bs >> loop+        Just Nothing   -> return ()+        Nothing        -> PE.throw ex+    ex = Timeout $ "socketReadTimeoutS: " <> show wait <> " microseconds." {-# INLINABLE socketReadTimeoutS #-}  -- | Like 'nsocketReadS', except it throws a 'Timeout' exception in the@@ -165,11 +177,12 @@   -> Int -> P.Server (PE.EitherP Timeout p) Int B.ByteString IO () nsocketReadTimeoutS wait sock = loop where     loop nbytes = do-      mbs <- lift . timeout wait $ recv sock nbytes-      case mbs of-        Nothing -> PE.throw ex-        Just bs -> unless (B.null bs) $ P.respond bs >>= loop-    ex = Timeout $ "recv: " <> show wait <> " microseconds."+      mmbs <- lift (timeout wait (recv sock nbytes))+      case mmbs of+        Just (Just bs) -> P.respond bs >>= loop+        Just Nothing   -> return ()+        Nothing        -> PE.throw ex+    ex = Timeout $ "nsocketReadTimeoutS: " <> show wait <> " microseconds." {-# INLINABLE nsocketReadTimeoutS #-}  -- | Like 'socketWriteD', except it throws a 'Timeout' exception in the@@ -179,14 +192,16 @@   :: P.Proxy p   => Int                -- ^Timeout in microseconds (1/10^6 seconds).   -> NS.Socket          -- ^Connected socket.-  -> x -> (PE.EitherP Timeout p) x B.ByteString x B.ByteString IO r+  -> x -> (PE.EitherP Timeout p) x B.ByteString x B.ByteString IO () socketWriteTimeoutD wait sock = loop where     loop x = do       a <- P.request x-      mbs <- lift . timeout wait $ sendAll sock a-      case mbs of-        Nothing -> PE.throw ex-        Just () -> P.respond a >>= loop-    ex = Timeout $ "recv: " <> show wait <> " microseconds."+      mt <- lift (timeout wait (send sock a))+      case mt of+        Just True  -> P.respond a >>= loop+        Just False -> return ()+        Nothing    -> PE.throw ex+    ex = Timeout $ "socketWriteTimeoutD: " <> show wait <> " microseconds." {-# INLINABLE socketWriteTimeoutD #-}+ 
src/Control/Proxy/TCP/Safe.hs view
@@ -51,7 +51,6 @@ import qualified Data.ByteString                as B import           Data.Monoid import qualified Network.Socket                 as NS-import           Network.Socket.ByteString      (sendAll, recv) import qualified Network.Simple.TCP             as S import           System.Timeout                 (timeout) @@ -112,13 +111,16 @@ -- -- Using this proxy you can write straightforward code like the following, which -- prints whatever is received from a single TCP connection to a given server--- listening locally on port 9000:+-- listening locally on port 9000, in chunks of up to 4096 bytes: -- -- >>> runSafeIO . runProxy . runEitherK $ connectReadS Nothing 4096 "127.0.0.1" "9000" >-> tryK printD connectReadS   :: P.Proxy p   => Maybe Int          -- ^Optional timeout in microseconds (1/10^6 seconds).-  -> Int                -- ^Maximum number of bytes to receive at once.+  -> Int                -- ^Maximum number of bytes to receive and send+                        -- dowstream at once. Any positive value is fine, the+                        -- optimal value depends on how you deal with the+                        -- received data. Try using @4096@ if you don't care.   -> NS.HostName        -- ^Server host name.   -> NS.ServiceName     -- ^Server service port.   -> () -> P.Producer (P.ExceptionP p) B.ByteString P.SafeIO ()@@ -137,6 +139,8 @@ -- -- The connection socket is closed when done or in case of exceptions. --+-- If the remote peer closes its side of the connection, this proxy returns.+-- -- Using this proxy you can write straightforward code like the following, which -- greets a TCP client listening locally at port 9000: --@@ -285,14 +289,18 @@ -- exceptions. -- -- Using this proxy you can write straightforward code like the following, which--- prints whatever is received from a single TCP connection to port 9000:+-- prints whatever is received from a single TCP connection to port 9000, in+-- chunks of up to 4096 bytes. -- -- >>> :set -XOverloadedStrings -- >>> runSafeIO . runProxy . runEitherK $ serveReadS Nothing 4096 "127.0.0.1" "9000" >-> tryK printD serveReadS   :: P.Proxy p   => Maybe Int          -- ^Optional timeout in microseconds (1/10^6 seconds).-  -> Int                -- ^Maximum number of bytes to receive at once.+  -> Int                -- ^Maximum number of bytes to receive and send+                        -- dowstream at once. Any positive value is fine, the+                        -- optimal value depends on how you deal with the+                        -- received data. Try using @4096@ if you don't care.   -> S.HostPreference   -- ^Preferred host to bind.   -> NS.ServiceName     -- ^Service port to bind.   -> () -> P.Producer (P.ExceptionP p) B.ByteString P.SafeIO ()@@ -351,19 +359,25 @@ socketReadS   :: P.Proxy p   => Maybe Int          -- ^Optional timeout in microseconds (1/10^6 seconds).-  -> Int                -- ^Maximum number of bytes to receive at once.+  -> Int                -- ^Maximum number of bytes to receive and send+                        -- dowstream at once. Any positive value is fine, the+                        -- optimal value depends on how you deal with the+                        -- received data. Try using @4096@ if you don't care.   -> NS.Socket          -- ^Connected socket.   -> () -> P.Producer (P.ExceptionP p) B.ByteString P.SafeIO () socketReadS Nothing nbytes sock () = loop where     loop = do-      bs <- P.tryIO $ recv sock nbytes-      unless (B.null bs) $ P.respond bs >> loop+      mbs <- P.tryIO (recv sock nbytes)+      case mbs of+        Just bs -> P.respond bs >> loop+        Nothing -> return () socketReadS (Just wait) nbytes sock () = loop where     loop = do-      mbs <- P.tryIO . timeout wait $ recv sock nbytes-      case mbs of-        Nothing -> P.throw ex-        Just bs -> unless (B.null bs) $ P.respond bs >> loop+      mmbs <- P.tryIO (timeout wait (recv sock nbytes))+      case mmbs of+        Just (Just bs) -> P.respond bs >> loop+        Just Nothing   -> return ()+        Nothing        -> P.throw ex     ex = Timeout $ "socketReadS: " <> show wait <> " microseconds." {-# INLINABLE socketReadS #-} @@ -376,14 +390,17 @@   -> Int -> P.Server (P.ExceptionP p) Int B.ByteString P.SafeIO () nsocketReadS Nothing sock = loop where     loop nbytes = do-      bs <- P.tryIO $ recv sock nbytes-      unless (B.null bs) $ P.respond bs >>= loop+      mbs <- P.tryIO (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 (recv sock nbytes))       case mbs of-        Nothing -> P.throw ex-        Just bs -> unless (B.null bs) $ P.respond bs >>= loop+        Just (Just bs) -> P.respond bs >>= loop+        Just Nothing   -> return ()+        Nothing        -> P.throw ex     ex = Timeout $ "nsocketReadS: " <> show wait <> " microseconds." {-# INLINABLE nsocketReadS #-} @@ -395,23 +412,26 @@ -- 'P.ExceptionP' proxy transformer. -- -- Requests from downstream are forwarded upstream.+--+-- If the remote peer closes its side of the connection, this proxy returns. socketWriteD   :: P.Proxy p   => Maybe Int          -- ^Optional timeout in microseconds (1/10^6 seconds).   -> NS.Socket          -- ^Connected socket.-  -> x -> (P.ExceptionP p) x B.ByteString x B.ByteString P.SafeIO r+  -> x -> (P.ExceptionP p) x B.ByteString x B.ByteString P.SafeIO () socketWriteD Nothing sock = loop where     loop x = do       a <- P.request x-      P.tryIO $ sendAll sock a-      P.respond a >>= loop+      ok <- P.tryIO (send sock a)+      when ok (P.respond a >>= loop) socketWriteD (Just wait) sock = loop where     loop x = do       a <- P.request x-      m <- P.tryIO . timeout wait $ sendAll sock a-      case m of-        Nothing -> P.throw ex-        Just () -> P.respond a >>= loop+      mok <- P.tryIO (timeout wait (send sock a))+      case mok of+        Just True  -> P.respond a >>= loop+        Just False -> return ()+        Nothing    -> P.throw ex     ex = Timeout $ "socketWriteD: " <> show wait <> " microseconds." {-# INLINABLE socketWriteD #-} 
src/Control/Proxy/TCP/Safe/Sync.hs view
@@ -28,7 +28,6 @@ import qualified Data.ByteString                  as B import           Data.Monoid import qualified Network.Socket                   as NS-import           Network.Socket.ByteString        (recv, sendAll) import           System.Timeout                   (timeout)  @@ -52,26 +51,30 @@   => Maybe Int          -- ^Optional timeout in microseconds (1/10^6 seconds).   -> NS.Socket          -- ^Connected socket.   -> Request B.ByteString-  -> P.Server (P.ExceptionP p) (Request B.ByteString) Response P.SafeIO()+  -> P.Server (P.ExceptionP p) (Request B.ByteString) Response P.SafeIO () socketSyncServer Nothing sock = loop where     loop (Send bs) = do-        P.tryIO $ sendAll sock bs-        P.respond Sent >>= loop+        ok <- P.tryIO (send sock bs)+        when ok (P.respond Sent >>= loop)     loop (Receive nbytes) = do-        bs <- P.tryIO $ recv sock nbytes-        unless (B.null bs) $ P.respond (Received bs) >>= loop+        mbs <- P.tryIO (recv sock nbytes)+        case mbs of+          Just bs -> P.respond (Received bs) >>= loop+          Nothing -> return () socketSyncServer (Just wait) sock = loop where     loop (Send bs) = do-        m <- P.tryIO . timeout wait $ sendAll sock bs-        case m of-          Nothing -> P.throw $ ex "sendAll"-          Just () -> P.respond Sent >>= loop+        mok <- P.tryIO (timeout wait (send sock bs))+        case mok of+          Just True  -> P.respond Sent >>= loop+          Just False -> return ()+          Nothing    -> P.throw ex     loop (Receive nbytes) = do-        mbs <- P.tryIO . timeout wait $ recv sock nbytes-        case mbs of-          Nothing -> P.throw $ ex "recv"-          Just bs -> unless (B.null bs) $ P.respond (Received bs) >>= loop-    ex s = Timeout $ s <> ": " <> show wait <> " microseconds."+        mmbs <- P.tryIO (timeout wait (recv sock nbytes))+        case mmbs of+          Just (Just bs) -> P.respond (Received bs) >>= loop+          Just Nothing   -> return ()+          Nothing        -> P.throw ex+    ex = Timeout $ "socketSyncServer: " <> show wait <> " microseconds." {-# INLINABLE socketSyncServer #-}  -- | 'P.Proxy' able to send and receive bytes through a 'NS.Socket'.@@ -99,23 +102,28 @@   -> (P.ExceptionP p) a' B.ByteString (Request a') Response P.SafeIO () socketSyncProxy Nothing sock = loop where     loop (Send a') = do-        P.request a' >>= P.tryIO . sendAll sock-        P.respond Sent >>= loop+        ok <- P.tryIO . send sock =<< P.request a'+        when ok (P.respond Sent >>= loop)     loop (Receive nbytes) = do-        bs <- P.tryIO $ recv sock nbytes-        unless (B.null bs) $ P.respond (Received bs) >>= loop+        mbs <- P.tryIO (recv sock nbytes)+        case mbs of+          Just bs -> P.respond (Received bs) >>= loop+          Nothing -> return () socketSyncProxy (Just wait) sock = loop where     loop (Send a') = do         bs <- P.request a'-        m <- P.tryIO . timeout wait $ sendAll sock bs-        case m of-          Nothing -> P.throw $ ex "sendAll"-          Just () -> P.respond Sent >>= loop+        mok <- P.tryIO (timeout wait (send sock bs))+        case mok of+          Just True  -> P.respond Sent >>= loop+          Just False -> return ()+          Nothing    -> P.throw ex     loop (Receive nbytes) = do-        mbs <- P.tryIO . timeout wait $ recv sock nbytes-        case mbs of-          Nothing -> P.throw $ ex "recv"-          Just bs -> unless (B.null bs) $ P.respond (Received bs) >>= loop-    ex s = Timeout $ s <> ": " <> show wait <> " microseconds."+        mmbs <- P.tryIO (timeout wait (recv sock nbytes))+        case mmbs of+          Just (Just bs) -> P.respond (Received bs) >>= loop+          Just Nothing   -> return ()+          Nothing        -> P.throw ex+    ex = Timeout $ "socketSyncProxy: " <> show wait <> " microseconds." {-# INLINABLE socketSyncProxy #-}+ 
src/Control/Proxy/TCP/Sync.hs view
@@ -34,7 +34,6 @@ import qualified Data.ByteString.Char8            as B import           Data.Monoid import qualified Network.Socket                   as NS-import           Network.Socket.ByteString        (recv, sendAll) import           System.Timeout                   (timeout)  @@ -66,11 +65,13 @@   -> P.Server p (Request B.ByteString) Response IO () socketSyncServer sock = P.runIdentityK loop where     loop (Send bs) = do-        lift $ sendAll sock bs-        P.respond Sent >>= loop+        ok <- lift (send sock bs)+        when ok (P.respond Sent >>= loop)     loop (Receive nbytes) = do-        bs <- lift $ recv sock nbytes-        unless (B.null bs) $ P.respond (Received bs) >>= loop+        mbs <- lift (recv sock nbytes)+        case mbs of+          Just bs -> P.respond (Received bs) >>= loop+          Nothing -> return () {-# INLINABLE socketSyncServer #-}  -- | 'P.Proxy' able to send and receive bytes through a 'NS.Socket'.@@ -93,11 +94,13 @@   -> p a' B.ByteString (Request a') Response IO () socketSyncProxy sock = P.runIdentityK loop where     loop (Send a') = do-        P.request a' >>= lift . sendAll sock-        P.respond Sent >>= loop+        ok <- lift . send sock =<< P.request a'+        when ok (P.respond Sent >>= loop)     loop (Receive nbytes) = do-        bs <- lift $ recv sock nbytes-        unless (B.null bs) $ P.respond (Received bs) >>= loop+        mbs <- lift (recv sock nbytes)+        case mbs of+          Just bs -> P.respond (Received bs) >>= loop+          Nothing -> return () {-# INLINABLE socketSyncProxy #-}  --------------------------------------------------------------------------------@@ -118,16 +121,18 @@   -> P.Server (PE.EitherP Timeout p) (Request B.ByteString) Response IO () socketSyncServerTimeout wait sock = loop where     loop (Send bs) = do-        m <- lift . timeout wait $ sendAll sock bs-        case m of-          Nothing -> PE.throw $ ex "sendAll"-          Just () -> P.respond Sent >>= loop+        mok <- lift (timeout wait (send sock bs))+        case mok of+          Just True  -> P.respond Sent >>= loop+          Just False -> return ()+          Nothing    -> PE.throw ex     loop (Receive nbytes) = do-        mbs <- lift . timeout wait $ recv sock nbytes-        case mbs of-          Nothing -> PE.throw $ ex "recv"-          Just bs -> unless (B.null bs) $ P.respond (Received bs) >>= loop-    ex s = Timeout $ s <> ": " <> show wait <> " microseconds."+        mmbs <- lift (timeout wait (recv sock nbytes))+        case mmbs of+          Just (Just bs) -> P.respond (Received bs) >>= loop+          Just Nothing   -> return ()+          Nothing        -> PE.throw ex+    ex = Timeout $ "socketSyncServerTimeout: " <> show wait <> " microseconds." {-# INLINABLE socketSyncServerTimeout #-}  -- | Like 'socketSyncProxy', except it throws a 'Timeout' exception in the@@ -141,17 +146,18 @@   -> (PE.EitherP Timeout p) a' B.ByteString (Request a') Response IO () socketSyncProxyTimeout wait sock = loop where     loop (Send a') = do-        bs <- P.request a'-        m <- lift . timeout wait $ sendAll sock bs-        case m of-          Nothing -> PE.throw $ ex "sendAll"-          Just () -> P.respond Sent >>= loop+        mok <- lift . timeout wait . send sock =<< P.request a'+        case mok of+          Just True  -> P.respond Sent >>= loop+          Just False -> return ()+          Nothing    -> PE.throw ex     loop (Receive nbytes) = do-        mbs <- lift . timeout wait $ recv sock nbytes-        case mbs of-          Nothing -> PE.throw $ ex "recv"-          Just bs -> unless (B.null bs) $ P.respond (Received bs) >>= loop-    ex s = Timeout $ s <> ": " <> show wait <> " microseconds."+        mmbs <- lift (timeout wait (recv sock nbytes))+        case mmbs of+          Just (Just bs) -> P.respond (Received bs) >>= loop+          Just Nothing   -> return ()+          Nothing        -> PE.throw ex+    ex = Timeout $ "socketSyncProxyTimeout: " <> show wait <> " microseconds." {-# INLINABLE socketSyncProxyTimeout #-}  --------------------------------------------------------------------------------