ProtoCore v1.0.16
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
client.h
Go to the documentation of this file.
1// ProtoCore v1.0.16 - Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file client.h
6 * @brief The client engine: drive the handshake, authenticate, and request the port forward.
7 */
8
9#ifndef PROTOCORE_CLIENT_CLIENT_H
10#define PROTOCORE_CLIENT_CLIENT_H
11
13
15
16/** @brief Lifecycle phase of the forward, for observability. */
18{
19 PROTOCORE_SSH_CLIENT_IDLE = 0, ///< not started.
20 PROTOCORE_SSH_CLIENT_CONNECTING, ///< TCP + SSH handshake + auth in progress.
21 PROTOCORE_SSH_CLIENT_UP, ///< authenticated and the remote forward is established.
22 PROTOCORE_SSH_CLIENT_FAILED ///< the last attempt failed (host-key mismatch, auth, or transport).
24
25#if PROTOCORE_ENABLE_SSH_CLIENT
26
27/** @brief How to reach the relay, who to log in as, and what to forward back. */
28typedef struct
29{
30 const char *host; ///< relay hostname or dotted-quad.
31 uint16_t port; ///< relay SSH port (0 => 22).
32 const char *user; ///< SSH username on the relay.
33 const uint8_t *auth_seed; ///< 32-byte ssh-ed25519 private seed the device authenticates with.
34 const uint8_t *host_pin; ///< 32-byte SHA-256 of the relay's host-key blob (K_S); handshake aborts on mismatch.
35 const char *bind_addr; ///< address the relay binds the forward on ("" / null => "" = all, "localhost", ...).
36 uint16_t
37 bind_port; ///< remote port the relay listens on (tcpip-forward); connections accepted there are forwarded back.
38 uint16_t local_port; ///< local TCP port a forwarded connection is bridged to (e.g. 80).
39} protocore_ssh_client_cfg;
40
41/**
42 * @brief Start (or restart) the forward: connect to the relay, handshake, authenticate, and request
43 * the remote forward. Non-blocking after the initial connect; drive it with poll().
44 * @return true if the connection and handshake started; false on bad args or immediate failure.
45 *
46 * @warning Call begin() and poll() from the SAME task, and give that task enough stack for the
47 * negotiated KEX. The handshake's field arithmetic runs in the caller's task: curve25519/ed25519
48 * peak ~10.5 KB, and the mlkem768x25519 hybrid (PROTOCORE_ENABLE_PQC_KEX) adds ML-KEM-768 for ~16 KB total.
49 * The Arduino loop() task's default 8 KB is NOT enough - run the forward from a dedicated task created
50 * with a >= 20480-byte stack (see the example). begin() claims a private scratch arena for the calling
51 * task, so poll() must run in that same task or the packet-decrypt tripwire fires.
52 */
53
54/**
55 * @brief Pump the forward: advance the handshake, service the relay's keepalives, accept
56 * forwarded-tcpip channels and bridge their bytes to/from the local service. Call every loop,
57 * from the same (adequately-stacked) task that called begin() - see the begin() @warning.
58 */
59
60/** @brief Tear the forward down and close the relay connection. */
61
62/**
63 * @brief The client engine's operations, for the layers that frame messages on its connection.
64 *
65 * @var SshClientNs::send frame one payload as a binary packet and write it to the relay
66 * @var SshClientNs::crypto_work the client slot's handshake scratch, or null when the pool is short
67 * @var SshClientNs::state the forward's lifecycle phase
68 */
69/** @brief The message bytes one send frames as a binary packet. */
70typedef struct
71{
72 const uint8_t *payload; ///< the message bytes a send carries
73 size_t len; ///< how many
74} SshClientMsgArgs;
75
76typedef struct
77{
78 const protocore_ssh_client_cfg *cfg; ///< what a begin dials with
79
80 SshClientMsgArgs msg; ///< the message bytes a send carries
81
82 proto_bool ok; ///< a call's true/false outcome
83 uint8_t *work; ///< the crypto scratch a lookup reports
84 protocore_ssh_client_state state_of; ///< the phase a lookup reports
85
86 void (*const send)(uint8_t *work);
87 void (*const crypto_work)(uint8_t *work);
88 void (*const state)(uint8_t *work);
89 void (*const begin)(uint8_t *work);
90 void (*const poll)(uint8_t *work);
91 void (*const end)(uint8_t *work);
92} SshClientNs;
93
94/** @brief The one instance, defined in client.c. */
95extern SshClientNs SshClient;
96
97/**
98 * @brief The PROTOCORE_SSH_CLIENT_BORROW bytes this module's state lives in.
99 *
100 * Stated beside the namespace rather than on it: an entry takes a borrow, and this is where
101 * that borrow comes from. Taken once from the end of the pool, which no mark and no release
102 * walks, so the state lasts the life of the program.
103 *
104 * @return the span.
105 */
106uint8_t *protocore_ssh_client_span(void);
107
108#endif // PROTOCORE_ENABLE_SSH_CLIENT
109
111
112#endif // PROTOCORE_CLIENT_CLIENT_H
PROTO_ENUM_PACKED
Application protocol spoken on a listener port or connection slot.
PROTOCORE_BEGIN_DECLS enum PROTO_ENUM_PACKED protocore_ssh_client_state
Lifecycle phase of the forward, for observability.
@ PROTOCORE_SSH_CLIENT_FAILED
the last attempt failed (host-key mismatch, auth, or transport).
Definition client.h:22
@ PROTOCORE_SSH_CLIENT_UP
authenticated and the remote forward is established.
Definition client.h:21
@ PROTOCORE_SSH_CLIENT_IDLE
not started.
Definition client.h:19
@ PROTOCORE_SSH_CLIENT_CONNECTING
TCP + SSH handshake + auth in progress.
Definition client.h:20
Root infrastructure: fixed widths, serializers, opcodes and sizes, for every layer above.
#define PROTOCORE_BEGIN_DECLS
Give a header's declarations C linkage, so their symbol names carry no parameter types.
Definition types.h:96
_Bool proto_bool
The truth value.
Definition types.h:64
#define PROTOCORE_END_DECLS
Definition types.h:97