diff --git a/impl/src/layer2/connection.c b/impl/src/layer2/connection.c index 059ac00..e6ee834 100644 --- a/impl/src/layer2/connection.c +++ b/impl/src/layer2/connection.c @@ -18,9 +18,7 @@ result_t connection_init( connection_ctx_t *ctx, const ham64_t *my_addr, - const ham64_t *peer_addr, - connection_event_callback_t event_cb, - void *user_ctx) + const ham64_t *peer_addr) { ctx->last_acked_seq = 0; ctx->next_expected_seq = 0; @@ -32,14 +30,10 @@ result_t connection_init( ctx->my_addr = *my_addr; ctx->peer_addr = *peer_addr; - ctx->event_cb = event_cb; - uint64_t now = get_hires_time(); ctx->last_rx_time = now; ctx->retransmit_time = 0; - ctx->user_context = user_ctx; - // calculate IPv6 address struct in6_addr 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(); if(now > ctx->last_rx_time + HRTIME_MS(CONNECTION_TIMEOUT_MS)) { LOG(LVL_INFO, "Connection timed out."); ctx->conn_state = CONN_STATE_CLOSED; - ctx->event_cb(ctx, CONN_EVT_TIMEOUT, ctx->user_context); + *evt = CONN_EVT_TIMEOUT; return OK; } @@ -533,7 +527,8 @@ result_t connection_maintain(connection_ctx_t *ctx) LOG(LVL_INFO, "Retransmit triggered."); ctx->retransmit_time = 0; connection_restart_tx(ctx); - ctx->event_cb(ctx, CONN_EVT_RETRANSMIT, ctx->user_context); + *evt = CONN_EVT_RETRANSMIT; + return OK; } return OK; diff --git a/impl/src/layer2/connection.h b/impl/src/layer2/connection.h index a577ce8..410c0bc 100644 --- a/impl/src/layer2/connection.h +++ b/impl/src/layer2/connection.h @@ -27,18 +27,14 @@ typedef enum { } connection_state_t; typedef enum { + CONN_EVT_NONE, //!< No event has occurred CONN_EVT_TIMEOUT, //!< The connection timed out because no packets were received CONN_EVT_RETRANSMIT, //!< Packet queue transmission is restarted } 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 { 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 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 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; @@ -64,16 +58,12 @@ typedef struct connection_ctx_s { * \param ctx The connection context to initialize. * \param my_addr The local 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. */ result_t connection_init( connection_ctx_t *ctx, const ham64_t *my_addr, - const ham64_t *peer_addr, - connection_event_callback_t event_cb, - void *user_ctx); + const ham64_t *peer_addr); /*!\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. * * 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. * diff --git a/impl/src/layer2/digipeater.c b/impl/src/layer2/digipeater.c index 1635dd2..1da927d 100644 --- a/impl/src/layer2/digipeater.c +++ b/impl/src/layer2/digipeater.c @@ -17,23 +17,6 @@ #include "results.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) { 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. 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)); @@ -369,7 +352,19 @@ result_t digipeater_maintain(digipeater_ctx_t *ctx) LOG(LVL_INFO, "No active connection -> force beacon state for packet handling."); ctx->state = DIGIPEATER_STATE_BEACON; } 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; } diff --git a/impl/src/layer2/digipeater.h b/impl/src/layer2/digipeater.h index 4536fb0..4075b71 100644 --- a/impl/src/layer2/digipeater.h +++ b/impl/src/layer2/digipeater.h @@ -26,14 +26,9 @@ typedef enum { DIGIPEATER_EVT_INTERVAL_END, //!< The current cycle has ended and new packets should be transmitted. } 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 { 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. packet_queue_t oneshot_queue; //!< Queue for packets that are sent once and connection-independent diff --git a/impl/test/layer2_over_udp/l2udptest_client.c b/impl/test/layer2_over_udp/l2udptest_client.c index e18ceb2..5f86ff8 100644 --- a/impl/test/layer2_over_udp/l2udptest_client.c +++ b/impl/test/layer2_over_udp/l2udptest_client.c @@ -161,7 +161,7 @@ int main(int argc, char **argv) ham64_t my_address, peer_address; ham64_encode(MY_CALL, &my_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 l2conn.conn_state = CONN_STATE_ESTABLISHED; @@ -232,7 +232,13 @@ int main(int argc, char **argv) while(m_running) { 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 while(connection_can_enqueue_packet(&l2conn)) {