53 lines
1.6 KiB
C
53 lines
1.6 KiB
C
#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;
|
|
}
|
|
}
|
|
|
|
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->pending = false;
|
|
} else {
|
|
sender->pending = was_pending;
|
|
}
|
|
return status;
|
|
}
|