packages feed

splice 0.1 → 0.2

raw patch · 2 files changed

+115/−31 lines, 2 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Network.Socket.Splice: loopSplice :: Length -> Socket -> Socket -> IO ()
- Network.Socket.Splice: type Length = Word32
+ Network.Socket.Splice: sPLICE_F_MORE :: Word
+ Network.Socket.Splice: sPLICE_F_MOVE :: Word
+ Network.Socket.Splice: sPLICE_F_NONBLOCK :: Word
+ Network.Socket.Splice: splice :: ChunkSize -> Socket -> Socket -> IO ()
+ Network.Socket.Splice: try_ :: IO () -> IO ()
+ Network.Socket.Splice: type ChunkSize = Word32

Files

splice.cabal view
@@ -1,5 +1,5 @@ name:          splice-version:       0.1+version:       0.2 stability:     stable on Linux, experimental on other operating systems synopsis:      Socket to Socket Data Splicing description:   A library that implements efficient socket to socket@@ -15,8 +15,13 @@                lots of tiny allocations as would otherwise be caused by                recv and sendAll functions from Network.Socket.ByteString.                .-               This work has been funded by Corsis Research and is used-               in PortFusion: <http://portfusion.sf.net>+               This work is funded by Corsis Research and used in:+               .+               PortFusion ]-[ayabusa – German+               research project for building the simplest+               high-performance distributed reverse / forward proxy.+               .+               <https://sourceforge.net/p/portfusion/wiki/RoadMap/> license:       BSD3 license-file:  LICENSE author:        Cetin Sert <fusion@corsis.eu>
src/Network/Socket/Splice.hsc view
@@ -1,11 +1,24 @@--- |+{- |+  This library implements efficient socket to socket+  data transfer loops for proxy servers.+               +   On Linux, it uses 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 that allocates a+   constant-sized memory buffer before it enters an inner+   loop which then uses hGetBufSome and hPutBuf; this avoids+   lots of tiny allocations as would otherwise be caused by+   recv and sendAll functions from Network.Socket.ByteString.+-}+--   -- Module      : Network.Socket.Splice -- Copyright   : (c) Cetin Sert 2012 -- License     : BSD-style--- -- Maintainer  : fusion@corsis.eu -- Stability   : stable--- Portability : GHC-only+-- Portability : GHC-only, works on all OSes  #ifdef LINUX_SPLICE #include <fcntl.h>@@ -14,12 +27,40 @@ #endif  module Network.Socket.Splice (-    Length++  -- * 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.++       It is an /infinite loop/ that is intended to be used with+       'Control.Concurrent.forkIO':++       > void . forkIO . try_ $ splice 1024 sourceSocket targetSocket+       > void . forkIO . try_ $ splice 1024 targetSocket sourceSocket+  -}++    splice+  , ChunkSize   , zeroCopy-  , loopSplice++  -- * Combinators for Exception Handling+  , try_+++  -- * Linux splice() Components+  {- | These are available only on Linux and+       will be moved to a different namespace+       in later releases. Their names will stay+       the same.+  -}+ #ifdef LINUX_SPLICE   , c_splice+  , sPLICE_F_MOVE+  , sPLICE_F_MORE+  , sPLICE_F_NONBLOCK #endif+   ) where  import Data.Word@@ -45,9 +86,9 @@ #endif  --- | Indicates whether 'loopSplice' uses zero copy system calls+-- | Indicates whether 'splice' uses zero-copy system calls --   or the portable user mode Haskell substitue implementation.-zeroCopy :: Bool -- ^ True: system calls; otherwise: portable.+zeroCopy :: Bool -- ^ True: uses zero-copy system calls; otherwise: portable. zeroCopy = #ifdef LINUX_SPLICE   True@@ -58,31 +99,32 @@  -------------------------------------------------------------------------------- --type Length =+-- | The numeric type used to recommend chunk sizes for moving+--   data between sockets used by both the Linux 'splice' and+--   the portable implementation of 'splice'.+type ChunkSize = #ifdef LINUX_SPLICE   (#type size_t) #else   Int #endif -try_ :: IO () -> IO ()-try_ a = (try a :: IO (Either SomeException ())) >> return () ---- | The 'loopSplice' function pipes data from---   one socket to another in an infinite loop.+-- | Pipes data from one socket to another in an+--   **infinite loop**.+-- --   On Linux this happens in kernel space with---   zero copying, between kernel and user space.+--   zero copying between kernel and user spaces.+-- --   On other operating systems, a portable --   implementation utilizes a user space buffer --   and works on handles instead of file descriptors.-loopSplice-  :: Length    -- ^ Splice length-  -> Socket    -- ^ Source socket-  -> Socket    -- ^ Target socket-  -> IO ()-loopSplice len sIn sOut = do+splice+  :: ChunkSize -- ^ Chunk size.+  -> Socket    -- ^ Source socket.+  -> Socket    -- ^ Target socket.+  -> IO ()     -- ^ Infinite loop.+splice len sIn sOut = do    let throwRecv0 = error "Network.Socket.Splice.splice ended" @@ -139,6 +181,15 @@ #endif  +-- | Similar to 'Control.Exception.Base.try' but used when an+--   obvious exception is expected whose type can be safely+--   ignored.+try_+  :: IO () -- ^ The action to run which can throw any exception.+  -> IO () -- ^ The new action where exceptions are silenced.+try_ a = (try a :: IO (Either SomeException ())) >> return ()++ --------------------------------------------------------------------------------  @@ -155,19 +206,47 @@ --   unsigned int flags -- ); +-- | 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+--   file descriptor 'fd_out', where one of the+--   descriptors must refer to a pipe.+--+--   'c_splice' is NOT a loop and needs to called repeatedly.+--   For an example, see the source code of 'splice'. foreign import ccall "splice"   c_splice-  :: Fd-  -> Ptr (#type loff_t)-  -> Fd-  -> Ptr (#type loff_t)-  -> (#type size_t)-  -> Word-  -> IO (#type ssize_t)+  :: Fd                  -- ^ fd_in+  -> Ptr (#type loff_t)  -- ^ off_in+  -> Fd                  -- ^ fd_out+  -> Ptr (#type loff_t)  -- ^ off_out+  -> (#type size_t)      -- ^ len+  -> Word                -- ^ flags+  -> IO (#type ssize_t)  -- ^ number of bytes moved or -1 on error ++-- | Attempt to move pages instead of copying. This is+--   only a hint to the kernel: pages may stil be copied+--   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 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 splice pipe+--   operations nonblocking, but splice() may nevertheless+--   block because the file descriptors that are spliced+--   to/from may block (unless they have the O_NONBLOCK flag+--   set).+sPLICE_F_NONBLOCK :: Word+sPLICE_F_NONBLOCK = (#const "SPLICE_F_NONBLOCK")+ #endif