packages feed

splice 0.6.1 → 0.6.1.1

raw patch · 5 files changed

+452/−451 lines, 5 files

Files

LICENSE view
@@ -1,31 +1,31 @@-Copyright (c) 2012, Cetin Sert
-
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
-    * Redistributions of source code must retain the above copyright
-      notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above
-      copyright notice, this list of conditions and the following
-      disclaimer in the documentation and/or other materials provided
-      with the distribution.
-
-    * The names of contributors may not be used to endorse or promote
-      products derived from this software without specific prior
-      written permission. 
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+Copyright (c) 2012, Cetin Sert++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are+met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * The names of contributors may not be used to endorse or promote+      products derived from this software without specific prior+      written permission. ++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
splice.cabal view
@@ -1,65 +1,66 @@-name:          splice
-version:       0.6.1
-stability:     stable on all operating systems
-synopsis:      Cross-platform Socket to Socket Data Splicing
-description:   A library that implements most efficient socket to socket
-               data transfer loops for proxy servers on all operating systems.
-               .
-               On GNU/Linux, it exports the zero-copy system call @c_splice()@
-               (<http://kerneltrap.org/node/6505>) in @System.IO.Splice.Linux@.
-               .
-               On other operating systems, it only exports a portable Haskell
-               implementation.
-               .
-               A unified sockets API for all operating systems is available in
-               @Network.Socket.Splice@.
-               .
-               [Version Scheme]
-               Major-@/R/@-ewrite . New-@/F/@-unctionality . @/I/@-mprovementAndBugFixes . @/P/@-ackagingOnly
-               .
-               * @PackagingOnly@ changes are made for quality assurance reasons.
-               
-copyright:     Copyright © 2012 Cetin Sert
-license:       BSD3
-license-file:  LICENSE
-author:        Cetin Sert <fusion@corsis.eu>, Corsis Research
-maintainer:    Cetin Sert <fusion@corsis.eu>, Corsis Research
-homepage:      http://corsis.github.com/splice/
-bug-reports:   http://github.com/corsis/splice/issues
-category:      System, Network
-build-type:    Simple
-cabal-version: >= 1.6
-
-
-source-repository head
-    type:      git
-    location:  git://github.com/corsis/splice.git
-
-
-flag portable
-    description: force portable 'splice' implementation on GNU\/Linux
-    default    : True
-
-
-flag llvm
-    description: compile via LLVM
-    default    : False
-
-
-library
-    hs-source-dirs:      src
-    exposed-modules:     Network.Socket.Splice
-    other-modules:       Network.Socket.Splice.Internal
-    build-depends:       base    >= 4 && <= 5,
-                         network -any
-
-    if os(linux) && !flag(portable)
-      exposed-modules:   System.IO.Splice.Linux
-      build-depends:     unix    >= 2 && <= 4
-      cpp-options:       -DLINUX_SPLICE
-
-      
-    ghc-options:         -Wall -O2
-
-    if flag(llvm)
+name:          splice+version:       0.6.1.1+stability:     stable on all operating systems+synopsis:      Cross-platform Socket to Socket Data Splicing+description:   A library that implements most efficient socket to socket+               data transfer loops for proxy servers on all operating systems.+               .+               On GNU/Linux, it exports the zero-copy system call @c_splice()@+               (<http://en.wikipedia.org/wiki/Splice_(system_call)#Requirements>)+               in @System.IO.Splice.Linux@.+               .+               On other operating systems, it only exports a portable Haskell+               implementation.+               .+               A unified sockets API for all operating systems is available in+               @Network.Socket.Splice@.+               .+               [Version Scheme]+               Major-@/R/@-ewrite . New-@/F/@-unctionality . @/I/@-mprovementAndBugFixes . @/P/@-ackagingOnly+               .+               * @PackagingOnly@ changes are made for quality assurance reasons.+               +copyright:     Copyright © 2012 Cetin Sert+license:       BSD3+license-file:  LICENSE+author:        Cetin Sert <fusion@corsis.eu>, Corsis Research+maintainer:    Cetin Sert <fusion@corsis.eu>, Corsis Research+homepage:      http://corsis.github.com/splice/+bug-reports:   http://github.com/corsis/splice/issues+category:      System, Network+build-type:    Simple+cabal-version: >= 1.6+++source-repository head+    type:      git+    location:  git://github.com/corsis/splice.git+++flag portable+    description: force portable 'splice' implementation on GNU\/Linux+    default    : True+++flag llvm+    description: compile via LLVM+    default    : False+++library+    hs-source-dirs:      src+    exposed-modules:     Network.Socket.Splice+    other-modules:       Network.Socket.Splice.Internal+    build-depends:       base    >= 4 && <= 5,+                         network -any++    if os(linux) && !flag(portable)+      exposed-modules:   System.IO.Splice.Linux+      build-depends:     unix    >= 2 && <= 4+      cpp-options:       -DLINUX_SPLICE++      +    ghc-options:         -Wall -O2++    if flag(llvm)       ghc-options:       -fllvm -optlo-O3
src/Network/Socket/Splice.hs view
@@ -1,29 +1,29 @@-{- |
-  This library implements most efficient socket to socket data transfer loops
-  for proxy servers on each operating system.
-               
-  On GNU\/Linux, it uses and exposes the zero-copy @splice()@ system call:
-  <http://kerneltrap.org/node/6505>.
-
-  On all other operating systems, it currently falls back to a portable Haskell
-  implementation – which allocates a single memory buffer in user address space,
-  then enters an inner loop that uses 'System.IO.hGetBufSome' and
-  'System.IO.hPutBuf'. This avoids lots of tiny allocations as would otherwise
-  be caused by 'Network.Socket.ByteString.recv' and
-  'Network.Socket.ByteString.sendAll' from the @bytestring@ package.
--}
---  
--- Module      : Network.Socket.Splice
--- Copyright   : (c) Cetin Sert 2012
--- License     : BSD3
--- Maintainer  : fusion@corsis.eu
--- Stability   : stable
--- Portability : works on all operating systems
-
-module Network.Socket.Splice (
-
-  module Network.Socket.Splice.Internal
-
-  ) where
-
-import Network.Socket.Splice.Internal
+{- |+  This library implements most efficient socket to socket data transfer loops+  for proxy servers on each operating system.+               +  On GNU\/Linux, it uses and exposes the zero-copy @splice()@ system call:+  <http://kerneltrap.org/node/6505>.++  On all other operating systems, it currently falls back to a portable Haskell+  implementation – which allocates a single memory buffer in user address space,+  then enters an inner loop that uses 'System.IO.hGetBufSome' and+  'System.IO.hPutBuf'. This avoids lots of tiny allocations as would otherwise+  be caused by 'Network.Socket.ByteString.recv' and+  'Network.Socket.ByteString.sendAll' from the @bytestring@ package.+-}+--  +-- Module      : Network.Socket.Splice+-- Copyright   : (c) Cetin Sert 2012+-- License     : BSD3+-- Maintainer  : fusion@corsis.eu+-- Stability   : stable+-- Portability : works on all operating systems++module Network.Socket.Splice (++  module Network.Socket.Splice.Internal++  ) where++import Network.Socket.Splice.Internal
src/Network/Socket/Splice/Internal.hsc view
@@ -1,251 +1,251 @@--- | Implementation.
---
--- Module      : Network.Socket.Splice.Internal
--- Copyright   : (c) Cetin Sert 2012
--- License     : BSD3
--- Maintainer  : fusion@corsis.eu
--- Stability   : stable
--- Portability : works on all operating systems
-
-
-#ifdef LINUX_SPLICE
-#include <fcntl.h>
-#endif
-{-# LANGUAGE CPP, ForeignFunctionInterface #-}
-
-
-module Network.Socket.Splice.Internal (
-
-  -- * Cross-platform API for Socket to Socket Data Transfer Loops
-
-  {- | 'splice' is the cross-platform API for continous, uni-directional
-       data transfer between two network sockets.
-
-       'splice' and its implementation primitives 'hSplice' and 'fdSplice' are
-       /infinite/ loops that are intended to be used with
-       'Control.Concurrent.forkIO' and exception handlers. 'splice' is a
-       terminal operation; it cannot be interleaved by other IO operations on
-       its sockets or handles.
-
-       [Initiate bi-directional continuous data transfer between two sockets:]
-    
-       > void . forkIO . tryWith handler $! splice void 1024 (sourceSocket, _) (targetSocket, _)
-       > void . forkIO . tryWith handler $! splice void 1024 (targetSocket, _) (sourceSocket, _)
-
-       where @handler@ is an IO operation that would do the necessary clean up –
-       such as ensuring the sockets are closed and any resources that may be
-       associated with the sockets are properly disposed of.
-
-       [Notes]
-
-         * 'System.IO.Splice.Linux.c_splice', the Linux-only system call, is not
-           a terminal infinite loop and can be safely interleaved by other IO
-           operations on sockets or socket handles.
-  -}
-
-    splice
-  , ChunkSize
-  , zeroCopy
-
-  -- * Combinators for Exception Handling
-  , tryWith
-  , try_
-
-  -- * Implementation Primitives
-  {- | Infinite loops used in the cross-platform implementation of 'splice'. -}
-
-  , hSplice
-#ifdef LINUX_SPLICE
-  , fdSplice
-#endif
-
-  ) where
-
-
-import Data.Word
-import Foreign.Ptr
-
-import System.IO
-import Network.Socket
-import Control.Monad
-import Control.Exception
-import Foreign.Marshal.Alloc
-
-#ifdef LINUX_SPLICE
-import Data.Int
-import Data.Bits
-import System.Posix.IO
-import Unsafe.Coerce
-import Foreign.C.Error
-import System.Posix.Types
-import System.Posix.Internals
-import qualified System.IO.Splice.Linux as L
-#else
-import Data.Maybe
-#endif
-
-
-----------------------------------------------------------------------------------------------------
-
-
--- | Indicates whether 'splice' uses zero-copy system calls or the portable user
---   space Haskell implementation.
-zeroCopy :: Bool -- ^ @True@ if 'splice' uses zero-copy system calls; otherwise, false.
-zeroCopy =
-#ifdef LINUX_SPLICE
-  True
-#else
-  False
-#endif
-
-
--- | The numeric type to recommend chunk sizes for moving data between sockets
---   used by both zero-copy and portable implementations of 'splice'.
-type ChunkSize =
-#ifdef LINUX_SPLICE
-  L.ChunkSize
-#else
-  Int
-#endif
-
-
-----------------------------------------------------------------------------------------------SPLICE
-
-
--- | Pipes data from one socket to another in an /infinite loop/.
---
---   'splice' currently has two implementations:
---
---   [on GNU\/Linux using 'fdSplice' ≅]
---
---   > splice len (sIn, _       ) (sOut, _        ) = ... fdSplice ...
---
---   [on all other operating systems using 'hSplice' ≅]
---
---   > splice len (_  , Just hIn) (_   , Just hOut) = ... hSplice  ...
---
---   [Notes]
---
---     * 'fdSplice' and 'fdSplice' implementation of 'splice' are only available
---        on GNU\/Linux.
---
---     * 'hSplice' is always available and the 'hSplice' implementation of
---       'splice' can be forced on GNU\/Linux by defining the @portable@ flag at
---       compile time.
---
---     * 'hSplice' implementation requires handles in 'NoBuffering' mode.
---
---     * 'splice' is a terminal loop on two sockets and once entered its sockets
---        and handles cannot be interleaved by other IO operations.
---
-splice
-  :: ChunkSize               -- ^ maximal chunk size.
-  -> (Socket, Maybe Handle)  -- ^ source socket and possibly its opened handle.
-  -> (Socket, Maybe Handle)  -- ^ target socket and possibly its opened handle.
-  -> IO ()                   -- ^ infinite loop.
-#ifdef LINUX_SPLICE
-splice len (sIn, _  ) (sOut, _   ) = do
-#else
-splice len (_  , hIn) (_   , hOut) = do
-#endif
-#ifdef LINUX_SPLICE
-  let s = Fd $! fdSocket sIn
-  let t = Fd $! fdSocket sOut
-  fdSplice len s t
-#else
-  let s = fromJust hIn
-  let t = fromJust hOut
-  hSplice (fromIntegral len) s t
-#endif
-
-
---------------------------------------------------------------------------------------------FDSPLICE
-
-
-#ifdef LINUX_SPLICE
-
-{- | GNU\/Linux @splice()@ system call loop.
-
-       1. creates a pipe in kernel address space
-
-       2. uses it until the loop terminates by exception
-
-       3. closes the pipe and returns
--}
-fdSplice :: ChunkSize -> Fd -> Fd -> IO ()
-fdSplice len s@(Fd fdIn) t@(Fd fdOut) = do
-
-  (r,w) <- createPipe
-  let n = nullPtr  
-  let u = unsafeCoerce :: (#type ssize_t) -> (#type size_t)
-  let check = throwErrnoIfMinus1 "Network.Socket.Splice.splice"
-  let flags = L.sPLICE_F_MOVE .|. L.sPLICE_F_MORE
-  let setNonBlockingMode v = do setNonBlockingFD fdIn  v
-                                setNonBlockingFD fdOut v
-  setNonBlockingMode False
-
-  finally
-    (forever $! do 
-       bytes   <- check $! L.c_splice s n w n    len    flags
-       if bytes > 0
-         then              L.c_splice r n t n (u bytes) flags
-         else              throwRecv0)
-    (do closeFd r
-        closeFd w
-        try_ $! setNonBlockingMode True)
-
-#endif
-
-
----------------------------------------------------------------------------------------------HSPLICE
-
-
-{- | The portable Haskell loop.
-
-       1. allocates a /single/ memory buffer in user address space
-
-       2. uses it until the loop terminates by exception
-
-       3. frees the buffer and returns
-
-   [Notes]
-
-     * the socket handles are required to be in 'NoBuffering' mode.
--} 
-hSplice :: Int -> Handle -> Handle -> IO ()
-hSplice len s t = do
-
-  a <- mallocBytes len :: IO (Ptr Word8)
-
-  finally
-    (forever $! do
-       bytes   <- hGetBufSome s a len
-       if bytes > 0
-         then     hPutBuf     t a bytes
-         else     throwRecv0)
-    (free a)
-
-
-------------------------------------------------------------------------------------------EXCEPTIONS
-
-
--- | Similar to 'Control.Exception.Base.try' but used when an obvious exception
---   is expected and can be handled easily. Unlike 'finally' exceptions are
---   /NOT/ rethrown once handled.
-tryWith
-  :: (SomeException -> IO a) -- ^ exception handler.
-  -> IO a                    -- ^ action to run which can throw /any/ exception.
-  -> IO a                    -- ^ new action where all exceptions are handled by the single handler.
-tryWith h a = try a >>= \r -> case r of Left x -> h x; Right y -> return y
-
-
--- | Similar to 'Control.Exception.Base.try' but used when an obvious exception
---   is expected which can be safely ignored.
-try_
-  :: IO ()                   -- ^ action to run which can throw /any/ exception.
-  -> IO ()                   -- ^ new action where exceptions are silenced.
-try_ a = (try a :: IO (Either SomeException ())) >> return ()
-
-
-throwRecv0 :: a
+-- | Implementation.+--+-- Module      : Network.Socket.Splice.Internal+-- Copyright   : (c) Cetin Sert 2012+-- License     : BSD3+-- Maintainer  : fusion@corsis.eu+-- Stability   : stable+-- Portability : works on all operating systems+++#ifdef LINUX_SPLICE+#include <fcntl.h>+#endif+{-# LANGUAGE CPP, ForeignFunctionInterface #-}+++module Network.Socket.Splice.Internal (++  -- * Cross-platform API for Socket to Socket Data Transfer Loops++  {- | 'splice' is the cross-platform API for continous, uni-directional+       data transfer between two network sockets.++       'splice' and its implementation primitives 'hSplice' and 'fdSplice' are+       /infinite/ loops that are intended to be used with+       'Control.Concurrent.forkIO' and exception handlers. 'splice' is a+       terminal operation; it cannot be interleaved by other IO operations on+       its sockets or handles.++       [Initiate bi-directional continuous data transfer between two sockets:]+    +       > void . forkIO . tryWith handler $! splice void 1024 (sourceSocket, _) (targetSocket, _)+       > void . forkIO . tryWith handler $! splice void 1024 (targetSocket, _) (sourceSocket, _)++       where @handler@ is an IO operation that would do the necessary clean up –+       such as ensuring the sockets are closed and any resources that may be+       associated with the sockets are properly disposed of.++       [Notes]++         * 'System.IO.Splice.Linux.c_splice', the Linux-only system call, is not+           a terminal infinite loop and can be safely interleaved by other IO+           operations on sockets or socket handles.+  -}++    splice+  , ChunkSize+  , zeroCopy++  -- * Combinators for Exception Handling+  , tryWith+  , try_++  -- * Implementation Primitives+  {- | Infinite loops used in the cross-platform implementation of 'splice'. -}++  , hSplice+#ifdef LINUX_SPLICE+  , fdSplice+#endif++  ) where+++import Data.Word+import Foreign.Ptr++import System.IO+import Network.Socket+import Control.Monad+import Control.Exception+import Foreign.Marshal.Alloc++#ifdef LINUX_SPLICE+import Data.Int+import Data.Bits+import System.Posix.IO+import Unsafe.Coerce+import Foreign.C.Error+import System.Posix.Types+import System.Posix.Internals+import qualified System.IO.Splice.Linux as L+#else+import Data.Maybe+#endif+++----------------------------------------------------------------------------------------------------+++-- | Indicates whether 'splice' uses zero-copy system calls or the portable user+--   space Haskell implementation.+zeroCopy :: Bool -- ^ @True@ if 'splice' uses zero-copy system calls; otherwise, false.+zeroCopy =+#ifdef LINUX_SPLICE+  True+#else+  False+#endif+++-- | The numeric type to recommend chunk sizes for moving data between sockets+--   used by both zero-copy and portable implementations of 'splice'.+type ChunkSize =+#ifdef LINUX_SPLICE+  L.ChunkSize+#else+  Int+#endif+++----------------------------------------------------------------------------------------------SPLICE+++-- | Pipes data from one socket to another in an /infinite loop/.+--+--   'splice' currently has two implementations:+--+--   [on GNU\/Linux using 'fdSplice' ≅]+--+--   > splice len (sIn, _       ) (sOut, _        ) = ... fdSplice ...+--+--   [on all other operating systems using 'hSplice' ≅]+--+--   > splice len (_  , Just hIn) (_   , Just hOut) = ... hSplice  ...+--+--   [Notes]+--+--     * 'fdSplice' and 'fdSplice' implementation of 'splice' are only available+--        on GNU\/Linux.+--+--     * 'hSplice' is always available and the 'hSplice' implementation of+--       'splice' can be forced on GNU\/Linux by defining the @portable@ flag at+--       compile time.+--+--     * 'hSplice' implementation requires handles in 'NoBuffering' mode.+--+--     * 'splice' is a terminal loop on two sockets and once entered its sockets+--        and handles cannot be interleaved by other IO operations.+--+splice+  :: ChunkSize               -- ^ maximal chunk size.+  -> (Socket, Maybe Handle)  -- ^ source socket and possibly its opened handle.+  -> (Socket, Maybe Handle)  -- ^ target socket and possibly its opened handle.+  -> IO ()                   -- ^ infinite loop.+#ifdef LINUX_SPLICE+splice len (sIn, _  ) (sOut, _   ) = do+#else+splice len (_  , hIn) (_   , hOut) = do+#endif+#ifdef LINUX_SPLICE+  let s = Fd $! fdSocket sIn+  let t = Fd $! fdSocket sOut+  fdSplice len s t+#else+  let s = fromJust hIn+  let t = fromJust hOut+  hSplice (fromIntegral len) s t+#endif+++--------------------------------------------------------------------------------------------FDSPLICE+++#ifdef LINUX_SPLICE++{- | GNU\/Linux @splice()@ system call loop.++       1. creates a pipe in kernel address space++       2. uses it until the loop terminates by exception++       3. closes the pipe and returns+-}+fdSplice :: ChunkSize -> Fd -> Fd -> IO ()+fdSplice len s@(Fd fdIn) t@(Fd fdOut) = do++  (r,w) <- createPipe+  let n = nullPtr  +  let u = unsafeCoerce :: (#type ssize_t) -> (#type size_t)+  let check = throwErrnoIfMinus1 "Network.Socket.Splice.splice"+  let flags = L.sPLICE_F_MOVE .|. L.sPLICE_F_MORE+  let setNonBlockingMode v = do setNonBlockingFD fdIn  v+                                setNonBlockingFD fdOut v+  setNonBlockingMode False++  finally+    (forever $! do +       bytes   <- check $! L.c_splice s n w n    len    flags+       if bytes > 0+         then              L.c_splice r n t n (u bytes) flags+         else              throwRecv0)+    (do closeFd r+        closeFd w+        try_ $! setNonBlockingMode True)++#endif+++---------------------------------------------------------------------------------------------HSPLICE+++{- | The portable Haskell loop.++       1. allocates a /single/ memory buffer in user address space++       2. uses it until the loop terminates by exception++       3. frees the buffer and returns++   [Notes]++     * the socket handles are required to be in 'NoBuffering' mode.+-} +hSplice :: Int -> Handle -> Handle -> IO ()+hSplice len s t = do++  a <- mallocBytes len :: IO (Ptr Word8)++  finally+    (forever $! do+       bytes   <- hGetBufSome s a len+       if bytes > 0+         then     hPutBuf     t a bytes+         else     throwRecv0)+    (free a)+++------------------------------------------------------------------------------------------EXCEPTIONS+++-- | Similar to 'Control.Exception.Base.try' but used when an obvious exception+--   is expected and can be handled easily. Unlike 'finally' exceptions are+--   /NOT/ rethrown once handled.+tryWith+  :: (SomeException -> IO a) -- ^ exception handler.+  -> IO a                    -- ^ action to run which can throw /any/ exception.+  -> IO a                    -- ^ new action where all exceptions are handled by the single handler.+tryWith h a = try a >>= \r -> case r of Left x -> h x; Right y -> return y+++-- | Similar to 'Control.Exception.Base.try' but used when an obvious exception+--   is expected which can be safely ignored.+try_+  :: IO ()                   -- ^ action to run which can throw /any/ exception.+  -> IO ()                   -- ^ new action where exceptions are silenced.+try_ a = (try a :: IO (Either SomeException ())) >> return ()+++throwRecv0 :: a throwRecv0 = error "Network.Socket.Splice.splice ended"
src/System/IO/Splice/Linux.hsc view
@@ -1,78 +1,78 @@-{- | Exposes the GNU\/Linux system call @splice()@: <http://kerneltrap.org/node/6505>.
-
-     /This module is only available (compiled & exposed) on GNU/\//Linux./
--}
---  
--- Module      : System.IO.Splice.Linux
--- Copyright   : (c) Cetin Sert 2012
--- License     : BSD3
--- Maintainer  : fusion@corsis.eu
--- Stability   : stable
--- Portability : GNU\/Linux-only
-
-
-#include <fcntl.h>
-{-# LANGUAGE CPP, ForeignFunctionInterface #-}
-
-
-module System.IO.Splice.Linux (
-
-    c_splice
-  , ChunkSize
-  , sPLICE_F_MOVE
-  , sPLICE_F_MORE
-  , sPLICE_F_NONBLOCK
-
-  ) where
-
-
-import Data.Int
-import Data.Word
-import Foreign.Ptr
-import Foreign.C.Types
-import System.Posix.Types
-
-
--- | The numeric type used by 'c_splice' for chunk size recommendations when
---   moving data.
-type ChunkSize = (#type size_t)
-
--- | Moves data between two file descriptors without copying between kernel
---   address space and user address space. It transfers up to @len@ bytes of
---   data from the file descriptor @fd_in@ to the file descriptor @fd_out@,
---   where one of the descriptors must refer to a pipe.
---
---   'c_splice' is /NOT/ a loop and needs to be called repeatedly.
---
---   For an example, see 'Network.Socket.Splice.Internal.splice'.
-foreign import ccall "splice"
-  c_splice
-  :: Fd                  -- ^ @fd_in@.
-  -> Ptr (#type loff_t)  -- ^ @off_in@.
-  -> Fd                  -- ^ @fd_out@.
-  -> Ptr (#type loff_t)  -- ^ @off_out@.
-  -> ChunkSize           -- ^ @len@.
-  -> Word                -- ^ @flags@.
-  -> IO (#type ssize_t)  -- ^ number of bytes moved if successful; otherwise -1.
-
-
--- | Attempt to move pages instead of copying. This is only a hint to the
---   kernel: pages may stil be copied (/in kernel address space/) if the kernel
---   cannot move the pages from the pipe, or if the pipe buffers don't refer to
---   full pages.
-sPLICE_F_MOVE :: Word
-sPLICE_F_MOVE = (#const "SPLICE_F_MOVE")
-
-
--- | More data will be coming in a subsequent 'c_splice'. This is a helpful hint
---   when @fd_out@ refers to a socket.
-sPLICE_F_MORE :: Word
-sPLICE_F_MORE = (#const "SPLICE_F_MORE")
-
-
--- | Do not block on I\/O. This makes the 'c_splice' pipe operations
---   nonblocking, but 'c_splice' may nevertheless block because the file
---   descriptors that are 'c_splice'd to\/from may block (unless they have the
---   @O_NONBLOCK@ flag set).
-sPLICE_F_NONBLOCK :: Word
+{- | Exposes the GNU\/Linux system call @splice()@: <http://kerneltrap.org/node/6505>.++     /This module is only available (compiled & exposed) on GNU/\//Linux./+-}+--  +-- Module      : System.IO.Splice.Linux+-- Copyright   : (c) Cetin Sert 2012+-- License     : BSD3+-- Maintainer  : fusion@corsis.eu+-- Stability   : stable+-- Portability : GNU\/Linux-only+++#include <fcntl.h>+{-# LANGUAGE CPP, ForeignFunctionInterface #-}+++module System.IO.Splice.Linux (++    c_splice+  , ChunkSize+  , sPLICE_F_MOVE+  , sPLICE_F_MORE+  , sPLICE_F_NONBLOCK++  ) where+++import Data.Int+import Data.Word+import Foreign.Ptr+import Foreign.C.Types+import System.Posix.Types+++-- | The numeric type used by 'c_splice' for chunk size recommendations when+--   moving data.+type ChunkSize = (#type size_t)++-- | Moves data between two file descriptors without copying between kernel+--   address space and user address space. It transfers up to @len@ bytes of+--   data from the file descriptor @fd_in@ to the file descriptor @fd_out@,+--   where one of the descriptors must refer to a pipe.+--+--   'c_splice' is /NOT/ a loop and needs to be called repeatedly.+--+--   For an example, see 'Network.Socket.Splice.Internal.splice'.+foreign import ccall "splice"+  c_splice+  :: Fd                  -- ^ @fd_in@.+  -> Ptr (#type loff_t)  -- ^ @off_in@.+  -> Fd                  -- ^ @fd_out@.+  -> Ptr (#type loff_t)  -- ^ @off_out@.+  -> ChunkSize           -- ^ @len@.+  -> Word                -- ^ @flags@.+  -> IO (#type ssize_t)  -- ^ number of bytes moved if successful; otherwise -1.+++-- | Attempt to move pages instead of copying. This is only a hint to the+--   kernel: pages may stil be copied (/in kernel address space/) if the kernel+--   cannot move the pages from the pipe, or if the pipe buffers don't refer to+--   full pages.+sPLICE_F_MOVE :: Word+sPLICE_F_MOVE = (#const "SPLICE_F_MOVE")+++-- | More data will be coming in a subsequent 'c_splice'. This is a helpful hint+--   when @fd_out@ refers to a socket.+sPLICE_F_MORE :: Word+sPLICE_F_MORE = (#const "SPLICE_F_MORE")+++-- | Do not block on I\/O. This makes the 'c_splice' pipe operations+--   nonblocking, but 'c_splice' may nevertheless block because the file+--   descriptors that are 'c_splice'd to\/from may block (unless they have the+--   @O_NONBLOCK@ flag set).+sPLICE_F_NONBLOCK :: Word sPLICE_F_NONBLOCK = (#const "SPLICE_F_NONBLOCK")