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


-- | A message-passing library for simplifying network applications
--   
--   Inspired by Erlang's simple message-passing facilities, courier
--   provides roughly similar capabilities. Applications simply create one
--   or more endpoints, bind each to a transport using a given name, then
--   can freely send / receive messages to other endpoints just by
--   referencing the name each endpoint bound to its transport.
--   
--   A primary driver of this package's design is separation of concerns:
--   many algorithms (especially for distributed applications) depend upon
--   a message-passing foundation, but the algorithms are sufficiently
--   complex that the details of how those messages are transmitted among
--   nodes are best hidden away and solved separately from the distributed
--   algorithm itself. With this in mind, this package aims to provide a
--   variety of transports as well as support for common communication
--   idioms (e.g., in order message delivery, selective out of order
--   message delivery, synchronous RPC, etc.).
--   
--   Applications may process messages in the order received at an
--   endpoint, or use selective message reception to process the first
--   message arriving at an endpoint that also matches a provided selection
--   function. Through selective message reception, applications may
--   approximate the style of an Erlang application, and enjoy better
--   composability of message reception with multiple independent dispatch
--   routines or message pumps.
@package courier
@version 0.1.1.5


-- | A <a>Mailbox</a> is a drop-in replacement for <a>TQueue</a> in
--   <a>Control.Concurrent.STM</a>, except that it also supports selective
--   out of order message reception: that is, it allows the caller to
--   dequeue the first message among the messages available in the queue
--   that matches a supplied test function, or block if no such match is
--   possible with the messages currently in the queue.
--   
--   As <a>Mailbox</a> implements the same basic <tt>read <i> write </i>
--   peek</tt> group of functions as a <a>TQueue</a>, it offers a superset
--   of <a>TQueue</a> functionality by extending it with the <tt>find <i>
--   select </i> handle</tt> groups of functions. Thus, applications can
--   safely use <a>Mailbox</a>es in place of <a>TQueue</a>s, but choose
--   when to take the slight extra overhead of <a>Mailbox</a>
--   functionality.
--   
--   Because message selection in worst case requires fully traversing all
--   messages in the queue, application designers are encouraged to
--   understand this aspect when choosing to use <a>Mailbox</a>es in their
--   designs, or when using the additional features of <a>Mailbox</a>es
--   beyond that of <a>TQueue</a>s. Dispatching messages with a
--   <a>Mailbox</a> is analogous to using a <tt>case</tt> expression (O(n))
--   to dispatch messages to a handler function, except that new cases can
--   be added or removed at any time. In essence, one can regard
--   <a>Mailbox</a>es as a useful means of creating an extensible message
--   dispatch function. If, however, if O(1) message dispatching time is
--   necessary or desired, (using hashmaps, for example) then
--   <a>Mailbox</a>es are not the correct choice.
--   
--   Despite this extra cost, <a>Mailbox</a>es offer advantages to
--   designers:
--   
--   <ul>
--   <li>Implementation of Erlang-style message reception: as messages can
--   be received out of order, a mailbox is analogous to a process input
--   queue in Erlang.</li>
--   <li>Better composability: if applications must only dequeue messages
--   in the order in which they are queued (which is sufficient for many
--   applications), then the main message pump requires modification each
--   time a new class of message must be handled. With selective message
--   reception, multiple concurrent message pumps are possible (with a
--   small performance impact), each processing the messages they expect
--   and with no need to be aware of other message pumps performing their
--   own work on the same mailbox.</li>
--   <li>Mixing synchronous and asynchronous programming styles: if
--   restricted to in order message delivery, an application must carefully
--   construct all logic to avoid blocking its central message loop. By
--   supporting out of message delivery and multiple selective recipients,
--   it becomes possible to combine synchronous and asynchronous
--   programming styles using the same <a>Mailbox</a>.</li>
--   </ul>
--   
--   Basic framework for <a>Mailbox</a> brazenly copied from
--   <a>Control.Concurrent.STM.TQueue</a>.
module Control.Concurrent.Mailbox

-- | A <a>Mailbox</a> is a variation of a <a>TQueue</a>, with the added
--   feature of selective message retrieval.
data Mailbox m

-- | Build and returns a new instance of <a>Mailbox</a>
newMailbox :: STM (Mailbox m)

-- | <tt>IO</tt> version of <a>newMailbox</a>. This is useful for creating
--   top-level <a>Mailbox</a>s using <a>unsafePerformIO</a>, because using
--   <a>atomically</a> inside <a>unsafePerformIO</a> isn't possible.
newMailboxIO :: IO (Mailbox m)

-- | Write a value to a <a>Mailbox</a>.
writeMailbox :: Mailbox m -> m -> STM ()

-- | Read the next value from the <a>Mailbox</a>.
readMailbox :: Mailbox m -> STM m

-- | A version of <a>readMailbox</a> which does not retry. Instead it
--   returns <tt>Nothing</tt> if no value is available.
tryReadMailbox :: Mailbox m -> STM (Maybe m)

-- | Get the next value from the <tt>Mailbox</tt> without removing it,
--   retrying if the channel is empty.
peekMailbox :: Mailbox m -> STM m

-- | A version of <a>peekMailbox</a> which does not retry. Instead it
--   returns <tt>Nothing</tt> if no value is available.
tryPeekMailbox :: Mailbox m -> STM (Maybe m)

-- | Find the next message in the mailbox that matches the supplied test
--   function or block until there is a message that does. When a message
--   matches (e.g., test functions returns <tt>Just v</tt>), return it.
selectMailbox :: Mailbox m -> (m -> Maybe v) -> STM v

-- | A version of <a>selectMailbox</a> which does not retry. Instead it
--   returns <tt>Nothing</tt> if no value is available.
trySelectMailbox :: Mailbox m -> (m -> Maybe v) -> STM (Maybe v)

-- | Wait until there is a message in the mailbox matching the supplied
--   test function (using <a>selectMailbox</a>), then when a message is
--   found, handle it in the <a>IO</a> monad with the supplied function.
handleMailbox :: Mailbox m -> (m -> Maybe v) -> (v -> IO r) -> IO r

-- | Find the next value from the <tt>Mailbox</tt> matching <tt>testFn</tt>
--   without removing it, retrying if the channel is empty.
findMailbox :: Mailbox m -> (m -> Maybe v) -> STM v

-- | A version of <a>findMailbox</a> which does not retry. Instead it
--   returns <tt>Nothing</tt> if no value is available.
tryFindMailbox :: Mailbox m -> (m -> Maybe v) -> STM (Maybe v)

-- | Put a data item back onto a mailbox, where it will be the next item
--   read.
unGetMailbox :: Mailbox m -> m -> STM ()

-- | Returns <a>True</a> if the supplied <a>Mailbox</a> is empty.
isEmptyMailbox :: Mailbox m -> STM Bool
instance GHC.Classes.Eq (Control.Concurrent.Mailbox.Mailbox m)


-- | <a>Endpoint</a>s are a generalized abstraction for communication
--   between parts of a program, whether on the same physical host or
--   distributed over a network. <a>Endpoint</a>s are intended to simplify
--   the development of network-centric applications by providing a small
--   transport-independent message-passing interface, and application
--   writers can independently alter their implementation by enabling their
--   <a>Endpoint</a>s with different <a>Transport</a>s without modifying
--   the logic of their application that sends / receives <a>Message</a>s.
module Network.Endpoints

-- | Endpoints are a locus of communication, used for sending and receive
--   messages.
data Endpoint
Endpoint :: Mailbox Message -> Mailbox Envelope -> TVar (Set Name) -> Endpoint

-- | The <tt>Transport</tt> used by this <a>Endpoint</a> endpointTransport
--   :: Transport, | The <a>Mailbox</a> where inbound <a>Message</a>s that
--   the <a>Endpoint</a> will receive are queued
[endpointInbound] :: Endpoint -> Mailbox Message
[endpointOutbound] :: Endpoint -> Mailbox Envelope

-- | The <a>Name</a>s to which the <a>Endpoint</a> is bound
[boundEndpointNames] :: Endpoint -> TVar (Set Name)

-- | Create a new <a>Endpoint</a> using the provided transports.
newEndpoint :: IO Endpoint

-- | Declare an <a>Endpoint</a> as having the specified <a>Name</a> while
--   the supplied function executes. This can often be useful for
--   establishing the <a>Name</a> of a client or initiator of a
--   <a>Connection</a>, without requiring the client also have a
--   <a>Binding</a>.
withName :: Endpoint -> Name -> IO a -> IO a

-- | Establish <a>Name</a> as one of the <a>boundEndpointNames</a> for an
--   <a>Endpoint</a>. Throws <a>BindingExists</a> if the <a>Endpoint</a> is
--   already bound to the <a>Name</a>.
bindName :: Endpoint -> Name -> STM ()

-- | Remove <a>Name</a> as one of the <a>boundEndpointNames</a> for an
--   <a>Endpoint</a>. Throws <a>BindingDoesNotExist</a> if the
--   <a>Endpoint</a> is not bound to the <a>Name</a>.
unbindName :: Endpoint -> Name -> STM ()

-- | Exceptions generated when <a>bind</a>ing a <a>Name</a>.
data BindException
BindingExists :: Name -> BindException
BindingDoesNotExist :: Name -> BindException

-- | Send a <a>Message</a> to specific <a>Name</a> via the indicated
--   <a>Endpoint</a>.
sendMessage :: Endpoint -> Name -> Message -> IO ()

-- | Helper for sending a single <a>Message</a> to several
--   <a>Endpoint</a>s.
broadcastMessage :: Endpoint -> [Name] -> Message -> IO ()

-- | Receive the next <a>Message</a> sent to the <a>Endpoint</a>, blocking
--   until a message is available.
receiveMessage :: Endpoint -> IO Message

-- | Wait for a message to be received within the timeout, blocking until
--   either a message is available or the timeout has occurred. If a
--   message was available, returns <tt>Just message</tt>, but returns
--   <tt>Nothing</tt> if no message available before the timeout occurred.
receiveMessageTimeout :: Endpoint -> Int -> IO (Maybe Message)

-- | Posts a <a>Message</a> directly to an <a>Endpoint</a>, without use of
--   a transport. This may be useful for applications that prefer to use
--   the <tt>Endpoint'</tt>s <a>Mailbox</a> as a general queue of ordered
--   messages.
postMessage :: Endpoint -> Message -> STM ()

-- | Select the next available message in the <a>Endpoint</a>
--   <a>Mailbox</a> matching the supplied test function, or blocking until
--   one is available. This function differs from <a>receiveMessage</a> in
--   that it supports out of order message reception.
selectMessage :: Endpoint -> (Message -> Maybe v) -> IO v

-- | Wait for a message to be selected within the timeout, blocking until
--   either a message is available or the timeout has occurred. If a
--   message was available, returns <tt>Just message</tt>, but returns
--   <tt>Nothing</tt> if no message available before the timeout occurred.
--   Like <a>selectMessage</a>, this function enables out of order message
--   reception.
selectMessageTimeout :: Endpoint -> Int -> (Message -> Maybe v) -> IO (Maybe v)

-- | Find a <a>Message</a> in the <a>Endpoint</a> <a>Mailbox</a> matching
--   the supplied test function, or block until one is available. Note that
--   any such message is left in the mailbox, and thus repeated calls to
--   this function could find the message if it is not consumed
--   immediately.
detectMessage :: Endpoint -> (Message -> Maybe v) -> IO v

-- | Find a <a>Message</a> in the <a>Endpoint</a> <a>Mailbox</a> matching
--   the supplied test function, or block until either one is available or
--   the timeout expires. Note that any such message is left in the
--   mailbox, and thus repeated calls to this function could find the
--   message if it is not consumed immediately.
detectMessageTimeout :: Endpoint -> Int -> (Message -> Maybe v) -> IO (Maybe v)

-- | An <a>Envelope</a> wraps a <a>Message</a> with the <a>Name</a>s of the
--   destination for the message and (optionally) the origin.
data Envelope
Envelope :: Maybe Name -> Name -> Message -> Envelope
[messageOrigin] :: Envelope -> Maybe Name
[messageDestination] :: Envelope -> Name
[envelopeMessage] :: Envelope -> Message

-- | Messages are containers for arbitrary data that may be sent to other
--   <a>Endpoint</a>s.
type Message = ByteString

-- | Name for uniquely identifying an <a>Endpoint</a>; suitable for
--   identifying the target destination for a <a>Message</a>. The specific
--   interpretation of a name is left to each <a>Transport</a>
newtype Name
Name :: String -> Name
instance GHC.Show.Show Network.Endpoints.BindException
instance GHC.Show.Show Network.Endpoints.Envelope
instance GHC.Classes.Eq Network.Endpoints.Envelope
instance GHC.Generics.Generic Network.Endpoints.Name
instance GHC.Show.Show Network.Endpoints.Name
instance GHC.Classes.Ord Network.Endpoints.Name
instance GHC.Classes.Eq Network.Endpoints.Name
instance GHC.Exception.Exception Network.Endpoints.BindException
instance Data.Serialize.Serialize Network.Endpoints.Name


-- | An implementation of synchronous remote procedure calls (<a>RPC</a>)
--   on top of <a>Endpoint</a>s.
--   
--   Applications exporting services for use by other applications via RPC
--   call <a>handle</a> to start listening for incoming RPC requests for a
--   specific <a>Method</a>. If multiple functions or <a>Method</a>s are
--   exported, then separate calls to <a>handle</a> are necessary, one for
--   each exported <a>Method</a>. Each call to <a>handle</a> produces a
--   <a>HandleSite</a> which may be used to terminate future handling of
--   RPCs for that specific method by calling <a>hangup</a> on the returned
--   <a>HandleSite</a>.
--   
--   Applications wishing to make RPCs to other applications or services do
--   so by first constructing a <a>CallSite</a>, and then <a>call</a>ing
--   specific methods on the target handler through that <a>CallSite</a>.
--   
--   Both single and multiple target RPCs are available, as are variants
--   that either wait indefinitely or at most for a defined timeout.
module Network.RPC

-- | An identifier for what method to invoke on the receiving
--   <a>Endpoint</a>. If <a>hear</a> has been invoked on the
--   <a>Endpoint</a> with a matching identifier, then calls will be
--   delivered to that invocation of <a>hear</a>.
type Method = String

-- | Create a new <a>CallSite</a> using the indicated <a>Endpoint</a> for
--   sending RPCs and using the specified <a>Name</a> for receiving
--   responses.
newCallSite :: Endpoint -> Name -> CallSite

-- | A call site is a location for making RPCs: it includes an endpoint and
--   a name by which recipients can return the call
data CallSite

-- | Call a method with the provided arguments on the recipient with the
--   given name.
--   
--   The caller will wait until a matching response is received.
call :: CallSite -> Name -> Method -> Message -> IO Message

-- | Call a method with the provided arguments on the recipient with the
--   given name. A request will be made through the <tt>CallSite'</tt>s
--   <a>Endpoint</a>, and then the caller will wait until a matching
--   response is received. If a response is received within the provided
--   timeout (measured in microseconds), then return the value wrapped in
--   <a>Just</a>; otherwise, if the timeout expires before the call
--   returns, then return 'Nothing.
callWithTimeout :: CallSite -> Name -> Method -> Int -> Message -> IO (Maybe Message)

-- | Group call or RPC: call a method with the provided arguments on all
--   the recipients with the given names. A request will be made through
--   the <tt>CallSite'</tt>s <a>Endpoint</a>, and then the caller will wait
--   until all matching responses are received.
gcall :: CallSite -> [Name] -> Method -> Message -> IO (Map Name Message)

-- | Group call or RPC but with a timeout: call a method with the provided
--   arguments on all the recipients with the given names. A request will
--   be made through the <tt>CallSite'</tt>s <a>Endpoint</a>, and then the
--   caller will wait until all matching responses are received or the
--   timeout occurs. The returned <a>Map</a> has a key for every
--   <a>Name</a> that was a target of the call, and the value of that key
--   will be <tt>Nothing</tt> if no response was received before the
--   timeout, or <tt>Just value</tt> if a response was received.
gcallWithTimeout :: CallSite -> [Name] -> Method -> Int -> Message -> IO (Map Name (Maybe Message))

-- | Invoke the same method on multiple <a>Name</a>s, and wait indefinitely
--   until the first response from any <a>Name</a>, returning the value and
--   the <a>Name</a> which responded.
anyCall :: CallSite -> [Name] -> Method -> Message -> IO (Message, Name)

-- | A simple function that, given a <a>Method</a>, returns a filter
--   suitable for use with <a>selectMessage</a>. The typical use case will
--   involve partial application: <tt>methodSelector method</tt> passed as
--   an argument to <a>selectMessage</a>.
methodSelector :: Method -> Message -> Maybe (Name, RequestId, Message)

-- | Wait for a single incoming request to invoke the indicated
--   <a>Method</a> on the specified <a>Endpoint</a>. Return both the method
--   arguments and a <a>Reply</a> function useful for sending the reply. A
--   good pattern for using <a>hear</a> will pattern match the result to a
--   tuple of the form <tt>(args,reply)</tt>, then use the args as needed
--   to compute a result, and then finally send the result back to the
--   client by simply passing the result to reply: <tt>reply result</tt>.
--   
--   The invoker of <a>hear</a> must supply the <a>Name</a> they have bound
--   to the <a>Endpoint</a>, as this helps the original requestor of the
--   RPC differentiate responses when the RPC was a group call.
hear :: Endpoint -> Name -> Method -> IO (Message, Reply Message)

-- | Same as <a>hear</a>, except return <a>Nothing</a> if no request
--   received within the specified timeout (measured in microseconds), or
--   return a <a>Just</a> instance containing both the method arguments and
--   a <a>Reply</a> function useful for sending the reply.
hearTimeout :: Endpoint -> Name -> Method -> Int -> IO (Maybe (Message, Reply Message))

-- | A variant of <a>hear</a>, except it listens for any incoming RPC
--   request on the specified <a>Endpoint</a>.
hearAll :: Endpoint -> Name -> IO (Method, Message, Reply Message)

-- | A variant of <a>hearTimeout</a>, except it listens for any incoming
--   RPC request on the specified <a>Endpoint</a>
hearAllTimeout :: Endpoint -> Name -> Int -> IO (Maybe (Method, Message, Reply Message))

-- | A <a>Reply</a> is a one-shot function for sending a response to an
--   incoming request.
type Reply b = b -> IO ()

-- | A <a>HandleSite</a> is a just reference to the actual handler of a
--   specific method. Mostly for invoking <a>hangup</a> on the handler,
--   once it is no longer needed.
data HandleSite
HandleSite :: Name -> (Async ()) -> HandleSite

-- | Handle all RPCs to invoke the indicated <a>Method</a> on the specified
--   <a>Endpoint</a>, until <a>hangup</a> is called on the returned
--   <a>HandleSite</a>.
handle :: Endpoint -> Name -> Method -> (Message -> IO Message) -> IO HandleSite

-- | Handle all RPCs on the specified <a>Endpoint</a> until <a>hangup</a>
--   is called on the returned <a>HandleSite</a>
handleAll :: Endpoint -> Name -> (Method -> Message -> IO Message) -> IO HandleSite

-- | Stop handling incoming RPCs for the indicated <a>HandleSite</a>.
hangup :: HandleSite -> IO ()

-- | Encapsulates the initiating side of a <a>call</a>: every invocation of
--   <a>call</a> produces a <a>Request</a> that is sent to the destination
--   <a>Endpoint</a>, where the <a>hear</a>ing side will generate a
--   <a>Response</a> after completing the request'
data Request
Request :: RequestId -> Name -> Method -> Message -> Request
[requestId] :: Request -> RequestId
[requestCaller] :: Request -> Name
[requestMethod] :: Request -> Method
[requestArgs] :: Request -> Message

-- | A unique identifier for a <a>Request</a>
data RequestId

-- | Create a new identifier for <a>Request</a>s
mkRequestId :: IO RequestId

-- | Encapsulates the completion side of a <a>call</a>: every invocation of
--   <a>call</a> produces a <a>Request</a> that is sent to the destination
--   <a>Endpoint</a>, where the <a>hear</a>ing side will generate a
--   <a>Response</a> after completing the request'
data Response
Response :: RequestId -> Name -> Message -> Response
[responseId] :: Response -> RequestId
[responseFrom] :: Response -> Name
[responseValue] :: Response -> Message
instance GHC.Show.Show Network.RPC.Response
instance GHC.Classes.Eq Network.RPC.Response
instance GHC.Show.Show Network.RPC.Request
instance GHC.Classes.Eq Network.RPC.Request
instance GHC.Show.Show Network.RPC.RequestId
instance GHC.Classes.Eq Network.RPC.RequestId
instance GHC.Generics.Generic Network.RPC.RequestId
instance GHC.Generics.Generic Network.RPC.RPCMessageType
instance GHC.Enum.Enum Network.RPC.RPCMessageType
instance GHC.Show.Show Network.RPC.RPCMessageType
instance GHC.Classes.Eq Network.RPC.RPCMessageType
instance Data.Serialize.Serialize Network.RPC.Response
instance Data.Serialize.Serialize Network.RPC.Request
instance Data.Serialize.Serialize Network.RPC.RequestId
instance Data.Serialize.Serialize Network.RPC.RPCMessageType


module Network.RPC.Typed

-- | Call a method with the provided arguments on the recipient with the
--   given name.
--   
--   The caller will wait until a matching response is received.
call :: (Serialize a, Serialize b) => CallSite -> Name -> Method -> a -> IO b

-- | Call a method with the provided arguments on the recipient with the
--   given name. A request will be made through the <tt>CallSite'</tt>s
--   <a>Endpoint</a>, and then the caller will wait until a matching
--   response is received. If a response is received within the provided
--   timeout (measured in microseconds), then return the value wrapped in
--   <a>Just</a>; otherwise, if the timeout expires before the call
--   returns, then return 'Nothing.
callWithTimeout :: (Serialize a, Serialize r) => CallSite -> Name -> Method -> Int -> a -> IO (Maybe r)

-- | Group call or RPC but with a timeout: call a method with the provided
--   arguments on all the recipients with the given names. A request will
--   be made through the <tt>CallSite'</tt>s <a>Endpoint</a>, and then the
--   caller will wait until all matching responses are received or the
--   timeout occurs. The returned <a>Map</a> has a key for every
--   <a>Name</a> that was a target of the call, and the value of that key
--   will be <tt>Nothing</tt> if no response was received before the
--   timeout, or <tt>Just value</tt> if a response was received.
gcallWithTimeout :: (Serialize a, Serialize r) => CallSite -> [Name] -> Method -> Int -> a -> IO (Map Name (Maybe r))

-- | Wait for a single incoming request to invoke the indicated
--   <a>Method</a> on the specified <a>Endpoint</a>. Return both the method
--   arguments and a <a>Reply</a> function useful for sending the reply. A
--   good pattern for using <a>hear</a> will pattern match the result to a
--   tuple of the form <tt>(args,reply)</tt>, then use the args as needed
--   to compute a result, and then finally send the result back to the
--   client by simply passing the result to reply: <tt>reply result</tt>.
--   
--   The invoker of <a>hear</a> must supply the <a>Name</a> they have bound
--   to the <a>Endpoint</a>, as this helps the original requestor of the
--   RPC differentiate responses when the RPC was a group call.
hear :: (Serialize a, Serialize r) => Endpoint -> Name -> Method -> IO (a, Reply r)

-- | Same as <a>hear</a>, except return <a>Nothing</a> if no request
--   received within the specified timeout (measured in microseconds), or
--   return a <a>Just</a> instance containing both the method arguments and
--   a <a>Reply</a> function useful for sending the reply.
hearTimeout :: (Serialize a, Serialize r) => Endpoint -> Name -> Method -> Int -> IO (Maybe (a, Reply r))

-- | Handle all RPCs to invoke the indicated <a>Method</a> on the specified
--   <a>Endpoint</a>, until <a>hangup</a> is called on the returned
--   <a>HandleSite</a>.
handle :: (Serialize a, Serialize r) => Endpoint -> Name -> Method -> (a -> IO r) -> IO HandleSite

-- | A method selector that only matches if the message deserializes into a
--   type that matches arguments to a call.
typedMethodSelector :: (Serialize a) => Method -> Message -> Maybe (Name, RequestId, a)

-- | A <a>HandleSite</a> is a just reference to the actual handler of a
--   specific method. Mostly for invoking <a>hangup</a> on the handler,
--   once it is no longer needed.
data HandleSite
HandleSite :: Name -> (Async ()) -> HandleSite

-- | A <a>Reply</a> is a one-shot function for sending a response to an
--   incoming request.
type Reply b = b -> IO ()

-- | A call site is a location for making RPCs: it includes an endpoint and
--   a name by which recipients can return the call
data CallSite

-- | Encapsulates the completion side of a <a>call</a>: every invocation of
--   <a>call</a> produces a <a>Request</a> that is sent to the destination
--   <a>Endpoint</a>, where the <a>hear</a>ing side will generate a
--   <a>Response</a> after completing the request'
data Response
Response :: RequestId -> Name -> Message -> Response
[responseId] :: Response -> RequestId
[responseFrom] :: Response -> Name
[responseValue] :: Response -> Message

-- | Encapsulates the initiating side of a <a>call</a>: every invocation of
--   <a>call</a> produces a <a>Request</a> that is sent to the destination
--   <a>Endpoint</a>, where the <a>hear</a>ing side will generate a
--   <a>Response</a> after completing the request'
data Request
Request :: RequestId -> Name -> Method -> Message -> Request
[requestId] :: Request -> RequestId
[requestCaller] :: Request -> Name
[requestMethod] :: Request -> Method
[requestArgs] :: Request -> Message

-- | A unique identifier for a <a>Request</a>
data RequestId

-- | An identifier for what method to invoke on the receiving
--   <a>Endpoint</a>. If <a>hear</a> has been invoked on the
--   <a>Endpoint</a> with a matching identifier, then calls will be
--   delivered to that invocation of <a>hear</a>.
type Method = String

-- | Create a new identifier for <a>Request</a>s
mkRequestId :: IO RequestId

-- | Create a new <a>CallSite</a> using the indicated <a>Endpoint</a> for
--   sending RPCs and using the specified <a>Name</a> for receiving
--   responses.
newCallSite :: Endpoint -> Name -> CallSite

-- | Group call or RPC: call a method with the provided arguments on all
--   the recipients with the given names. A request will be made through
--   the <tt>CallSite'</tt>s <a>Endpoint</a>, and then the caller will wait
--   until all matching responses are received.
gcall :: CallSite -> [Name] -> Method -> Message -> IO (Map Name Message)

-- | Invoke the same method on multiple <a>Name</a>s, and wait indefinitely
--   until the first response from any <a>Name</a>, returning the value and
--   the <a>Name</a> which responded.
anyCall :: CallSite -> [Name] -> Method -> Message -> IO (Message, Name)

-- | A simple function that, given a <a>Method</a>, returns a filter
--   suitable for use with <a>selectMessage</a>. The typical use case will
--   involve partial application: <tt>methodSelector method</tt> passed as
--   an argument to <a>selectMessage</a>.
methodSelector :: Method -> Message -> Maybe (Name, RequestId, Message)

-- | A variant of <a>hear</a>, except it listens for any incoming RPC
--   request on the specified <a>Endpoint</a>.
hearAll :: Endpoint -> Name -> IO (Method, Message, Reply Message)

-- | A variant of <a>hearTimeout</a>, except it listens for any incoming
--   RPC request on the specified <a>Endpoint</a>
hearAllTimeout :: Endpoint -> Name -> Int -> IO (Maybe (Method, Message, Reply Message))

-- | Handle all RPCs on the specified <a>Endpoint</a> until <a>hangup</a>
--   is called on the returned <a>HandleSite</a>
handleAll :: Endpoint -> Name -> (Method -> Message -> IO Message) -> IO HandleSite

-- | Stop handling incoming RPCs for the indicated <a>HandleSite</a>.
hangup :: HandleSite -> IO ()


-- | A <a>Transport</a> abstracts the details of message delivery, and
--   defines the interfaces that specific <a>Transport</a> implementations
--   should provide in order to move messages between <a>Endpoint</a>s.
--   
--   The definition of a transport is deliberately low-level in nature.
--   Unless a specific transport describes itself as supporting features
--   like guaranteed delivery, applications should NOT assume that message
--   delivery is reliable.
--   
--   For example, if a sender sends a message to a name that has not yet
--   been bound, then immediately waits on the response for that message,
--   then the application may hang, as the original message may have been
--   dropped.
--   
--   However, many application may find it easier to push features such as
--   reliable message delivery into a custom transport, leaving the
--   application only having to concern itself with the messages being
--   delivered rather than how they arrive.
--   
--   The main abstractions common to all transports:
--   
--   <ul>
--   <li><a>Endpoint</a>s may not receive messages until either <a>bind</a>
--   has been called on an available <a>Transport</a>, or a <a>bindName</a>
--   has been called on the <a>Endpoint</a>. The latter is typically useful
--   for <a>Endpoint</a>s that originate connections but do not accept them
--   directly.</li>
--   <li>A <a>Connection</a> defines a bi-directional pathway for messages
--   to flow between <a>Endpoint</a>s. The initiator of the connection is a
--   client, and the destination for the connection is a server. Server
--   <a>Endpoint</a>s may have to have called <a>bind</a> on the
--   <a>Transport</a> before being able to accept connections or receive
--   messages; a client only has to have called <a>bindName</a> in order to
--   receive responses from the server.</li>
--   <li>Client's proactively attempt to maintain <a>Connection</a>s to the
--   server; in the event a server breaks the connection (other because of
--   a crash or deliberate exit), the client will continue to restore the
--   connection.</li>
--   <li><a>Connection</a>s essentially define the topology over which
--   messages will propagate between <a>Endpoint</a>s.</li>
--   </ul>
module Network.Transport

-- | A <a>Transport</a> defines a specific method for establishing
--   connections between <a>Endpoint</a>s.
data Transport
Transport :: Endpoint -> Name -> IO Binding -> Endpoint -> IO Dispatcher -> Endpoint -> Name -> IO Connection -> IO () -> Transport
[bind] :: Transport -> Endpoint -> Name -> IO Binding
[dispatch] :: Transport -> Endpoint -> IO Dispatcher
[connect] :: Transport -> Endpoint -> Name -> IO Connection
[shutdown] :: Transport -> IO ()

-- | An exception encountered by a <a>Transport</a>.
data TransportException
NoDataRead :: TransportException
DataUnderflow :: TransportException

-- | A <a>Dispatcher</a> encapsulates a <a>Transport</a>s interaction with
--   an <a>Endpoint</a> for outbound message flow.
data Dispatcher
Dispatcher :: IO () -> Dispatcher
[stop] :: Dispatcher -> IO ()

-- | Wraps in a continually repeating call to <a>dispatchMessage</a> in a
--   <a>Dispatcher</a> so that dispatching can be stopped when no longer
--   needed.
dispatcher :: Mailboxes -> Endpoint -> IO Dispatcher

-- | A mutable <tt>Map</tt> of <a>Name</a>s to <a>Mailbox</a>es of
--   <a>Message</a>s.
type Mailboxes = TVar (Map Name (Mailbox Message))

-- | Pull a <a>Message</a> intended for a destination name from a
--   <a>Mailboxes</a> directly, without the use of a <a>Transport</a>
pullMessage :: Mailboxes -> Name -> STM Message

-- | A simple function to multiplex messages (each wrapped in an
--   <a>Envelope</a>) in the <a>endpointOutbound</a> mailbox of an
--   <a>Endpoint</a> to one or more <a>Mailboxes</a> by extract the
--   <a>messageDestination</a> from the <a>Envelope</a> and finding or
--   creating a <a>Mailbox</a> containing messages only for that
--   destination. This is often useful for <a>Transport</a>s, who then only
--   have to monitor a specific <a>Mailbox</a> to know when there are
--   messages to send to a particular destination.
dispatchMessage :: Mailboxes -> Name -> Message -> STM ()

-- | Within the body of the function, ensures that <a>Message</a>s are
--   dispatched as necessary.
withTransport :: IO Transport -> (Transport -> IO a) -> IO a

-- | Within the body of the function, ensure that there is a
--   <a>Dispatcher</a> for the <a>Endpoint</a>.
withEndpoint :: Transport -> Endpoint -> IO a -> IO a

-- | Helper for easily creating clients capable of sending messages on the
--   <a>Transport</a> and receiving messages at the provided <a>Name</a>
withClient :: IO Transport -> Name -> (Endpoint -> IO a) -> IO a

-- | Helper for easily creating servers listening messages sent to the
--   specified <a>Name</a> over the provided <a>Transport</a>
withServer :: IO Transport -> Name -> (Transport -> Endpoint -> IO a) -> IO a

-- | Bindings are a site for receiving messages on a particular <a>Name</a>
--   through a <a>Transport</a>.
data Binding
Binding :: Name -> IO () -> Binding
[bindingName] :: Binding -> Name
[unbind] :: Binding -> IO ()

-- | A helper for ensuring there is a <a>Binding</a> of a specific
--   <a>Endpoint</a> to a specific <a>Name</a> on the provided
--   <a>Transport</a> during a function.
withBinding :: Transport -> Endpoint -> Name -> IO a -> IO a

-- | A helper for ensuring there are <a>Binding</a>s of a specific
--   <a>Endpoint</a> to specific <a>Name</a>s on the provided
--   <a>Transport</a> during a function.
withBinding2 :: Transport -> (Endpoint, Name) -> (Endpoint, Name) -> IO a -> IO a

-- | A helper for ensuring there are <a>Binding</a>s of a specific
--   <a>Endpoint</a> to specific <a>Name</a>s on the provided
--   <a>Transport</a> during a function.
withBinding3 :: Transport -> (Endpoint, Name) -> (Endpoint, Name) -> (Endpoint, Name) -> IO a -> IO a

-- | A helper for ensuring there are <a>Binding</a>s of a specific
--   <a>Endpoint</a> to specific <a>Name</a>s on the provided
--   <a>Transport</a> during a function.
withBinding4 :: Transport -> (Endpoint, Name) -> (Endpoint, Name) -> (Endpoint, Name) -> (Endpoint, Name) -> IO a -> IO a

-- | Connections are bi-directional pathways for exchanging <a>Message</a>s
--   with another <a>Endpoint</a> that is bound to a specific <a>Name</a>
--   on a shared <a>Transport</a>.
data Connection
Connection :: IO () -> Connection
[disconnect] :: Connection -> IO ()

-- | A helper for ensuring that a <a>Connection</a> is maintained during
--   execution of a function.
withConnection :: Transport -> Endpoint -> Name -> IO a -> IO a

-- | A helper for ensuring that 2 <a>Connection</a>s are maintained during
--   execution of a function.
withConnection2 :: Transport -> Endpoint -> Name -> Name -> IO a -> IO a

-- | A helper for ensuring that 3 <a>Connection</a>s are maintained during
--   execution of a function.
withConnection3 :: Transport -> Endpoint -> Name -> Name -> Name -> IO a -> IO a

-- | A helper for ensuring that 4 <a>Connection</a>s are maintained during
--   execution of a function.
withConnection4 :: Transport -> Endpoint -> Name -> Name -> Name -> Name -> IO a -> IO a
withConnections :: Transport -> Endpoint -> [Name] -> IO a -> IO a

-- | This is a helper designed to create a complete network, where there
--   are enough connections to ensure every endpoint has a connection to
--   every other endpoint.
withCompleteNetwork :: Transport -> [Name] -> Endpoint -> Name -> IO a -> IO a
instance GHC.Show.Show Network.Transport.TransportException
instance GHC.Exception.Exception Network.Transport.TransportException


-- | Memory transports deliver messages to other <a>Endpoint</a>s within
--   the same shared address space, or operating system process.
module Network.Transport.Memory

-- | Create a new memory <a>Transport</a> for use by <a>Endpoint</a>s.
newMemoryTransport :: IO Transport


-- | Helpers for socket transports.
module Network.Transport.Sockets

-- | A <a>SocketConnection</a> encapsulates the state of a single outbound
--   connection.
data SocketConnection
SocketConnection :: TMVar Name -> Message -> IO () -> IO Message -> IO () -> SocketConnection
[connectionDestination] :: SocketConnection -> TMVar Name
[sendSocketMessage] :: SocketConnection -> Message -> IO ()
[receiveSocketMessage] :: SocketConnection -> IO Message
[disconnectSocket] :: SocketConnection -> IO ()

-- | Mutble <a>Map</a> of <a>Name</a>s to <a>Connection</a>s.
type Connections = TVar (Map Name Connection)

-- | Establish a <a>connector</a> for exchanging messages from
--   <a>Endpoint</a> with a destination specified by <a>Name</a>.
socketConnect :: Mailboxes -> Connect -> Endpoint -> Name -> IO Connection

-- | Listens for new connections on a new <a>Socket</a>, and return the
--   <a>Socket</a>.
socketListen :: Family -> SocketType -> Resolver -> Name -> IO Socket

-- | Exchange <tt>Messages</tt> with the <a>Endpoint</a> on the other side
--   of a <a>SocketConnection</a>.
messenger :: Mailboxes -> Endpoint -> SocketConnection -> IO ()

-- | Maintain a <a>Connection</a> between an <a>Endpoint</a> and a
--   destination specified by <a>Name</a>. Should the connection, the
--   connection will automatically be re-attempted.
connector :: Mailboxes -> Endpoint -> Name -> Connect -> IO ()

-- | A <a>Resolver</a> translates a name into a list of <a>SockAddr</a> for
--   use with a socket-based <a>Transport</a>.
type Resolver = Name -> IO [SockAddr]

-- | Exceptions thrown by a <a>Resolver</a>.
data ResolverException

-- | Helper to resolve a <a>Name</a> to a single <a>SockAddr</a> for use
--   with a socket-based <a>Transport</a>.
resolve1 :: Resolver -> Name -> IO SockAddr

-- | Variation of <tt>socketResolve</tt> for standard IP addresses.
socketResolver4 :: SocketType -> Name -> IO [SockAddr]

-- | Variation of <tt>socketResolve</tt> for standard IPv6 addresses.
socketResolver6 :: SocketType -> Name -> IO [SockAddr]

-- | Returns the wildcard <a>SockAddr</a> for the specified
--   <a>SockAddr</a>, if possible.
wildcard :: SockAddr -> IO SockAddr
instance GHC.Generics.Generic Network.Transport.Sockets.SocketMessage
instance GHC.Show.Show Network.Transport.Sockets.ResolverException
instance Data.Serialize.Serialize Network.Transport.Sockets.SocketMessage
instance GHC.Exception.Exception Network.Transport.Sockets.ResolverException


-- | TCP transport.
module Network.Transport.Sockets.TCP

-- | Create a <a>Transport</a> for exchanging <a>Message</a>s between
--   endpoints via TCP over IP
newTCPTransport4 :: Resolver -> IO Transport

-- | Create a <a>Transport</a> for exchanging <a>Message</a>s between
--   endpoints via TCP over IPv6
newTCPTransport6 :: Resolver -> IO Transport

-- | Create a <tt>Resolve</tt> for resolving <a>Name</a>s for use with TCP
--   over IP.
tcpSocketResolver4 :: Name -> IO [SockAddr]

-- | Create a <tt>Resolve</tt> for resolving <a>Name</a>s for use with TCP
--   over IPv6.
tcpSocketResolver6 :: Name -> IO [SockAddr]


-- | UDP transport.
module Network.Transport.Sockets.UDP

-- | Create a <a>Transport</a> for exchanging <a>Message</a>s between
--   endpoints via UDP over IP
newUDPTransport4 :: Resolver -> IO Transport

-- | Create a <a>Transport</a> for exchanging <a>Message</a>s between
--   endpoints via UDP over IPv6
newUDPTransport6 :: Resolver -> IO Transport

-- | Create a <tt>Resolve</tt> for resolving <a>Name</a>s for use with UDP
--   over IP.
udpSocketResolver4 :: Name -> IO [SockAddr]

-- | Create a <tt>Resolve</tt> for resolving <a>Name</a>s for use with UDP
--   over IPv6.
udpSocketResolver6 :: Name -> IO [SockAddr]
