-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | High-level network sockets -- -- This library provides a high-level abstraction for network sockets. It -- uses Haskell2010 (along with GADTs) without typeclasses to ensure that -- consumers of the API can only call appropriate functions on a socket. -- -- Exceptions are tracked in the types of functions and returned to the -- caller with Either. The caller is free to handle these -- gracefully or to throw them. This library has another class of -- exceptions described as _unrecoverable_. This library only throws -- exceptions in three situations: -- -- @package sockets @version 0.4.0.0 module Socket.Address posixToIPv4Peer :: SocketAddressInternet -> Peer ipv4PeerToPosix :: Peer -> SocketAddressInternet -- | Internet datagram sockets with a fixed destination. module Socket.Datagram.IPv4.Connected newtype Socket (a :: Connectedness) (b :: Family) Socket :: Fd -> Socket data Peer Peer :: !IPv4 -> !Word16 -> Peer [$sel:address:Peer] :: Peer -> !IPv4 [$sel:port:Peer] :: Peer -> !Word16 data Message Message :: {-# UNPACK #-} !Peer -> !ByteArray -> Message [$sel:peer:Message] :: Message -> {-# UNPACK #-} !Peer [$sel:payload:Message] :: Message -> !ByteArray withSocket :: Peer -> Peer -> (Socket 'Connected ( 'Internet 'V4) -> Word16 -> IO a) -> IO (Either SocketException a) data SocketException SocketPermissionDenied :: SocketException SocketAddressInUse :: SocketException SocketEphemeralPortsExhausted :: SocketException SocketFileDescriptorLimit :: SocketException -- | Internet datagram sockets without a fixed destination. module Socket.Datagram.IPv4.Unconnected newtype Socket (a :: Connectedness) (b :: Family) Socket :: Fd -> Socket data Peer Peer :: !IPv4 -> !Word16 -> Peer [$sel:address:Peer] :: Peer -> !IPv4 [$sel:port:Peer] :: Peer -> !Word16 data Message Message :: {-# UNPACK #-} !Peer -> !ByteArray -> Message [$sel:peer:Message] :: Message -> {-# UNPACK #-} !Peer [$sel:payload:Message] :: Message -> !ByteArray -- | Open a socket and run the supplied callback on it. This closes the -- socket when the callback finishes or when an exception is thrown. Do -- not return the socket from the callback. This leads to undefined -- behavior. If the address 0.0.0.0 is used, the socket receives -- on all network interfaces. If the port 0 is used, an unused port is -- chosen by the operating system. The callback provides the chosen port -- (or if the user specified a non-zero port, the chosen port will be -- that value). withSocket :: Peer -> (Socket 'Unconnected ( 'Internet 'V4) -> Word16 -> IO a) -> IO (Either SocketException a) data SocketException SocketPermissionDenied :: SocketException SocketAddressInUse :: SocketException SocketEphemeralPortsExhausted :: SocketException SocketFileDescriptorLimit :: SocketException module Socket.Datagram.Interruptible.MutableBytes -- | Send a datagram using a socket with a pre-designated peer. This refers -- to a datagram socket for which POSIX connect has locked down -- communication to an individual peer. send :: TVar Bool -> Socket 'Connected a -> MutableBytes RealWorld -> IO (Either (SendException 'Interruptible) ()) sendToIPv4 :: TVar Bool -> Socket 'Unconnected ( 'Internet 'V4) -> Peer -> MutableBytes RealWorld -> IO (Either (SendException 'Interruptible) ()) -- | Receive a datagram, discarding the peer address. This can be used with -- datagram sockets of any family. It is usable with both connected and -- unconnected datagram sockets. receive :: TVar Bool -> Socket c a -> MutableBytes RealWorld -> IO (Either (ReceiveException 'Interruptible) Int) receiveFromIPv4 :: TVar Bool -> Socket 'Unconnected ( 'Internet 'V4) -> MutableBytes RealWorld -> MutablePrimArrayOffset RealWorld SocketAddressInternet -> IO (Either (ReceiveException 'Interruptible) Int) -- | Receive up to the specified number of datagrams into freshly allocated -- byte arrays. When there are many datagrams present in the receive -- buffer, this is more efficient than calling receive -- repeatedly. This is guaranteed to fill the buffer with at least one -- message. -- -- The length buffer and the payload buffers arrange data in a -- structure-of-arrays fashion. The size of the payload received into -- payloads[j] is stored at lengths[j]. receiveMany :: TVar Bool -> Socket c a -> PeerlessSlab -> IO (Either (ReceiveException 'Interruptible) Int) -- | Variant of receiveMany that provides that source address -- corresponding to each datagram. This introduces another array to the -- structure-of-arrays. receiveManyFromIPv4 :: TVar Bool -> Socket 'Unconnected ( 'Internet 'V4) -> IPv4Slab -> IO (Either (ReceiveException 'Interruptible) Int) module Socket.Datagram.Interruptible.Bytes -- | Receive a datagram, discarding the peer address. This can be used with -- datagram sockets of any family. It is usable with both connected and -- unconnected datagram sockets. receive :: TVar Bool -> Socket c a -> Int -> IO (Either (ReceiveException 'Interruptible) ByteArray) receiveFromIPv4 :: TVar Bool -> Socket 'Unconnected ( 'Internet 'V4) -> Int -> IO (Either (ReceiveException 'Interruptible) Message) receiveMany :: TVar Bool -> Socket 'Unconnected ( 'Internet 'V4) -> PeerlessSlab -> IO (Either (ReceiveException 'Interruptible) (UnliftedArray ByteArray)) receiveManyFromIPv4 :: TVar Bool -> Socket 'Unconnected ( 'Internet 'V4) -> IPv4Slab -> IO (Either (ReceiveException 'Interruptible) (SmallArray Message)) module Socket.Datagram.Slab data PeerlessSlab PeerlessSlab :: !MutablePrimArray RealWorld CInt -> !MutableUnliftedArray RealWorld (MutableByteArray RealWorld) -> PeerlessSlab [$sel:sizes:PeerlessSlab] :: PeerlessSlab -> !MutablePrimArray RealWorld CInt [$sel:payloads:PeerlessSlab] :: PeerlessSlab -> !MutableUnliftedArray RealWorld (MutableByteArray RealWorld) data IPv4Slab IPv4Slab :: !MutablePrimArray RealWorld CInt -> !MutablePrimArray RealWorld SocketAddressInternet -> !MutableUnliftedArray RealWorld (MutableByteArray RealWorld) -> IPv4Slab [$sel:sizes:IPv4Slab] :: IPv4Slab -> !MutablePrimArray RealWorld CInt [$sel:peers:IPv4Slab] :: IPv4Slab -> !MutablePrimArray RealWorld SocketAddressInternet [$sel:payloads:IPv4Slab] :: IPv4Slab -> !MutableUnliftedArray RealWorld (MutableByteArray RealWorld) newPeerlessSlab :: Int -> Int -> IO PeerlessSlab newIPv4Slab :: Int -> Int -> IO IPv4Slab freezePeerlessSlab :: PeerlessSlab -> Int -> IO (UnliftedArray ByteArray) freezeIPv4Slab :: IPv4Slab -> Int -> IO (SmallArray Message) module Socket.Datagram.Uninterruptible.MutableBytes -- | Send a datagram using a socket with a pre-designated peer. This refers -- to a datagram socket for which POSIX connect has locked down -- communication to an individual peer. send :: Socket 'Connected a -> MutableBytes RealWorld -> IO (Either (SendException 'Uninterruptible) ()) sendToIPv4 :: Socket 'Unconnected ( 'Internet 'V4) -> Peer -> MutableBytes RealWorld -> IO (Either (SendException 'Uninterruptible) ()) -- | Receive a datagram, discarding the peer address. This can be used with -- datagram sockets of any family. It is usable with both connected and -- unconnected datagram sockets. receive :: Socket c a -> MutableBytes RealWorld -> IO (Either (ReceiveException 'Uninterruptible) Int) receiveFromIPv4 :: Socket 'Unconnected ( 'Internet 'V4) -> MutableBytes RealWorld -> MutablePrimArrayOffset RealWorld SocketAddressInternet -> IO (Either (ReceiveException 'Uninterruptible) Int) -- | Receive up to the specified number of datagrams into freshly allocated -- byte arrays. When there are many datagrams present in the receive -- buffer, this is more efficient than calling receive -- repeatedly. This is guaranteed to fill the buffer with at least one -- message. -- -- The length buffer and the payload buffers arrange data in a -- structure-of-arrays fashion. The size of the payload received into -- payloads[j] is stored at lengths[j]. receiveMany :: Socket c a -> PeerlessSlab -> IO (Either (ReceiveException 'Uninterruptible) Int) -- | Variant of receiveMany that provides that source address -- corresponding to each datagram. This introduces another array to the -- structure-of-arrays. receiveManyFromIPv4 :: Socket 'Unconnected ( 'Internet 'V4) -> IPv4Slab -> IO (Either (ReceiveException 'Uninterruptible) Int) data PeerlessSlab PeerlessSlab :: !MutablePrimArray RealWorld CInt -> !MutableUnliftedArray RealWorld (MutableByteArray RealWorld) -> PeerlessSlab [$sel:sizes:PeerlessSlab] :: PeerlessSlab -> !MutablePrimArray RealWorld CInt [$sel:payloads:PeerlessSlab] :: PeerlessSlab -> !MutableUnliftedArray RealWorld (MutableByteArray RealWorld) data IPv4Slab IPv4Slab :: !MutablePrimArray RealWorld CInt -> !MutablePrimArray RealWorld SocketAddressInternet -> !MutableUnliftedArray RealWorld (MutableByteArray RealWorld) -> IPv4Slab [$sel:sizes:IPv4Slab] :: IPv4Slab -> !MutablePrimArray RealWorld CInt [$sel:peers:IPv4Slab] :: IPv4Slab -> !MutablePrimArray RealWorld SocketAddressInternet [$sel:payloads:IPv4Slab] :: IPv4Slab -> !MutableUnliftedArray RealWorld (MutableByteArray RealWorld) newPeerlessSlab :: Int -> Int -> IO PeerlessSlab newIPv4Slab :: Int -> Int -> IO IPv4Slab module Socket.Datagram.Uninterruptible.Bytes -- | Send a datagram using a socket with a pre-designated peer. This refers -- to a datagram socket for which POSIX connect has locked down -- communication to an individual peer. send :: Socket 'Connected a -> Bytes -> IO (Either (SendException 'Uninterruptible) ()) sendToIPv4 :: Socket 'Unconnected ( 'Internet 'V4) -> Peer -> Bytes -> IO (Either (SendException 'Uninterruptible) ()) -- | Receive a datagram, discarding the peer address. This can be used with -- datagram sockets of any family. It is usable with both connected and -- unconnected datagram sockets. receive :: Socket c a -> Int -> IO (Either (ReceiveException 'Uninterruptible) ByteArray) receiveFromIPv4 :: Socket 'Unconnected ( 'Internet 'V4) -> Int -> IO (Either (ReceiveException 'Uninterruptible) Message) receiveMany :: Socket 'Unconnected ( 'Internet 'V4) -> PeerlessSlab -> IO (Either (ReceiveException 'Uninterruptible) (UnliftedArray ByteArray)) receiveManyFromIPv4 :: Socket 'Unconnected ( 'Internet 'V4) -> IPv4Slab -> IO (Either (ReceiveException 'Uninterruptible) (SmallArray Message)) data Message Message :: {-# UNPACK #-} !Peer -> !ByteArray -> Message [$sel:peer:Message] :: Message -> {-# UNPACK #-} !Peer [$sel:payload:Message] :: Message -> !ByteArray data Peer Peer :: !IPv4 -> !Word16 -> Peer [$sel:address:Peer] :: Peer -> !IPv4 [$sel:port:Peer] :: Peer -> !Word16 data ReceiveException (a :: Interruptibility) [ReceiveTruncated] :: forall (a :: Interruptibility). () => !Int -> ReceiveException a [ReceiveInterrupted] :: forall (a :: Interruptibility). () => ReceiveException Interruptible data PeerlessSlab PeerlessSlab :: !MutablePrimArray RealWorld CInt -> !MutableUnliftedArray RealWorld (MutableByteArray RealWorld) -> PeerlessSlab [$sel:sizes:PeerlessSlab] :: PeerlessSlab -> !MutablePrimArray RealWorld CInt [$sel:payloads:PeerlessSlab] :: PeerlessSlab -> !MutableUnliftedArray RealWorld (MutableByteArray RealWorld) data IPv4Slab IPv4Slab :: !MutablePrimArray RealWorld CInt -> !MutablePrimArray RealWorld SocketAddressInternet -> !MutableUnliftedArray RealWorld (MutableByteArray RealWorld) -> IPv4Slab [$sel:sizes:IPv4Slab] :: IPv4Slab -> !MutablePrimArray RealWorld CInt [$sel:peers:IPv4Slab] :: IPv4Slab -> !MutablePrimArray RealWorld SocketAddressInternet [$sel:payloads:IPv4Slab] :: IPv4Slab -> !MutableUnliftedArray RealWorld (MutableByteArray RealWorld) newPeerlessSlab :: Int -> Int -> IO PeerlessSlab newIPv4Slab :: Int -> Int -> IO IPv4Slab module Socket.Stream.IPv4 -- | A socket that listens for incomming connections. data Listener newtype Connection Connection :: Fd -> Connection data Peer Peer :: !IPv4 -> !Word16 -> Peer [$sel:address:Peer] :: Peer -> !IPv4 [$sel:port:Peer] :: Peer -> !Word16 -- | Open a socket that is used to listen for inbound connections. withListener :: Peer -> (Listener -> Word16 -> IO a) -> IO (Either SocketException a) -- | Accept a connection on the listener and run the supplied callback on -- it. This closes the connection when the callback finishes or if an -- exception is thrown. Since this function blocks the thread until the -- callback finishes, it is only suitable for stream socket clients that -- handle one connection at a time. The variant -- forkAcceptedUnmasked is preferrable for servers that need to -- handle connections concurrently (most use cases). withAccepted :: Listener -> (Either CloseException () -> a -> IO b) -> (Connection -> Peer -> IO a) -> IO (Either (AcceptException 'Uninterruptible) b) -- | Establish a connection to a server. withConnection :: Peer -> (Either CloseException () -> a -> IO b) -> (Connection -> IO a) -> IO (Either (ConnectException ( 'Internet 'V4) 'Uninterruptible) b) -- | Accept a connection on the listener and run the supplied callback in a -- new thread. Prefer forkAcceptedUnmasked unless the masking -- state needs to be preserved for the callback. Such a situation seems -- unlikely to the author. forkAccepted :: Listener -> (Either CloseException () -> a -> IO ()) -> (Connection -> Peer -> IO a) -> IO (Either (AcceptException 'Uninterruptible) ThreadId) -- | Accept a connection on the listener and run the supplied callback in a -- new thread. The masking state is set to Unmasked when running -- the callback. Typically, a is instantiated to (). forkAcceptedUnmasked :: Listener -> (Either CloseException () -> a -> IO ()) -> (Connection -> Peer -> IO a) -> IO (Either (AcceptException 'Uninterruptible) ThreadId) -- | Accept a connection on the listener and run the supplied callback in a -- new thread. The masking state is set to Unmasked when running -- the callback. Typically, a is instantiated to (). -- --

Discussion

-- -- Why is the counter argument present? At first, it seems like -- this is something that the API consumer should implement on top of -- this library. The argument for the inclusion of the counter is has two -- parts: (1) clients supporting graceful termination always need these -- semantics and (2) these semantics cannot be provided without building -- in counter as a TVar. -- --
    --
  1. Clients supporting graceful termination always need these -- semantics. To gracefully bring down a server that has been accepting -- connections with a forking function, an application must wait for all -- active connections to finish. Since all connections run on separate -- threads, this can only be accomplished by a concurrency primitive. The -- straightforward solution is to wrap a counter with either -- MVar or TVar. To complete graceful termination, the -- application must block until the counter reaches zero.
  2. --
  3. These semantics cannot be provided without building in -- counter as a TVar. When abandon becomes -- True, graceful termination begins. From this point onward, if -- at any point the counter reaches zero, the application consuming this -- API will complete termination. Consequently, we need the guarantee -- that the counter does not increment after the abandon -- transaction completes. If it did increment in this forbidden way (e.g. -- if it was incremented some unspecified amount of time after a -- connection was accepted), there would be a race condition in which the -- application may terminate without giving the newly accepted connection -- a chance to finish. Fortunately, STM gives us the composable -- transaction we need to get this guarantee. To wait for an inbound -- connection, we use:
  4. --
-- --
--   (isReady,deregister) <- threadWaitReadSTM fd
--   shouldReceive <- atomically $ do
--     readTVar abandon >>= \case
--       True -> do
--         isReady
--         modifyTVar' counter (+1)
--         pure True
--       False -> pure False
--   
-- -- This eliminates the window for the race condition. If a connection is -- accepted, the counter is guaranteed to be incremented _before_ -- abandon becomes True. However, this code would be -- more simple and would perform better if GHC's event manager used TVar -- instead of STM. interruptibleForkAcceptedUnmasked :: TVar Int -> TVar Bool -> Listener -> (Either CloseException () -> a -> IO ()) -> (Connection -> Peer -> IO a) -> IO (Either (AcceptException 'Interruptible) ThreadId) data SendException (a :: Interruptibility) [SendShutdown] :: forall (a :: Interruptibility). () => SendException a [SendReset] :: forall (a :: Interruptibility). () => SendException a [SendInterrupted] :: forall (a :: Interruptibility). () => !Int -> SendException Interruptible data ReceiveException (a :: Interruptibility) [ReceiveShutdown] :: forall (a :: Interruptibility). () => ReceiveException a [ReceiveReset] :: forall (a :: Interruptibility). () => ReceiveException a [ReceiveInterrupted] :: forall (a :: Interruptibility). () => !Int -> ReceiveException Interruptible [ReceiveHostUnreachable] :: forall (a :: Interruptibility). () => ReceiveException a data ConnectException (a :: Family) (b :: Interruptibility) [ConnectFirewalled] :: forall (a :: Family) (b :: Interruptibility). () => ConnectException a b [ConnectFileDescriptorLimit] :: forall (a :: Family) (b :: Interruptibility). () => ConnectException a b [ConnectNetworkUnreachable] :: forall (a :: Family) (b :: Interruptibility) (v :: Version). () => ConnectException (Internet v) b [ConnectHostUnreachable] :: forall (a :: Family) (b :: Interruptibility) (v :: Version). () => ConnectException (Internet v) b [ConnectEphemeralPortsExhausted] :: forall (a :: Family) (b :: Interruptibility). () => ConnectException a b [ConnectRefused] :: forall (a :: Family) (b :: Interruptibility). () => ConnectException a b [ConnectTimeout] :: forall (a :: Family) (b :: Interruptibility). () => ConnectException a b [ConnectProtocolType] :: forall (a :: Family) (b :: Interruptibility). () => ConnectException Unix b [ConnectInterrupted] :: forall (a :: Family) (b :: Interruptibility). () => ConnectException a Interruptible data SocketException SocketPermissionDenied :: SocketException SocketAddressInUse :: SocketException SocketEphemeralPortsExhausted :: SocketException SocketFileDescriptorLimit :: SocketException data AcceptException (a :: Interruptibility) [AcceptConnectionAborted] :: forall (a :: Interruptibility). () => AcceptException a [AcceptFileDescriptorLimit] :: forall (a :: Interruptibility). () => AcceptException a [AcceptFirewalled] :: forall (a :: Interruptibility). () => AcceptException a [AcceptInterrupted] :: forall (a :: Interruptibility). () => AcceptException Interruptible data CloseException ClosePeerContinuedSending :: CloseException data Interruptibility Interruptible :: Interruptibility Uninterruptible :: Interruptibility data Family Internet :: Version -> Family Unix :: Family data Version V4 :: Version V6 :: Version -- | Open a socket that can be used to listen for inbound connections. -- Requirements: -- -- -- -- Noncompliant use of this function leads to undefined behavior. Prefer -- withListener unless you are writing an integration with a -- resource-management library. listen :: Peer -> IO (Either SocketException (Listener, Word16)) -- | Close a listener. This throws an unrecoverable exception if the socket -- cannot be closed. unlisten :: Listener -> IO () -- | Close a listener. This does not check to see whether or not the -- operating system successfully closed the socket. It never throws -- exceptions of any kind. This should only be preferred to -- unlistener in exception-cleanup contexts where there is -- already an exception that will be rethrown. See the implementation of -- withListener for an example of appropriate use of both -- unlistener and unlistener_. unlisten_ :: Listener -> IO () -- | Open a socket and connect to a peer. Requirements: -- -- -- -- Noncompliant use of this function leads to undefined behavior. Prefer -- withConnection unless you are writing an integration with a -- resource-management library. connect :: Peer -> IO (Either (ConnectException ( 'Internet 'V4) 'Uninterruptible) Connection) -- | Close a connection gracefully, reporting a CloseException when -- the connection has to be terminated by sending a TCP reset. This uses -- a combination of shutdown, recv, close to -- detect when resets need to be sent. disconnect :: Connection -> IO (Either CloseException ()) -- | Close a connection. This does not check to see whether or not the -- connection was brought down gracefully. It just calls close -- and is likely to cause a TCP reset to be sent. It never throws -- exceptions of any kind (even if close fails). This should -- only be preferred to disconnect in exception-cleanup contexts -- where there is already an exception that will be rethrown. See the -- implementation of withConnection for an example of appropriate -- use of both disconnect and disconnect_. disconnect_ :: Connection -> IO () -- | Listen for an inbound connection. accept :: Listener -> IO (Either (AcceptException 'Uninterruptible) (Connection, Peer)) -- | Listen for an inbound connection. Can be interrupted by an STM-style -- interrupt. interruptibleAccept :: TVar Bool -> Listener -> IO (Either (AcceptException 'Interruptible) (Connection, Peer)) module Socket.Stream.Interruptible.Addr -- | Send an exact number of bytes starting from a given address. If -- needed, this calls POSIX send repeatedly until the requested -- number of bytes has been sent. send :: TVar Bool -> Connection -> Addr -> Int -> IO (Either (SendException 'Interruptible) ()) -- | Receive the requested number of bytes into memory beginning at the -- specified address. If needed, this may call recv repeatedly -- until the requested number of bytes have been received. receiveExactly :: TVar Bool -> Connection -> Addr -> Int -> IO (Either (ReceiveException 'Interruptible) ()) -- | Receive at most the specified number of bytes. This only makes -- multiple calls to POSIX recv if EAGAIN is returned. It makes -- at most one recv call that successfully fills the buffer. receiveOnce :: TVar Bool -> Connection -> Addr -> Int -> IO (Either (ReceiveException 'Interruptible) Int) -- | Receive a number of bytes that is between the inclusive lower and -- upper bounds. If needed, this may call recv repeatedly until -- the minimum requested number of bytes have been received. receiveBetween :: TVar Bool -> Connection -> Addr -> Int -> Int -> IO (Either (ReceiveException 'Interruptible) Int) module Socket.Stream.Interruptible.ByteString -- | Send a slice of a buffer. If needed, this calls POSIX send -- repeatedly until the entire contents of the buffer slice have been -- sent. send :: TVar Bool -> Connection -> ByteString -> IO (Either (SendException 'Interruptible) ()) -- | Receive a number of bytes exactly equal to the length of the buffer -- slice. If needed, this may call recv repeatedly until the -- requested number of bytes have been received. receiveExactly :: TVar Bool -> Connection -> Int -> IO (Either (ReceiveException 'Interruptible) ByteString) -- | Receive at most the specified number of bytes. This only makes -- multiple calls to POSIX recv if EAGAIN is returned. It makes -- at most one recv call that successfully fills the buffer. receiveOnce :: TVar Bool -> Connection -> Int -> IO (Either (ReceiveException 'Interruptible) ByteString) -- | Receive a number of bytes that is between the inclusive lower and -- upper bounds. If needed, this may call recv repeatedly until -- the minimum requested number of bytes have been received. receiveBetween :: TVar Bool -> Connection -> Int -> Int -> IO (Either (ReceiveException 'Interruptible) ByteString) module Socket.Stream.Interruptible.Bytes -- | Send a slice of a buffer. If needed, this calls POSIX send -- repeatedly until the entire contents of the buffer slice have been -- sent. send :: TVar Bool -> Connection -> Bytes -> IO (Either (SendException 'Interruptible) ()) -- | Receive a number of bytes exactly equal to the length of the buffer -- slice. If needed, this may call recv repeatedly until the -- requested number of bytes have been received. receiveExactly :: TVar Bool -> Connection -> Int -> IO (Either (ReceiveException 'Interruptible) ByteArray) -- | Receive at most the specified number of bytes. This only makes -- multiple calls to POSIX recv if EAGAIN is returned. It makes -- at most one recv call that successfully fills the buffer. receiveOnce :: TVar Bool -> Connection -> Int -> IO (Either (ReceiveException 'Interruptible) ByteArray) -- | Receive a number of bytes that is between the inclusive lower and -- upper bounds. If needed, this may call recv repeatedly until -- the minimum requested number of bytes have been received. receiveBetween :: TVar Bool -> Connection -> Int -> Int -> IO (Either (ReceiveException 'Interruptible) ByteArray) module Socket.Stream.Interruptible.Hybrid sendMutableBytesUnmanagedBytes :: TVar Bool -> Connection -> MutableBytes RealWorld -> UnmanagedBytes -> IO (Either (SendException 'Interruptible) ()) module Socket.Stream.Interruptible.MutableBytes -- | Send a slice of a buffer. If needed, this calls POSIX send -- repeatedly until the entire contents of the buffer slice have been -- sent. send :: TVar Bool -> Connection -> MutableBytes RealWorld -> IO (Either (SendException 'Interruptible) ()) -- | Send as much of the buffer slice as there is space for in the TCP send -- buffer. Returns the number of bytes sent. sendOnce :: TVar Bool -> Connection -> MutableBytes RealWorld -> IO (Either (SendException 'Interruptible) Int) -- | Receive a number of bytes exactly equal to the length of the buffer -- slice. If needed, this may call recv repeatedly until the -- requested number of bytes have been received. receiveExactly :: TVar Bool -> Connection -> MutableBytes RealWorld -> IO (Either (ReceiveException 'Interruptible) ()) -- | Receive a number of bytes exactly equal to the length of the slice. -- This only makes multiple calls to POSIX recv if EAGAIN is -- returned. It makes at most one recv call that successfully -- fills the buffer. receiveOnce :: TVar Bool -> Connection -> MutableBytes RealWorld -> IO (Either (ReceiveException 'Interruptible) Int) -- | Receive a number of bytes that is at least the minimum size and is at -- most the length of the slice. If needed, this may call recv -- repeatedly until the minimum requested number of bytes have been -- received. receiveBetween :: TVar Bool -> Connection -> MutableBytes RealWorld -> Int -> IO (Either (ReceiveException 'Interruptible) Int) module Socket.Stream.Uninterruptible.Addr -- | Send an exact number of bytes starting from a given address. If -- needed, this calls POSIX send repeatedly until the requested -- number of bytes has been sent. send :: Connection -> Addr -> Int -> IO (Either (SendException 'Uninterruptible) ()) -- | Receive the requested number of bytes into memory beginning at the -- specified address. If needed, this may call recv repeatedly -- until the requested number of bytes have been received. receiveExactly :: Connection -> Addr -> Int -> IO (Either (ReceiveException 'Uninterruptible) ()) -- | Receive at most the specified number of bytes. This only makes -- multiple calls to POSIX recv if EAGAIN is returned. It makes -- at most one recv call that successfully fills the buffer. receiveOnce :: Connection -> Addr -> Int -> IO (Either (ReceiveException 'Uninterruptible) Int) -- | Receive a number of bytes that is between the inclusive lower and -- upper bounds. If needed, this may call recv repeatedly until -- the minimum requested number of bytes have been received. receiveBetween :: Connection -> Addr -> Int -> Int -> IO (Either (ReceiveException 'Uninterruptible) Int) module Socket.Stream.Uninterruptible.ByteString -- | Send a slice of a buffer. If needed, this calls POSIX send -- repeatedly until the entire contents of the buffer slice have been -- sent. send :: Connection -> ByteString -> IO (Either (SendException 'Uninterruptible) ()) -- | Receive a number of bytes exactly equal to the length of the buffer -- slice. If needed, this may call recv repeatedly until the -- requested number of bytes have been received. receiveExactly :: Connection -> Int -> IO (Either (ReceiveException 'Uninterruptible) ByteString) -- | Receive at most the specified number of bytes. This only makes -- multiple calls to POSIX recv if EAGAIN is returned. It makes -- at most one recv call that successfully fills the buffer. receiveOnce :: Connection -> Int -> IO (Either (ReceiveException 'Uninterruptible) ByteString) -- | Receive a number of bytes that is between the inclusive lower and -- upper bounds. If needed, this may call recv repeatedly until -- the minimum requested number of bytes have been received. receiveBetween :: Connection -> Int -> Int -> IO (Either (ReceiveException 'Uninterruptible) ByteString) -- | Communicate over a connection using immutable byte arrays. Reception -- functions return ByteArray instead of Bytes since this -- result always takes up the entirity of a ByteArray. The -- Bytes would have redundant information since the offset would -- be zero and the length would be the length of the ByteArray -- payload. module Socket.Stream.Uninterruptible.Bytes -- | Send a slice of a buffer. If needed, this calls POSIX send -- repeatedly until the entire contents of the buffer slice have been -- sent. send :: Connection -> Bytes -> IO (Either (SendException 'Uninterruptible) ()) -- | Receive a number of bytes exactly equal to the length of the buffer -- slice. If needed, this may call recv repeatedly until the -- requested number of bytes have been received. receiveExactly :: Connection -> Int -> IO (Either (ReceiveException 'Uninterruptible) ByteArray) -- | Receive at most the specified number of bytes. This only makes -- multiple calls to POSIX recv if EAGAIN is returned. It makes -- at most one recv call that successfully fills the buffer. receiveOnce :: Connection -> Int -> IO (Either (ReceiveException 'Uninterruptible) ByteArray) -- | Receive a number of bytes that is between the inclusive lower and -- upper bounds. If needed, this may call recv repeatedly until -- the minimum requested number of bytes have been received. receiveBetween :: Connection -> Int -> Int -> IO (Either (ReceiveException 'Uninterruptible) ByteArray) module Socket.Stream.Uninterruptible.Hybrid sendMutableBytesUnmanagedBytes :: Connection -> MutableBytes RealWorld -> UnmanagedBytes -> IO (Either (SendException 'Uninterruptible) ()) module Socket.Stream.Uninterruptible.MutableBytes -- | Send a slice of a buffer. If needed, this calls POSIX send -- repeatedly until the entire contents of the buffer slice have been -- sent. send :: Connection -> MutableBytes RealWorld -> IO (Either (SendException 'Uninterruptible) ()) -- | Receive a number of bytes exactly equal to the length of the buffer -- slice. If needed, this may call recv repeatedly until the -- requested number of bytes have been received. receiveExactly :: Connection -> MutableBytes RealWorld -> IO (Either (ReceiveException 'Uninterruptible) ()) -- | Receive a number of bytes exactly equal to the length of the slice. -- This only makes multiple calls to POSIX recv if EAGAIN is -- returned. It makes at most one recv call that successfully -- fills the buffer. receiveOnce :: Connection -> MutableBytes RealWorld -> IO (Either (ReceiveException 'Uninterruptible) Int) -- | Receive a number of bytes that is at least the minimum size and is at -- most the length of the slice. If needed, this may call recv -- repeatedly until the minimum requested number of bytes have been -- received. receiveBetween :: Connection -> MutableBytes RealWorld -> Int -> IO (Either (ReceiveException 'Uninterruptible) Int)