-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | TCP instantiation of Network.Transport
--   
--   TCP instantiation of Network.Transport
@package network-transport-tcp
@version 0.6.0


-- | Utility functions for TCP sockets
module Network.Transport.TCP.Internal

-- | Control headers
data ControlHeader

-- | Tell the remote endpoint that we created a new connection
CreatedNewConnection :: ControlHeader

-- | Tell the remote endpoint we will no longer be using a connection
CloseConnection :: ControlHeader

-- | Request to close the connection (see module description)
CloseSocket :: ControlHeader

-- | Sent by an endpoint when it is closed.
CloseEndPoint :: ControlHeader

-- | Message sent to probe a socket
ProbeSocket :: ControlHeader

-- | Acknowledgement of the ProbeSocket message
ProbeSocketAck :: ControlHeader
encodeControlHeader :: ControlHeader -> Word32
decodeControlHeader :: Word32 -> Maybe ControlHeader

-- | Response sent by <i>B</i> to <i>A</i> when <i>A</i> tries to connect
data ConnectionRequestResponse

-- | <i>B</i> does not support the protocol version requested by <i>A</i>.
ConnectionRequestUnsupportedVersion :: ConnectionRequestResponse

-- | <i>B</i> accepts the connection
ConnectionRequestAccepted :: ConnectionRequestResponse

-- | <i>A</i> requested an invalid endpoint
ConnectionRequestInvalid :: ConnectionRequestResponse

-- | <i>A</i>s request crossed with a request from <i>B</i> (see protocols)
ConnectionRequestCrossed :: ConnectionRequestResponse

-- | <i>A</i> gave an incorrect host (did not match the host that <i>B</i>
--   observed).
ConnectionRequestHostMismatch :: ConnectionRequestResponse
encodeConnectionRequestResponse :: ConnectionRequestResponse -> Word32
decodeConnectionRequestResponse :: Word32 -> Maybe ConnectionRequestResponse

-- | Start a server at the specified address.
--   
--   This sets up a server socket for the specified host and port.
--   Exceptions thrown during setup are not caught.
--   
--   Once the socket is created we spawn a new thread which repeatedly
--   accepts incoming connections and executes the given request handler in
--   another thread. If any exception occurs the accepting thread
--   terminates and calls the terminationHandler. Threads spawned for
--   previous accepted connections are not killed. This exception may occur
--   because of a call to <a>accept</a>, or because the thread was
--   explicitly killed.
--   
--   The request handler is not responsible for closing the socket. It will
--   be closed once that handler returns. Take care to ensure that the
--   socket is not used after the handler returns, or you will get
--   undefined behavior (the file descriptor may be re-used).
--   
--   The return value includes the port was bound to. This is not always
--   the same port as that given in the argument. For example, binding to
--   port 0 actually binds to a random port, selected by the OS.
forkServer :: HostName -> ServiceName -> Int -> Bool -> (SomeException -> IO ()) -> (SomeException -> IO ()) -> (IO () -> (Socket, SockAddr) -> IO ()) -> IO (ServiceName, ThreadId)

-- | Read a length and then a payload of that length, subject to a limit on
--   the length. If the length (first <a>Word32</a> received) is greater
--   than the limit then an exception is thrown.
recvWithLength :: Word32 -> Socket -> IO [ByteString]

-- | Read an exact number of bytes from a socket
--   
--   Throws an I/O exception if the socket closes before the specified
--   number of bytes could be read
recvExact :: Socket -> Word32 -> IO [ByteString]

-- | Receive a 32-bit unsigned integer
recvWord32 :: Socket -> IO Word32

-- | Serialize 32-bit to network byte order
encodeWord32 :: Word32 -> ByteString

-- | Close a socket, ignoring I/O exceptions.
tryCloseSocket :: Socket -> IO ()

-- | Shutdown socket sends and receives, ignoring I/O exceptions.
tryShutdownSocketBoth :: Socket -> IO ()

-- | Produce a HostName and ServiceName from a SockAddr. Only gives
--   <a>Just</a> for IPv4 addresses.
decodeSockAddr :: SockAddr -> IO (Maybe (HostName, ServiceName))

-- | Local identifier for an endpoint within this transport
type EndPointId = Word32

-- | Encode end point address
encodeEndPointAddress :: HostName -> ServiceName -> EndPointId -> EndPointAddress

-- | Decode end point address
decodeEndPointAddress :: EndPointAddress -> Maybe (HostName, ServiceName, EndPointId)

-- | Identifies the version of the network-transport-tcp protocol. It's the
--   first piece of data sent when a new heavyweight connection is
--   established.
type ProtocolVersion = Word32
currentProtocolVersion :: ProtocolVersion
instance GHC.Show.Show Network.Transport.TCP.Internal.ConnectionRequestResponse
instance GHC.Show.Show Network.Transport.TCP.Internal.ControlHeader


-- | TCP implementation of the transport layer.
--   
--   The TCP implementation guarantees that only a single TCP connection
--   (socket) will be used between endpoints, provided that the addresses
--   specified are canonical. If <i>A</i> connects to <i>B</i> and reports
--   its address as <tt>192.168.0.1:8080</tt> and <i>B</i> subsequently
--   connects tries to connect to <i>A</i> as
--   <tt>client1.local:http-alt</tt> then the transport layer will not
--   realize that the TCP connection can be reused.
--   
--   Applications that use the TCP transport should use
--   <a>withSocketsDo</a> in their main function for Windows compatibility
--   (see <a>Network.Socket</a>).
module Network.Transport.TCP

-- | Create a TCP transport
createTransport :: HostName -> ServiceName -> (ServiceName -> (HostName, ServiceName)) -> TCPParameters -> IO (Either IOException Transport)

-- | Parameters for setting up the TCP transport
data TCPParameters
TCPParameters :: Int -> Bool -> Bool -> Bool -> Bool -> Maybe Int -> Maybe Int -> (forall t. IO (QDisc t)) -> Word32 -> Word32 -> Bool -> TCPParameters

-- | Backlog for <tt>listen</tt>. Defaults to SOMAXCONN.
[tcpBacklog] :: TCPParameters -> Int

-- | Should we set SO_REUSEADDR on the server socket? Defaults to True.
[tcpReuseServerAddr] :: TCPParameters -> Bool

-- | Should we set SO_REUSEADDR on client sockets? Defaults to True.
[tcpReuseClientAddr] :: TCPParameters -> Bool

-- | Should we set TCP_NODELAY on connection sockets? Defaults to True.
[tcpNoDelay] :: TCPParameters -> Bool

-- | Should we set TCP_KEEPALIVE on connection sockets?
[tcpKeepAlive] :: TCPParameters -> Bool

-- | Value of TCP_USER_TIMEOUT in milliseconds
[tcpUserTimeout] :: TCPParameters -> Maybe Int

-- | A connect timeout for all <a>connect</a> calls of the transport in
--   microseconds
--   
--   This can be overriden for each connect call with
--   'ConnectHints'.'connectTimeout'.
--   
--   Connection requests to this transport will also timeout if they don't
--   send the required data before this many microseconds.
[transportConnectTimeout] :: TCPParameters -> Maybe Int

-- | Create a QDisc for an EndPoint.
[tcpNewQDisc] :: TCPParameters -> forall t. IO (QDisc t)

-- | Maximum length (in bytes) for a peer's address. If a peer attempts to
--   send an address of length exceeding the limit, the connection will be
--   refused (socket will close).
[tcpMaxAddressLength] :: TCPParameters -> Word32

-- | Maximum length (in bytes) to receive from a peer. If a peer attempts
--   to send data on a lightweight connection exceeding the limit, the
--   heavyweight connection which carries that lightweight connection will
--   go down. The peer and the local node will get an EventConnectionLost.
[tcpMaxReceiveLength] :: TCPParameters -> Word32

-- | If True, new connections will be accepted only if the socket's host
--   matches the host that the peer claims in its EndPointAddress. This is
--   useful when operating on untrusted networks, because the peer could
--   otherwise deny service to some victim by claiming the victim's
--   address.
[tcpCheckPeerHost] :: TCPParameters -> Bool

-- | Default TCP parameters
defaultTCPParameters :: TCPParameters

-- | You should probably not use this function (used for unit testing only)
createTransportExposeInternals :: HostName -> ServiceName -> (ServiceName -> (HostName, ServiceName)) -> TCPParameters -> IO (Either IOException (Transport, TransportInternals))

-- | Internal functionality we expose for unit testing
data TransportInternals
TransportInternals :: ThreadId -> ((forall t. Maybe (QDisc t)) -> IO (Either (TransportError NewEndPointErrorCode) EndPoint)) -> (EndPointAddress -> EndPointAddress -> IO Socket) -> TransportInternals

-- | The ID of the thread that listens for new incoming connections
[transportThread] :: TransportInternals -> ThreadId

-- | A variant of newEndPoint in which the QDisc determined by the
--   transport's TCPParameters can be optionally overridden.
[newEndPointInternal] :: TransportInternals -> (forall t. Maybe (QDisc t)) -> IO (Either (TransportError NewEndPointErrorCode) EndPoint)

-- | Find the socket between a local and a remote endpoint
[socketBetween] :: TransportInternals -> EndPointAddress -> EndPointAddress -> IO Socket

-- | Local identifier for an endpoint within this transport
type EndPointId = Word32

-- | Control headers
data ControlHeader

-- | Tell the remote endpoint that we created a new connection
CreatedNewConnection :: ControlHeader

-- | Tell the remote endpoint we will no longer be using a connection
CloseConnection :: ControlHeader

-- | Request to close the connection (see module description)
CloseSocket :: ControlHeader

-- | Sent by an endpoint when it is closed.
CloseEndPoint :: ControlHeader

-- | Message sent to probe a socket
ProbeSocket :: ControlHeader

-- | Acknowledgement of the ProbeSocket message
ProbeSocketAck :: ControlHeader

-- | Response sent by <i>B</i> to <i>A</i> when <i>A</i> tries to connect
data ConnectionRequestResponse

-- | <i>B</i> does not support the protocol version requested by <i>A</i>.
ConnectionRequestUnsupportedVersion :: ConnectionRequestResponse

-- | <i>B</i> accepts the connection
ConnectionRequestAccepted :: ConnectionRequestResponse

-- | <i>A</i> requested an invalid endpoint
ConnectionRequestInvalid :: ConnectionRequestResponse

-- | <i>A</i>s request crossed with a request from <i>B</i> (see protocols)
ConnectionRequestCrossed :: ConnectionRequestResponse

-- | <i>A</i> gave an incorrect host (did not match the host that <i>B</i>
--   observed).
ConnectionRequestHostMismatch :: ConnectionRequestResponse

-- | We reserve a bunch of connection IDs for control messages
firstNonReservedLightweightConnectionId :: LightweightConnectionId

-- | We reserve some connection IDs for special heavyweight connections
firstNonReservedHeavyweightConnectionId :: HeavyweightConnectionId

-- | Establish a connection to a remote endpoint
--   
--   Maybe throw a TransportError
--   
--   If a socket is created and returned (Right is given) then the caller
--   is responsible for eventually closing the socket and filling the MVar
--   (which is empty). The MVar must be filled immediately after, and never
--   before, the socket is closed.
socketToEndPoint :: EndPointAddress -> EndPointAddress -> Bool -> Bool -> Bool -> Maybe Int -> Maybe Int -> IO (Either (TransportError ConnectErrorCode) (MVar (), Socket, ConnectionRequestResponse))

-- | Lightweight connection ID (sender allocated)
--   
--   A ConnectionId is the concentation of a <a>HeavyweightConnectionId</a>
--   and a <a>LightweightConnectionId</a>.
type LightweightConnectionId = Word32

-- | Abstraction of a queue for an <a>EndPoint</a>.
--   
--   A value of type <tt>QDisc t</tt> is a queue of events of an abstract
--   type <tt>t</tt>.
--   
--   This specifies which <a>Event</a>s will come from 'receive :: EndPoint
--   -&gt; IO Event' and when. It is highly general so that the simple yet
--   potentially very fast implementation backed by a single unbounded
--   channel can be used, without excluding more nuanced policies like
--   class-based queueing with bounded buffers for each peer, which may be
--   faster in certain conditions but probably has lower maximal
--   throughput.
--   
--   A <a>QDisc</a> must satisfy some properties in order for the semantics
--   of network-transport to hold true. In general, an event fed with
--   <a>qdiscEnqueue</a> must not be dropped. i.e. provided that no other
--   event in the QDisc has higher priority, the event should eventually be
--   returned by <a>qdiscDequeue</a>. An exception to this are
--   <tt>Receive</tt> events of unreliable connections.
--   
--   Every call to <a>receive</a> is just <a>qdiscDequeue</a> on that
--   <a>EndPoint</a>s <a>QDisc</a>. Whenever an event arises from a socket,
--   <a>qdiscEnqueue</a> is called with the relevant metadata in the same
--   thread that reads from the socket. You can be clever about when to
--   block here, so as to control network ingress. This applies also to
--   loopback connections (an <a>EndPoint</a> connects to itself), in which
--   case blocking on the enqueue would only block some thread in your
--   program rather than some chatty network peer. The <a>Event</a> which
--   is to be enqueued is given to <a>qdiscEnqueue</a> so that the
--   <a>QDisc</a> can know about open connections, their identifiers and
--   peer addresses, etc.
data QDisc t
QDisc :: IO t -> (EndPointAddress -> Event -> t -> IO ()) -> QDisc t

-- | Dequeue an event.
[qdiscDequeue] :: QDisc t -> IO t

-- | <tt>qdiscEnqueue ep ev t</tt> enqueues and event <tt>t</tt>,
--   originated from the given remote endpoint <tt>ep</tt> and with data
--   <tt>ev</tt>.
--   
--   <tt>ep</tt> might be the local endpoint if it relates to a
--   self-connection.
--   
--   <tt>ev</tt> might be in practice the value given as <tt>t</tt>. It is
--   passed in the abstract form <tt>t</tt> to enforce it is dequeued
--   unmodified, but the <a>QDisc</a> implementation can still observe the
--   concrete form <tt>ev</tt> to make prioritization decisions.
[qdiscEnqueue] :: QDisc t -> EndPointAddress -> Event -> t -> IO ()

-- | A very simple QDisc backed by an unbounded channel.
simpleUnboundedQDisc :: forall t. IO (QDisc t)

-- | A very simple QDisc backed by a 1-place queue (MVar). With this QDisc,
--   all threads reading from sockets will try to put their events into the
--   same MVar. That MVar will be cleared by calls to <a>receive</a>. Thus
--   the rate at which data is read from the wire is directly related to
--   the rate at which data is pulled from the EndPoint by <a>receive</a>.
simpleOnePlaceQDisc :: forall t. IO (QDisc t)
instance GHC.Show.Show Network.Transport.TCP.RequestedBy
instance GHC.Classes.Eq Network.Transport.TCP.RequestedBy
