Safe Haskell | Safe-Infered |
---|
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.
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
forkIO
:
void . forkIO . try_ $ splice 1024 sourceSocket targetSocket void . forkIO . try_ $ splice 1024 targetSocket sourceSocket
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 spaces.
On other operating systems, a portable implementation utilizes a user space buffer and works on handles instead of file descriptors.
:: Bool | True: uses zero-copy system calls; otherwise: portable. |
Indicates whether splice
uses zero-copy system calls
or the portable user mode Haskell substitue implementation.
Combinators for Exception Handling
:: IO () | The action to run which can throw any exception. |
-> IO () | The new action where exceptions are silenced. |
Similar to try
but used when an
obvious exception is expected whose type can be safely
ignored.
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.
:: Fd | fd_in |
-> Ptr Int64 | off_in |
-> Fd | fd_out |
-> Ptr Int64 | off_out |
-> Word32 | len |
-> Word | flags |
-> IO Int32 | number of bytes moved or -1 on error |
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
.
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.
More data will be coming in a subsequent splice.
This is a helpful hint when fd_out
refers to a
socket.
sPLICE_F_NONBLOCK :: WordSource
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).