-- 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:
--
--
-- - The library detects that it has misused the operating system's
-- sockets API. This includes getting a sockaddr with an
-- unexpected socket family. It also includes getting an error code that
-- should not be possible. For example, the abstractions provided for
-- both datagram sockets and stream sockets mean that send system
-- calls in either context should never return the error code
-- ENOTCONN. Consequently, this error is treated as
-- unrecoverable.
-- - The caller asks for a negatively-sized slice of a buffer (such
-- exceptions indicate a mistake in the code consuming this API).
-- - A system call fails with ENOBUFS or ENOMEM. These
-- indicate that the operating system is out of memory. If this happens,
-- the Out Of Memory (OOM) manager is likely killing processes to reclaim
-- memory, so the process that received this message may be killed soon.
-- Making things even worse is that the GHC runtime requests pages of
-- memory from the operating system at times that are effectively
-- unpredictable to Haskell developers. (Most memory-managed languages
-- have this behavior). Any attempt to recover from ENOBUFS or
-- ENOMEM might cause the runtime to allocate memory from the
-- operating system. According to the documentation for the
-- HeapOverflow exception, an allocation failure at this point in
-- time (likely given the recent ENOBUFS/ENOMEM) would
-- result in immidiate termination of the program. So, although it is
-- technically possible to recover from ENOBUFS/ENOMEM, the
-- OOM killer and the GHC runtime make it impossible to do so reliably.
-- Consequently, these error codes are treated as fatal.
--
@package sockets
@version 0.3.1.0
-- | Internet datagram sockets without a fixed destination.
module Socket.Datagram.IPv4.Undestined
-- | A connectionless datagram socket that may communicate with many
-- different endpoints on a datagram-by-datagram basis.
newtype Socket
Socket :: Fd -> Socket
-- | An endpoint for an IPv4 socket, connection, or listener. Everything is
-- in host byte order, and the user is not responisble for performing any
-- conversions.
data Endpoint
Endpoint :: !IPv4 -> !Word16 -> Endpoint
[$sel:address:Endpoint] :: Endpoint -> !IPv4
[$sel:port:Endpoint] :: Endpoint -> !Word16
data Message
Message :: {-# UNPACK #-} !Endpoint -> !ByteArray -> Message
[remote] :: Message -> {-# UNPACK #-} !Endpoint
[payload] :: 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 :: Endpoint -> (Socket -> Word16 -> IO a) -> IO (Either SocketException a)
-- | Send a slice of a bytearray to the specified endpoint.
send :: Socket -> Endpoint -> ByteArray -> Int -> Int -> IO (Either SocketException ())
-- | Send a slice of a bytearray to the specified endpoint.
sendMutableByteArraySlice :: Socket -> Endpoint -> MutableByteArray RealWorld -> Int -> Int -> IO (Either (SendException 'Uninterruptible) ())
-- | Receive a datagram into a freshly allocated bytearray.
receiveByteArray :: Socket -> Int -> IO (Either (ReceiveException 'Uninterruptible) Message)
-- | Receive a datagram into a mutable byte array, ignoring information
-- about the remote endpoint. Returns the actual number of bytes present
-- in the datagram. Precondition: buffer_length - offset >=
-- max_datagram_length.
receiveMutableByteArraySlice_ :: Socket -> MutableByteArray RealWorld -> Int -> Int -> IO (Either SocketException Int)
-- | Receive up to the specified number of datagrams into freshly allocated
-- byte arrays. When there are many datagrams present on the receive
-- buffer, this is more efficient than calling receive
-- repeatedly. The array is guaranteed to have at least one message.
--
-- The byte arrays in the resulting messages are always pinned.
receiveMany :: Socket -> Int -> Int -> IO (Either SocketException (Array Message))
-- | This has the same behavior as receiveMany. However, it also
-- takes an STM action that it attempts to run while the event
-- manager is waiting for the socket to be ready for a reads. If the
-- supplied action finishes first, this abandons the attempt to receive
-- datagrams and returns Left ReceptionAbandoned.
receiveManyUnless :: STM () -> Socket -> Int -> Int -> IO (Either SocketException (Array Message))
-- | Represents any unexpected behaviors that a function working on a
-- socket, connection, or listener can exhibit.
data SocketException
-- | The datagram did not fit in the buffer. This can happen while sending.
-- The field is the size of the number of bytes in the datagram that were
-- successfully copied into the send buffer.
SentMessageTruncated :: !Int -> SocketException
-- | The datagram did not fit in the buffer. This can happen while
-- receiving. The field is the original size of the datagram that was was
-- truncated while copying it into the buffer.
ReceivedMessageTruncated :: !Int -> SocketException
-- | The socket address was not the expected size. This exception indicates
-- a bug in this library or (less likely) in the operating system.
SocketAddressSize :: SocketException
-- | The socket address had an unexpected family. This exception indicates
-- a bug in this library or (less likely) in the operating system. The
-- int argument is the actual family found in the socket address.
SocketAddressFamily :: !CInt -> SocketException
-- | The option value was not the expected size. This exception indicates a
-- bug in this library or (less likely) in the operating system.
OptionValueSize :: SocketException
-- | The user requested a negative number of bytes in a call to a receive
-- function.
NegativeBytesRequested :: SocketException
-- | This happens when the Unless variant of a function is used
-- and the STM action completes before the socket is ready for a
-- read.
ReceptionAbandoned :: SocketException
-- | The remote end sent more data when it was expected to send a shutdown.
RemoteNotShutdown :: SocketException
-- | The remote end has shutdown its side of the full-duplex connection.
-- This can happen receive is called on a stream socket. This is
-- not necessarily a bad thing. Many protocols use shutdown to indicate
-- that no more data is available. These protocols can be contrasted with
-- protocols that send a length representing a number of expected bytes.
RemoteShutdown :: SocketException
-- | Any error code from the operating system that this library does not
-- expect or recognize. Consult your operating system manual for details
-- about the error code.
ErrorCode :: !CInt -> SocketException
-- | Internet datagram sockets without a fixed destination. The user may
-- spoof the source address and may specify the packet ID. An application
-- must have CAP_NET_RAW or be running as root to use the
-- functions in this module.
module Socket.Datagram.IPv4.Spoof
-- | A socket that send datagrams with spoofed source IP addresses. It
-- cannot receive datagrams.
newtype Socket
Socket :: Fd -> Socket
-- | An endpoint for an IPv4 socket, connection, or listener. Everything is
-- in host byte order, and the user is not responisble for performing any
-- conversions.
data Endpoint
Endpoint :: !IPv4 -> !Word16 -> Endpoint
[$sel:address:Endpoint] :: Endpoint -> !IPv4
[$sel:port:Endpoint] :: Endpoint -> !Word16
data Message
Message :: {-# UNPACK #-} !Endpoint -> !ByteArray -> Message
[remote] :: Message -> {-# UNPACK #-} !Endpoint
[payload] :: 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. The user cannot specify an endpoint since the socket cannot
-- receive traffic.
withSocket :: (Socket -> IO a) -> IO (Either SocketException a)
-- | Send a slice of a bytearray to the specified endpoint.
sendMutableByteArray :: Socket -> Endpoint -> Endpoint -> MutableByteArray RealWorld -> Int -> Int -> IO (Either (SendException 'Uninterruptible) ())
data SocketException :: Type
-- | Permission to create a raw socket was denied. The process needs the
-- capability CAP_NET_RAW, or it must be run as root.
[SocketPermissionDenied] :: SocketException
-- | A limit on the number of open file descriptors has been reached. This
-- could be the per-process limit or the system limit. (EMFILE
-- and ENFILE)
[SocketFileDescriptorLimit] :: SocketException
data SendException :: Interruptibility -> Type
-- | The datagram did not fit in the buffer. The field is the number of
-- bytes that were successfully copied into the send buffer. The datagram
-- does still get sent when this happens.
[SendTruncated] :: !Int -> SendException i
-- | Attempted to send to a broadcast address.
[SendBroadcasted] :: SendException i
-- | STM-style interrupt (much safer than C-style interrupt)
[SendInterrupted] :: SendException 'Interruptible
instance GHC.Show.Show Socket.Datagram.IPv4.Spoof.Socket
instance GHC.Classes.Ord Socket.Datagram.IPv4.Spoof.Socket
instance GHC.Classes.Eq Socket.Datagram.IPv4.Spoof.Socket
instance GHC.Show.Show Socket.Datagram.IPv4.Spoof.SocketException
instance GHC.Exception.Type.Exception Socket.Datagram.IPv4.Spoof.SocketException
module Socket.Stream.IPv4
-- | A socket that listens for incomming connections.
data Listener
-- | A connection-oriented stream socket.
data Connection
-- | An endpoint for an IPv4 socket, connection, or listener. Everything is
-- in host byte order, and the user is not responisble for performing any
-- conversions.
data Endpoint
Endpoint :: !IPv4 -> !Word16 -> Endpoint
[$sel:address:Endpoint] :: Endpoint -> !IPv4
[$sel:port:Endpoint] :: Endpoint -> !Word16
withListener :: Endpoint -> (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 -> Endpoint -> IO a) -> IO (Either (AcceptException 'Uninterruptible) b)
-- | Establish a connection to a server.
withConnection :: Endpoint -> (Either CloseException () -> a -> IO b) -> (Connection -> IO a) -> IO (Either (ConnectException 'Uninterruptible) b)
interruptibleWithConnection :: TVar Bool -> Endpoint -> (Either CloseException () -> a -> IO b) -> (Connection -> IO a) -> IO (Either (ConnectException 'Interruptible) 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 -> Endpoint -> 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 -> Endpoint -> 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.
--
--
-- - 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.
-- - 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:
--
--
--
-- (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 -> Endpoint -> IO a) -> IO (Either (AcceptException 'Interruptible) ThreadId)
sendByteArray :: Connection -> ByteArray -> IO (Either (SendException 'Uninterruptible) ())
sendByteArraySlice :: Connection -> ByteArray -> Int -> Int -> IO (Either (SendException 'Uninterruptible) ())
sendMutableByteArray :: Connection -> MutableByteArray RealWorld -> IO (Either (SendException 'Uninterruptible) ())
sendMutableByteArraySlice :: Connection -> MutableByteArray RealWorld -> Int -> Int -> IO (Either (SendException 'Uninterruptible) ())
sendAddr :: Connection -> Addr -> Int -> IO (Either (SendException 'Uninterruptible) ())
-- | Send a ByteString over a connection.
sendByteString :: Connection -> ByteString -> IO (Either (SendException 'Uninterruptible) ())
-- | Send a lazy ByteString over a connection.
sendLazyByteString :: Connection -> ByteString -> IO (Either (SendException 'Uninterruptible) ())
interruptibleSendByteArray :: TVar Bool -> Connection -> ByteArray -> IO (Either (SendException 'Interruptible) ())
interruptibleSendByteArraySlice :: TVar Bool -> Connection -> ByteArray -> Int -> Int -> IO (Either (SendException 'Interruptible) ())
interruptibleSendMutableByteArraySlice :: TVar Bool -> Connection -> MutableByteArray RealWorld -> Int -> Int -> IO (Either (SendException 'Interruptible) ())
-- | Receive exactly the given number of bytes. If the remote application
-- shuts down its end of the connection before sending the required
-- number of bytes, this returns Left
-- ReceiveShutdown.
receiveByteArray :: Connection -> Int -> IO (Either (ReceiveException 'Uninterruptible) ByteArray)
-- | Receive up to the given number of bytes. If the remote application
-- shuts down its end of the connection instead of sending any bytes,
-- this returns Left (SocketException Receive
-- RemoteShutdown).
receiveBoundedByteArray :: Connection -> Int -> IO (Either (ReceiveException 'Uninterruptible) ByteArray)
-- | Receive up to the given number of bytes, using the given array and
-- starting at the given offset.
receiveBoundedMutableByteArraySlice :: Connection -> Int -> MutableByteArray RealWorld -> Int -> IO (Either (ReceiveException 'Uninterruptible) Int)
-- | Receive a number of bytes exactly equal to the size of the mutable
-- byte array. If the remote application shuts down its end of the
-- connection before sending the required number of bytes, this returns
-- Left (SocketException Receive
-- RemoteShutdown).
receiveMutableByteArray :: Connection -> MutableByteArray RealWorld -> IO (Either (ReceiveException 'Uninterruptible) ())
-- | Receive exactly the given number of bytes.
receiveByteString :: Connection -> Int -> IO (Either (ReceiveException 'Uninterruptible) ByteString)
-- | Variant of receiveByteArray that support STM-style interrupts.
interruptibleReceiveByteArray :: TVar Bool -> Connection -> Int -> IO (Either (ReceiveException 'Interruptible) ByteArray)
-- | Receive up to the given number of bytes, using the given array and
-- starting at the given offset. This can be interrupted by the
-- completion of an STM transaction.
interruptibleReceiveBoundedMutableByteArraySlice :: TVar Bool -> Connection -> Int -> MutableByteArray RealWorld -> Int -> IO (Either (ReceiveException 'Interruptible) Int)
data SendException :: Interruptibility -> Type
-- | The local socket has already shutdown its writing channel.
-- Consequently, sending is no longer possible. This can happen even if
-- the process does not shutdown the socket. If the peer decides
-- to close the connection, the local operating system will
-- shutdown both the reading and writing channels. (EPIPE)
[SendShutdown] :: SendException i
-- | The peer reset the connection.
[SendReset] :: SendException i
-- | STM-style interrupt (much safer than C-style interrupt)
[SendInterrupted] :: SendException 'Interruptible
-- | Recoverable exceptions that can occur while receiving data on a stream
-- socket.
--
-- Discussion
--
-- The recv man page explicitly documents these:
--
--
-- - EAGAIN/EAGAIN: Not possible after using event
-- manager to wait.
-- - EBADF: Prevented by this library.
-- - ECONNREFUSED: Not sure if this is possible. Currently
-- treated as an unrecoverable exception.
-- - EFAULT: Not recoverable. API consumer has misused
-- Addr.
-- - EINTR: Prevented by this library. Unsafe FFI is not
-- interruptible.
-- - EINVAL: Prevented by this library.
-- - ENOMEM: Not recoverable.
-- - ENOTCONN: Prevented by this library.
-- - ENOTSOCK: Prevented by this library.
--
--
-- The man page includes a disclaimer: "Additional errors may be
-- generated and returned from the underlying protocol modules". One such
-- error when dealing with stream sockets in ECONNRESET. One
-- scenario where this happens is when the process running on the peer
-- terminates ungracefully and the operating system on the peer cleans up
-- by sending a reset.
data ReceiveException :: Interruptibility -> Type
-- | The peer shutdown its writing channel. (zero-length chunk)
[ReceiveShutdown] :: ReceiveException i
-- | The peer reset the connection. (ECONNRESET)
[ReceiveReset] :: ReceiveException i
-- | STM-style interrupt (much safer than C-style interrupt)
[ReceiveInterrupted] :: ReceiveException 'Interruptible
-- | Recoverable exceptions that can occur while connecting to a peer. This
-- includes both failures while opening the socket and failures while
-- connecting to the peer.
--
-- Discussion
--
-- In its API for connecting to a peer, this library combines the step of
-- creating a socket with the step of connecting to the peer. In other
-- words, the end user never gets access to an unconnected stream socket.
-- Consequently, the connection exceptions correspond to the
-- socket errors EMFILE and ENFILE as well as
-- the connect errors ECONNREFUSED,
-- EACCES/EPERM, ETIMEDOUT,
-- ENETUNREACH, and EADDRNOTAVAIL.
--
-- Somewhat surprisingly, EADDRINUSE is not included in the list
-- of connect error codes we recognize as recoverable. The
-- accept man page describes EADDRINUSE as "Local address
-- is already in use". However, it is unclear what this means. The caller
-- of connect does not provide an internet socket address. If
-- ephemeral ports are exhausted, connect will error with
-- EADDRNOTAVAIL. An unresolved Stack Overflow question
-- calls into question whether or not it is actually possible for this
-- error to happen with an internet domain socket. The author has decided
-- to omit any checks for it. This means that, if it does ever happen, it
-- will cause a SocketUnrecoverableException to be thrown. The
-- Linux cognoscenti are encouraged to open an issue if they have more
-- information about the circumstances under which this exception can
-- occur.
data ConnectException :: Interruptibility -> Type
-- | Either the connection was blocked by a local firewall rule or it was
-- blocked because it was to a broadcast address. Sadly, these two errors
-- are not distinguished by the Linux sockets API.
-- (EACCES/EPERM)
[ConnectFirewalled] :: ConnectException i
-- | A limit on the number of open file descriptors has been reached. This
-- could be the per-process limit or the system limit. (EMFILE
-- and ENFILE)
[ConnectFileDescriptorLimit] :: ConnectException i
-- | The network is unreachable. (ENETUNREACH)
[ConnectNetworkUnreachable] :: ConnectException i
-- | All port numbers in the ephemeral port range are currently in use.
-- (EADDRNOTAVAIL)
[ConnectEphemeralPortsExhausted] :: ConnectException i
-- | No one is listening on the remote address. (ECONNREFUSED)
[ConnectRefused] :: ConnectException i
-- | Timeout while attempting connection. The server may be too busy to
-- accept new connections. Note that stock Linux configuration has
-- timeout at appropriately 20 seconds. Users interested in timing
-- out more quickly are encouraged to use registerDelay with the
-- interruptible variants of the connection functions in this
-- library. (ETIMEDOUT)
[ConnectTimeout] :: ConnectException i
-- | STM-style interrupt (much safer than C-style interrupt)
[ConnectInterrupted] :: ConnectException 'Interruptible
-- | Recoverable exceptions that happen when establishing an
-- internet-domain stream listener or datagram socket.
--
-- Discussion
--
-- The recoverable exceptions that we from stream sockets (established
-- with socket-bind-listen) and datagram
-- sockets (established with socket-bind) are the exact
-- same exceptions. Consequently, we reuse the same type in both case. It
-- is a little unfortunate since the name ListenException would
-- be more appropriate for stream sockets. But the code reuse is worth
-- the naming quibble.
data SocketException :: Type
-- | The address is protected, and the user is not the superuser. This most
-- commonly happens when trying to bind to a port below 1024. On Linux,
-- When it is necessary to bind to such a port on Linux, consider using
-- the CAP_NET_BIND_SERVICE capability instead of running the
-- process as root. (EACCES)
[SocketPermissionDenied] :: SocketException
-- | The given address is already in use. (EADDRINUSE with
-- specified port)
[SocketAddressInUse] :: SocketException
-- | The port number was specified as zero, but upon attempting to bind to
-- an ephemeral port, it was determined that all port numbers numbers in
-- the ephemeral port range are currently in use. (EADDRINUSE
-- with unspecified port)
[SocketEphemeralPortsExhausted] :: SocketException
-- | A limit on the number of open file descriptors has been reached. This
-- could be the per-process limit or the system limit. (EMFILE
-- and ENFILE)
[SocketFileDescriptorLimit] :: SocketException
-- | Recoverable exceptions that can occur while accepting an inbound
-- connection.
data AcceptException :: Interruptibility -> Type
-- | The peer reset the connection before the running process accepted it.
-- This is not typically treated as fatal. The process may continue
-- accepting connections. (ECONNABORTED)
[AcceptConnectionAborted] :: AcceptException i
-- | A limit on the number of open file descriptors has been reached. This
-- could be the per-process limit or the system limit. (EMFILE
-- and ENFILE)
[AcceptFileDescriptorLimit] :: AcceptException i
-- | Firewall rules forbid connection. (EPERM)
[AcceptFirewalled] :: AcceptException i
-- | STM-style interrupt (much safer than C-style interrupt)
[AcceptInterrupted] :: AcceptException 'Interruptible
data CloseException :: Type
-- | After the local process shut down the writing channel, it was
-- expecting the peer to do the same. However, the peer sent more data
-- instead. If this happens, the local process does still close the
-- socket. However, it must send a TCP reset to accomplish this since
-- there is still unread data in the receive buffer.
--
-- This can happen if the peer is misbehaving or if the consumer of the
-- sockets API has incorrectly implemented a protocol living
-- above layer 4 of the OSI model.
[ClosePeerContinuedSending] :: CloseException
data Interruptibility
Interruptible :: Interruptibility
Uninterruptible :: Interruptibility
-- | Open a socket that can be used to listen for inbound connections.
-- Requirements:
--
--
-- - This function may only be called in contexts where exceptions are
-- masked.
-- - The caller must be sure to call unlistener on the
-- resulting Listener exactly once to close underlying file
-- descriptor.
-- - The Listener cannot be used after being given as an
-- argument to unlistener.
--
--
-- Noncompliant use of this function leads to undefined behavior. Prefer
-- withListener unless you are writing an integration with a
-- resource-management library.
listen :: Endpoint -> 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:
--
--
-- - This function may only be called in contexts where exceptions are
-- masked.
-- - The caller must be sure to call disconnect or
-- disconnect_ on the resulting Connection exactly once to
-- close underlying file descriptor.
-- - The Connection cannot be used after being given as an
-- argument to disconnect or disconnect_.
--
--
-- Noncompliant use of this function leads to undefined behavior. Prefer
-- withConnection unless you are writing an integration with a
-- resource-management library.
connect :: Endpoint -> IO (Either (ConnectException 'Uninterruptible) Connection)
-- | Variant of connect that is interruptible using STM-style
-- interrupts.
interruptibleConnect :: TVar Bool -> Endpoint -> IO (Either (ConnectException 'Interruptible) 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, Endpoint))
-- | Listen for an inbound connection. Can be interrupted by an STM-style
-- interrupt.
interruptibleAccept :: TVar Bool -> Listener -> IO (Either (AcceptException 'Interruptible) (Connection, Endpoint))