diff options
Diffstat (limited to 'src/retransmit.c')
-rw-r--r-- | src/retransmit.c | 169 |
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 | |||
11 | static pthread_mutex_t retransmitter_mutex = PTHREAD_MUTEX_INITIALIZER; | ||
12 | |||
13 | void ack_map_init(struct ack_map *map) | ||
14 | { | ||
15 | map->top = NULL; | ||
16 | } | ||
17 | |||
18 | void 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 | |||
47 | void 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 | |||
59 | int 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 | |||
74 | void ack_map_clear(struct ack_map *map) | ||
75 | { | ||
76 | while (map->top != NULL) | ||
77 | { | ||
78 | ack_map_pop(map); | ||
79 | } | ||
80 | } | ||
81 | |||
82 | void *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 | |||
121 | struct 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 | |||
134 | void 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 | |||
145 | void 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 | |||
159 | void 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 | } | ||