pipes-network-0.6.4: Use network sockets together with the pipes library.

Safe HaskellNone
LanguageHaskell98

Pipes.Network.TCP.Safe

Contents

Description

This module exports facilities allowing you to safely obtain, use and release Socket resources within a Pipes pipeline, by relying on pipes-safe.

This module is meant to be used as a replacement of Pipes.Network.TCP, and as such it overrides some functions from Network.Simple.TCP so that they use MonadSafe instead of IO as their base monad. Additionally, It also exports pipes that establish a TCP connection and interact with it in a streaming fashion at once.

If you just want to use Socket obtained outside the Pipes pipeline, then you can just ignore this module and use the simpler module Pipes.Network.TCP instead.

Synopsis

MonadSafe-compatible upgrades

The following functions are analogous versions of those exported by Network.Simple.TCP, but compatible with MonadSafe.

connect :: MonadSafe m => HostName -> ServiceName -> ((Socket, SockAddr) -> m r) -> m r

Like connect from Network.Simple.TCP, but compatible with MonadSafe.

serve :: MonadSafe m => HostPreference -> ServiceName -> ((Socket, SockAddr) -> IO ()) -> m r

Like serve from Network.Simple.TCP, but compatible with MonadSafe.

listen :: MonadSafe m => HostPreference -> ServiceName -> ((Socket, SockAddr) -> m r) -> m r

Like listen from Network.Simple.TCP, but compatible with MonadSafe.

accept :: MonadSafe m => Socket -> ((Socket, SockAddr) -> m r) -> m r

Like accept from Network.Simple.TCP, but compatible with MonadSafe.

Streaming

Client side

The following pipes allow you to easily connect to a TCP server and immediately interact with it in a streaming fashion, all at once, instead of having to perform the individual steps separately. However, keep in mind that you'll be able to interact with the remote end in only one direction, that is, you'll either send or receive data, but not both.

fromConnect

Arguments

:: MonadSafe m 
=> Int

Maximum number of bytes to receive and send dowstream at once. Any positive value is fine, the optimal value depends on how you deal with the received data. Try using 4096 if you don't care.

-> HostName

Server host name.

-> ServiceName

Server service port.

-> Producer' ByteString m () 

Connect to a TCP server and send downstream the bytes received from the remote end.

The connection socket is closed when done or in case of exceptions.

Using this Producer' you can write straightforward code like the following, which prints whatever is received from a single TCP connection to a given server listening locally on port 9000, in chunks of up to 4096 bytes:

>>> runSafeT . runEffect $ fromConnect 4096 "127.0.0.1" "9000" >-> P.print

toConnect

Arguments

:: MonadSafe m 
=> HostName

Server host name.

-> ServiceName

Server service port.

-> Consumer' ByteString m r 

Connects to a TCP server, sends to the remote end the bytes received from upstream.

The connection socket is closed in case of exceptions.

Using this Consumer' you can write straightforward code like the following, which greets a TCP client listening locally at port 9000:

>>> :set -XOverloadedStrings
>>> runSafeT . runEffect $ each ["He","llo\r\n"] >-> toConnect "127.0.0.1" "9000"

toConnectLazy

Arguments

:: MonadSafe m 
=> HostName

Server host name.

-> ServiceName

Server service port.

-> Consumer' ByteString m r 

Like toConnect, but works more efficiently on lazy ByteStrings (compared to converting them to a strict ByteString and sending it)

toConnectMany

Arguments

:: MonadSafe m 
=> HostName

Server host name.

-> ServiceName

Server service port.

-> Consumer' [ByteString] m r 

Like toConnect, but works more efficiently on [ByteString] (compared to converting them to a strict ByteString and sending it)

Server side

The following pipes allow you to easily run a TCP server and immediately interact with incoming connections in a streaming fashion, all at once, instead of having to perform the individual steps separately. However, keep in mind that you'll be able to interact with the remote end in only one direction, that is, you'll either send or receive data, but not both.

fromServe

Arguments

:: MonadSafe m 
=> Int

Maximum number of bytes to receive and send dowstream at once. Any positive value is fine, the optimal value depends on how you deal with the received data. Try using 4096 if you don't care.

-> HostPreference

Preferred host to bind.

-> ServiceName

Service port to bind.

-> Producer' ByteString m () 

Binds a listening socket, accepts a single connection and sends downstream any bytes received from the remote end.

Less than the specified maximum number of bytes might be received at once.

This Producer' returns if the remote peer closes its side of the connection or EOF is received.

Both the listening and connection sockets are closed when done or in case of exceptions.

Using this Producer' you can write straightforward code like the following, which prints whatever is received from a single TCP connection to port 9000, in chunks of up to 4096 bytes.

>>> :set -XOverloadedStrings
>>> runSafeT . runEffect $ fromServe 4096 "127.0.0.1" "9000" >-> P.print

toServe

Arguments

:: MonadSafe m 
=> HostPreference

Preferred host to bind.

-> ServiceName

Service port to bind.

-> Consumer' ByteString m r 

Binds a listening socket, accepts a single connection, sends to the remote end the bytes received from upstream.

Both the listening and connection sockets are closed when done or in case of exceptions.

Using this Consumer' you can write straightforward code like the following, which greets a TCP client connecting to port 9000:

>>> :set -XOverloadedStrings
>>> runSafeT . runEffect $ each ["He","llo\r\n"] >-> toServe "127.0.0.1" "9000"

toServeLazy

Arguments

:: MonadSafe m 
=> HostPreference

Preferred host to bind.

-> ServiceName

Service port to bind.

-> Consumer' ByteString m r 

Like toServe, but works more efficiently on lazy ByteStrings (compared to converting them to a strict ByteString and sending it)

toServeMany

Arguments

:: MonadSafe m 
=> HostPreference

Preferred host to bind.

-> ServiceName

Service port to bind.

-> Consumer' [ByteString] m r 

Like toServe, but works more efficiently on [ByteString] (compared to converting them to a strict ByteString and sending it)

Exports

module Pipes.Safe