CCSDS File Delivery Protocol (CCSDS 727.0-B-5) for space file transfer
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

OCaml 70.8%
Python 13.3%
C 11.3%
Java 1.0%
PHP 1.0%
Roff 0.4%
Shell 0.4%
Dune 0.4%
Other 1.3%
73 1 0

Clone this repository

https://tangled.org/gazagnaire.org/ocaml-cfdp https://tangled.org/did:plc:jhift2vwcxhou52p3sewcrpx/ocaml-cfdp
git@git.recoil.org:gazagnaire.org/ocaml-cfdp git@git.recoil.org:did:plc:jhift2vwcxhou52p3sewcrpx/ocaml-cfdp

For self-hosted knots, clone URLs may differ based on your setup.

Download tar.gz
README.md

cfdp#

Pure OCaml implementation of CCSDS File Delivery Protocol (CCSDS 727.0-B-5) for reliable file transfer in space communications.

Overview#

CFDP provides file transfer services for space missions with support for high-delay and disruption-prone links:

  • Class 1: Unacknowledged (unreliable) transfers
  • Class 2: Acknowledged (reliable) transfers with NAK-based retransmission

Packages#

  • cfdp -- Core protocol: PDU types, codecs, state machines
  • cfdp-eio -- TCP transport and file I/O using Eio

Installation#

Install with opam:

$ opam install cfdp cfdp-eio

If opam cannot find the packages, they may not yet be released in the public opam-repository. Add the overlay repository, then install them:

$ opam repo add samoht https://tangled.org/gazagnaire.org/opam-overlay.git
$ opam update
$ opam install cfdp cfdp-eio

Usage#

Send a file#

let send_firmware env =
  Eio.Switch.run @@ fun sw ->
  let conn =
    let net = (env#net :> [ `Generic ] Eio.Net.ty Eio.Resource.t) in
    Cfdp_eio.connect ~sw ~net ~host:"flatsat-1" ~port:1734 ()
  in
  match
    Cfdp_eio.Sender.send_file conn
      ~src:(Fpath.v "firmware.elf")
      ~dst:"firmware.elf"
      ()
  with
  | Ok tid -> Format.printf "Done: %a@." Cfdp.pp_transaction_id tid
  | Error msg -> Format.eprintf "Error: %s@." msg

Receive a file#

let receive_firmware env =
  Eio.Switch.run @@ fun sw ->
  let conn =
    let net = (env#net :> [ `Generic ] Eio.Net.ty Eio.Resource.t) in
    Cfdp_eio.connect ~sw ~net ~host:"flatsat-1" ~port:1734 ()
  in
  match
    Cfdp_eio.Receiver.recv_file conn ~dest_dir:(Fpath.v "./incoming") ()
  with
  | Ok (path, tid) ->
      Format.printf "Received %a (txn %a)@."
        Fpath.pp path Cfdp.pp_transaction_id tid
  | Error msg -> Format.eprintf "Error: %s@." msg

Both calls accept an optional ~on_progress callback receiving {bytes_sent; bytes_total; segments_sent; segments_total}.

Features#

  • Full PDU header encoding/decoding with variable-length entity IDs (1-8 bytes)
  • File directive PDUs: Metadata, EOF, ACK, NAK, Finished, Prompt, Keep Alive
  • Segmented file data with optional record boundaries and segment metadata
  • CRC-32 integrity checking on PDUs
  • Checksum computation: modular, CRC-32, CRC-32C, and null
  • State machines for all four transfer roles:
    • Sender1 -- Class 1 (unacknowledged) sender
    • Sender2 -- Class 2 (acknowledged) sender with NAK retransmission
    • Receiver1 -- Class 1 (unacknowledged) receiver
    • Receiver2 -- Class 2 (acknowledged) receiver with NAK generation
  • Timer management for inactivity, NAK, EOF, Finished, and Keep Alive
  • Wire codecs for Finished, ACK, and Prompt directives

Low-level API#

State machine (Class 1 Sender)#

For custom transports or in-process simulation, drive the state machines directly:

let sender = Cfdp.Sender1.initial (Cfdp.Entity_id.of_int_exn 1)
let req =
  Cfdp.put_request
    ~dest_entity:(Cfdp.Entity_id.of_int_exn 2)
    ~source_filename:"firmware.elf"
    ~dest_filename:"firmware.elf"
    ()

let file_size = 4096L
let read_data _offset = Bytes.create 1024
let sender, actions =
  Cfdp.Sender1.step sender
    (Cfdp.Sender1.Ev_put_request (req, file_size, read_data))

Feed events in, get actions out (Act_send_metadata, Act_send_file_data, ...).

PDU encode / decode#

open Cfdp

let source = Entity_id.of_int_exn 1
let dest = Entity_id.of_int_exn 2
let config = default_config
let meta =
  metadata
    ~file_size:1024L
    ~source_filename:"data.bin"
    ~dest_filename:"data.bin" ()

let hdr : header =
  { version = 1;
    pdu_type = File_directive;
    direction = Toward_receiver;
    transmission_mode = Unacknowledged;
    crc_present = false;
    large_file = false;
    segment_ctrl = false;
    segment_metadata = false;
    source_entity = source;
    transaction_seq = 1L;
    dest_entity = dest;
    data_len = 0;
  }

let bytes = encode config (Pdu_directive (hdr, Metadata meta))

let () =
  match decode bytes with
  | Ok (pdu, _consumed) -> Format.printf "%a@." pp_pdu pdu
  | Error e -> Format.printf "Error: %a@." pp_error e

State Machines#

Module Class Role
Sender1 1 (unacknowledged) Sender
Sender2 2 (acknowledged) Sender with NAK retransmission
Receiver1 1 (unacknowledged) Receiver
Receiver2 2 (acknowledged) Receiver with NAK generation

Timer types: Timer_nak, Timer_eof, Timer_finished, Timer_inactivity, Timer_keep_alive.

  • ION -- NASA/JPL DTN with CFDP
  • lib-cfdp -- NASA CFDP library

References#

Licence#

ISC