-- | Network Transport
module Network.Transport ( -- * Types
Transport(..)
, EndPoint(..)
, Connection(..)
, Event(..)
, ConnectionId
, Reliability(..)
, MulticastGroup(..)
, EndPointAddress(..)
, MulticastAddress(..)
-- * Hints
, ConnectHints(..)
, defaultConnectHints
-- * Error codes
, TransportError(..)
, NewEndPointErrorCode(..)
, ConnectErrorCode(..)
, NewMulticastGroupErrorCode(..)
, ResolveMulticastGroupErrorCode(..)
, SendErrorCode(..)
, EventErrorCode(..)
) where
import Data.ByteString (ByteString)
import qualified Data.ByteString.Char8 as BSC (unpack)
import Control.Exception (Exception)
import Data.Typeable (Typeable)
import Data.Binary (Binary)
--------------------------------------------------------------------------------
-- Main API --
--------------------------------------------------------------------------------
-- | To create a network abstraction layer, use one of the
-- @Network.Transport.*@ packages.
data Transport = Transport {
-- | Create a new end point (heavyweight operation)
newEndPoint :: IO (Either (TransportError NewEndPointErrorCode) EndPoint)
-- | Shutdown the transport completely
, closeTransport :: IO ()
}
-- | Network endpoint.
data EndPoint = EndPoint {
-- | Endpoints have a single shared receive queue.
receive :: IO Event
-- | EndPointAddress of the endpoint.
, address :: EndPointAddress
-- | Create a new lightweight connection.
, connect :: EndPointAddress -> Reliability -> ConnectHints -> IO (Either (TransportError ConnectErrorCode) Connection)
-- | Create a new multicast group.
, newMulticastGroup :: IO (Either (TransportError NewMulticastGroupErrorCode) MulticastGroup)
-- | Resolve an address to a multicast group.
, resolveMulticastGroup :: MulticastAddress -> IO (Either (TransportError ResolveMulticastGroupErrorCode) MulticastGroup)
-- | Close the endpoint
, closeEndPoint :: IO ()
}
-- | Lightweight connection to an endpoint.
data Connection = Connection {
-- | Send a message on this connection.
send :: [ByteString] -> IO (Either (TransportError SendErrorCode) ())
-- | Close the connection.
, close :: IO ()
}
-- | Event on an endpoint.
data Event =
-- | Received a message
Received ConnectionId [ByteString]
-- | Connection closed
| ConnectionClosed ConnectionId
-- | Connection opened
| ConnectionOpened ConnectionId Reliability EndPointAddress
-- | Received multicast
| ReceivedMulticast MulticastAddress [ByteString]
-- | The endpoint got closed (manually, by a call to closeEndPoint or closeTransport)
| EndPointClosed
-- | An error occurred
| ErrorEvent (TransportError EventErrorCode)
deriving (Show, Eq)
-- | Connection data ConnectHintsIDs enable receivers to distinguish one connection from another.
type ConnectionId = Int
-- | Reliability guarantees of a connection.
data Reliability =
ReliableOrdered
| ReliableUnordered
| Unreliable
deriving (Show, Eq)
-- | Multicast group.
data MulticastGroup = MulticastGroup {
-- | EndPointAddress of the multicast group.
multicastAddress :: MulticastAddress
-- | Delete the multicast group completely.
, deleteMulticastGroup :: IO ()
-- | Maximum message size that we can send to this group.
, maxMsgSize :: Maybe Int
-- | Send a message to the group.
, multicastSend :: [ByteString] -> IO ()
-- | Subscribe to the given multicast group (to start receiving messages from the group).
, multicastSubscribe :: IO ()
-- | Unsubscribe from the given multicast group (to stop receiving messages from the group).
, multicastUnsubscribe :: IO ()
-- | Close the group (that is, indicate you no longer wish to send to the group).
, multicastClose :: IO ()
}
-- | EndPointAddress of an endpoint.
newtype EndPointAddress = EndPointAddress { endPointAddressToByteString :: ByteString }
deriving (Eq, Ord, Typeable, Binary)
instance Show EndPointAddress where
show = BSC.unpack . endPointAddressToByteString
-- | EndPointAddress of a multicast group.
newtype MulticastAddress = MulticastAddress { multicastAddressToByteString :: ByteString }
deriving (Eq, Ord)
instance Show MulticastAddress where
show = show . multicastAddressToByteString
--------------------------------------------------------------------------------
-- Hints --
-- --
-- Hints provide transport-generic "suggestions". For now, these are --
-- placeholders only. --
--------------------------------------------------------------------------------
-- | Hints used by 'connect'
data ConnectHints = ConnectHints {
-- Timeout
connectTimeout :: Maybe Int
}
-- | Default hints for connecting
defaultConnectHints :: ConnectHints
defaultConnectHints = ConnectHints {
connectTimeout = Nothing
}
--------------------------------------------------------------------------------
-- Error codes --
-- --
-- Errors should be transport-implementation independent. The deciding factor --
-- for distinguishing one kind of error from another should be: might --
-- application code have to take a different action depending on the kind of --
-- error? --
--------------------------------------------------------------------------------
-- | Errors returned by Network.Transport API functions consist of an error
-- code and a human readable description of the problem
data TransportError error = TransportError error String
deriving (Show, Typeable)
-- | Although the functions in the transport API never throw TransportErrors
-- (but return them explicitly), application code may want to turn these into
-- exceptions.
instance (Typeable err, Show err) => Exception (TransportError err)
-- | When comparing errors we ignore the human-readable strings
instance Eq error => Eq (TransportError error) where
TransportError err1 _ == TransportError err2 _ = err1 == err2
-- | Errors during the creation of an endpoint
data NewEndPointErrorCode =
-- | Not enough resources
NewEndPointInsufficientResources
-- | Failed for some other reason
| NewEndPointFailed
deriving (Show, Typeable, Eq)
-- | Connection failure
data ConnectErrorCode =
-- | Could not resolve the address
ConnectNotFound
-- | Insufficient resources (for instance, no more sockets available)
| ConnectInsufficientResources
-- | Timeout
| ConnectTimeout
-- | Failed for other reasons (including syntax error)
| ConnectFailed
deriving (Show, Typeable, Eq)
-- | Failure during the creation of a new multicast group
data NewMulticastGroupErrorCode =
-- | Insufficient resources
NewMulticastGroupInsufficientResources
-- | Failed for some other reason
| NewMulticastGroupFailed
-- | Not all transport implementations support multicast
| NewMulticastGroupUnsupported
deriving (Show, Typeable, Eq)
-- | Failure during the resolution of a multicast group
data ResolveMulticastGroupErrorCode =
-- | Multicast group not found
ResolveMulticastGroupNotFound
-- | Failed for some other reason (including syntax error)
| ResolveMulticastGroupFailed
-- | Not all transport implementations support multicast
| ResolveMulticastGroupUnsupported
deriving (Show, Typeable, Eq)
-- | Failure during sending a message
data SendErrorCode =
-- | Connection was closed
SendClosed
-- | Send failed for some other reason
| SendFailed
deriving (Show, Typeable, Eq)
-- | Error codes used when reporting errors to endpoints (through receive)
data EventErrorCode =
-- | Failure of the entire endpoint
EventEndPointFailed
-- | Transport-wide fatal error
| EventTransportFailed
-- | Some incoming connections were closed abruptly.
-- If an endpoint address is specified, then all connections to and
-- from that endpoint are now lost
| EventConnectionLost (Maybe EndPointAddress) [ConnectionId]
deriving (Show, Typeable, Eq)