network-transport 0.2.0.2 → 0.3.0
raw patch · 4 files changed
+121/−69 lines, 4 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Network.Transport: ConnectionClosed :: ConnectionId -> Event
+ Network.Transport: ConnectionClosed :: {-# UNPACK #-} !ConnectionId -> Event
- Network.Transport: ConnectionOpened :: ConnectionId -> Reliability -> EndPointAddress -> Event
+ Network.Transport: ConnectionOpened :: {-# UNPACK #-} !ConnectionId -> Reliability -> EndPointAddress -> Event
- Network.Transport: EventConnectionLost :: (Maybe EndPointAddress) -> [ConnectionId] -> EventErrorCode
+ Network.Transport: EventConnectionLost :: EndPointAddress -> EventErrorCode
- Network.Transport: Received :: ConnectionId -> [ByteString] -> Event
+ Network.Transport: Received :: {-# UNPACK #-} !ConnectionId -> [ByteString] -> Event
- Network.Transport: type ConnectionId = Int
+ Network.Transport: type ConnectionId = Word64
Files
- network-transport.cabal +1/−1
- src/Network/Transport.hs +79/−32
- src/Network/Transport/Internal.hs +35/−31
- src/Network/Transport/Util.hs +6/−5
network-transport.cabal view
@@ -1,5 +1,5 @@ Name: network-transport-Version: 0.2.0.2+Version: 0.3.0 Cabal-Version: >=1.6 Build-Type: Simple License: BSD3
src/Network/Transport.hs view
@@ -1,32 +1,36 @@ -- | 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+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 as BS (copy) import qualified Data.ByteString.Char8 as BSC (unpack) import Control.Exception (Exception)+import Control.Applicative ((<$>)) import Data.Typeable (Typeable)-import Data.Binary (Binary)+import Data.Binary (Binary(get, put))+import Data.Word (Word64) -------------------------------------------------------------------------------- -- Main API --@@ -48,6 +52,11 @@ -- | EndPointAddress of the endpoint. , address :: EndPointAddress -- | Create a new lightweight connection. + --+ -- 'connect' should be as asynchronous as possible; for instance, in+ -- Transport implementations based on some heavy-weight underlying network+ -- protocol (TCP, ssh), a call to 'connect' should be asynchronous when a+ -- heavyweight connection has already been established. , connect :: EndPointAddress -> Reliability -> ConnectHints -> IO (Either (TransportError ConnectErrorCode) Connection) -- | Create a new multicast group. , newMulticastGroup :: IO (Either (TransportError NewMulticastGroupErrorCode) MulticastGroup)@@ -60,6 +69,11 @@ -- | Lightweight connection to an endpoint. data Connection = Connection { -- | Send a message on this connection.+ -- + -- 'send' provides vectored I/O, and allows multiple data segments to be+ -- sent using a single call (cf. 'Network.Socket.ByteString.sendMany').+ -- Note that this segment structure is entirely unrelated to the segment+ -- structure /returned/ by a 'Received' event. send :: [ByteString] -> IO (Either (TransportError SendErrorCode) ()) -- | Close the connection. , close :: IO ()@@ -68,11 +82,13 @@ -- | Event on an endpoint. data Event = -- | Received a message- Received ConnectionId [ByteString]+ Received {-# UNPACK #-} !ConnectionId [ByteString] -- | Connection closed- | ConnectionClosed ConnectionId+ | ConnectionClosed {-# UNPACK #-} !ConnectionId -- | Connection opened- | ConnectionOpened ConnectionId Reliability EndPointAddress + --+ -- 'ConnectionId's need not be allocated contiguously.+ | ConnectionOpened {-# UNPACK #-} !ConnectionId Reliability EndPointAddress -- | Received multicast | ReceivedMulticast MulticastAddress [ByteString] -- | The endpoint got closed (manually, by a call to closeEndPoint or closeTransport)@@ -82,7 +98,7 @@ deriving (Show, Eq) -- | Connection data ConnectHintsIDs enable receivers to distinguish one connection from another.-type ConnectionId = Int+type ConnectionId = Word64 -- | Reliability guarantees of a connection. data Reliability = @@ -111,8 +127,12 @@ -- | EndPointAddress of an endpoint. newtype EndPointAddress = EndPointAddress { endPointAddressToByteString :: ByteString }- deriving (Eq, Ord, Typeable, Binary)+ deriving (Eq, Ord, Typeable) +instance Binary EndPointAddress where+ put = put . endPointAddressToByteString+ get = EndPointAddress . BS.copy <$> get+ instance Show EndPointAddress where show = BSC.unpack . endPointAddressToByteString @@ -219,8 +239,35 @@ 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] + -- | We lost connection to another endpoint+ --+ -- Although "Network.Transport" provides multiple independent lightweight+ -- connections between endpoints, those connections cannot /fail/+ -- independently: once one connection has failed, /all/ connections, in+ -- both directions, must now be considered to have failed; they fail as a+ -- "bundle" of connections, with only a single "bundle" of connections per+ -- endpoint at any point in time.+ -- + -- That is, suppose there are multiple connections in either direction+ -- between endpoints A and B, and A receives a notification that it has+ -- lost contact with B. Then A must not be able to send any further+ -- messages to B on existing connections. + --+ -- Although B may not realize /immediately/ that its connection to A has+ -- been broken, messages sent by B on existing connections should not be+ -- delivered, and B must eventually get an EventConnectionLost message,+ -- too. + --+ -- Moreover, this event must be posted before A has successfully+ -- reconnected (in other words, if B notices a reconnection attempt from A,+ -- it must post the EventConnectionLost before acknowledging the connection+ -- from A) so that B will not receive events about new connections or+ -- incoming messages from A without realizing that it got disconnected. + -- + -- If B attempts to establish another connection to A before it realized+ -- that it got disconnected from A then it's okay for this connection+ -- attempt to fail, and the EventConnectionLost to be posted at that point,+ -- or for the EventConnectionLost to be posted and for the new connection+ -- to be considered the first connection of the "new bundle".+ | EventConnectionLost EndPointAddress deriving (Show, Typeable, Eq)
src/Network/Transport/Internal.hs view
@@ -1,22 +1,23 @@ -- | Internal functions-module Network.Transport.Internal ( -- * Encoders/decoders- encodeInt32- , decodeInt32- , encodeInt16- , decodeInt16- , prependLength- -- * Miscellaneous abstractions- , mapIOException- , tryIO- , tryToEnum- , timeoutMaybe- , asyncWhenCancelled- -- * Replicated functionality from "base"- , void- , forkIOWithUnmask- -- * Debugging- , tlog- ) where+module Network.Transport.Internal + ( -- * Encoders/decoders+ encodeInt32+ , decodeInt32+ , encodeInt16+ , decodeInt16+ , prependLength+ -- * Miscellaneous abstractions+ , mapIOException+ , tryIO+ , tryToEnum+ , timeoutMaybe+ , asyncWhenCancelled+ -- * Replicated functionality from "base"+ , void+ , forkIOWithUnmask+ -- * Debugging+ , tlog+ ) where #if ! MIN_VERSION_base(4,6,0) import Prelude hiding (catch)@@ -27,20 +28,23 @@ import Foreign.ForeignPtr (withForeignPtr) import Data.ByteString (ByteString) import qualified Data.ByteString as BS (length)-import qualified Data.ByteString.Internal as BSI ( unsafeCreate- , toForeignPtr- , inlinePerformIO)+import qualified Data.ByteString.Internal as BSI + ( unsafeCreate+ , toForeignPtr+ , inlinePerformIO+ ) import Control.Monad.IO.Class (MonadIO, liftIO)-import Control.Exception ( IOException- , SomeException- , AsyncException- , Exception- , catch- , try- , throw- , throwIO- , mask_- )+import Control.Exception + ( IOException+ , SomeException+ , AsyncException+ , Exception+ , catch+ , try+ , throw+ , throwIO+ , mask_+ ) import Control.Concurrent (ThreadId, forkIO) import Control.Concurrent.MVar (MVar, newEmptyMVar, takeMVar, putMVar) import GHC.IO (unsafeUnmask)
src/Network/Transport/Util.hs view
@@ -3,11 +3,12 @@ -- Note: this module is bound to change even more than the rest of the API :) module Network.Transport.Util (spawn) where -import Network.Transport ( Transport- , EndPoint(..)- , EndPointAddress- , newEndPoint- )+import Network.Transport + ( Transport+ , EndPoint(..)+ , EndPointAddress+ , newEndPoint+ ) import Control.Concurrent (forkIO) import Control.Concurrent.MVar (newEmptyMVar, putMVar, takeMVar)