// SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute // SPDX-License-Identifier: GPL-3.0-only #pragma once #include constexpr uint32_t JFJOCH_TCP_MAGIC = 0x4A464A54; // JFJT constexpr uint32_t JFJOCH_TCP_VERSION = 5; // Upper bound on a single frame's payload. A receiver rejects any header claiming more // before allocating for it: an uncapped payload_size would otherwise drive a huge // resize() and take down the receiving thread. 1 GiB is far above any real image frame. constexpr uint64_t JFJOCH_TCP_MAX_PAYLOAD_SIZE = static_cast(1) << 30; enum class TCPFrameType : uint16_t { START = 1, DATA = 2, CALIBRATION = 3, END = 4, ACK = 5, CANCEL = 6, KEEPALIVE = 7, // Writer -> pusher liveness/backpressure heartbeat. Tells the pusher the writer // is alive but busy (e.g. stalled on a slow filesystem) and that it should keep // waiting for a proper ACK rather than declaring the connection dead. Carries the // writer's current FIFO occupancy in the ack_fifo_* fields. BUSY = 8, // Pusher -> writer dry run, sent before the detector is armed. Carries the same CBOR // StartMessage a START would, but the writer only checks that it could write the output // (path, directory, no file in the way) and answers with an ACK; it opens nothing and // leaves its state untouched. A rejected PREFLIGHT is not fatal - the run was never // started, so the connection stays usable for the next attempt. PREFLIGHT = 9, // Writer -> pusher, sent as an ACK with ack_for = FILE_CLOSED: a data file has been closed and // renamed into place. image_number is the file number (from 0), ack_processed_images the images // the file holds. Lets the broker tell a reader following the collection which files it can read. FILE_CLOSED = 10, }; enum class TCPAckCode : uint16_t { None = 0, StartFailed = 1, DataWriteFailed = 2, EndFailed = 3, DiskQuotaExceeded = 4, NoSpaceLeft = 5, PermissionDenied = 6, IoError = 7, ProtocolError = 8 }; constexpr uint32_t TCP_ACK_FLAG_OK = 1u << 0; constexpr uint32_t TCP_ACK_FLAG_FATAL = 1u << 1; constexpr uint32_t TCP_ACK_FLAG_HAS_ERROR_TEXT = 1u << 2; struct alignas(64) TcpFrameHeader { uint32_t magic = JFJOCH_TCP_MAGIC; uint16_t version = JFJOCH_TCP_VERSION ; uint16_t type = 0; uint64_t image_number = 0; uint64_t payload_size = 0; uint32_t socket_number = 0; uint32_t flags = 0; uint64_t run_number = 0; uint32_t ack_processed_images = 0; uint16_t ack_code = 0; uint16_t ack_for = 0; uint64_t ack_fifo_occupancy = 0; uint64_t ack_fifo_max_occupancy = 0; };