From 27e0133d40f7b328482b501a18e22b12a55564ea Mon Sep 17 00:00:00 2001 From: Star Rauchenberger Date: Sun, 13 Jul 2025 10:07:59 -0400 Subject: Associate --- src/retransmit.c | 169 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 src/retransmit.c (limited to 'src/retransmit.c') diff --git a/src/retransmit.c b/src/retransmit.c new file mode 100644 index 0000000..44f609c --- /dev/null +++ b/src/retransmit.c @@ -0,0 +1,169 @@ +#include "retransmit.h" + +#include +#include +#include +#include +#include + +#include "transmit.h" + +static pthread_mutex_t retransmitter_mutex = PTHREAD_MUTEX_INITIALIZER; + +void ack_map_init(struct ack_map *map) +{ + map->top = NULL; +} + +void ack_map_add(struct ack_map *map, const unsigned char dst_addr[6], const unsigned char *packet, int packet_size) +{ + struct ack_map_node *cur = map->top; + struct ack_map_node *prev = NULL; + + while (cur != NULL) + { + prev = cur; + cur = cur->next; + } + + struct ack_map_node *next = (struct ack_map_node *)malloc(sizeof(struct ack_map_node)); + next->next = NULL; + memcpy(next->dst_addr, dst_addr, 6); + next->packet = (unsigned char *)malloc(packet_size); + memcpy(next->packet, packet, packet_size); + next->packet_size = packet_size; + next->retries_left = 7; + + if (prev == NULL) + { + map->top = next; + } + else + { + prev->next = next; + } +} + +void ack_map_pop(struct ack_map *map) +{ + if (map->top != NULL) + { + struct ack_map_node *cur = map->top; + map->top = cur->next; + + free(cur->packet); + free(cur); + } +} + +int ack_map_length(struct ack_map *map) +{ + int result = 0; + + struct ack_map_node *cur = map->top; + while (cur != NULL) + { + result++; + + cur = cur->next; + } + + return result; +} + +void ack_map_clear(struct ack_map *map) +{ + while (map->top != NULL) + { + ack_map_pop(map); + } +} + +void *retransmit_thread(void *arg) +{ + struct retransmitter *retransmitter = (struct retransmitter *)arg; + + for (;;) + { + pthread_mutex_lock(&retransmitter_mutex); + + if (retransmitter->quit) + { + pthread_mutex_unlock(&retransmitter_mutex); + + break; + } + + struct ack_map_node *cur = retransmitter->messages.top; + if (cur != NULL) + { + send_packet_with_radiotap(retransmitter->sock, retransmitter->device_index, cur->dst_addr, cur->packet, cur->packet_size); + + // Set retransmit flag for future. + cur->packet[1] |= (1 << 3); + + cur->retries_left--; + + if (cur->retries_left <= 0) + { + ack_map_pop(&retransmitter->messages); + } + } + + pthread_mutex_unlock(&retransmitter_mutex); + + usleep(5000); + } + + return NULL; +} + +struct retransmitter *start_retransmit_thread(int sock, int device_index) +{ + struct retransmitter *retransmitter = (struct retransmitter *)malloc(sizeof(struct retransmitter)); + retransmitter->sock = sock; + retransmitter->device_index = device_index; + ack_map_init(&retransmitter->messages); + retransmitter->quit = false; + + pthread_create(&retransmitter->thread_id, NULL, &retransmit_thread, retransmitter); + + return retransmitter; +} + +void send_until_acked(struct retransmitter *retransmitter, const unsigned char dst_addr[6], const unsigned char *packet, int packet_size) +{ + pthread_mutex_lock(&retransmitter_mutex); + + ack_map_add(&retransmitter->messages, dst_addr, packet, packet_size); + + printf("Adding message for " MACSTR ". Current length: %d\n", MAC2STR(dst_addr), ack_map_length(&retransmitter->messages)); + + pthread_mutex_unlock(&retransmitter_mutex); +} + +void handle_ack(struct retransmitter *retransmitter) +{ + pthread_mutex_lock(&retransmitter_mutex); + + if (retransmitter->messages.top != NULL) + { + retransmitter->messages.top->retries_left = 0; + } + + printf("Received ACK. Current length: %d\n", ack_map_length(&retransmitter->messages)); + + pthread_mutex_unlock(&retransmitter_mutex); +} + +void free_retransmitter(struct retransmitter *retransmitter) +{ + pthread_mutex_lock(&retransmitter_mutex); + retransmitter->quit = true; + pthread_mutex_unlock(&retransmitter_mutex); + + pthread_join(retransmitter->thread_id, NULL); + + ack_map_clear(&retransmitter->messages); + free(retransmitter); +} -- cgit 1.4.1