cfdp

package
v0.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 2, 2026 License: Apache-2.0 Imports: 9 Imported by: 0

Documentation

Overview

Package cfdp implements the CCSDS File Delivery Protocol per CCSDS 727.0-B-5 (July 2020).

CFDP moves files over space links. A transaction sends one file from a source entity to a destination entity as a run of Protocol Data Units: a Metadata PDU describing the file, a stream of File Data PDUs carrying its contents, and an EOF PDU closing it out. In acknowledged mode the receiver answers with NAK PDUs naming the gaps it still needs, and the exchange ends with a Finished PDU and its ACK.

CFDP PDUs are ordinary payload bytes. They ride inside Space Packets or Encapsulation Packets, so this package composes with pkg/spp and pkg/epp from the outside and changes neither.

The transaction machines here own no goroutines and no clock. The caller pumps them, the same shape as pkg/cop's FOP-1: hand PDUs in, ask what to send next, drive timeouts from your own scheduler. That keeps the library testable and leaves scheduling policy where it belongs.

Index

Constants

View Source
const (
	// ChecksumModular is the legacy modular checksum. Clause 4.2.2.3 requires every
	// implementation to provide it.
	ChecksumModular uint8 = 0
	// ChecksumCRC32C is CRC-32 Castagnoli, registry entry 2.
	ChecksumCRC32C uint8 = 2
	// ChecksumCRC32 is the standard CRC-32, registry entry 3.
	ChecksumCRC32 uint8 = 3
	// ChecksumNull always yields zero. Clause 4.2.2.4 requires it, and warns that it
	// protects nothing.
	ChecksumNull uint8 = 15
)

Checksum types from the SANA Checksum Identifiers registry, as referenced by CCSDS 727.0-B-5 clause 4.2.2.2.

View Source
const (
	// StatusSuccessful is status code 0 for every action.
	StatusSuccessful uint8 = 0x0
	// StatusNotPerformed is status code 15 for every action.
	StatusNotPerformed uint8 = 0xF
)

Status codes shared across actions, per table 5-18. Code 0 is success for every action and 15 means the action was not attempted.

View Source
const CRCSize = 2

CRCSize is the width of the optional PDU CRC, in octets (clause 4.1.3).

View Source
const DefaultSegmentSize = 1024

DefaultSegmentSize is the file data payload size used when a SenderConfig leaves SegmentSize at zero.

View Source
const FixedHeaderSize = 4

FixedHeaderSize is the width of the PDU header before the variable-width entity IDs and transaction sequence number.

View Source
const MaxIDWidth = 8

MaxIDWidth is the widest entity ID or sequence number the 3-bit length fields of table 5-1 can describe: the encoded value is the width less one.

View Source
const MaxSegmentMetadataSize = 63

MaxSegmentMetadataSize is the widest segment metadata a 6-bit length field can describe (clause 5.3, table 5-14).

View Source
const MessageMagicSize = 4

MessageMagicSize is the width of the message identifier in octets.

View Source
const Version = 1

Version is the PDU version of CCSDS 727.0-B-5 table 5-1: binary '001', the second version of the protocol.

Variables

View Source
var (
	// ErrDataTooShort indicates the input ended before a field it must contain.
	ErrDataTooShort = errors.New("data too short for the PDU field being read")

	// ErrInvalidVersion indicates a PDU version other than the '001' of
	// CCSDS 727.0-B-5 table 5-1.
	ErrInvalidVersion = errors.New("invalid PDU version: this implementation speaks version 1")

	// ErrInvalidEntityIDWidth indicates an entity ID or transaction sequence
	// number width outside the 1-to-8 octet range the 3-bit length field allows.
	ErrInvalidEntityIDWidth = errors.New("invalid entity ID or sequence number width: must be 1 to 8 octets")

	// ErrEntityIDOverflow indicates a value too large for its declared width.
	ErrEntityIDOverflow = errors.New("entity ID or sequence number does not fit its declared width")

	// ErrValueTooLong indicates an LV or TLV value beyond the 255 octets its
	// 8-bit length field can describe.
	ErrValueTooLong = errors.New("LV or TLV value exceeds 255 octets")

	// ErrInvalidDirectiveCode indicates a reserved or unrecognized directive code.
	ErrInvalidDirectiveCode = errors.New("invalid or reserved file directive code")

	// ErrWrongDirectiveCode indicates a decode call for one directive was
	// handed the bytes of another.
	ErrWrongDirectiveCode = errors.New("directive code does not match the PDU being decoded")

	// ErrNotFileDirective indicates a file directive operation on a File Data PDU.
	ErrNotFileDirective = errors.New("PDU is file data, not a file directive")

	// ErrNotFileData indicates a file data operation on a File Directive PDU.
	ErrNotFileData = errors.New("PDU is a file directive, not file data")

	// ErrCRCMismatch indicates the optional PDU CRC failed validation, so the
	// PDU must be discarded per clause 4.1.2.
	ErrCRCMismatch = errors.New("PDU CRC mismatch: received CRC does not match computed CRC")

	// ErrDataLengthMismatch indicates the header's PDU data field length does
	// not match the bytes supplied.
	ErrDataLengthMismatch = errors.New("PDU data field length does not match the data supplied")

	// ErrUnsupportedChecksumType indicates a checksum algorithm this
	// implementation does not provide.
	ErrUnsupportedChecksumType = errors.New("unsupported checksum type")

	// ErrChecksumFailure indicates the received file did not match the
	// checksum in its EOF PDU.
	ErrChecksumFailure = errors.New("file checksum failure")

	// ErrFileSizeError indicates received file data extends beyond the size
	// declared in the EOF PDU.
	ErrFileSizeError = errors.New("file size error: data extends past the declared file size")

	// ErrInvalidTransmissionMode indicates an operation that the transaction's
	// class does not support.
	ErrInvalidTransmissionMode = errors.New("invalid transmission mode for this operation")

	// ErrTransactionFinished indicates the transaction has already completed.
	ErrTransactionFinished = errors.New("transaction has already finished")

	// ErrSuspended indicates the transaction is suspended and will emit
	// nothing until resumed.
	ErrSuspended = errors.New("transaction is suspended")

	// ErrFileNotFound indicates the filestore has no such file.
	ErrFileNotFound = errors.New("file not found in the filestore")

	// ErrFilestoreRejection indicates the filestore refused the operation.
	ErrFilestoreRejection = errors.New("filestore rejected the operation")

	// ErrUnsupportedAction indicates a filestore action code this
	// implementation does not execute.
	ErrUnsupportedAction = errors.New("unsupported filestore action")

	// ErrSegmentTooLarge indicates segment metadata beyond the 63 octets its
	// 6-bit length field can describe.
	ErrSegmentTooLarge = errors.New("segment metadata exceeds 63 octets")

	// ErrInvalidFaultHandler indicates a fault handler override TLV whose
	// handler code is not one of the four defined by clause 5.4.4.
	ErrInvalidFaultHandler = errors.New("invalid fault handler code")

	// ErrNotUserMessage indicates a Message to User TLV that does not open
	// with the "cfdp" identifier, so it is an application message rather than
	// a Reserved CFDP Message. It is how a receiver tells the two apart, not
	// a malformed protocol message.
	ErrNotUserMessage = errors.New("message to user is not a Reserved CFDP Message")

	// ErrReservedBitsSet indicates a field the standard requires to be zero
	// that is not. A sender setting one is using something this issue has not
	// defined, and reading the rest of the field out from under it would be a
	// guess.
	ErrReservedBitsSet = errors.New("a field reserved for future use is not zero")
)

Sentinel errors returned by the CFDP protocol machinery.

View Source
var MessageMagic = [4]byte{'c', 'f', 'd', 'p'}

MessageMagic is the message identifier every Reserved CFDP Message opens with: the ASCII characters "cfdp" (clause 6.1.2, table 6-1).

It is what distinguishes a protocol message from an application one, since both travel in a Message to User TLV.

Functions

func DecodeFaultHandlerOverride

func DecodeFaultHandlerOverride(t TLV) (ConditionCode, FaultHandler, error)

DecodeFaultHandlerOverride reads a fault handler override TLV (clause 5.4.4).

Types

type ACKPDU

type ACKPDU struct {
	// AckedDirective is the directive being acknowledged: EOF or Finished.
	AckedDirective DirectiveCode
	// DirectiveSubtype is binary '0001' when acknowledging a Finished PDU and
	// '0000' for everything else (clause 5.2.4).
	DirectiveSubtype uint8
	// ConditionCode is the condition code of the acknowledged PDU.
	ConditionCode     ConditionCode
	TransactionStatus TransactionStatus
}

ACKPDU acknowledges an EOF or Finished PDU. Table 5-8 allows no others.

func DecodeACKPDU

func DecodeACKPDU(data []byte) (*ACKPDU, error)

DecodeACKPDU parses an ACK PDU data field.

func NewACK

func NewACK(acked DirectiveCode, cond ConditionCode, status TransactionStatus) (*ACKPDU, error)

NewACK builds an ACK for one directive, filling in the subtype table 5-8 requires.

func (*ACKPDU) Encode

func (p *ACKPDU) Encode() ([]byte, error)

Encode serializes the ACK PDU data field.

func (*ACKPDU) Humanize

func (p *ACKPDU) Humanize() string

Humanize returns a human-readable summary.

type Checksum

type Checksum interface {
	// Update folds a run of file octets at the given file offset into the sum.
	Update(offset uint64, data []byte)
	// Sum returns the checksum computed so far.
	Sum() uint32
	// Type returns the SANA registry identifier for this algorithm.
	Type() uint8
}

Checksum accumulates a CFDP file checksum. Every checksum is 32 bits (clause 4.2.1.2).

Segments may arrive in any order and at any offset: Update takes the file offset with the data, so an out-of-order stream produces the same result as a sequential one.

func NewChecksum

func NewChecksum(checksumType uint8) (Checksum, error)

NewChecksum returns an accumulator for a checksum type, or ErrUnsupportedChecksumType if this package does not implement it.

type ConditionCode

type ConditionCode uint8

ConditionCode reports why a transaction ended as it did, per table 5-5.

const (
	CondNoError                 ConditionCode = 0x0
	CondPositiveACKLimitReached ConditionCode = 0x1
	CondKeepAliveLimitReached   ConditionCode = 0x2
	CondInvalidTransmissionMode ConditionCode = 0x3
	CondFilestoreRejection      ConditionCode = 0x4
	CondFileChecksumFailure     ConditionCode = 0x5
	CondFileSizeError           ConditionCode = 0x6
	CondNAKLimitReached         ConditionCode = 0x7
	CondInactivityDetected      ConditionCode = 0x8
	CondInvalidFileStructure    ConditionCode = 0x9
	CondCheckLimitReached       ConditionCode = 0xA
	CondUnsupportedChecksumType ConditionCode = 0xB
	CondSuspendRequestReceived  ConditionCode = 0xE
	CondCancelRequestReceived   ConditionCode = 0xF
)

func (ConditionCode) String

func (c ConditionCode) String() string

String names the condition.

type DeliveryCode

type DeliveryCode uint8

DeliveryCode says whether the receiver got everything (clause 5.2.3).

const (
	// DeliveryDataComplete means metadata, all file data and EOF arrived and
	// the checksum verified.
	DeliveryDataComplete DeliveryCode = 0
	// DeliveryDataIncomplete means something is still missing.
	DeliveryDataIncomplete DeliveryCode = 1
)

func (DeliveryCode) String added in v0.4.0

func (d DeliveryCode) String() string

String names the delivery code.

type Direction

type Direction uint8

Direction indicates which way a PDU travels, per table 5-1. It exists so intermediate nodes can forward PDUs without parsing them.

const (
	// TowardReceiver marks a PDU heading to the file receiver ('0').
	TowardReceiver Direction = 0
	// TowardSender marks a PDU heading back to the file sender ('1').
	TowardSender Direction = 1
)

func (Direction) String

func (d Direction) String() string

String names the direction.

type DirectiveCode

type DirectiveCode uint8

DirectiveCode identifies a file directive, per CCSDS 727.0-B-5 table 5-4.

const (
	// DirectiveEOF closes out the file data stream (clause 5.2.2).
	DirectiveEOF DirectiveCode = 0x04
	// DirectiveFinished reports delivery at the receiver (clause 5.2.3).
	DirectiveFinished DirectiveCode = 0x05
	// DirectiveACK acknowledges an EOF or Finished PDU (clause 5.2.4).
	DirectiveACK DirectiveCode = 0x06
	// DirectiveMetadata opens a transaction (clause 5.2.5).
	DirectiveMetadata DirectiveCode = 0x07
	// DirectiveNAK names the file segments still missing (clause 5.2.6).
	DirectiveNAK DirectiveCode = 0x08
	// DirectivePrompt asks the far end for a NAK or Keep Alive (clause 5.2.7).
	DirectivePrompt DirectiveCode = 0x09
	// DirectiveKeepAlive reports the receiver's progress (clause 5.2.8).
	DirectiveKeepAlive DirectiveCode = 0x0C
)

func DirectiveCodeOf

func DirectiveCodeOf(data []byte) (DirectiveCode, error)

DirectiveCodeOf returns the directive code of a File Directive PDU data field.

func (DirectiveCode) String

func (d DirectiveCode) String() string

String names the directive.

func (DirectiveCode) Valid

func (d DirectiveCode) Valid() bool

Valid reports whether the code is one of the seven defined directives. Table 5-4 reserves 00-03 and 0D-FF, and leaves 0A-0B undefined.

type DirectoryListingRequest added in v0.4.0

type DirectoryListingRequest struct {
	DirectoryName string
	// DirectoryFileName is where the responder should put the listing, on the
	// filestore local to the requesting user.
	DirectoryFileName string
}

DirectoryListingRequest asks a remote user for a directory listing, to be written to a named file on the requester's own filestore (table 6-15).

func DecodeDirectoryListingRequest added in v0.4.0

func DecodeDirectoryListingRequest(content []byte) (*DirectoryListingRequest, error)

DecodeDirectoryListingRequest reads the message content.

func (DirectoryListingRequest) Encode added in v0.4.0

Encode builds the message.

func (*DirectoryListingRequest) Humanize added in v0.4.0

func (m *DirectoryListingRequest) Humanize() string

Humanize returns a human-readable summary.

type DirectoryListingResponse added in v0.4.0

type DirectoryListingResponse struct {
	// Successful is the listing response code. Table 6-16 encodes success as
	// '0'. The opposite polarity from the Remote Status Report Response,
	// where table 6-19 encodes success as '1'. The flag here reads the same
	// way in both, and each encoder writes what its own table says.
	Successful bool

	DirectoryName     string
	DirectoryFileName string
}

DirectoryListingResponse reports whether the listing could be produced (table 6-16).

func DecodeDirectoryListingResponse added in v0.4.0

func DecodeDirectoryListingResponse(content []byte) (*DirectoryListingResponse, error)

DecodeDirectoryListingResponse reads the message content.

func (DirectoryListingResponse) Encode added in v0.4.0

Encode builds the message: the response code, seven spare bits, then the two names.

func (*DirectoryListingResponse) Humanize added in v0.4.0

func (m *DirectoryListingResponse) Humanize() string

Humanize returns a human-readable summary.

type EOFPDU

type EOFPDU struct {
	ConditionCode ConditionCode
	FileChecksum  uint32
	FileSize      uint64 // FSS
	// FaultLocation is an entity ID TLV, present only when ConditionCode is
	// not "no error".
	FaultLocation *TLV
}

EOFPDU closes the file data stream and carries the checksum the receiver verifies against.

func DecodeEOFPDU

func DecodeEOFPDU(data []byte, largeFile bool) (*EOFPDU, error)

DecodeEOFPDU parses an EOF PDU data field.

func (*EOFPDU) Encode

func (p *EOFPDU) Encode(largeFile bool) ([]byte, error)

Encode serializes the EOF PDU data field, directive code included.

func (*EOFPDU) Humanize

func (p *EOFPDU) Humanize() string

Humanize returns a human-readable summary.

type EntityID

type EntityID struct {
	Value uint64
	Width int // octets on the wire, 1 to 8
}

EntityID is a CFDP entity identifier or transaction sequence number: an unsigned integer whose octet width travels in the PDU header (clause 5.1.4).

Width carries semantic weight on the wire but none in comparisons: Clause 5.1.7 note 3 says two IDs of different widths compare by zero-padding the shorter.

func NewEntityID

func NewEntityID(value uint64) EntityID

NewEntityID returns an EntityID just wide enough to hold value.

func (EntityID) Encode

func (e EntityID) Encode() ([]byte, error)

Encode writes the value big-endian at its declared width.

func (EntityID) Validate

func (e EntityID) Validate() error

Validate checks the width against the 3-bit length field's range and confirms the value fits inside it.

type FaultHandler

type FaultHandler uint8

FaultHandler is a disposition for a fault condition, per CCSDS 727.0-B-5 Clause 4.8. Table 4-1 assigns every fault condition a default handler; a fault handler override TLV (clause 5.4.4) or per-transaction configuration replaces it.

The numeric values are the handler codes of the fault handler override TLV, so a FaultHandler travels on the wire unchanged.

const (
	// FaultHandlerCancel issues a Notice of Cancellation ('0001'): the
	// transaction closes out with the fault's condition code.
	FaultHandlerCancel FaultHandler = 0x1
	// FaultHandlerSuspend issues a Notice of Suspension ('0010'): the
	// transaction goes quiet until the caller resumes it.
	FaultHandlerSuspend FaultHandler = 0x2
	// FaultHandlerIgnore ignores the fault ('0011') and lets the transaction
	// carry on.
	FaultHandlerIgnore FaultHandler = 0x3
	// FaultHandlerAbandon abandons the transaction ('0100') with no further
	// protocol activity, not even a Finished PDU.
	FaultHandlerAbandon FaultHandler = 0x4
)

func DefaultFaultHandler

func DefaultFaultHandler(ConditionCode) FaultHandler

DefaultFaultHandler returns table 4-1's default disposition for a fault condition: every condition defaults to a Notice of Cancellation.

func (FaultHandler) String

func (h FaultHandler) String() string

String names the handler.

func (FaultHandler) Valid

func (h FaultHandler) Valid() bool

Valid reports whether the handler is one of the four defined codes.

type FileDataPDU

type FileDataPDU struct {
	// RecordContinuation and SegmentMetadata are present only when the
	// header's segment metadata flag is set.
	RecordContinuation RecordContinuationState
	SegmentMetadata    []byte

	// Offset is where this data belongs in the file, in octets from the start.
	Offset uint64 // FSS
	// Data is the file content itself.
	Data []byte
}

FileDataPDU carries a run of file octets at a given offset.

func DecodeFileDataPDU

func DecodeFileDataPDU(data []byte, segmentMetadataPresent, largeFile bool) (*FileDataPDU, error)

DecodeFileDataPDU parses a File Data PDU data field. The flags must match the header that carried it.

func (*FileDataPDU) Encode

func (p *FileDataPDU) Encode(segmentMetadataPresent, largeFile bool) ([]byte, error)

Encode serializes the File Data PDU data field.

segmentMetadataPresent and largeFile must match the flags in the PDU header that will carry this data field; the wire format is not self-describing.

func (*FileDataPDU) End

func (p *FileDataPDU) End() uint64

End returns the file offset just past this segment's last octet.

func (*FileDataPDU) Humanize

func (p *FileDataPDU) Humanize() string

Humanize returns a human-readable summary.

type FileStatus

type FileStatus uint8

FileStatus reports what became of the delivered file (clause 5.2.3).

const (
	FileDiscardedDeliberately FileStatus = 0
	FileDiscardedRejection    FileStatus = 1
	FileRetainedSuccessfully  FileStatus = 2
	FileStatusUnreported      FileStatus = 3
)

func (FileStatus) String

func (f FileStatus) String() string

String names the file status.

type Filestore

type Filestore interface {
	// Read returns the whole contents of name.
	Read(name string) ([]byte, error)
	// WriteAt writes data at a byte offset, growing the file as needed.
	WriteAt(name string, offset uint64, data []byte) error
	// Create makes an empty file, replacing any existing one.
	Create(name string) error
	// Delete removes a file.
	Delete(name string) error
	// Rename moves a file.
	Rename(from, to string) error
	// Size returns the current length of a file.
	Size(name string) (uint64, error)
	// Exists reports whether a file is present.
	Exists(name string) bool
}

Filestore is the file system a CFDP entity reads from and writes to.

It is deliberately small: CFDP needs to read a source file, write a destination file at arbitrary offsets, and run the handful of filestore actions of table 5-16. Anything richer belongs to the application.

type FilestoreAction

type FilestoreAction uint8

FilestoreAction is a filestore request action code, per CCSDS 727.0-B-5 table 5-16.

const (
	ActionCreateFile      FilestoreAction = 0x0
	ActionDeleteFile      FilestoreAction = 0x1
	ActionRenameFile      FilestoreAction = 0x2
	ActionAppendFile      FilestoreAction = 0x3
	ActionReplaceFile     FilestoreAction = 0x4
	ActionCreateDirectory FilestoreAction = 0x5
	ActionRemoveDirectory FilestoreAction = 0x6
	ActionDenyFile        FilestoreAction = 0x7
	ActionDenyDirectory   FilestoreAction = 0x8
)

func (FilestoreAction) NeedsSecondFileName

func (a FilestoreAction) NeedsSecondFileName() bool

NeedsSecondFileName reports whether this action takes two filenames, per table 5-16.

func (FilestoreAction) String

func (a FilestoreAction) String() string

String names the action.

type FilestoreRequest

type FilestoreRequest struct {
	Action         FilestoreAction
	FirstFileName  LV
	SecondFileName LV
}

FilestoreRequest is the value of a filestore request TLV (table 5-15).

func DecodeFilestoreRequest

func DecodeFilestoreRequest(t TLV) (*FilestoreRequest, error)

DecodeFilestoreRequest parses a filestore request TLV.

func (FilestoreRequest) Encode

func (r FilestoreRequest) Encode() (TLV, error)

Encode serializes the request as a TLV of type 00.

type FilestoreResponse

type FilestoreResponse struct {
	Action         FilestoreAction
	StatusCode     uint8
	FirstFileName  LV
	SecondFileName LV
	Message        LV
}

FilestoreResponse is the value of a filestore response TLV (table 5-17).

func DecodeFilestoreResponse

func DecodeFilestoreResponse(t TLV) (*FilestoreResponse, error)

DecodeFilestoreResponse parses a filestore response TLV.

func ExecuteFilestoreRequest

func ExecuteFilestoreRequest(fs Filestore, req *FilestoreRequest) FilestoreResponse

ExecuteFilestoreRequest runs one filestore action and returns the response TLV value that belongs in the Finished PDU.

Actions this package does not execute (append, replace, and the directory actions) come back with status "not performed" rather than an error, which is what table 5-18 provides for.

func (FilestoreResponse) Encode

func (r FilestoreResponse) Encode() (TLV, error)

Encode serializes the response as a TLV of type 01.

type FinishedPDU

type FinishedPDU struct {
	ConditionCode      ConditionCode
	DeliveryCode       DeliveryCode
	FileStatus         FileStatus
	FilestoreResponses []TLV
	FaultLocation      *TLV
}

FinishedPDU reports the outcome of a transaction at the receiver.

func DecodeFinishedPDU

func DecodeFinishedPDU(data []byte) (*FinishedPDU, error)

DecodeFinishedPDU parses a Finished PDU data field.

The trailing TLVs are all filestore responses except a final entity ID TLV, which is the fault location. Table 5-7 distinguishes them by type, not by position, so this splits on the type code.

func (*FinishedPDU) Encode

func (p *FinishedPDU) Encode() ([]byte, error)

Encode serializes the Finished PDU data field.

func (*FinishedPDU) Humanize

func (p *FinishedPDU) Humanize() string

Humanize returns a human-readable summary.

type KeepAlivePDU

type KeepAlivePDU struct {
	Progress uint64 // FSS, offset from the start of the file
}

KeepAlivePDU reports how much of the file the receiver has.

func DecodeKeepAlivePDU

func DecodeKeepAlivePDU(data []byte, largeFile bool) (*KeepAlivePDU, error)

DecodeKeepAlivePDU parses a Keep Alive PDU data field.

func (*KeepAlivePDU) Encode

func (p *KeepAlivePDU) Encode(largeFile bool) ([]byte, error)

Encode serializes the Keep Alive PDU data field.

func (*KeepAlivePDU) Humanize

func (p *KeepAlivePDU) Humanize() string

Humanize returns a human-readable summary.

type LV

type LV struct {
	Value []byte
}

LV is a Length-Value object per CCSDS 727.0-B-5 table 5-2: an 8-bit length followed by that many octets. Used for filenames, whose position in the PDU is fixed even though their length is not.

A zero length means the value is absent, an empty filename, for instance, marks a transaction with no associated file (clause 5.2.5).

func DecodeLV

func DecodeLV(data []byte) (LV, int, error)

DecodeLV reads one LV object from the front of data, returning it and the number of octets consumed.

func (LV) Encode

func (l LV) Encode() ([]byte, error)

Encode serializes the LV object.

func (LV) IsEmpty

func (l LV) IsEmpty() bool

IsEmpty reports whether the LV carries no value.

func (LV) String

func (l LV) String() string

String returns the value as text, which is how filenames are carried.

type MemoryFilestore

type MemoryFilestore struct {
	// contains filtered or unexported fields
}

MemoryFilestore is an in-memory Filestore, useful for tests and for entities that never touch a disk. It is safe for concurrent use.

func NewMemoryFilestore

func NewMemoryFilestore() *MemoryFilestore

NewMemoryFilestore returns an empty in-memory filestore.

func (*MemoryFilestore) Create

func (f *MemoryFilestore) Create(name string) error

Create makes an empty file, discarding any existing contents.

func (*MemoryFilestore) Delete

func (f *MemoryFilestore) Delete(name string) error

Delete removes a file.

func (*MemoryFilestore) Exists

func (f *MemoryFilestore) Exists(name string) bool

Exists reports whether the file is present.

func (*MemoryFilestore) Read

func (f *MemoryFilestore) Read(name string) ([]byte, error)

Read returns a copy of the file's contents.

func (*MemoryFilestore) Rename

func (f *MemoryFilestore) Rename(from, to string) error

Rename moves a file.

func (*MemoryFilestore) Size

func (f *MemoryFilestore) Size(name string) (uint64, error)

Size returns the file length.

func (*MemoryFilestore) WriteAt

func (f *MemoryFilestore) WriteAt(name string, offset uint64, data []byte) error

WriteAt writes data at offset, zero-filling any gap.

type MetadataPDU

type MetadataPDU struct {
	// ClosureRequested asks the receiver for a Finished PDU. Table 5-9 says
	// set it to '0' and ignore it in acknowledged mode, where a Finished PDU
	// is sent regardless.
	ClosureRequested bool
	// ChecksumType selects the algorithm, per the SANA registry. Zero is the
	// legacy modular checksum.
	ChecksumType uint8
	// FileSize is the file length in octets, or zero for unbounded size.
	FileSize uint64 // FSS
	// SourceFileName and DestinationFileName are empty when the transaction
	// carries no file (metadata-only, as used by proxy operations).
	SourceFileName      LV
	DestinationFileName LV
	// Options are filestore requests, messages to user, fault handler
	// overrides and flow labels.
	Options []TLV
}

MetadataPDU opens a transaction and describes the file being sent.

func DecodeMetadataPDU

func DecodeMetadataPDU(data []byte, largeFile bool) (*MetadataPDU, error)

DecodeMetadataPDU parses a Metadata PDU data field.

func (*MetadataPDU) Encode

func (p *MetadataPDU) Encode(largeFile bool) ([]byte, error)

Encode serializes the Metadata PDU data field.

func (*MetadataPDU) Humanize

func (p *MetadataPDU) Humanize() string

Humanize returns a human-readable summary.

type NAKPDU

type NAKPDU struct {
	StartOfScope uint64 // FSS
	EndOfScope   uint64 // FSS
	Requests     []SegmentRequest
}

NAKPDU lists the gaps the receiver is still missing.

func DecodeNAKPDU

func DecodeNAKPDU(data []byte, largeFile bool) (*NAKPDU, error)

DecodeNAKPDU parses a NAK PDU data field.

func (*NAKPDU) Encode

func (p *NAKPDU) Encode(largeFile bool) ([]byte, error)

Encode serializes the NAK PDU data field.

func (*NAKPDU) Humanize

func (p *NAKPDU) Humanize() string

Humanize returns a human-readable summary.

type OSFilestore

type OSFilestore struct {
	Root string
}

OSFilestore is a Filestore backed by a directory on disk. Every name is resolved inside Root, and names that would escape it are refused.

func NewOSFilestore

func NewOSFilestore(dir string) *OSFilestore

NewOSFilestore returns a filestore rooted at dir.

func (*OSFilestore) Create

func (f *OSFilestore) Create(name string) error

Create makes an empty file, truncating any existing one.

func (*OSFilestore) Delete

func (f *OSFilestore) Delete(name string) error

Delete removes a file.

func (*OSFilestore) Exists

func (f *OSFilestore) Exists(name string) bool

Exists reports whether the file is present.

func (*OSFilestore) Read

func (f *OSFilestore) Read(name string) ([]byte, error)

Read returns the whole contents of the file.

func (*OSFilestore) Rename

func (f *OSFilestore) Rename(from, to string) error

Rename moves a file.

func (*OSFilestore) Size

func (f *OSFilestore) Size(name string) (uint64, error)

Size returns the file length.

func (*OSFilestore) WriteAt

func (f *OSFilestore) WriteAt(name string, offset uint64, data []byte) error

WriteAt writes data at offset, creating the file and any parent directories.

type OriginatingTransactionID added in v0.4.0

type OriginatingTransactionID struct {
	Transaction TransactionID
}

OriginatingTransactionID is the message every User operation carries alongside its own, naming the transaction the operation refers to.

func DecodeOriginatingTransactionID added in v0.4.0

func DecodeOriginatingTransactionID(content []byte) (*OriginatingTransactionID, error)

DecodeOriginatingTransactionID reads the message content.

func (OriginatingTransactionID) Encode added in v0.4.0

Encode builds the message.

func (*OriginatingTransactionID) Humanize added in v0.4.0

func (m *OriginatingTransactionID) Humanize() string

Humanize returns a human-readable summary.

type PDU

type PDU struct {
	Header *PDUHeader
	// Data is the PDU data field with any trailing CRC already removed.
	Data []byte
}

PDU is one complete Protocol Data Unit: a header plus its data field.

func DecodePDU

func DecodePDU(data []byte) (*PDU, error)

DecodePDU parses one complete PDU, verifying the CRC when the header says one is present. A CRC failure returns ErrCRCMismatch and the caller must discard the PDU, per clause 4.1.2.

func (*PDU) Encode

func (p *PDU) Encode() ([]byte, error)

Encode serializes the PDU, setting the data field length and appending the CRC when the header asks for one.

Per clause 4.1.3.2 the CRC occupies the final octets of the data field, its length counts toward the data field length, and it covers everything from the first octet of the header to the last octet before the CRC itself.

type PDUHeader

type PDUHeader struct {
	// IsFileData distinguishes a File Data PDU ('1') from a File Directive ('0').
	IsFileData bool

	// Direction is which way the PDU travels.
	Direction Direction

	// Acknowledged selects acknowledged mode. Note the wire encoding is
	// inverted: table 5-1 gives '0' for acknowledged and '1' for
	// unacknowledged, so this field is the logical sense, not the bit.
	Acknowledged bool

	// CRCFlag marks a PDU carrying a trailing CRC (clause 4.1).
	CRCFlag bool

	// LargeFile widens every File-Size Sensitive field from 32 to 64 bits
	// (clause 5.1.10).
	LargeFile bool

	// DataLength is the octet length of the PDU data field. When CRCFlag is
	// set this includes the two CRC octets (clause 4.1.3.2).
	DataLength uint16

	// SegmentationControl records whether record boundaries survive
	// segmentation. Always '0' and ignored for File Directive PDUs.
	SegmentationControl bool

	// SegmentMetadataFlag marks a File Data PDU carrying segment metadata.
	// Always '0' and ignored for File Directive PDUs.
	SegmentMetadataFlag bool

	// Source, TransactionSeq and Destination identify the transaction. All
	// three entity IDs share one width; the sequence number has its own.
	Source         EntityID
	TransactionSeq EntityID
	Destination    EntityID
}

PDUHeader is the fixed PDU header of CCSDS 727.0-B-5 table 5-1.

The first octet packs version, PDU type, direction, transmission mode, the CRC flag and the large-file flag. Then comes the 16-bit data field length. The fourth octet packs segmentation control, the entity ID width, the segment metadata flag and the sequence number width. The three variable width fields follow in the order source, sequence number, destination.

func DecodePDUHeader

func DecodePDUHeader(data []byte) (*PDUHeader, int, error)

DecodePDUHeader parses a PDU header from the front of data and returns the header along with the number of octets consumed.

func (*PDUHeader) Encode

func (h *PDUHeader) Encode() ([]byte, error)

Encode serializes the PDU header per table 5-1.

func (*PDUHeader) Humanize

func (h *PDUHeader) Humanize() string

Humanize returns a human-readable summary of the PDU header.

func (*PDUHeader) Size

func (h *PDUHeader) Size() int

Size returns the encoded width of the header in octets.

func (*PDUHeader) Validate

func (h *PDUHeader) Validate() error

Validate checks the header against table 5-1.

type PromptPDU

type PromptPDU struct {
	Response PromptResponse
}

PromptPDU asks the far end for a NAK or a Keep Alive.

func DecodePromptPDU

func DecodePromptPDU(data []byte) (*PromptPDU, error)

DecodePromptPDU parses a Prompt PDU data field.

func (*PromptPDU) Encode

func (p *PromptPDU) Encode() ([]byte, error)

Encode serializes the Prompt PDU data field.

func (*PromptPDU) Humanize

func (p *PromptPDU) Humanize() string

Humanize returns a human-readable summary.

type PromptResponse

type PromptResponse uint8

PromptResponse selects what the far end should send back (clause 5.2.7).

const (
	// PromptNAK asks for a NAK PDU.
	PromptNAK PromptResponse = 0
	// PromptKeepAlive asks for a Keep Alive PDU.
	PromptKeepAlive PromptResponse = 1
)

type ProxyClosureRequest added in v0.4.0

type ProxyClosureRequest struct {
	ClosureRequested bool
}

ProxyClosureRequest asks for transaction closure on the proxied transaction (table 6-11).

func DecodeProxyClosureRequest added in v0.4.0

func DecodeProxyClosureRequest(content []byte) (*ProxyClosureRequest, error)

DecodeProxyClosureRequest reads the message content.

func (ProxyClosureRequest) Encode added in v0.4.0

func (m ProxyClosureRequest) Encode() UserMessage

Encode builds the message.

type ProxyFaultHandlerOverride added in v0.4.0

type ProxyFaultHandlerOverride struct {
	Condition ConditionCode
	Handler   FaultHandler
}

ProxyFaultHandlerOverride changes a fault handler for the proxied transaction (table 6-7).

Its content is one octet holding the same condition code and handler code pairing clause 5.4.4 defines for the fault handler override TLV.

func DecodeProxyFaultHandlerOverride added in v0.4.0

func DecodeProxyFaultHandlerOverride(content []byte) (*ProxyFaultHandlerOverride, error)

DecodeProxyFaultHandlerOverride reads the message content.

func (ProxyFaultHandlerOverride) Encode added in v0.4.0

Encode builds the message.

type ProxyFilestoreRequest added in v0.4.0

type ProxyFilestoreRequest struct {
	Request FilestoreRequest
}

ProxyFilestoreRequest carries one filestore request for the respondent to perform as part of the proxy operation.

Its content is a length octet and then a filestore request TLV's value, not a whole TLV: table 6-6 says the field "is a single CFDP filestore request as defined in table 5-15", and the length octet in front of it does the job the TLV's own length would.

func DecodeProxyFilestoreRequest added in v0.4.0

func DecodeProxyFilestoreRequest(content []byte) (*ProxyFilestoreRequest, error)

DecodeProxyFilestoreRequest reads the message content.

func (ProxyFilestoreRequest) Encode added in v0.4.0

func (m ProxyFilestoreRequest) Encode() (UserMessage, error)

Encode builds the message.

func (*ProxyFilestoreRequest) Humanize added in v0.4.0

func (m *ProxyFilestoreRequest) Humanize() string

Humanize returns a human-readable summary.

type ProxyFilestoreResponse added in v0.4.0

type ProxyFilestoreResponse struct {
	Response FilestoreResponse
}

ProxyFilestoreResponse reports the outcome of one proxy filestore request.

func DecodeProxyFilestoreResponse added in v0.4.0

func DecodeProxyFilestoreResponse(content []byte) (*ProxyFilestoreResponse, error)

DecodeProxyFilestoreResponse reads the message content.

func (ProxyFilestoreResponse) Encode added in v0.4.0

Encode builds the message.

func (*ProxyFilestoreResponse) Humanize added in v0.4.0

func (m *ProxyFilestoreResponse) Humanize() string

Humanize returns a human-readable summary.

type ProxyFlowLabel added in v0.4.0

type ProxyFlowLabel struct {
	Label []byte
}

ProxyFlowLabel carries a mission-defined flow label for the proxied transaction (table 6-9).

func DecodeProxyFlowLabel added in v0.4.0

func DecodeProxyFlowLabel(content []byte) (*ProxyFlowLabel, error)

DecodeProxyFlowLabel reads the message content.

func (ProxyFlowLabel) Encode added in v0.4.0

func (m ProxyFlowLabel) Encode() (UserMessage, error)

Encode builds the message.

type ProxyMessageToUser added in v0.4.0

type ProxyMessageToUser struct {
	Text []byte
}

ProxyMessageToUser carries a message for the beneficiary's user, to be placed in the proxied transaction's metadata (table 6-5).

func DecodeProxyMessageToUser added in v0.4.0

func DecodeProxyMessageToUser(content []byte) (*ProxyMessageToUser, error)

DecodeProxyMessageToUser reads the message content.

func (ProxyMessageToUser) Encode added in v0.4.0

func (m ProxyMessageToUser) Encode() (UserMessage, error)

Encode builds the message.

type ProxyPutRequest added in v0.4.0

type ProxyPutRequest struct {
	// Destination is the beneficiary's entity ID.
	Destination EntityID
	// SourceFileName and DestinationFileName are empty when omitted, which
	// table 6-4 expresses as a zero-length LV rather than an absent field.
	SourceFileName      string
	DestinationFileName string
}

ProxyPutRequest asks a remote user to send a file to a third entity.

The remote user is the respondent, and the entity named here is the beneficiary. When the beneficiary is the originator the operation works as a Get (clause 6.2, note).

func DecodeProxyPutRequest added in v0.4.0

func DecodeProxyPutRequest(content []byte) (*ProxyPutRequest, error)

DecodeProxyPutRequest reads the message content.

func (ProxyPutRequest) Encode added in v0.4.0

func (m ProxyPutRequest) Encode() (UserMessage, error)

Encode builds the message.

func (*ProxyPutRequest) Humanize added in v0.4.0

func (m *ProxyPutRequest) Humanize() string

Humanize returns a human-readable summary.

type ProxyPutResponse added in v0.4.0

type ProxyPutResponse struct {
	Condition ConditionCode
	Delivery  DeliveryCode
	File      FileStatus
}

ProxyPutResponse reports the outcome of a proxy put back to the originator.

func DecodeProxyPutResponse added in v0.4.0

func DecodeProxyPutResponse(content []byte) (*ProxyPutResponse, error)

DecodeProxyPutResponse reads the message content.

func (ProxyPutResponse) Encode added in v0.4.0

func (m ProxyPutResponse) Encode() (UserMessage, error)

Encode builds the message.

The layout is condition code (4 bits), one spare bit, delivery code (1 bit), file status (2 bits). The same packing the Finished PDU uses, which is why the codes are the shared types.

func (*ProxyPutResponse) Humanize added in v0.4.0

func (m *ProxyPutResponse) Humanize() string

Humanize returns a human-readable summary.

type ProxySegmentationControl added in v0.4.0

type ProxySegmentationControl struct {
	// RecordBoundariesRespected is '0' on the wire when true, per table 6-10.
	RecordBoundariesRespected bool
}

ProxySegmentationControl says whether record boundaries are respected (table 6-10).

func DecodeProxySegmentationControl added in v0.4.0

func DecodeProxySegmentationControl(content []byte) (*ProxySegmentationControl, error)

DecodeProxySegmentationControl reads the message content.

func (ProxySegmentationControl) Encode added in v0.4.0

Encode builds the message.

type ProxyTransmissionMode added in v0.4.0

type ProxyTransmissionMode struct {
	Acknowledged bool
}

ProxyTransmissionMode selects acknowledged or unacknowledged transmission for the proxied transaction (table 6-8).

func DecodeProxyTransmissionMode added in v0.4.0

func DecodeProxyTransmissionMode(content []byte) (*ProxyTransmissionMode, error)

DecodeProxyTransmissionMode reads the message content.

func (ProxyTransmissionMode) Encode added in v0.4.0

Encode builds the message: seven spare bits then the mode.

type Receiver

type Receiver struct {
	// contains filtered or unexported fields
}

Receiver drives one incoming CFDP transaction.

Like Sender it owns no goroutines and no clock: the caller feeds it PDUs with HandlePDU and asks NextPDU what to send back.

Usage:

  1. Create with NewReceiver
  2. Call HandlePDU for every PDU that arrives
  3. Call NextPDU and transmit whatever it returns
  4. Check Done or State to see when the transaction has completed

A Receiver is safe for concurrent use.

func NewReceiver

func NewReceiver(fs Filestore, config ReceiverConfig) *Receiver

NewReceiver prepares a transaction to receive one file.

func (*Receiver) Cancel

func (r *Receiver) Cancel()

Cancel abandons the receive (clause 4.11.1): the partial file is discarded and, when the class calls for one, a Finished PDU with condition code "cancel request received" closes the transaction out.

func (*Receiver) Complete

func (r *Receiver) Complete() bool

Complete reports whether every octet of the file has arrived and the EOF PDU has been seen.

func (*Receiver) ConditionCode

func (r *Receiver) ConditionCode() ConditionCode

ConditionCode returns why the transaction ended as it did.

func (*Receiver) DeclareFault

func (r *Receiver) DeclareFault(cond ConditionCode)

DeclareFault raises a fault the caller's own timers detected (a NAK limit, a keep-alive limit, a positive-ACK limit, or inactivity (table 5-5)) and applies the fault handler configured for it, defaulting to the table 4-1 disposition. The library owns no clock, so counting those limits is the caller's job.

func (*Receiver) Done

func (r *Receiver) Done() bool

Done reports whether the transaction has completed.

func (*Receiver) ExpireCheckLimit

func (r *Receiver) ExpireCheckLimit()

ExpireCheckLimit reports that the caller's transaction check timer has expired for the last time (clause 4.6.3.3). The caller drives this from its own clock, like RequestNAK and ResendEOF. Under the table 4-1 default the transaction cancels with condition code "check limit reached", which forces the Finished PDU a Class 1 closure-requested transaction still owes.

func (*Receiver) FileName

func (r *Receiver) FileName() string

FileName returns the destination filename in use.

func (*Receiver) HandlePDU

func (r *Receiver) HandlePDU(pdu *PDU) error

HandlePDU feeds one arriving PDU into the transaction.

func (*Receiver) Metadata

func (r *Receiver) Metadata() *MetadataPDU

Metadata returns the Metadata PDU that opened the transaction, if it has arrived.

func (*Receiver) MissingSegments

func (r *Receiver) MissingSegments() []SegmentRequest

MissingSegments returns the byte ranges still outstanding.

func (*Receiver) NextPDU

func (r *Receiver) NextPDU() (*PDU, bool, error)

NextPDU returns the next PDU to send back, or ok == false when nothing is pending. A suspended transaction emits nothing.

func (*Receiver) RequestNAK

func (r *Receiver) RequestNAK() error

RequestNAK queues a NAK for whatever is still missing. The caller drives this from its own timer, since this library owns no clock.

func (*Receiver) ResendFinished

func (r *Receiver) ResendFinished()

ResendFinished re-queues the Finished PDU when its ACK does not arrive.

func (*Receiver) Resume

func (r *Receiver) Resume()

Resume lets a suspended transaction emit again.

func (*Receiver) State

func (r *Receiver) State() TransactionState

State returns the current transaction state.

func (*Receiver) Suspend

func (r *Receiver) Suspend()

Suspend stops the transaction emitting PDUs until Resume.

func (*Receiver) Suspended

func (r *Receiver) Suspended() bool

Suspended reports whether the transaction is suspended.

type ReceiverConfig

type ReceiverConfig struct {
	// Source, Destination and TransactionSeq identify the transaction. They
	// come from the first PDU received. Inbound PDUs whose source entity ID or
	// transaction sequence number differ are ignored (clause 5.1), so one Receiver
	// never applies a foreign transaction's PDUs.
	Source         EntityID
	Destination    EntityID
	TransactionSeq EntityID

	// Acknowledged selects Class 2 behavior: NAKs, Finished, and its ACK.
	Acknowledged bool

	// CRCFlag adds a CRC to every outgoing PDU.
	CRCFlag bool

	// DestinationFileName overrides the name in the Metadata PDU. Leave it
	// empty to use what the sender asked for.
	DestinationFileName string

	// FaultHandlers overrides the default disposition for the given fault
	// conditions at this entity. Table 4-1 defaults every condition to a
	// Notice of Cancellation; fault handler override TLVs arriving in the
	// Metadata PDU take precedence over both (clause 4.8).
	FaultHandlers map[ConditionCode]FaultHandler
}

ReceiverConfig describes one incoming transaction.

type RecordContinuationState

type RecordContinuationState uint8

RecordContinuationState says how a File Data PDU's payload sits relative to record boundaries, per CCSDS 727.0-B-5 clause 5.3. It is present only when the header's segment metadata flag is set.

const (
	// RecordNeitherStartNorEnd means the payload holds no record boundary. With
	// segmentation control set it continues a record from an earlier PDU;
	// otherwise the file simply has no records.
	RecordNeitherStartNorEnd RecordContinuationState = 0
	// RecordStartOnly means the payload starts a record that does not end here.
	RecordStartOnly RecordContinuationState = 1
	// RecordEndOnly means the payload ends a record that began earlier.
	RecordEndOnly RecordContinuationState = 2
	// RecordStartAndEnd means the payload holds one or more whole records.
	RecordStartAndEnd RecordContinuationState = 3
)

func (RecordContinuationState) String

func (r RecordContinuationState) String() string

String names the continuation state.

type RemoteResumeRequest added in v0.4.0

type RemoteResumeRequest struct {
	Transaction TransactionID
}

RemoteResumeRequest asks a remote user to resume one transaction (table 6-24). Clause 6.6.3.1.2 requires the carrying transaction to be Acknowledged.

func DecodeRemoteResumeRequest added in v0.4.0

func DecodeRemoteResumeRequest(content []byte) (*RemoteResumeRequest, error)

DecodeRemoteResumeRequest reads the message content.

func (RemoteResumeRequest) Encode added in v0.4.0

func (m RemoteResumeRequest) Encode() (UserMessage, error)

Encode builds the message.

type RemoteResumeResponse added in v0.4.0

type RemoteResumeResponse struct {
	SuspensionResponse
}

RemoteResumeResponse reports the suspension state after a resume request (table 6-25).

func DecodeRemoteResumeResponse added in v0.4.0

func DecodeRemoteResumeResponse(content []byte) (*RemoteResumeResponse, error)

DecodeRemoteResumeResponse reads the message content.

func (RemoteResumeResponse) Encode added in v0.4.0

func (m RemoteResumeResponse) Encode() (UserMessage, error)

Encode builds the message.

type RemoteStatusReportRequest added in v0.4.0

type RemoteStatusReportRequest struct {
	Transaction TransactionID
	// ReportFileName is where the responder should put the report.
	ReportFileName string
}

RemoteStatusReportRequest asks a remote user for a status report on one transaction, written to a named file on the requester's filestore (table 6-18).

func DecodeRemoteStatusReportRequest added in v0.4.0

func DecodeRemoteStatusReportRequest(content []byte) (*RemoteStatusReportRequest, error)

DecodeRemoteStatusReportRequest reads the message content.

func (RemoteStatusReportRequest) Encode added in v0.4.0

Encode builds the message.

func (*RemoteStatusReportRequest) Humanize added in v0.4.0

func (m *RemoteStatusReportRequest) Humanize() string

Humanize returns a human-readable summary.

type RemoteStatusReportResponse added in v0.4.0

type RemoteStatusReportResponse struct {
	Status TransactionStatus
	// Successful is the report response code. Table 6-19 encodes success as
	// '1', the opposite of the Directory Listing Response's '0'.
	Successful bool

	Transaction TransactionID
}

RemoteStatusReportResponse reports whether the status report could be produced (table 6-19).

func DecodeRemoteStatusReportResponse added in v0.4.0

func DecodeRemoteStatusReportResponse(content []byte) (*RemoteStatusReportResponse, error)

DecodeRemoteStatusReportResponse reads the message content.

func (RemoteStatusReportResponse) Encode added in v0.4.0

Encode builds the message.

The first octet packs transaction status (2 bits), five spare bits, then the response code in the low bit, an unusual order, with the flag last rather than first as in table 6-16.

func (*RemoteStatusReportResponse) Humanize added in v0.4.0

func (m *RemoteStatusReportResponse) Humanize() string

Humanize returns a human-readable summary.

type RemoteSuspendRequest added in v0.4.0

type RemoteSuspendRequest struct {
	Transaction TransactionID
}

RemoteSuspendRequest asks a remote user to suspend one transaction (table 6-21).

Clause 6.5.3.1.2 requires the carrying transaction to be Acknowledged.

func DecodeRemoteSuspendRequest added in v0.4.0

func DecodeRemoteSuspendRequest(content []byte) (*RemoteSuspendRequest, error)

DecodeRemoteSuspendRequest reads the message content.

func (RemoteSuspendRequest) Encode added in v0.4.0

func (m RemoteSuspendRequest) Encode() (UserMessage, error)

Encode builds the message.

type RemoteSuspendResponse added in v0.4.0

type RemoteSuspendResponse struct {
	SuspensionResponse
}

RemoteSuspendResponse reports the suspension state after a suspend request (table 6-22).

func DecodeRemoteSuspendResponse added in v0.4.0

func DecodeRemoteSuspendResponse(content []byte) (*RemoteSuspendResponse, error)

DecodeRemoteSuspendResponse reads the message content.

func (RemoteSuspendResponse) Encode added in v0.4.0

func (m RemoteSuspendResponse) Encode() (UserMessage, error)

Encode builds the message.

type SegmentRequest

type SegmentRequest struct {
	StartOffset uint64 // FSS
	EndOffset   uint64 // FSS, first octet after the requested segment
}

SegmentRequest names one range of file data the receiver still needs. A request of 0..0 asks for the metadata (table 5-11).

func (SegmentRequest) IsMetadataRequest

func (s SegmentRequest) IsMetadataRequest() bool

IsMetadataRequest reports whether this request asks for the Metadata PDU rather than a run of file data.

type Sender

type Sender struct {
	// contains filtered or unexported fields
}

Sender drives one outgoing CFDP transaction.

It owns no goroutines and no clock. The caller pumps it: NextPDU returns the next PDU to transmit, HandlePDU feeds inbound PDUs back in, and the caller's own scheduler decides when to retransmit. This is the same contract as pkg/cop's FOP-1.

Usage:

  1. Create with NewSender
  2. Call NextPDU repeatedly and transmit what it returns, until it reports that nothing is pending
  3. Call HandlePDU when a PDU arrives on the return link
  4. Check Done or State to see when the transaction has completed

A Sender is safe for concurrent use.

func NewSender

func NewSender(fs Filestore, config SenderConfig) (*Sender, error)

NewSender prepares a transaction to send one file. It reads the source file up front and computes its checksum, so the file must be readable now.

A transaction with an empty source filename carries metadata only, which is how proxy operations and pure filestore requests travel (clause 5.2.5).

func (*Sender) AckFinished

func (s *Sender) AckFinished() (*PDU, bool, error)

AckFinished builds the ACK a Class 2 sender owes for a Finished PDU (clause 5.2.4). Returns ok == false when no Finished PDU has arrived.

func (*Sender) Cancel

func (s *Sender) Cancel()

Cancel cancels the transaction (clause 4.11.1). The next PDU out is an EOF carrying the cancel condition code of table 5-5 and the transaction's progress so far.

func (*Sender) Checksum

func (s *Sender) Checksum() uint32

Checksum returns the checksum computed over the source file.

func (*Sender) DeclareFault

func (s *Sender) DeclareFault(cond ConditionCode)

DeclareFault raises a fault the caller's own timers detected (the positive ACK limit of clause 4.7, a keep-alive limit, or inactivity (table 5-5)) and applies the fault handler configured for it, defaulting to the table 4-1 disposition (cancel). The library owns no clock, so counting those limits is the caller's job.

func (*Sender) Done

func (s *Sender) Done() bool

Done reports whether the transaction has completed or been cancelled.

func (*Sender) Finished

func (s *Sender) Finished() *FinishedPDU

Finished returns the Finished PDU the receiver sent, if any.

func (*Sender) HandlePDU

func (s *Sender) HandlePDU(pdu *PDU) error

HandlePDU feeds a PDU arriving on the return link into the transaction.

The sender expects NAK, ACK of its EOF, Finished, Keep Alive and Prompt. Anything else is ignored rather than treated as an error, since a shared link may carry PDUs for other transactions.

func (*Sender) NextPDU

func (s *Sender) NextPDU() (*PDU, bool, error)

NextPDU returns the next PDU to transmit, or ok == false when nothing is pending right now. A false does not mean the transaction is over: check Done for that.

The order is metadata, then any segments a NAK asked for again, then fresh file data, then EOF. A suspended transaction emits nothing.

func (*Sender) ResendEOF

func (s *Sender) ResendEOF()

ResendEOF re-queues the EOF PDU. The caller invokes this from its own timer when an EOF ACK does not arrive; clause 4.2 leaves the timing to the implementation and this library owns no clock.

func (*Sender) Resume

func (s *Sender) Resume()

Resume lets a suspended transaction emit again.

func (*Sender) State

func (s *Sender) State() TransactionState

State returns the current transaction state.

func (*Sender) Suspend

func (s *Sender) Suspend()

Suspend stops the transaction emitting PDUs until Resume. Because the caller owns the clock, a suspended transaction simply goes quiet.

func (*Sender) Suspended

func (s *Sender) Suspended() bool

Suspended reports whether the transaction is suspended.

type SenderConfig

type SenderConfig struct {
	// Source, Destination and TransactionSeq identify the transaction.
	Source         EntityID
	Destination    EntityID
	TransactionSeq EntityID

	// Acknowledged selects Class 2 (acknowledged) rather than Class 1.
	Acknowledged bool

	// SegmentSize is the largest file data payload per PDU, in octets.
	SegmentSize int

	// SourceFileName and DestinationFileName name the file at each end.
	SourceFileName      string
	DestinationFileName string

	// ChecksumType selects the file checksum algorithm. Zero is the modular
	// checksum every implementation must provide.
	ChecksumType uint8

	// ClosureRequested asks for a Finished PDU in unacknowledged mode. It is
	// ignored in acknowledged mode, where one always comes back.
	ClosureRequested bool

	// CRCFlag adds a CRC to every outgoing PDU.
	CRCFlag bool

	// FilestoreRequests travel in the Metadata PDU for the receiver to run.
	FilestoreRequests []FilestoreRequest

	// MessagesToUser are opaque application messages for the Metadata PDU.
	MessagesToUser [][]byte

	// FaultHandlers overrides the default disposition for the given fault
	// conditions at this entity. Table 4-1 defaults every condition to a
	// Notice of Cancellation (clause 4.8).
	FaultHandlers map[ConditionCode]FaultHandler

	// FaultHandlerOverrides travel as TLVs in the Metadata PDU (clause 5.4.4) and
	// change the receiver's disposition for the named conditions.
	FaultHandlerOverrides map[ConditionCode]FaultHandler
}

SenderConfig describes one outgoing transaction.

type SuspensionResponse added in v0.4.0

type SuspensionResponse struct {
	Suspended bool
	Status    TransactionStatus

	Transaction TransactionID
}

SuspensionResponse is the body both the suspend and the resume response share: whether the transaction is now suspended, its status, and which transaction it was (tables 6-22 and 6-25).

Clause 6.6.4.2 notes that a successful resume may not change the suspension status at all, because several motivations for suspending can be valid at once, so the indicator reports the state, not the outcome of the request.

func (*SuspensionResponse) Humanize added in v0.4.0

func (m *SuspensionResponse) Humanize() string

Humanize returns a human-readable summary.

type TLV

type TLV struct {
	Type  TLVType
	Value []byte
}

TLV is a Type-Length-Value object per table 5-3. Unlike an LV, a TLV can sit anywhere in the PDU, because its type field says what it is.

func DecodeTLV

func DecodeTLV(data []byte) (TLV, int, error)

DecodeTLV reads one TLV object from the front of data, returning it and the number of octets consumed.

func DecodeTLVs

func DecodeTLVs(data []byte) ([]TLV, error)

DecodeTLVs reads TLV objects until data runs out. A trailing partial object is an error, not a silent truncation.

func EntityIDTLV

func EntityIDTLV(id EntityID) (TLV, error)

EntityIDTLV builds the entity ID TLV that carries a fault location (clause 5.4.6).

func FaultHandlerOverrideTLV

func FaultHandlerOverrideTLV(cond ConditionCode, handler FaultHandler) (TLV, error)

FaultHandlerOverrideTLV builds the fault handler override TLV of clause 5.4.4: one octet holding the condition code (4 bits) and the handler code (4 bits).

func (TLV) AsEntityID

func (t TLV) AsEntityID() (EntityID, error)

AsEntityID reads an entity ID out of a TLV of type 06.

func (TLV) Encode

func (t TLV) Encode() ([]byte, error)

Encode serializes the TLV object.

type TLVType

type TLVType uint8

TLVType identifies the kind of a TLV object, per clause 5.4.

const (
	// TLVFilestoreRequest carries a filestore action to perform (clause 5.4.1).
	TLVFilestoreRequest TLVType = 0x00
	// TLVFilestoreResponse reports the outcome of one request (clause 5.4.2).
	TLVFilestoreResponse TLVType = 0x01
	// TLVMessageToUser carries an opaque application message (clause 5.4.3).
	TLVMessageToUser TLVType = 0x02
	// TLVFaultHandlerOverride changes the handler for one condition (clause 5.4.4).
	TLVFaultHandlerOverride TLVType = 0x04
	// TLVFlowLabel carries a mission-defined flow label (clause 5.4.5).
	TLVFlowLabel TLVType = 0x05
	// TLVEntityID carries an entity ID, used for fault location (clause 5.4.6).
	TLVEntityID TLVType = 0x06
)

func (TLVType) String

func (t TLVType) String() string

String names the TLV type.

type TransactionID added in v0.4.0

type TransactionID struct {
	Source   EntityID
	Sequence EntityID
}

TransactionID identifies one transaction by the entity that started it and the sequence number that entity gave it.

It appears on its own as the Originating Transaction ID message (table 6-2) and again inside the request and response messages of the remote operations, always in the same encoding: a length nibble pair, then the two values.

func (TransactionID) Encode added in v0.4.0

func (t TransactionID) Encode() ([]byte, error)

Encode writes the length octet and the two values (table 6-2).

The two 3-bit length fields hold the width less one, so a one-octet value encodes as zero. Each is preceded by a reserved bit that the standard requires to be zero.

func (TransactionID) Humanize added in v0.4.0

func (t TransactionID) Humanize() string

Humanize returns a human-readable summary.

type TransactionState

type TransactionState int

TransactionState is where a transaction has got to.

const (
	// StateIdle means the transaction has not started.
	StateIdle TransactionState = iota
	// StateSendingMetadata means the Metadata PDU is next out.
	StateSendingMetadata
	// StateSendingData means file data is flowing.
	StateSendingData
	// StateSendingEOF means the EOF PDU is next out.
	StateSendingEOF
	// StateAwaitingEOFAck means the sender is waiting for the ACK of its EOF.
	StateAwaitingEOFAck
	// StateAwaitingFinished means the sender is waiting for a Finished PDU.
	StateAwaitingFinished
	// StateFinished means the transaction is complete.
	StateFinished
	// StateCancelled means the transaction was abandoned.
	StateCancelled
)

func (TransactionState) String

func (s TransactionState) String() string

String names the state.

type TransactionStatus

type TransactionStatus uint8

TransactionStatus is the acknowledging entity's view of the transaction (clause 5.2.4).

const (
	StatusUndefined    TransactionStatus = 0
	StatusActive       TransactionStatus = 1
	StatusTerminated   TransactionStatus = 2
	StatusUnrecognized TransactionStatus = 3
)

func (TransactionStatus) String

func (s TransactionStatus) String() string

String names the transaction status.

type UserMessage added in v0.4.0

type UserMessage struct {
	Type UserMessageType
	// Content is the message body, whose shape the type decides. It is empty
	// for Proxy Put Cancel, which clause 6.2.6.2 says has no content.
	Content []byte
}

UserMessage is one Reserved CFDP Message: its type and its content, with the "cfdp" identifier already checked off the front.

func DecodeUserMessage added in v0.4.0

func DecodeUserMessage(data []byte) (*UserMessage, error)

DecodeUserMessage reads a Reserved CFDP Message from a Message to User TLV's value.

A Message to User that does not open with "cfdp" is an application message and not this package's business, so it comes back as ErrNotUserMessage rather than as a malformed protocol message. A receiver walks the metadata TLVs and uses that to tell the two apart.

func ProxyPutCancel added in v0.4.0

func ProxyPutCancel() UserMessage

ProxyPutCancel asks the respondent to cancel the proxied transaction.

Clause 6.2.6.2: "A Proxy Put Cancel message is mandatory. It has no content."

func UserMessagesFrom added in v0.4.0

func UserMessagesFrom(tlvs []TLV) []*UserMessage

UserMessagesFrom picks the Reserved CFDP Messages out of a run of metadata TLVs, leaving application messages alone.

func (UserMessage) Encode added in v0.4.0

func (m UserMessage) Encode() []byte

Encode serializes the message with its identifier and type octet.

func (UserMessage) EncodeTLV added in v0.4.0

func (m UserMessage) EncodeTLV() TLV

EncodeTLV wraps the message in the Message to User TLV that carries it.

type UserMessageType added in v0.4.0

type UserMessageType uint8

UserMessageType identifies a Reserved CFDP Message, per the message type tables of section 6.

const (
	// Proxy operations, table 6-3.
	MsgProxyPutRequest           UserMessageType = 0x00
	MsgProxyMessageToUser        UserMessageType = 0x01
	MsgProxyFilestoreRequest     UserMessageType = 0x02
	MsgProxyFaultHandlerOverride UserMessageType = 0x03
	MsgProxyTransmissionMode     UserMessageType = 0x04
	MsgProxyFlowLabel            UserMessageType = 0x05
	MsgProxySegmentationControl  UserMessageType = 0x06
	MsgProxyPutResponse          UserMessageType = 0x07
	MsgProxyFilestoreResponse    UserMessageType = 0x08
	MsgProxyPutCancel            UserMessageType = 0x09

	// MsgOriginatingTransactionID is common to all User operations (clause 6.1.5),
	// which is why it sits inside the proxy range rather than after it.
	MsgOriginatingTransactionID UserMessageType = 0x0A

	MsgProxyClosureRequest UserMessageType = 0x0B

	// Directory operations, table 6-14.
	MsgDirectoryListingRequest  UserMessageType = 0x10
	MsgDirectoryListingResponse UserMessageType = 0x11

	// Remote status report operations, table 6-17.
	MsgRemoteStatusReportRequest  UserMessageType = 0x20
	MsgRemoteStatusReportResponse UserMessageType = 0x21

	// Remote suspend operations, table 6-20.
	MsgRemoteSuspendRequest  UserMessageType = 0x30
	MsgRemoteSuspendResponse UserMessageType = 0x31

	// Remote resume operations, table 6-23.
	MsgRemoteResumeRequest  UserMessageType = 0x38
	MsgRemoteResumeResponse UserMessageType = 0x39
)

The message types, from tables 6-3, 6-14, 6-17, 6-20 and 6-23.

The numbering is grouped by operation with gaps between groups, and one gap inside the proxy group: 0x0A is the Originating Transaction ID, which is common to every operation rather than belonging to proxy, so the proxy group runs 0x00 to 0x09 and then resumes at 0x0B.

func (UserMessageType) String added in v0.4.0

func (t UserMessageType) String() string

String names the message type.

func (UserMessageType) Valid added in v0.4.0

func (t UserMessageType) Valid() bool

Valid reports whether this is a message type section 6 defines.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL