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) senderSender2-- Class 2 (acknowledged) sender with NAK retransmissionReceiver1-- Class 1 (unacknowledged) receiverReceiver2-- 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.
Related Work#
References#
- CCSDS 727.0-B-5 -- CFDP Blue Book
- CCSDS 720.1-G-4 -- CFDP Green Book
Licence#
ISC