splice-0.6.1.1: Cross-platform Socket to Socket Data Splicing

Safe HaskellSafe-Infered

Network.Socket.Splice

Contents

Description

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 hGetBufSome and hPutBuf. This avoids lots of tiny allocations as would otherwise be caused by recv and sendAll from the bytestring package.

Synopsis

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 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
  • 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.

spliceSource

Arguments

:: 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.

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.

type ChunkSize = IntSource

The numeric type to recommend chunk sizes for moving data between sockets used by both zero-copy and portable implementations of splice.

zeroCopySource

Arguments

:: Bool

True if splice uses zero-copy system calls; otherwise, false.

Indicates whether splice uses zero-copy system calls or the portable user space Haskell implementation.

Combinators for Exception Handling

tryWithSource

Arguments

:: (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.

Similar to try but used when an obvious exception is expected and can be handled easily. Unlike finally exceptions are NOT rethrown once handled.

try_Source

Arguments

:: IO ()

action to run which can throw any exception.

-> IO ()

new action where exceptions are silenced.

Similar to try but used when an obvious exception is expected which can be safely ignored.

Implementation Primitives

Infinite loops used in the cross-platform implementation of splice.

hSplice :: Int -> Handle -> Handle -> IO ()Source

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.