network-mux
Safe HaskellNone
LanguageHaskell2010

Network.Mux

Synopsis

Defining Mux protocol bundles

newMux :: forall m (mode :: MuxMode). MonadSTM m => MiniProtocolBundle mode -> m (Mux mode m) Source #

data Mux (mode :: MuxMode) (m :: Type -> Type) Source #

newtype MiniProtocolBundle (mode :: MuxMode) Source #

Application run by mux layer.

  • enumeration of client application, e.g. a wallet application communicating with a node using ChainSync and TxSubmission protocols; this only requires to run client side of each protocol.
  • enumeration of server applications: this application type is mostly useful tests.
  • enumeration of both client and server applications, e.g. a full node serving downstream peers using server side of each protocol and getting updates from upstream peers using client side of each of the protocols.

newtype MiniProtocolNum Source #

The wire format includes the protocol numbers, and it's vital that these are stable. They are not necessarily dense however, as new ones are added and some old ones retired. So we use a dedicated class for this rather than reusing Enum. This also covers unrecognised protocol numbers on the decoding side.

Constructors

MiniProtocolNum Word16 

Instances

Instances details
Enum MiniProtocolNum Source # 
Instance details

Defined in Network.Mux.Types

Ix MiniProtocolNum Source # 
Instance details

Defined in Network.Mux.Types

Show MiniProtocolNum Source # 
Instance details

Defined in Network.Mux.Types

Eq MiniProtocolNum Source # 
Instance details

Defined in Network.Mux.Types

Ord MiniProtocolNum Source # 
Instance details

Defined in Network.Mux.Types

newtype MiniProtocolLimits Source #

Per Miniprotocol limits

Constructors

MiniProtocolLimits 

Fields

  • maximumIngressQueue :: Int

    Limit on the maximum number of bytes that can be queued in the miniprotocol's ingress queue.

Running the Mux

runMux :: forall m (mode :: MuxMode). (MonadAsync m, MonadFork m, MonadLabelledSTM m, Alternative (STM m), MonadThrow (STM m), MonadTimer m, MonadMask m) => Tracer m MuxTrace -> Mux mode m -> MuxBearer m -> m () Source #

runMux starts a mux bearer for the specified protocols corresponding to one of the provided Versions.

Isometric flow control: analysis of head-of-line blocking of the ingress side of the multiplexer

For each mini-protocol (enumerated by ptcl), mux will create two channels. One for initiator and one for the responder. Each channel will use a single Wanton. When it is filled, it is put in a common queue tsrQueue. This means that the queue is bound by 2 * |ptcl|. Every side of a mini-protocol is served by a single Wanton: when an application sends data, the channel will try to put it into the Wanton (which might block). Wantons are taken from the tsrQueue queue by one of mux threads. This eliminates head of line blocking: each mini-protocol thread can block on putting more bytes into its Wanton, but it cannot block the other mini-protocols or the thread that is reading the tsrQueue queue. This is ensured since the muxChannel will put only a non-empty Wanton to the tsrQueue queue, and on such wantons the queue is never blocked. This means that the only way the queue can block is when its empty, which means that none of the mini-protocols wanted to send. The egress part will read a Wanton, take a fixed amount of bytes encode them in as an MuxSDU; if there are leftovers it will put them back in the Wanton and place it at the end of the queue (reading and writing to it will happen in a single STM transaction which assures that the order of requests from a mini-protocol is preserved.

Properties:

  • at any given time the tsrQueue contains at most one TranslocationServiceRequest from a given mini-protocol of the given MiniProtocolDir, thus the queue contains at most 2 * |ptcl| translocation requests.
  • at any given time each TranslocationServiceRequest contains a non-empty Wanton

runMiniProtocol :: forall (mode :: MuxMode) m a. (Alternative (STM m), MonadSTM m, MonadThrow m, MonadThrow (STM m)) => Mux mode m -> MiniProtocolNum -> MiniProtocolDirection mode -> StartOnDemandOrEagerly -> (Channel m -> m (a, Maybe ByteString)) -> m (STM m (Either SomeException a)) Source #

Arrange to run a protocol thread (for a particular MiniProtocolNum and MiniProtocolDirection) to interact on this protocol's Channel.

The protocol thread can either be started eagerly or on-demand:

  • With StartEagerly, the thread is started promptly. This is appropriate for mini-protocols where the opening message may be sent by this thread.
  • With StartOnDemand, the thread is not started until the first data is received for this mini-protocol. This is appropriate for mini-protocols where the opening message is sent by the remote peer.

The result is a STM action to block and wait on the protocol completion. It is safe to call this completion action multiple times: it will always return the same result once the protocol thread completes. In case the Mux has stopped, either due to an exception or because of a call to muxStop a `Left MuxError` will be returned from the STM action.

It is an error to start a new protocol thread while one is still running, for the same MiniProtocolNum and MiniProtocolDirection. This can easily be avoided by using the STM completion action to wait for the previous one to finish.

It is safe to ask to start a protocol thread before runMux. In this case the protocol thread will not actually start until runMux is called, irrespective of the StartOnDemandOrEagerly value.

stopMux :: forall m (mode :: MuxMode). MonadSTM m => Mux mode m -> m () Source #

Shut down the mux. This will cause runMux to return. It does not wait for any protocol threads to finish, so you should do that first if necessary.

Bearer

data MuxBearer (m :: Type -> Type) Source #

Low level access to underlying socket or pipe. There are three smart constructors:

newtype MakeBearer (m :: Type -> Type) fd Source #

Constructors

MakeBearer 

Fields

newtype SDUSize Source #

Constructors

SDUSize 

Fields

Instances

Instances details
Generic SDUSize Source # 
Instance details

Defined in Network.Mux.Types

Associated Types

type Rep SDUSize 
Instance details

Defined in Network.Mux.Types

type Rep SDUSize = D1 ('MetaData "SDUSize" "Network.Mux.Types" "network-mux-0.4.5.3-inplace" 'True) (C1 ('MetaCons "SDUSize" 'PrefixI 'True) (S1 ('MetaSel ('Just "getSDUSize") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Word16)))

Methods

from :: SDUSize -> Rep SDUSize x #

to :: Rep SDUSize x -> SDUSize #

Show SDUSize Source # 
Instance details

Defined in Network.Mux.Types

type Rep SDUSize Source # 
Instance details

Defined in Network.Mux.Types

type Rep SDUSize = D1 ('MetaData "SDUSize" "Network.Mux.Types" "network-mux-0.4.5.3-inplace" 'True) (C1 ('MetaCons "SDUSize" 'PrefixI 'True) (S1 ('MetaSel ('Just "getSDUSize") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Word16)))

Monitoring

muxStopped :: forall (m :: Type -> Type) (mode :: MuxMode). MonadSTM m => Mux mode m -> STM m (Maybe SomeException) Source #

Await until mux stopped.

Errors

data MuxError Source #

Error type used in across the mux layer.

Constructors

MuxError 

Instances

Instances details
Exception MuxError Source # 
Instance details

Defined in Network.Mux.Trace

Generic MuxError Source # 
Instance details

Defined in Network.Mux.Trace

Associated Types

type Rep MuxError 
Instance details

Defined in Network.Mux.Trace

type Rep MuxError = D1 ('MetaData "MuxError" "Network.Mux.Trace" "network-mux-0.4.5.3-inplace" 'False) (C1 ('MetaCons "MuxError" 'PrefixI 'True) (S1 ('MetaSel ('Just "errorType") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 MuxErrorType) :*: S1 ('MetaSel ('Just "errorMsg") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 String)))

Methods

from :: MuxError -> Rep MuxError x #

to :: Rep MuxError x -> MuxError #

Show MuxError Source # 
Instance details

Defined in Network.Mux.Trace

type Rep MuxError Source # 
Instance details

Defined in Network.Mux.Trace

type Rep MuxError = D1 ('MetaData "MuxError" "Network.Mux.Trace" "network-mux-0.4.5.3-inplace" 'False) (C1 ('MetaCons "MuxError" 'PrefixI 'True) (S1 ('MetaSel ('Just "errorType") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 MuxErrorType) :*: S1 ('MetaSel ('Just "errorMsg") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 String)))

data MuxErrorType Source #

Enumeration of error conditions.

Constructors

MuxUnknownMiniProtocol

returned by decodeMuxSDUHeader, thrown by MuxBearer.

MuxDecodeError

return by decodeMuxSDUHeader, thrown by MuxBearer.

MuxBearerClosed

thrown by MuxBearer when received a null byte.

MuxIngressQueueOverRun

thrown by demux when violating maximumIngressQueue byte limit.

MuxInitiatorOnly

thrown when data arrives on a responder channel when the mux was set up as an InitiatorApp.

MuxIOException IOException

IOException thrown by

MuxSDUReadTimeout

thrown when reading of a single SDU takes too long

MuxSDUWriteTimeout

thrown when writing a single SDU takes too long

MuxShutdown !(Maybe MuxErrorType)

Result of runMiniProtocol's completionAction in case of an error or mux being closed while a mini-protocol was still running, this is not a clean exit.

MuxCleanShutdown

Mux stopped by stopMux

Instances

Instances details
Show MuxErrorType Source # 
Instance details

Defined in Network.Mux.Trace

Eq MuxErrorType Source # 
Instance details

Defined in Network.Mux.Trace

Tracing

data MuxBearerState Source #

Constructors

Mature

MuxBearer has successfully completed the handshake.

Dead

MuxBearer is dead and the underlying bearer has been closed.

Instances

Instances details
Show MuxBearerState Source # 
Instance details

Defined in Network.Mux.Trace

Eq MuxBearerState Source # 
Instance details

Defined in Network.Mux.Trace

data WithMuxBearer peerid a Source #

Type used for tracing mux events.

Constructors

WithMuxBearer 

Fields

  • wmbPeerId :: !peerid

    A tag that should identify a specific mux bearer.

  • wmbEvent :: !a
     

Instances

Instances details
Generic (WithMuxBearer peerid a) Source # 
Instance details

Defined in Network.Mux.Trace

Associated Types

type Rep (WithMuxBearer peerid a) 
Instance details

Defined in Network.Mux.Trace

type Rep (WithMuxBearer peerid a) = D1 ('MetaData "WithMuxBearer" "Network.Mux.Trace" "network-mux-0.4.5.3-inplace" 'False) (C1 ('MetaCons "WithMuxBearer" 'PrefixI 'True) (S1 ('MetaSel ('Just "wmbPeerId") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 peerid) :*: S1 ('MetaSel ('Just "wmbEvent") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 a)))

Methods

from :: WithMuxBearer peerid a -> Rep (WithMuxBearer peerid a) x #

to :: Rep (WithMuxBearer peerid a) x -> WithMuxBearer peerid a #

(Show peerid, Show a) => Show (WithMuxBearer peerid a) Source # 
Instance details

Defined in Network.Mux.Trace

Methods

showsPrec :: Int -> WithMuxBearer peerid a -> ShowS #

show :: WithMuxBearer peerid a -> String #

showList :: [WithMuxBearer peerid a] -> ShowS #

type Rep (WithMuxBearer peerid a) Source # 
Instance details

Defined in Network.Mux.Trace

type Rep (WithMuxBearer peerid a) = D1 ('MetaData "WithMuxBearer" "Network.Mux.Trace" "network-mux-0.4.5.3-inplace" 'False) (C1 ('MetaCons "WithMuxBearer" 'PrefixI 'True) (S1 ('MetaSel ('Just "wmbPeerId") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 peerid) :*: S1 ('MetaSel ('Just "wmbEvent") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 a)))