#include "trikke_transport.h" static bool status_is_valid(trikke_transport_status_t status) { return status >= TRIKKE_TRANSPORT_COMPLETE && status <= TRIKKE_TRANSPORT_FATAL; } void trikke_transport_sender_init(trikke_transport_sender_t *sender) { if (sender != NULL) { sender->pending = false; sender->begin_retry_count = 0; } } trikke_transport_status_t trikke_transport_sender_step( trikke_transport_sender_t *sender, const trikke_transport_t *transport, const uint8_t *packet, size_t packet_size) { if (sender == NULL || transport == NULL || transport->begin == NULL || transport->poll == NULL || packet == NULL || packet_size == 0) { return TRIKKE_TRANSPORT_FATAL; } const bool was_pending = sender->pending; const trikke_transport_status_t status = was_pending ? transport->poll(transport->context) : transport->begin(transport->context, packet, packet_size); if (!status_is_valid(status)) { sender->pending = was_pending; return TRIKKE_TRANSPORT_FATAL; } if (status == TRIKKE_TRANSPORT_PENDING) { sender->pending = true; } else if (status == TRIKKE_TRANSPORT_COMPLETE) { sender->pending = false; } else if (status == TRIKKE_TRANSPORT_RETRY) { if (was_pending) { // Once accepted, generic transport code cannot prove that retrying // the whole frame is duplicate-safe. Fail closed and keep ownership. sender->pending = true; return TRIKKE_TRANSPORT_FATAL; } ++sender->begin_retry_count; sender->pending = false; } else { sender->pending = was_pending; } return status; }