network-connection-0.1.1: A wrapper around a generic stream-like connection

Stabilityexperimental
MaintainerAdam Langley <agl@imperialviolet.org>

Network.Connection

Contents

Description

Helpful functions to deal with stream-like connections

Synopsis

Base connections

data BaseConnection Source

A BaseConnection abstracts a stream like connection.

Constructors

BaseConnection 

Fields

baseRead :: Int -> IO ByteString

Read, at most, the given number of bytes from the connection and return a ByteString of the data. EOF is signaled by an exception and a zero length string is never a valid return value

baseWrite :: ByteString -> IO Int

Write the given ByteString to the connection. The write may write less than the requested number of bytes (but must always write at least one byte)

baseClose :: IO ()

Close a connection

baseConnectionFromSocket :: Socket -> BaseConnectionSource

Return a BaseConnection for the given socket.

Connection functions

data Connection Source

A Connection uses the functions from a BaseConnection and wraps them a number of commonly needed behaviours.

Firstly, a write queue is introduced so that writes can be non-blocking.

Secondly, the Connection can manage a number of threads. Almost always there will be a writer thread which is taking items from the write queue and writing them to the BaseConnection. In addition, there can be zero or more other threads managed by the Connection. If a thread which is managed dies, by throwing an exception or otherwise, it will close the connection and all other managed threads will be killed.

There is also the concept of pushing data back into the Connection. This is useful in a chain of reader functions where, for efficiency reasons, you would want to read large blocks at a time, but the data is self-deliminating so you would otherwise end up in a situation where you had read too much. See the pushBack function for details.

newSource

Arguments

:: IO ()

the action to run when the connection closes

-> BaseConnection

the socket-like object to make a connection from

-> IO Connection 

Create a new Connection from a BaseConnection object

newSTMSource

Arguments

:: IO ()

the action run when the connection closes

-> BaseConnection

the socket-like object to make a connection from

-> STM Connection 

This creates most of a Connection, purely in the STM monad. The Connection returned from this must be passed to forkWriterThread, otherwise nothing will ever get written.

forkWriterThreadSource

Arguments

:: Connection

the connection to fork the writer thread for

-> IO () 

If you created the Connection in the STM monad using newSTM, you need to call this on it in order to create the thread which processes the outgoing queue.

forkInConnectionSource

Arguments

:: Connection

the connection to close on death

-> IO ()

the action to run

-> IO () 

Run the given action, as if by forkIO, and manage the thread. If the given action completes or throws an exception, the connection will be closed and all other managed threads will be killed

close :: Connection -> IO ()Source

Close a connection

write :: Connection -> ByteString -> STM ()Source

Enqueue a ByteString to a connection. This does not block.

writeAtLowWaterSource

Arguments

:: Int

the max number of bytes in the queue before we enqueue anything

-> Connection

the connection to write to

-> ByteString

the data to enqueue

-> STM () 

Block until the write queue has less than the given number of bytes in it then enqueue a new ByteString.

read :: Connection -> Int -> IO ByteStringSource

Read some number of bytes from a connection. The size is only a hint, the returned data may be shorter. A zero length read is EOF

reada :: Connection -> Int -> IO ByteStringSource

Read exactly a give number of bytes

pushBack :: Connection -> ByteString -> STM ()Source

Unread some amount of data. It will be returned in the next call to read.

The function pushes data to the front of the queue. Thus you need to push all the data base in one go, or the order of future reads will be wrong.

This might seem like an error, but consider the case of two actions: the first reads 20 bytes and pushs back the last 10 of them. The second reads 5 bytes and pushs back the last 4. If we appended to the push back queue the second action would put those 4 bytes after the remaining 5 from the first action.