WIP: digipeater module managing multiple connections
Backup commit. This is a basic setup with lots of TODOs and errors. Will not compile yet.
This commit is contained in:
parent
8572018c4e
commit
6e303e8aed
122
impl/src/layer2/digipeater.c
Normal file
122
impl/src/layer2/digipeater.c
Normal file
|
@ -0,0 +1,122 @@
|
|||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "digipeater.h"
|
||||
|
||||
#include "config.h"
|
||||
#include "layer2/connection.h"
|
||||
#include "layer2/ham64.h"
|
||||
#include "results.h"
|
||||
#include "utils.h"
|
||||
|
||||
result_t digipeater_init(digipeater_ctx_t *ctx, const ham64_t *my_addr, digipeater_data_callback_t data_cb)
|
||||
{
|
||||
ctx->my_addr = *my_addr;
|
||||
ctx->data_cb = data_cb;
|
||||
|
||||
ctx->state = DIGIPEATER_STATE_CONN;
|
||||
|
||||
uint64_t now = get_hires_time();
|
||||
ctx->next_beacon_time = now + HRTIME_MS(BEACON_INTERVAL_MS);
|
||||
|
||||
return connection_list_init(&ctx->conn_list);
|
||||
}
|
||||
|
||||
|
||||
void digipeater_destroy(digipeater_ctx_t *ctx)
|
||||
{
|
||||
connection_list_destroy(&ctx->conn_list);
|
||||
}
|
||||
|
||||
|
||||
result_t digipeater_handle_packet(digipeater_ctx_t *ctx, const uint8_t *buf, size_t buf_len)
|
||||
{
|
||||
// check the CRC
|
||||
size_t packet_size = buf_len - crc_sizeof_key(PAYLOAD_CRC_SCHEME);
|
||||
|
||||
if(!crc_check_key(PAYLOAD_CRC_SCHEME, (unsigned char*)buf, packet_size)) {
|
||||
LOG(LVL_ERR, "CRC check failed!");
|
||||
return ERR_INTEGRITY;
|
||||
}
|
||||
|
||||
// decode the header
|
||||
layer2_packet_header_t header;
|
||||
|
||||
if(!layer2_decode_packet_header(buf, buf_len, &header)) {
|
||||
LOG(LVL_ERR, "Header could not be decoded!");
|
||||
return ERR_INTEGRITY;
|
||||
}
|
||||
|
||||
layer2_dump_packet_header(LVL_DUMP, &header);
|
||||
|
||||
// check if the packet really should be handled by us
|
||||
if(ham64_is_equal(&ctx->my_addr, &header.src_addr)) {
|
||||
LOG(LVL_DEBUG, "Packet is from ourselves. Ignored.");
|
||||
return OK;
|
||||
}
|
||||
|
||||
if(!ham64_is_equal(&header.dst_addr, &ctx->my_addr)) {
|
||||
char fmt_dst_addr[HAM64_FMT_MAX_LEN];
|
||||
char fmt_my_addr[HAM64_FMT_MAX_LEN];
|
||||
|
||||
ham64_format(&header.dst_addr, fmt_dst_addr);
|
||||
ham64_format(&ctx->my_addr, fmt_my_addr);
|
||||
|
||||
LOG(LVL_ERR, "Packet has the wrong destination address: got %s, expected %s",
|
||||
fmt_dst_addr, fmt_my_addr);
|
||||
|
||||
return ERR_INVALID_ADDRESS;
|
||||
}
|
||||
|
||||
// FIXME: handle connection management packets here
|
||||
// FIXME: handle data and empty packets in the current connection
|
||||
|
||||
size_t header_size = layer2_get_encoded_header_size(&header);
|
||||
|
||||
const uint8_t *payload = buf + header_size;
|
||||
size_t payload_len = packet_size - header_size;
|
||||
|
||||
connection_handle_packet_prechecked(current_conn, &header, payload, payload_len);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
size_t digipeater_encode_next_packet(digipeater_ctx_t *ctx, uint8_t *buf, size_t buf_len, bool *end_burst)
|
||||
{
|
||||
uint64_t now = get_hires_time();
|
||||
|
||||
*end_burst = false;
|
||||
|
||||
if(now > ctx->next_beacon_time) {
|
||||
// TODO: build a beacon packet
|
||||
return 0;
|
||||
}
|
||||
|
||||
// TODO: pull packets from the current connection
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
bool digipeater_can_transmit(const digipeater_ctx_t *ctx)
|
||||
{
|
||||
uint64_t now = get_hires_time();
|
||||
|
||||
if(now > ctx->next_beacon_time) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: also true if next TX time has expired and there are packets waiting for this connection.
|
||||
|
||||
/*return (packet_queue_get_used_space(&ctx->packet_queue) != 0)
|
||||
&& (packet_queue_get(&ctx->packet_queue, ctx->next_packet_index) != NULL); */
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
result_t digipeater_maintain(digipeater_ctx_t *ctx)
|
||||
{
|
||||
(void)ctx;
|
||||
return OK;
|
||||
}
|
94
impl/src/layer2/digipeater.h
Normal file
94
impl/src/layer2/digipeater.h
Normal file
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* This file contains functions to handle a single layer 2 digipeater.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* Copyright (C) 2024 Thomas Kolb
|
||||
*/
|
||||
|
||||
#ifndef DIGIPEATER_H
|
||||
#define DIGIPEATER_H
|
||||
|
||||
#include <results.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "connection_list.h"
|
||||
|
||||
struct digipeater_ctx_s;
|
||||
|
||||
typedef enum {
|
||||
DIGIPEATER_STATE_BEACON, //!< Beacon sent, waiting for connection requests
|
||||
DIGIPEATER_STATE_CONN, //!< Handling client connections
|
||||
} digipeater_state_t;
|
||||
|
||||
/*!\brief Type for a callback function that is called when a data packet was received. */
|
||||
typedef void (*digipeater_data_callback_t)(struct digipeater_ctx_s *conn, const uint8_t *data, size_t len);
|
||||
|
||||
typedef struct digipeater_ctx_s {
|
||||
digipeater_state_t state; //!< Current operating state
|
||||
|
||||
digipeater_data_callback_t data_cb; //!< Callback function for received data packets.
|
||||
|
||||
ham64_t my_addr; //!< The local link layer address.
|
||||
|
||||
uint64_t next_beacon_time; //!< Absolute timestamp of the next beacon transmission.
|
||||
|
||||
connection_list_t conn_list; //!< List of connections.
|
||||
} digipeater_ctx_t;
|
||||
|
||||
|
||||
/*!\brief Initialize the digipeater context.
|
||||
*
|
||||
* \param ctx The digipeater context to initialize.
|
||||
* \param my_addr The local link layer address.
|
||||
* \param data_cb Callback function that handles received (decoded) data packets.
|
||||
* \returns OK if everything worked or a fitting error code.
|
||||
*/
|
||||
result_t digipeater_init(
|
||||
digipeater_ctx_t *ctx,
|
||||
const ham64_t *my_addr,
|
||||
digipeater_data_callback_t data_cb);
|
||||
|
||||
/*!\brief Destroy the given digipeater context.
|
||||
*/
|
||||
void digipeater_destroy(digipeater_ctx_t *ctx);
|
||||
|
||||
/*!\brief Handle a received packet.
|
||||
*
|
||||
* \param ctx The digipeater context.
|
||||
* \param buf Pointer to the packet data.
|
||||
* \param buf_len Length of the packet.
|
||||
* \returns A result code from the packet handling procedure.
|
||||
*/
|
||||
result_t digipeater_handle_packet(digipeater_ctx_t *ctx, const uint8_t *buf, size_t buf_len);
|
||||
|
||||
/*!\brief Enqueue a packet for transmission.
|
||||
* \param ctx The digipeater context.
|
||||
* \param tun_fd File descriptor for an open TUN device.
|
||||
*/
|
||||
result_t digipeater_fill_packet_queues_from_tundev(digipeater_ctx_t *ctx, int tun_fd);
|
||||
|
||||
/*!\brief Encode the next packet for transmission.
|
||||
*
|
||||
* \note
|
||||
* If no packets are currently available for transmission, this function returns zero.
|
||||
*
|
||||
* \param ctx The digipeater context.
|
||||
* \param buf Where to write the encoded packet data.
|
||||
* \param buf_len Space available in the buffer.
|
||||
* \param end_burst Set to true if this packet should end the current burst and start the transmission.
|
||||
* \returns The number of bytes written to buf or zero if no packet was available.
|
||||
*/
|
||||
size_t digipeater_encode_next_packet(digipeater_ctx_t *ctx, uint8_t *buf, size_t buf_len, bool *end_burst);
|
||||
|
||||
/*!\brief Check if there are packets queued for transmission.
|
||||
*/
|
||||
bool digipeater_can_transmit(const digipeater_ctx_t *ctx);
|
||||
|
||||
/*!\brief Handle internal maintenance tasks.
|
||||
*
|
||||
* This should be called periodically to handle timeouts and retransmissions.
|
||||
*/
|
||||
result_t digipeater_maintain(digipeater_ctx_t *ctx);
|
||||
|
||||
#endif // DIGIPEATER_H
|
Loading…
Reference in a new issue