ProtoCore v0.0.1
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
cotp.h
Go to the documentation of this file.
1// Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file cotp.h
6 * @brief TPKT (RFC 1006) + COTP / ISO 8073 X.224 class-0 frame codec (PC_ENABLE_COTP) -
7 * zero-heap "ISO transport on TCP" framing, the reusable foundation under S7comm and
8 * IEC 61850 MMS.
9 *
10 * Two stacked layers over TCP:
11 * - TPKT (RFC 1006): a 4-octet envelope - version(1)=3, reserved(1)=0, length(2,
12 * big-endian, the whole packet including this header) - then an X.224 TPDU.
13 * - COTP / X.224 class 0: a Data TPDU is `LI(1) 0xF0 (EOT|TPDU-NR)` then the user data,
14 * where LI is the count of header octets after itself. Connection Request / Confirm use
15 * codes 0xE0 / 0xD0 and carry a destination ref, a source ref, a class octet, and
16 * variable parameters (e.g. the TPDU-size parameter 0xC0).
17 *
18 * The builders frame a payload into a caller buffer (fail-closed); the parsers validate and
19 * report the slices. TPKT/X.224 layout verified against RFC 1006 / ISO 8073.
20 *
21 * @author Douglas Quigg (dstroy0)
22 * @date 2026
23 */
24
25#ifndef PROTOCORE_COTP_H
26#define PROTOCORE_COTP_H
27
28#include "protocore_config.h"
29
30#if PC_ENABLE_COTP
31
32#include <stddef.h>
33#include <stdint.h>
34
35#define TPKT_VERSION 0x03 ///< RFC 1006 TPKT version (always 3)
36#define TPKT_HEADER_SIZE 4 ///< version + reserved + 2-octet length
37
38// X.224 TPDU type codes (the high nibble of the code octet; the low nibble is the CDT /
39// credit, which is 0 for class 0).
40#define COTP_DT 0xF0 ///< Data
41#define COTP_CR 0xE0 ///< Connection Request
42#define COTP_CC 0xD0 ///< Connection Confirm
43#define COTP_DR 0x80 ///< Disconnect Request
44#define COTP_DC 0xC0 ///< Disconnect Confirm
45#define COTP_ER 0x70 ///< TPDU Error
46
47#define COTP_EOT 0x80 ///< end-of-TSDU bit in the DT TPDU-NR octet
48#define COTP_PARAM_TPDU_SIZE 0xC0 ///< variable-parameter code: TPDU size (value = size exponent)
49#define COTP_DT_HEADER_LEN 3 ///< DT TPDU header octets: LI + code + (EOT|NR)
50
51// ---- TPKT ----
52
53/** @brief Wrap @p payload in a TPKT envelope. Returns total octets, or 0 on overflow. */
54size_t pc_tpkt_build(uint8_t *buf, size_t cap, const uint8_t *payload, size_t payload_len);
55
56/**
57 * @brief Parse a TPKT envelope; reports the X.224 payload slice and bytes consumed.
58 * @return true on a complete, version-3 packet; false on bad version / truncation.
59 */
60bool pc_tpkt_parse(const uint8_t *buf, size_t len, const uint8_t **payload, size_t *payload_len, size_t *consumed);
61
62// ---- COTP (X.224 class 0) ----
63
64/** @brief Build a COTP Data TPDU around @p data: `LI=2, 0xF0, (EOT|0)` + data. */
65size_t pc_cotp_build_dt(uint8_t *buf, size_t cap, const uint8_t *data, size_t data_len, bool eot);
66
67/**
68 * @brief Build a COTP Connection Request: `LI 0xE0 dst-ref(0) src-ref class(0)` + a TPDU-size
69 * parameter + any @p extra_params (e.g. the S7 src/dst TSAP parameters).
70 * @param tpdu_size_code the TPDU-size exponent (e.g. 0x0A = 1024).
71 */
72size_t pc_cotp_build_cr(uint8_t *buf, size_t cap, uint16_t src_ref, uint8_t tpdu_size_code, const uint8_t *extra_params,
73 size_t extra_len);
74
75/**
76 * @brief Build a COTP Connection Confirm (the server's response to a CR): `LI 0xD0 dst-ref src-ref
77 * class(0)` + a TPDU-size parameter + any @p extra_params.
78 * @param dst_ref the connecting peer's source reference, echoed back as the destination reference.
79 * @param src_ref this end's source reference.
80 * @param tpdu_size_code the negotiated TPDU-size exponent (e.g. 0x0A = 1024).
81 */
82size_t pc_cotp_build_cc(uint8_t *buf, size_t cap, uint16_t dst_ref, uint16_t src_ref, uint8_t tpdu_size_code,
83 const uint8_t *extra_params, size_t extra_len);
84
85/** @brief A parsed COTP header. For DT, @ref data is the user data; for CR/CC, the refs. */
86struct CotpHeader
87{
88 uint8_t code; ///< TPDU type (high nibble): COTP_DT / COTP_CR / ...
89 uint16_t dst_ref; ///< CR / CC destination reference
90 uint16_t src_ref; ///< CR / CC source reference
91 bool eot; ///< DT end-of-TSDU flag
92 const uint8_t *data; ///< DT user data (points INTO the source buffer)
93 size_t data_len;
94};
95
96/** @brief Parse a COTP TPDU (typically the TPKT payload). */
97bool pc_cotp_parse(const uint8_t *buf, size_t len, CotpHeader *out);
98
99#endif // PC_ENABLE_COTP
100
101#endif // PROTOCORE_COTP_H
User-facing configuration for ProtoCore.