@hyperfrontend/network-protocol/receiver

Receiver

Purpose

The Receiver module provides the inbound half of a channel: frames are opened one at a time on the session's receiving key and delivered as plaintext packets. A frame that does not authenticate is never delivered.


Key Interfaces

Receiver

interface Receiver {
  readonly receive: ReceiveFn // Feeds an incoming frame into the pipeline
  readonly stop: () => void // Pauses opening (frames accumulate)
  readonly resume: () => void // Resumes opening
  readonly queue: InboundQueue // The frames waiting to be opened
}

ReceiveFn

Takes raw wire bytes from the transport.

type ReceiveFn = (packet: Uint8Array) => void

ReceivePacketFn<T>

Called with each opened packet.

type ReceivePacketFn<T = any> = (packet: UnencryptedPacket<T>) => void

InboundQueue

interface InboundQueue {
  readonly size: number // Frames waiting to be opened
}

CreateReceiver<T> and ReceiverFactory

type CreateReceiver<T = any> = (
  label: string,
  receiver: ReceivePacketFn<T>,
  logger: Logger,
  open: PacketOpener<T>,
  onDrop?: PacketDropHandler
) => Receiver

type ReceiverFactory = CreateReceiver

Factory Functions

createReceiver

Location: @hyperfrontend/network-protocol/browser/receiver, @hyperfrontend/network-protocol/node/receiver

ParameterTypeDescription
labelstringIdentifier for logging (a channel passes '<label> receiver')
receivePacketReceivePacketFn<T>Receives each opened packet
loggerLoggerLogger instance from @hyperfrontend/logging
openPacketOpener<T>The session's opener, protocol.open
onDropPacketDropHandlerOptional; receives each frame the opener rejects
import { createReceiver } from '@hyperfrontend/network-protocol/browser/receiver'

const receiver = createReceiver(
  'host receiver',
  (packet) => deliver(packet.data.message),
  logger,
  protocol.open,
  (drop) => report(drop)
)
window.addEventListener('message', (event) => receiver.receive(event.data))

A channel creates its receiver for you; standalone use needs a Protocol instance from a provider (see protocol/). Hello frames are not for the receiver: route them to the protocol's acceptHello instead.


Inbound Pipeline

The open queue processes one frame at a time, which keeps the session's replay counter exact, and delivers each opened packet in order.


Lifecycle Management

receiver.stop() // Frames keep accumulating; nothing is opened
receiver.resume() // Accumulated frames open in FIFO order

Queue Monitoring

if (receiver.queue.size > 100) {
  receiver.stop()
}

Error Handling

A frame the opener rejects is logged and reported through onDrop as { direction: 'inbound', stage: 'open', reason, cause, packet }; the receiver continues with the next frame. When cause is a ProtocolError, getProtocolErrorCode(drop.cause) yields why:

CodeMeaning
malformedFewer than 27 bytes, or the plaintext is not a valid packet
unsupported-versionThe version byte is not this protocol's
replayedThe counter is not above the last accepted one
authentication-failedThe tag does not verify under the session's receiving key
invalid-sessionThe session's keys could not be derived

Bytes that are not a Uint8Array with at least one byte are dropped with reason Invalid frame ignored before the opener runs.


Relationship to Other Modules


See Also

Related Modules

ModuleRelationship
sender/Counterpart for outbound packets
channel/Composes receiver into channel
queue/The open queue
security/Error codes carried in cause
packet/Packet types processed
API reference for receiver is not available yet; rebuild docs to regenerate.