Documentation
¶
Overview ¶
Package wspacket contains types related to managing packets for the github.com/gordian-engine/dragon/wingspan package.
This is an independent package, rather than part of the wingspan package, in order to simplify an internal dependency graph.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ( // Error to be returned from [InboundRemoteState.CheckIncoming] // when a peer sends a packet that was already observed // due to a call to ApplyUpdateFromCentral. // This is a normal occurrence which short-circuits some work. ErrAlreadyHavePacket = errors.New("already had packet") // Error to be returned from [InboundRemoteState.CheckIncoming] // when a peer sends the same packet more than once. // This is a protocol violation that will result in disconnection. ErrDuplicateSentPacket = errors.New("peer sent same packet twice") )
var ErrRedundantUpdate = errors.New("delta contained redundant data")
Returned from [CentralState.UpdateFromPeer] indicating that the delta did not add new information. This is a normal case when many peers are gossiping at once.
Functions ¶
This section is empty.
Types ¶
type CentralState ¶
type CentralState[ PktIn any, PktOut OutboundPacket, DeltaIn, DeltaOut any, ] interface { // UpdateFromPeer updates the central state with // new information originating from a remote peer. // // If the delta does not add new information to the state, // this method must return [ErrRedundantUpdate]. // // This method must return nil on success or [ErrRedundantUpdate] // if the packet contained no new information. // Any other error value is treated as a protocol violation, // which will result in a disconnection from the peer. UpdateFromPeer(context.Context, DeltaIn) error // NewOutboundRemoteState returns an OutboundRemoteState instance // that contains a copy of the state in the current central state, // and a Stream that is valid for the returned state. // // Returning the stream here avoids the possibility // of a data race between constructing the state // and observing the stream. NewOutboundRemoteState(context.Context) ( OutboundRemoteState[PktIn, PktOut, DeltaIn, DeltaOut], *dpubsub.Stream[DeltaOut], error, ) // NewInboundRemoteState returns a new [InboundRemoteState] // that contains a copy of the state in the current central state, // and a Stream that is valid for the returned state. // // Returning the stream here avoids the possibility // of a data race between constructing the state // and observing the stream. NewInboundRemoteState(context.Context) ( InboundRemoteState[PktIn, DeltaIn, DeltaOut], *dpubsub.Stream[DeltaOut], error, ) }
CentralState is the state management that is central to a session, related to but decoupled from any remote state.
It has four type parameters:
- PktIn is the parsed but unprocessed packet from a peer
- PktOut is the outbound packet including its byte-level representation
- DeltaIn is the "stateless" representation of an incoming state change
- DeltaOut is the "stateless" representation of an outgoing state change
The PktIn and DeltaIn types are separate for two primary reasons. First, the packet may be stateful with regard to the underlying stream, and the delta is intended to be stateless (has no regard to any single QUIC stream). Second, the delta may contain computed values that are necessary for the central state but which are not encoded in the packet.
While this interface contains the methods necessary for integration with the [wingspan.Protocol], there is other functionality required outside of this interface.
For instance, there must be an outbound delta *dpubsub.Stream associated with the CentralState and provided when creating a new Wingspan session.
type InboundRemoteState ¶
type InboundRemoteState[PktIn, DeltaIn, DeltaOut any] interface { // Apply the outbound delta that was dispatched from the [CentralState]. // Wingspan internals handle routing this request. // // The purpose of the inbound state being aware of central state // is to affect the return value of CheckIncoming, // in order to avoid sending redundant values back to the central state. ApplyUpdateFromCentral(DeltaOut) error // ApplyUpdateFromPeer indicates that the given inbound delta // was accepted by the central state (or was noted as redundant // due to a concurrent update from another peer). // // For many implementations of InboundRemoteState, // ApplyUpdateFromPeer will be a no-op. // // It is possible although unlikely that a call to // ApplyUpdateFromCentral could occur before ApplyUpdateFromPeer, // so the implementation must handle that case gracefully, // returning nil. ApplyUpdateFromPeer(DeltaIn) error // Parse an incoming packet. // This should simply consume bytes from the reader // and produce a packet. ParsePacket(io.Reader) (PktIn, error) // Convert the lightweight packet to a delta value for the [CentralState]. // Wingspan internals call this if the inbound state passes CheckIncoming. // This allows expensive work to be skipped for redundant packets. PacketToDelta(PktIn) (DeltaIn, error) // Determine if this is a packet we've seen before, // or if it is a packet this peer has already sent // (which is a protocol violation). // // Immediately after Wingspan internals parse a packet from a peer, // the packet is passed to CheckIncoming. // This method must return [ErrAlreadyHavePacket], // [ErrDuplicateSentPacket], or nil. // // If CheckIncoming returns nil, // the Wingspan internals route the packet to // [OutboundRemoteState.AddUnverifiedFromPeer] // and to [CentralState.UpdateFromPeer]. // // The implementation is responsible for ensuring // that multiple calls with the same delta // return ErrDuplicateSentPacket on the second or later calls. CheckIncoming(PktIn) error }
InboundRemoteState is the state associated with an inbound stream.
Create an instance of InboundRemoteState with [CentralState.NewInboundRemoteState].
Implementers may note that the sequence of calls for a single delta depends on the origin of the delta.
If a different peer sends the delta, only ApplyUpdateFromCentral is called.
If the peer associated with the state sends the Delta, CheckIncoming is called first to ensure the peer is not violating the protocol by sending the same packet twice, and also to short circuit unnecessary work if the peer sends a packet that we already received from another peer.
If the packet received from the peer is new, and if the central state verifies and accepts the delta, then the session calls ApplyUpdateFromPeer.
If another peer is concurrently sending the same packet, it is possible for ApplyUpdateFromCentral to be called between CheckIncoming and ApplyUpdateFromPeer.
type OutboundPacket ¶
type OutboundPacket interface {
// Bytes is the raw byte slice that needs to be sent
// to the peer over a QUIC stream.
//
// To minimize allocations,
// independent packets should return the same underlying slice.
// Callers will not modify the slice.
Bytes() []byte
// After sending a packet to a peer,
// Wingspan internals call MarkSent
// in order to update the [OutboundRemoteState],
// which will influence future calls to [OutboundRemoteState.UnsentPackets].
MarkSent()
}
OutboundPacket is an opaque view of a single outgoing packet.
OutboundPacket values are accessed through [OutboundRemoteState.UnsentPackets].
type OutboundRemoteState ¶
type OutboundRemoteState[ PktIn any, PktOut OutboundPacket, DeltaIn, DeltaOut any, ] interface { // Apply the outbound delta that was dispatched from the [CentralState]. // Wingspan internals handle routing this request. // // An update from the central state indicates a new packet // that should be included in the UnsentPackets output, // unless there was a prior call to AddUnverifiedFromPeer // that matches the update. // In that case, the state should treat the delta // as though the peer already has it. ApplyUpdateFromCentral(DeltaOut) error // AddUnverifiedFromPeer is called after // successfully parsing an inbound delta from a packet, // on the corresponding inbound worker, // but before Wingspan internals pass the delta // to the [CentralState] for verification. // // The implementation should optimistically accumulate // delta values in a buffer, removing entries upon // a corresponding call to ApplyUpdateFromCentral. // // In the event that the peer provides an invalid delta, // the session will stop using this state value // once the delta is determined to be invalid // (implying that the peer cannot be trusted). // // The implementation must gracefully handle an unverified delta // arriving after a call to ApplyUpdateFromCentral, // although that case is unlikely. // // Returning an error from this method will cause the session // to close the underlying connection to the peer. AddUnverifiedFromPeer(DeltaIn) error // An iterator over the packets in the OutboundRemoteState // which have not yet been sent. // // Wingspan internals will not call ApplyUpdateFromCentral // while the iterator is active, // but AddUnverifiedFromPeer may be called // (which ought to be fine since // that should not affect the iteration). // // It is possible that there may be many calls // to ApplyUpdateFromCentral or AddUnverifiedFromPeer // before UnsentPackets is called again. UnsentPackets() iter.Seq[PktOut] }
OutboundRemoteState is the state management related to a single peer.
The type parameter D is the type of the "delta" that propagates from the CentralState to the OutboundRemoteState.
The methods on OutboundRemoteState are all called in Wingspan internals, and implementers can assume no methods are called concurrently.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package wspackettest contains types useful for tests involving the wspacket package.
|
Package wspackettest contains types useful for tests involving the wspacket package. |