16#if DETWS_ENABLE_SSH_ZLIB
36static void ensure_init()
49static void ssh_emit(uint8_t i,
const uint8_t *payload,
size_t len)
54 if (!det_conn_active(conn->
id))
64 if (
ssh_pkt_send(i, payload, len, wire, &wlen, wire_cap) != 0)
71static void ssh_msg_handler(uint8_t i, uint8_t msg_type,
const uint8_t *payload,
size_t len)
74 s_sshc.
close[i] =
true;
94 return &s_ssh_handler;
97int ssh_conn_send(uint8_t ssh_slot, uint32_t channel,
const uint8_t *data,
size_t len)
102 if (!det_conn_active(conn->
id))
113 if (!payload || !wire)
119 if (
ssh_pkt_send(ssh_slot, payload, plen, wire, &wlen, wire_cap) != 0)
131 if (!det_conn_active(conn->
id))
134 uint8_t close_msgs[10];
147 for (
size_t off = 0; off < 10; off += 5)
150 if (
ssh_pkt_send(ssh_slot, close_msgs + off, 5, wire, &wlen, wire_cap) != 0)
164 if (!det_conn_active(conn->
id))
173 if (!payload || !wire)
181 if (
ssh_pkt_send(ssh_slot, payload, plen, wire, &wlen, wire_cap) != 0)
193 if (!det_conn_active(conn_slot))
217#if DETWS_SSH_PORT_FORWARD
248 s_sshc.
close[j] =
false;
253#if DETWS_ENABLE_SSH_ZLIB
267static void close_conn(uint8_t conn_slot)
282 size_t n = det_conn_read(conn_slot, buf,
sizeof(buf));
293 close_conn(conn_slot);
308 close_conn(conn_slot);
317#if DETWS_SSH_PORT_FORWARD
318 ssh_forward_reset(j);
#define SSH_REKEY_TIME_MS
Elapsed-time re-key trigger in milliseconds (RFC 4253 §9: "after each hour"). Default 1 hour.
#define MAX_SSH_CONNS
Maximum simultaneous SSH connections.
#define RX_BUF_SIZE
Ring-buffer capacity in bytes per connection slot.
#define SSH_REKEY_PACKET_THRESHOLD
Re-key when either packet sequence number reaches this value.
#define SSH_PKT_BUF_SIZE
Packet assembly buffer per SSH connection (bytes).
RAII scope guard for transient scratch borrows.
Pluggable monotonic clock for all library timing.
uint32_t detws_millis(void)
The library's monotonic time at 1000 Hz (milliseconds).
Layer 5 (Session) - per-protocol connection handler dispatch table.
void * scratch_alloc(size_t n, size_t align)
Borrow n bytes of scratch, aligned to align.
Shared per-dispatch scratch arena (Layer 5, session-scoped memory).
int ssh_channel_open_forwarded(uint8_t i, const char *conn_addr, uint16_t conn_port, const char *orig_addr, uint16_t orig_port, uint8_t *out, size_t *out_len, size_t cap)
Open a server-initiated "forwarded-tcpip" channel (RFC 4254 §7.2, ssh -R).
int ssh_channel_build_data(uint8_t i, uint32_t channel, const uint8_t *data, size_t len, uint8_t *out, size_t *out_len, size_t cap)
Build an SSH_MSG_CHANNEL_DATA message carrying data to the client on channel channel (a local channel...
int ssh_channel_build_close(uint8_t i, uint32_t channel, uint8_t *out, size_t *out_len, size_t cap)
Build SSH_MSG_CHANNEL_EOF + SSH_MSG_CHANNEL_CLOSE for channel channel and mark it closed.
void ssh_channel_init(uint8_t i)
Reset channel state for slot i.
SSH connection protocol - multiplexed "session" channels (RFC 4254).
SSH per-connection compression owner (server-to-client zlib / zlib@openssh.com).
int ssh_conn_close_channel(uint8_t ssh_slot, uint32_t channel)
Close an SSH channel from the server side: frame CHANNEL_EOF and CHANNEL_CLOSE as two binary packets ...
int ssh_conn_open_forwarded(uint8_t ssh_slot, const char *conn_addr, uint16_t conn_port, const char *orig_addr, uint16_t orig_port)
Open a server-initiated "forwarded-tcpip" channel to the client (ssh -R): build the CHANNEL_OPEN (RFC...
void ssh_conn_rx(uint8_t conn_slot)
Drain conn_slot's receive ring buffer through the SSH stack.
void ssh_conn_accept(uint8_t conn_slot)
Handle a new ConnProto::PROTO_SSH connection on conn_slot.
void ssh_conn_poll(uint8_t conn_slot)
Per-loop poll hook for an SSH connection (registered as the SSH protocol handler's on_poll)....
int ssh_conn_send(uint8_t ssh_slot, uint32_t channel, const uint8_t *data, size_t len)
Send application data to the client over an SSH channel.
void ssh_conn_setup()
One-time setup: install the dispatcher's binary-packet emit callback.
const ProtoHandler * ssh_proto_handler(void)
void ssh_conn_close(uint8_t conn_slot)
Tear down SSH state for conn_slot (disconnect / error).
Glue between the TCP transport (conn_pool) and the SSH protocol stack.
SSH direct-tcpip port-forwarding owner (the ssh -L target side).
SSH session key material - types, pools, and security model.
SshPacketState ssh_pkt[MAX_SSH_CONNS]
Static packet state pool (BSS). One entry per SSH slot.
int ssh_pkt_send(uint8_t i, const uint8_t *payload, size_t payload_len, uint8_t *out, size_t *out_len, size_t out_cap)
Build and send one SSH binary packet.
void ssh_pkt_init(uint8_t i)
Initialize the packet state for SSH connection slot i.
int ssh_pkt_recv(uint8_t i, const uint8_t *data, size_t len, ssh_msg_handler_t handler)
Receive and process one or more SSH binary packets from data.
SSH binary packet protocol: framing, AES-256-CTR encryption, HMAC-SHA2-256 integrity,...
int ssh_server_dispatch(uint8_t i, uint8_t msg_type, const uint8_t *payload, size_t len)
Dispatch one decrypted inbound SSH message for slot i.
void ssh_server_set_emit_cb(SshEmitCb cb)
Install the outbound-message callback.
SSH message dispatcher - ties the transport, auth, and channel layers into one server state machine.
int ssh_transport_recv_banner(uint8_t i, const uint8_t *data, size_t len, size_t *consumed)
Feed raw bytes while awaiting the client identification string.
int ssh_transport_begin_rekey(uint8_t i, uint8_t *out, size_t *out_len, size_t cap)
Begin a server-initiated re-key by emitting a fresh KEXINIT.
bool ssh_rekey_due(uint32_t seq_send, uint32_t seq_recv, uint32_t elapsed_ms, uint32_t pkt_threshold, uint32_t time_threshold_ms)
Pure re-key decision (RFC 4253 §9: "after each gigabyte ... or after each hour").
SshSession ssh_sess[MAX_SSH_CONNS]
Static pool of SSH session state (BSS), one per SSH slot.
void ssh_transport_init(uint8_t i)
Reset transport state for slot i to the start of a handshake.
int ssh_transport_server_banner(uint8_t *out, size_t *out_len, size_t cap)
Write the server identification string ("SSH-2.0-…\r\n") to out.
SSH transport-layer protocol state machine (RFC 4253).
@ SSH_PHASE_KEXINIT
Awaiting the client KEXINIT.
@ SSH_PHASE_OPEN
Authenticated; connection/channel protocol active.
@ SSH_PHASE_BANNER
Awaiting the client identification string.
Per-protocol connection event/poll callbacks (Layer 5 dispatch vtable).
volatile bool close[MAX_SSH_CONNS]
uint8_t conn_for_ssh[MAX_SSH_CONNS]
bool kex_active
True while KEX is in progress (no user data).
SshPhase phase
Current handshake phase.
uint32_t last_kex_ms
detws_millis() when the last KEX completed (server-initiated re-key timer).
A single TCP connection context.
uint8_t id
Fixed slot index (0 … MAX_CONNS-1).
uint8_t proto_slot
Per-protocol session/pool index (0xFF = none): the SSH session, an MQTT/Modbus session,...
bool det_conn_send(uint8_t slot, const void *data, u16_t len)
Send len bytes on connection slot (copies data; TLS-aware).
void det_conn_flush(uint8_t slot)
Flush queued bytes / finish the send on slot (TLS-aware).
void det_conn_close(uint8_t slot)
Close connection slot gracefully (tcp_close), aborting if the FIN cannot be queued....
TcpConn conn_pool[CONN_POOL_SLOTS]
Static pool of connection contexts. Defined in tcp.cpp. Sized CONN_POOL_SLOTS: MAX_CONNS TCP slots pl...
Layer 4 (Transport) - TCP connection pool, ring buffers, and lwIP integration.
#define DETWS_PROTO_SLOT_NONE
Sentinel for TcpConn::proto_slot meaning "no per-protocol session bound".