diff --git a/impl/src/layer2/connection.c b/impl/src/layer2/connection.c index a9879c7..c5a8f0a 100644 --- a/impl/src/layer2/connection.c +++ b/impl/src/layer2/connection.c @@ -84,7 +84,7 @@ void connection_setup_incoming(connection_ctx_t *ctx) } -result_t connection_handle_packet(connection_ctx_t *ctx, const uint8_t *buf, size_t buf_len, layer2_data_packet_t *data_packet) +result_t connection_handle_packet(connection_ctx_t *ctx, const uint8_t *buf, size_t buf_len, layer2_data_packet_t *data_packet, bool *tx_req_rcvd) { // check the connection state switch(ctx->conn_state) { @@ -144,7 +144,7 @@ result_t connection_handle_packet(connection_ctx_t *ctx, const uint8_t *buf, siz const uint8_t *payload = buf + header_size; size_t payload_len = packet_size - header_size; - return connection_handle_packet_prechecked(ctx, &header, payload, payload_len, data_packet); + return connection_handle_packet_prechecked(ctx, &header, payload, payload_len, data_packet, tx_req_rcvd); } static result_t handle_conn_mgmt( @@ -205,7 +205,8 @@ result_t connection_handle_packet_prechecked( connection_ctx_t *ctx, const layer2_packet_header_t *header, const uint8_t *payload, size_t payload_len, - layer2_data_packet_t *data_packet) + layer2_data_packet_t *data_packet, + bool *tx_req_rcvd) { data_packet->payload_type = L2_PAYLOAD_TYPE_INVALID; data_packet->payload_len = 0; @@ -243,11 +244,14 @@ result_t connection_handle_packet_prechecked( ctx->last_acked_seq = header->rx_seq_nr; + *tx_req_rcvd = false; switch(header->msg_type) { case L2_MSG_TYPE_EMPTY: LOG(LVL_DEBUG, "Empty packet: accepted ACK for %u.", ctx->last_acked_seq); + *tx_req_rcvd = header->tx_request; + // empty packets also reset the timeout timer ctx->last_rx_time = get_hires_time(); @@ -263,6 +267,7 @@ result_t connection_handle_packet_prechecked( return OK; case L2_MSG_TYPE_DATA: + *tx_req_rcvd = header->tx_request; break; default: diff --git a/impl/src/layer2/connection.h b/impl/src/layer2/connection.h index ea9ac8e..d13fb04 100644 --- a/impl/src/layer2/connection.h +++ b/impl/src/layer2/connection.h @@ -89,13 +89,15 @@ void connection_setup_incoming(connection_ctx_t *ctx); * \param[in] buf Pointer to the packet data. * \param[in] buf_len Length of the packet. * \param[out] data_packet Structure will be filled with a received data packet. + * \param[out] tx_req_rcvd Was the tx_request flag set in the decoded packet. * \returns A result code from the packet handling procedure. */ result_t connection_handle_packet( connection_ctx_t *ctx, const uint8_t *buf, size_t buf_len, - layer2_data_packet_t *data_packet); + layer2_data_packet_t *data_packet, + bool *tx_req_rcvd); /*!\brief Handle a received packet where the header has already been decoded. * @@ -109,13 +111,15 @@ result_t connection_handle_packet( * \param[in] payload Pointer to the payload data. * \param[in] payload_len Length of the payload data. * \param[out] data_packet Structure will be filled with a received data packet. + * \param[out] tx_req_rcvd Was the tx_request flag set in the decoded packet. * \returns A result code from the packet handling procedure. */ result_t connection_handle_packet_prechecked( connection_ctx_t *ctx, const layer2_packet_header_t *header, const uint8_t *payload, size_t payload_len, - layer2_data_packet_t *data_packet); + layer2_data_packet_t *data_packet, + bool *tx_req_rcvd); /*!\brief Return the sequence number expected next by our side. */ diff --git a/impl/src/layer2/digipeater.c b/impl/src/layer2/digipeater.c index 97f4005..47a9327 100644 --- a/impl/src/layer2/digipeater.c +++ b/impl/src/layer2/digipeater.c @@ -158,8 +158,9 @@ result_t digipeater_handle_packet( connection_list_entry_t *head = connection_list_get_head(&ctx->conn_list); if(head) { connection_ctx_t *current_conn = &head->connection; + bool tx_request_received = false; result = connection_handle_packet_prechecked( - current_conn, &header, payload, payload_len, data_packet); + current_conn, &header, payload, payload_len, data_packet, &tx_request_received); } else { LOG(LVL_WARN, "Digipeater in CONN state, but there is no active connection! Packet dropped."); result = OK; diff --git a/impl/test/layer2_over_udp/l2udptest_client.c b/impl/test/layer2_over_udp/l2udptest_client.c index 2a046f4..5a5e681 100644 --- a/impl/test/layer2_over_udp/l2udptest_client.c +++ b/impl/test/layer2_over_udp/l2udptest_client.c @@ -141,7 +141,8 @@ result_t connect_to_digipeater(connection_ctx_t *conn) } layer2_data_packet_t data_packet; - result_t err_code = connection_handle_packet(conn, packetbuf, ret, &data_packet); + bool tx_request_received = false; + result_t err_code = connection_handle_packet(conn, packetbuf, ret, &data_packet, &tx_request_received); switch(err_code) { case OK: @@ -287,14 +288,6 @@ int main(void) RESULT_CHECK(connect_to_digipeater(&l2conn)); while(m_running) { - 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)) { int ret = poll(&pfd_tun, 1, 0 /* timeout */); @@ -376,10 +369,17 @@ int main(void) LOG(LVL_DEBUG, "Burst finished: %zd packets sent.", burst_len); } - // make sure the receiver runs for a minimum amount of time - block_tx_for(TX_SWITCH_BACKOFF_AFTER_RX_ON_MS); + bool may_tx = false; + while(!may_tx) { + connection_evt_t evt; + RESULT_CHECK(connection_maintain(&l2conn, &evt)); + + if(evt == CONN_EVT_TIMEOUT) { + LOG(LVL_ERR, "Connection timed out. Shutting down."); + m_running = false; + break; + } - while(get_hires_time() < next_tx_switch_time) { // ** Receive signal ** int ret = poll(&pfd_bcast, 1, 10); @@ -406,7 +406,9 @@ int main(void) layer2_data_packet_t data_packet; - result_t result = connection_handle_packet(&l2conn, packetbuf, ret, &data_packet); + bool tx_request_received = false; + result_t result = connection_handle_packet(&l2conn, packetbuf, ret, &data_packet, &tx_request_received); + may_tx = may_tx || tx_request_received; switch(result) { case OK: m_rx_stats.successful_decodes++; @@ -456,6 +458,9 @@ int main(void) fprintf(stderr, "r"); } + + // give the other side some time to switch to rx + sleep_until(next_tx_switch_time); } // ** Cleanup **