|
ProtoCore v0.0.2
Deterministic, zero-heap network stack for embedded targets
|
SSH channel flow control - RFC 4254 sec 5.2 window arithmetic. More...
#include "network_drivers/presentation/ssh/connection/ssh_flow_control.h"#include "network_drivers/presentation/ssh/transport/ssh_packet.h"#include "protocore_config.h"#include "shared_primitives/endian.h"#include <string.h>Go to the source code of this file.
Functions | |
| void | pc_ssh_flow_init (SshFlow *f, uint32_t local_window, uint32_t peer_window, uint32_t peer_max_pkt) |
Start a channel's windows: ours at local_window, the peer's at what it advertised. | |
| bool | pc_ssh_flow_recv_take (SshFlow *f, uint32_t n) |
Account n inbound bytes against our window. | |
| bool | pc_ssh_flow_replenish_due (const SshFlow *f, uint32_t *add) |
| Decide whether a WINDOW_ADJUST is due, and for how much. Does not mutate. | |
| void | pc_ssh_flow_local_credit (SshFlow *f, uint32_t add) |
Credit our window by add, once that WINDOW_ADJUST has actually been sent. | |
| bool | pc_ssh_flow_send_allows (const SshFlow *f, size_t len) |
True if len bytes fit both the peer's remaining window and its maximum packet size. | |
| uint32_t | pc_ssh_flow_send_cap (const SshFlow *f, uint32_t want) |
| Clamp a would-be send to what the peer currently permits. | |
| void | pc_ssh_flow_send_take (SshFlow *f, uint32_t n) |
Account n outbound bytes against the peer's window (call only after send_allows()). | |
| void | pc_ssh_flow_peer_add (SshFlow *f, uint32_t add) |
| Credit the peer's window from an inbound WINDOW_ADJUST. | |
| uint32_t | pc_ssh_flow_peer_window (const SshFlow *f) |
| Bytes we may still send the peer - the bound a producer sizes its next read to. | |
| int32_t | pc_ssh_sig_build_open_failure (uint8_t *out, size_t cap, uint32_t peer_id, uint32_t reason, size_t *out_len) |
CHANNEL_OPEN_FAILURE. reason: 1 admin-prohibited, 2 connect-failed, 3 unknown-type, 4 resource. | |
| int32_t | pc_ssh_sig_build_open_confirm (const SshFlow *f, uint32_t peer_id, uint32_t local_id, uint8_t *out, size_t cap, size_t *out_len) |
| CHANNEL_OPEN_CONFIRMATION, advertising our current window and maximum packet size. | |
| int32_t | pc_ssh_sig_build_data (SshFlow *f, uint32_t peer_id, const uint8_t *data, size_t len, uint8_t *out, size_t cap, size_t *out_len) |
CHANNEL_DATA carrying len bytes, and account them against the peer's window. | |
| int32_t | pc_ssh_sig_build_window_adjust (uint32_t peer_id, uint32_t add, uint8_t *out, size_t cap, size_t *out_len) |
CHANNEL_WINDOW_ADJUST granting add more bytes. Credit the window only once this is sent. | |
| int32_t | pc_ssh_sig_build_close (uint32_t peer_id, uint8_t *out, size_t cap, size_t *out_len) |
| CHANNEL_EOF followed by CHANNEL_CLOSE, as one 10-byte pair. | |
SSH channel flow control - RFC 4254 sec 5.2 window arithmetic.
Definition in file ssh_flow_control.cpp.
| void pc_ssh_flow_init | ( | SshFlow * | f, |
| uint32_t | local_window, | ||
| uint32_t | peer_window, | ||
| uint32_t | peer_max_pkt | ||
| ) |
Start a channel's windows: ours at local_window, the peer's at what it advertised.
The local window is a parameter rather than a baked-in constant because the server and the client advertise different sizes, and the value we replenish to must be the value we told the peer about. Passing it here keeps the two from drifting apart.
| local_window | what we advertise in CHANNEL_OPEN / CONFIRMATION; also the replenish target. |
| peer_window | the peer's initial window from CHANNEL_OPEN / CONFIRMATION. |
| peer_max_pkt | the peer's maximum packet size from the same message. |
Definition at line 15 of file ssh_flow_control.cpp.
References SshFlow::local_max, SshFlow::local_window, SshFlow::peer_max_pkt, and SshFlow::peer_window.
Referenced by pc_ssh_channel_handle_open(), and pc_ssh_channel_open_forwarded().
| bool pc_ssh_flow_recv_take | ( | SshFlow * | f, |
| uint32_t | n | ||
| ) |
Account n inbound bytes against our window.
n exceeds what we advertised - the peer overran the window (RFC 4254 sec 5.2) and the caller must fail the channel. The window is left untouched on failure. Definition at line 23 of file ssh_flow_control.cpp.
References SshFlow::local_window.
Referenced by pc_ssh_channel_handle_data().
| bool pc_ssh_flow_replenish_due | ( | const SshFlow * | f, |
| uint32_t * | add | ||
| ) |
Decide whether a WINDOW_ADJUST is due, and for how much. Does not mutate.
Replenishes once the window has drained past half, which keeps a bulk transfer from stalling without emitting an adjust per packet.
Pair it with pc_ssh_flow_local_credit() only after the adjust has actually gone out. Deciding and crediting are separate because on some paths the send can fail, and crediting first would leave us believing we advertised bytes the peer never heard about - the peer then stops at its smaller window while we wait for data, and the transfer deadlocks.
*add receives the delta to advertise. Definition at line 33 of file ssh_flow_control.cpp.
References SshFlow::local_max, and SshFlow::local_window.
Referenced by pc_ssh_channel_handle_data().
| void pc_ssh_flow_local_credit | ( | SshFlow * | f, |
| uint32_t | add | ||
| ) |
Credit our window by add, once that WINDOW_ADJUST has actually been sent.
Definition at line 43 of file ssh_flow_control.cpp.
References SshFlow::local_window.
Referenced by pc_ssh_channel_handle_data().
| bool pc_ssh_flow_send_allows | ( | const SshFlow * | f, |
| size_t | len | ||
| ) |
True if len bytes fit both the peer's remaining window and its maximum packet size.
Definition at line 48 of file ssh_flow_control.cpp.
References SshFlow::peer_max_pkt, and SshFlow::peer_window.
Referenced by pc_ssh_sig_build_data().
| uint32_t pc_ssh_flow_send_cap | ( | const SshFlow * | f, |
| uint32_t | want | ||
| ) |
Clamp a would-be send to what the peer currently permits.
A producer that pulls from a local source sizes its read to this, so it never reads bytes it cannot legally forward. Returns 0 when the window is closed, which the caller treats as "stop pumping until a WINDOW_ADJUST arrives".
want, peer window, peer maximum packet size). Definition at line 53 of file ssh_flow_control.cpp.
References SshFlow::peer_max_pkt, and SshFlow::peer_window.
| void pc_ssh_flow_send_take | ( | SshFlow * | f, |
| uint32_t | n | ||
| ) |
Account n outbound bytes against the peer's window (call only after send_allows()).
Definition at line 67 of file ssh_flow_control.cpp.
References SshFlow::peer_window.
Referenced by pc_ssh_sig_build_data().
| void pc_ssh_flow_peer_add | ( | SshFlow * | f, |
| uint32_t | add | ||
| ) |
Credit the peer's window from an inbound WINDOW_ADJUST.
Saturates at UINT32_MAX rather than wrapping: a peer advertising a total past 2^32 is out of spec, and wrapping would hand us a tiny window and stall the transfer.
Definition at line 72 of file ssh_flow_control.cpp.
References SshFlow::peer_window.
Referenced by pc_ssh_channel_handle_open_confirm(), and pc_ssh_channel_handle_window_adjust().
| uint32_t pc_ssh_flow_peer_window | ( | const SshFlow * | f | ) |
Bytes we may still send the peer - the bound a producer sizes its next read to.
Definition at line 78 of file ssh_flow_control.cpp.
References SshFlow::peer_window.
| int32_t pc_ssh_sig_build_open_failure | ( | uint8_t * | out, |
| size_t | cap, | ||
| uint32_t | peer_id, | ||
| uint32_t | reason, | ||
| size_t * | out_len | ||
| ) |
CHANNEL_OPEN_FAILURE. reason: 1 admin-prohibited, 2 connect-failed, 3 unknown-type, 4 resource.
Definition at line 87 of file ssh_flow_control.cpp.
References pc_wr32be(), and SSH_MSG_CHANNEL_OPEN_FAILURE.
| int32_t pc_ssh_sig_build_open_confirm | ( | const SshFlow * | f, |
| uint32_t | peer_id, | ||
| uint32_t | local_id, | ||
| uint8_t * | out, | ||
| size_t | cap, | ||
| size_t * | out_len | ||
| ) |
CHANNEL_OPEN_CONFIRMATION, advertising our current window and maximum packet size.
Definition at line 102 of file ssh_flow_control.cpp.
References SshFlow::local_window, pc_wr32be(), SSH_CHAN_MAX_PACKET, and SSH_MSG_CHANNEL_OPEN_CONFIRM.
| int32_t pc_ssh_sig_build_data | ( | SshFlow * | f, |
| uint32_t | peer_id, | ||
| const uint8_t * | data, | ||
| size_t | len, | ||
| uint8_t * | out, | ||
| size_t | cap, | ||
| size_t * | out_len | ||
| ) |
CHANNEL_DATA carrying len bytes, and account them against the peer's window.
Refuses when the send would exceed the peer's window or its maximum packet size, so the RFC 4254 sec 5.2 limit cannot be violated by any caller - the check and the debit are one step here.
Definition at line 118 of file ssh_flow_control.cpp.
References pc_ssh_flow_send_allows(), pc_ssh_flow_send_take(), pc_wr32be(), and SSH_MSG_CHANNEL_DATA.
Referenced by pc_ssh_channel_build_data().
| int32_t pc_ssh_sig_build_window_adjust | ( | uint32_t | peer_id, |
| uint32_t | add, | ||
| uint8_t * | out, | ||
| size_t | cap, | ||
| size_t * | out_len | ||
| ) |
CHANNEL_WINDOW_ADJUST granting add more bytes. Credit the window only once this is sent.
Definition at line 138 of file ssh_flow_control.cpp.
References pc_wr32be(), and SSH_MSG_CHANNEL_WINDOW_ADJUST.
| int32_t pc_ssh_sig_build_close | ( | uint32_t | peer_id, |
| uint8_t * | out, | ||
| size_t | cap, | ||
| size_t * | out_len | ||
| ) |
CHANNEL_EOF followed by CHANNEL_CLOSE, as one 10-byte pair.
Definition at line 151 of file ssh_flow_control.cpp.
References pc_wr32be(), SSH_MSG_CHANNEL_CLOSE, and SSH_MSG_CHANNEL_EOF.