about summary refs log tree commit diff stats
path: root/src/retransmit.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/retransmit.c')
-rw-r--r--src/retransmit.c169
1 files changed, 169 insertions, 0 deletions
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 @@
1#include "retransmit.h"
2
3#include <libwifi.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <string.h>
7#include <unistd.h>
8
9#include "transmit.h"
10
11static pthread_mutex_t retransmitter_mutex = PTHREAD_MUTEX_INITIALIZER;
12
13void ack_map_init(struct ack_map *map)
14{
15 map->top = NULL;
16}
17
18void ack_map_add(struct ack_map *map, const unsigned char dst_addr[6], const unsigned char *packet, int packet_size)
19{
20 struct ack_map_node *cur = map->top;
21 struct ack_map_node *prev = NULL;
22
23 while (cur != NULL)
24 {
25 prev = cur;
26 cur = cur->next;
27 }
28
29 struct ack_map_node *next = (struct ack_map_node *)malloc(sizeof(struct ack_map_node));
30 next->next = NULL;
31 memcpy(next->dst_addr, dst_addr, 6);
32 next->packet = (unsigned char *)malloc(packet_size);
33 memcpy(next->packet, packet, packet_size);
34 next->packet_size = packet_size;
35 next->retries_left = 7;
36
37 if (prev == NULL)
38 {
39 map->top = next;
40 }
41 else
42 {
43 prev->next = next;
44 }
45}
46
47void ack_map_pop(struct ack_map *map)
48{
49 if (map->top != NULL)
50 {
51 struct ack_map_node *cur = map->top;
52 map->top = cur->next;
53
54 free(cur->packet);
55 free(cur);
56 }
57}
58
59int ack_map_length(struct ack_map *map)
60{
61 int result = 0;
62
63 struct ack_map_node *cur = map->top;
64 while (cur != NULL)
65 {
66 result++;
67
68 cur = cur->next;
69 }
70
71 return result;
72}
73
74void ack_map_clear(struct ack_map *map)
75{
76 while (map->top != NULL)
77 {
78 ack_map_pop(map);
79 }
80}
81
82void *retransmit_thread(void *arg)
83{
84 struct retransmitter *retransmitter = (struct retransmitter *)arg;
85
86 for (;;)
87 {
88 pthread_mutex_lock(&retransmitter_mutex);
89
90 if (retransmitter->quit)
91 {
92 pthread_mutex_unlock(&retransmitter_mutex);
93
94 break;
95 }
96
97 struct ack_map_node *cur = retransmitter->messages.top;
98 if (cur != NULL)
99 {
100 send_packet_with_radiotap(retransmitter->sock, retransmitter->device_index, cur->dst_addr, cur->packet, cur->packet_size);
101
102 // Set retransmit flag for future.
103 cur->packet[1] |= (1 << 3);
104
105 cur->retries_left--;
106
107 if (cur->retries_left <= 0)
108 {
109 ack_map_pop(&retransmitter->messages);
110 }
111 }
112
113 pthread_mutex_unlock(&retransmitter_mutex);
114
115 usleep(5000);
116 }
117
118 return NULL;
119}
120
121struct retransmitter *start_retransmit_thread(int sock, int device_index)
122{
123 struct retransmitter *retransmitter = (struct retransmitter *)malloc(sizeof(struct retransmitter));
124 retransmitter->sock = sock;
125 retransmitter->device_index = device_index;
126 ack_map_init(&retransmitter->messages);
127 retransmitter->quit = false;
128
129 pthread_create(&retransmitter->thread_id, NULL, &retransmit_thread, retransmitter);
130
131 return retransmitter;
132}
133
134void send_until_acked(struct retransmitter *retransmitter, const unsigned char dst_addr[6], const unsigned char *packet, int packet_size)
135{
136 pthread_mutex_lock(&retransmitter_mutex);
137
138 ack_map_add(&retransmitter->messages, dst_addr, packet, packet_size);
139
140 printf("Adding message for " MACSTR ". Current length: %d\n", MAC2STR(dst_addr), ack_map_length(&retransmitter->messages));
141
142 pthread_mutex_unlock(&retransmitter_mutex);
143}
144
145void handle_ack(struct retransmitter *retransmitter)
146{
147 pthread_mutex_lock(&retransmitter_mutex);
148
149 if (retransmitter->messages.top != NULL)
150 {
151 retransmitter->messages.top->retries_left = 0;
152 }
153
154 printf("Received ACK. Current length: %d\n", ack_map_length(&retransmitter->messages));
155
156 pthread_mutex_unlock(&retransmitter_mutex);
157}
158
159void free_retransmitter(struct retransmitter *retransmitter)
160{
161 pthread_mutex_lock(&retransmitter_mutex);
162 retransmitter->quit = true;
163 pthread_mutex_unlock(&retransmitter_mutex);
164
165 pthread_join(retransmitter->thread_id, NULL);
166
167 ack_map_clear(&retransmitter->messages);
168 free(retransmitter);
169}