splice 0.6.1 → 0.6.1.1
raw patch · 5 files changed
+452/−451 lines, 5 files
Files
- LICENSE +31/−31
- splice.cabal +65/−64
- src/Network/Socket/Splice.hs +29/−29
- src/Network/Socket/Splice/Internal.hsc +250/−250
- src/System/IO/Splice/Linux.hsc +77/−77
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")