layer2: Remove event callbacks

Instead, connection and digipeater now update a event code passed by reference
to the maintain() function. This was the only place where the callback was
called before.

Minor side effect: maintain must be called multiple times if multiple events
trigger at the same time.
This commit is contained in:
Thomas Kolb 2024-12-03 22:18:46 +01:00
parent 49dacffde1
commit a0ccf9699a
5 changed files with 33 additions and 49 deletions

View file

@ -18,9 +18,7 @@
result_t connection_init( result_t connection_init(
connection_ctx_t *ctx, connection_ctx_t *ctx,
const ham64_t *my_addr, const ham64_t *my_addr,
const ham64_t *peer_addr, const ham64_t *peer_addr)
connection_event_callback_t event_cb,
void *user_ctx)
{ {
ctx->last_acked_seq = 0; ctx->last_acked_seq = 0;
ctx->next_expected_seq = 0; ctx->next_expected_seq = 0;
@ -32,14 +30,10 @@ result_t connection_init(
ctx->my_addr = *my_addr; ctx->my_addr = *my_addr;
ctx->peer_addr = *peer_addr; ctx->peer_addr = *peer_addr;
ctx->event_cb = event_cb;
uint64_t now = get_hires_time(); uint64_t now = get_hires_time();
ctx->last_rx_time = now; ctx->last_rx_time = now;
ctx->retransmit_time = 0; ctx->retransmit_time = 0;
ctx->user_context = user_ctx;
// calculate IPv6 address // calculate IPv6 address
struct in6_addr net_addr; struct in6_addr net_addr;
inet_pton(AF_INET6, IPV6_NET, &net_addr); inet_pton(AF_INET6, IPV6_NET, &net_addr);
@ -518,14 +512,14 @@ bool connection_is_closed(const connection_ctx_t *ctx)
} }
result_t connection_maintain(connection_ctx_t *ctx) result_t connection_maintain(connection_ctx_t *ctx, connection_evt_t *evt)
{ {
uint64_t now = get_hires_time(); uint64_t now = get_hires_time();
if(now > ctx->last_rx_time + HRTIME_MS(CONNECTION_TIMEOUT_MS)) { if(now > ctx->last_rx_time + HRTIME_MS(CONNECTION_TIMEOUT_MS)) {
LOG(LVL_INFO, "Connection timed out."); LOG(LVL_INFO, "Connection timed out.");
ctx->conn_state = CONN_STATE_CLOSED; ctx->conn_state = CONN_STATE_CLOSED;
ctx->event_cb(ctx, CONN_EVT_TIMEOUT, ctx->user_context); *evt = CONN_EVT_TIMEOUT;
return OK; return OK;
} }
@ -533,7 +527,8 @@ result_t connection_maintain(connection_ctx_t *ctx)
LOG(LVL_INFO, "Retransmit triggered."); LOG(LVL_INFO, "Retransmit triggered.");
ctx->retransmit_time = 0; ctx->retransmit_time = 0;
connection_restart_tx(ctx); connection_restart_tx(ctx);
ctx->event_cb(ctx, CONN_EVT_RETRANSMIT, ctx->user_context); *evt = CONN_EVT_RETRANSMIT;
return OK;
} }
return OK; return OK;

View file

@ -27,18 +27,14 @@ typedef enum {
} connection_state_t; } connection_state_t;
typedef enum { typedef enum {
CONN_EVT_NONE, //!< No event has occurred
CONN_EVT_TIMEOUT, //!< The connection timed out because no packets were received CONN_EVT_TIMEOUT, //!< The connection timed out because no packets were received
CONN_EVT_RETRANSMIT, //!< Packet queue transmission is restarted CONN_EVT_RETRANSMIT, //!< Packet queue transmission is restarted
} connection_evt_t; } connection_evt_t;
/*!\brief Type for a callback function that is called on various connection events. */
typedef void (*connection_event_callback_t)(struct connection_ctx_s *conn, connection_evt_t evt, void *user_ctx);
typedef struct connection_ctx_s { typedef struct connection_ctx_s {
connection_state_t conn_state; //!< State of the connection. connection_state_t conn_state; //!< State of the connection.
connection_event_callback_t event_cb; //!< Callback function for event signalling.
ham64_t my_addr; //!< The local link layer address. ham64_t my_addr; //!< The local link layer address.
ham64_t peer_addr; //!< The link layer address of the peer. ham64_t peer_addr; //!< The link layer address of the peer.
@ -54,8 +50,6 @@ typedef struct connection_ctx_s {
uint64_t retransmit_time; //!< Time when a retransmit shall be triggered. uint64_t retransmit_time; //!< Time when a retransmit shall be triggered.
uint64_t last_rx_time; //!< Time when a packet was last received and decoded. uint64_t last_rx_time; //!< Time when a packet was last received and decoded.
void *user_context; //!< An arbitrary pointer that can set by the user.
} connection_ctx_t; } connection_ctx_t;
@ -64,16 +58,12 @@ typedef struct connection_ctx_s {
* \param ctx The connection context to initialize. * \param ctx The connection context to initialize.
* \param my_addr The local link layer address. * \param my_addr The local link layer address.
* \param peer_addr The remote link layer address. * \param peer_addr The remote link layer address.
* \param event_cb Callback for connection events.
* \param user_ctx User context pointer (for arbitrary data).
* \returns OK if everything worked or a fitting error code. * \returns OK if everything worked or a fitting error code.
*/ */
result_t connection_init( result_t connection_init(
connection_ctx_t *ctx, connection_ctx_t *ctx,
const ham64_t *my_addr, const ham64_t *my_addr,
const ham64_t *peer_addr, const ham64_t *peer_addr);
connection_event_callback_t event_cb,
void *user_ctx);
/*!\brief Destroy the given layer 2 connection context. /*!\brief Destroy the given layer 2 connection context.
*/ */
@ -189,8 +179,11 @@ bool connection_is_closed(const connection_ctx_t *ctx);
/*!\brief Handle internal maintenance tasks. /*!\brief Handle internal maintenance tasks.
* *
* This should be called periodically to handle timeouts and retransmissions. * This should be called periodically to handle timeouts and retransmissions.
*
* \param ctx[in] The connection context.
* \param evt[out] Set to an event that occurred, or CONN_EVT_NONE.
*/ */
result_t connection_maintain(connection_ctx_t *ctx); result_t connection_maintain(connection_ctx_t *ctx, connection_evt_t *evt);
/*!\brief Check if the given IPv6 peer address belongs to this connection. /*!\brief Check if the given IPv6 peer address belongs to this connection.
* *

View file

@ -17,23 +17,6 @@
#include "results.h" #include "results.h"
#include "utils.h" #include "utils.h"
void conn_event_cb(struct connection_ctx_s *conn, connection_evt_t evt, void *user_ctx)
{
(void)conn;
digipeater_ctx_t *digi_ctx = user_ctx;
switch(evt) {
case CONN_EVT_TIMEOUT:
// connection has been closed by timeout -> clean up the list
connection_list_delete_closed(&digi_ctx->conn_list);
break;
default:
// do nothing
break;
}
}
static result_t digipeater_handle_beacon_responses(digipeater_ctx_t *ctx, const layer2_packet_header_t *header, const uint8_t *buf, size_t buf_len) static result_t digipeater_handle_beacon_responses(digipeater_ctx_t *ctx, const layer2_packet_header_t *header, const uint8_t *buf, size_t buf_len)
{ {
LOG(LVL_DEBUG, "Handling beacon response packet."); LOG(LVL_DEBUG, "Handling beacon response packet.");
@ -60,7 +43,7 @@ static result_t digipeater_handle_beacon_responses(digipeater_ctx_t *ctx, const
// and add it at the beginning of the connection list. // and add it at the beginning of the connection list.
connection_ctx_t new_conn; connection_ctx_t new_conn;
ERR_CHECK(connection_init(&new_conn, &ctx->my_addr, &header->src_addr, conn_event_cb, ctx)); ERR_CHECK(connection_init(&new_conn, &ctx->my_addr, &header->src_addr));
ERR_CHECK(connection_send_parameters(&new_conn)); ERR_CHECK(connection_send_parameters(&new_conn));
@ -369,7 +352,19 @@ result_t digipeater_maintain(digipeater_ctx_t *ctx)
LOG(LVL_INFO, "No active connection -> force beacon state for packet handling."); LOG(LVL_INFO, "No active connection -> force beacon state for packet handling.");
ctx->state = DIGIPEATER_STATE_BEACON; ctx->state = DIGIPEATER_STATE_BEACON;
} else { } else {
ERR_CHECK(connection_maintain(&head->connection)); connection_evt_t evt;
ERR_CHECK(connection_maintain(&head->connection, &evt));
switch(evt) {
case CONN_EVT_TIMEOUT:
// connection has been closed by timeout -> clean up the list
connection_list_delete_closed(&ctx->conn_list);
break;
default:
// do nothing
break;
}
} }
break; break;
} }

View file

@ -26,14 +26,9 @@ typedef enum {
DIGIPEATER_EVT_INTERVAL_END, //!< The current cycle has ended and new packets should be transmitted. DIGIPEATER_EVT_INTERVAL_END, //!< The current cycle has ended and new packets should be transmitted.
} digipeater_evt_t; } digipeater_evt_t;
/*!\brief Type for a callback function that is called when certain events occur. */
typedef void (*digipeater_evt_callback_t)(struct digipeater_ctx_s *digi, digipeater_evt_t evt);
typedef struct digipeater_ctx_s { typedef struct digipeater_ctx_s {
digipeater_state_t state; //!< Current operating state digipeater_state_t state; //!< Current operating state
digipeater_evt_callback_t event_cb; //!< Callback function for events.
ham64_t my_addr; //!< The local link layer address. ham64_t my_addr; //!< The local link layer address.
packet_queue_t oneshot_queue; //!< Queue for packets that are sent once and connection-independent packet_queue_t oneshot_queue; //!< Queue for packets that are sent once and connection-independent

View file

@ -161,7 +161,7 @@ int main(int argc, char **argv)
ham64_t my_address, peer_address; ham64_t my_address, peer_address;
ham64_encode(MY_CALL, &my_address); ham64_encode(MY_CALL, &my_address);
ham64_encode(PEER_CALL, &peer_address); ham64_encode(PEER_CALL, &peer_address);
RESULT_CHECK(connection_init(&l2conn, &my_address, &peer_address, conn_evt_cb, NULL)); RESULT_CHECK(connection_init(&l2conn, &my_address, &peer_address));
// force connection into the established state // force connection into the established state
l2conn.conn_state = CONN_STATE_ESTABLISHED; l2conn.conn_state = CONN_STATE_ESTABLISHED;
@ -232,7 +232,13 @@ int main(int argc, char **argv)
while(m_running) { while(m_running) {
uint64_t now = get_hires_time(); uint64_t now = get_hires_time();
RESULT_CHECK(connection_maintain(&l2conn)); connection_evt_t evt;
RESULT_CHECK(connection_maintain(&l2conn, &evt));
if(evt == CONN_EVT_TIMEOUT) {
LOG(LVL_ERR, "Connection timed out. Shutting down.");
break;
}
// fill the TX queue from the TUN device // fill the TX queue from the TUN device
while(connection_can_enqueue_packet(&l2conn)) { while(connection_can_enqueue_packet(&l2conn)) {