ProtoCore v0.0.2
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
ssh_comp.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 ssh_comp.h
6 * @brief SSH per-connection compression owner (server-to-client `zlib` / `zlib@openssh.com`).
7 *
8 * One owner for the whole compression concern (per the "one owner per cross-layer concern" rule):
9 * it holds the per-connection streaming compressor + its PSRAM-resident buffers, records the
10 * negotiated s2c algorithm, and starts the stream at the right moment (immediately after NEWKEYS for
11 * `zlib`, or after SSH_MSG_USERAUTH_SUCCESS for the delayed `zlib@openssh.com`). The transport packet
12 * layer asks it, per outbound packet, whether to compress and hands it the payload; nothing else
13 * touches compression state.
14 *
15 * Only server-to-client is implemented (see ssh_zlib.h for why c2s stays `none`).
16 *
17 * @author Douglas Quigg (dstroy0)
18 * @date 2026
19 */
20
21#ifndef PROTOCORE_SSH_COMP_H
22#define PROTOCORE_SSH_COMP_H
23
24#include "protocore_config.h"
25#include <stddef.h>
26#include <stdint.h>
27
28#if PC_ENABLE_SSH_ZLIB
29
30/** @brief Negotiated server-to-client compression algorithm. */
31enum class SshCompAlg : uint8_t
32{
33 SSH_COMP_NONE = 0, ///< no compression (also the c2s direction, always)
34 SSH_COMP_ZLIB = 1, ///< "zlib" (RFC 4253) - starts right after NEWKEYS
35 SSH_COMP_ZLIB_DELAYED = 2 ///< "zlib@openssh.com" - starts after SSH_MSG_USERAUTH_SUCCESS
36};
37
38/** @brief Reset compression state for slot @p i (fresh connection). Does NOT run on a re-key. */
39void ssh_comp_reset(uint8_t i);
40
41/** @brief Record the s2c algorithm negotiated in KEXINIT (::SshCompAlg). */
42void ssh_comp_set_s2c(uint8_t i, SshCompAlg alg);
43
44/** @brief NEWKEYS completed: start the stream now if `zlib` was negotiated (idempotent). */
45void ssh_comp_on_newkeys(uint8_t i);
46
47/** @brief SSH_MSG_USERAUTH_SUCCESS sent: start the stream if `zlib@openssh.com` was negotiated. */
48void ssh_comp_on_auth_success(uint8_t i);
49
50/** @brief True once the s2c stream is active and outbound payloads must be compressed. */
51bool ssh_comp_s2c_active(uint8_t i);
52
53/**
54 * @brief Compress one outbound payload, continuing the session's zlib stream.
55 * @return 0 on success (*out_len set), -1 on overflow / oversized input / inactive slot.
56 */
57int ssh_comp_s2c(uint8_t i, const uint8_t *src, size_t src_len, uint8_t *dst, size_t dst_cap, size_t *out_len);
58
59/** @brief Record the client-to-server algorithm negotiated in KEXINIT (::SshCompAlg). */
60void ssh_comp_set_c2s(uint8_t i, SshCompAlg alg);
61
62/** @brief True once the c2s stream is active and inbound payloads must be decompressed. */
63bool ssh_comp_c2s_active(uint8_t i);
64
65/**
66 * @brief Decompress one inbound payload, continuing the session's client-to-server zlib stream. The
67 * peer (OpenSSH) flushes with Z_PARTIAL_FLUSH, so this resumes a context-takeover inflate.
68 * @return 0 on success (*out_len set), -1 on a malformed stream / output overflow / inactive slot.
69 */
70int ssh_comp_c2s(uint8_t i, const uint8_t *src, size_t src_len, uint8_t *dst, size_t dst_cap, size_t *out_len);
71
72#endif // PC_ENABLE_SSH_ZLIB
73#endif // PROTOCORE_SSH_COMP_H
User-facing configuration for ProtoCore.