summaryrefslogtreecommitdiff
path: root/toxcore/ping_array.c
diff options
context:
space:
mode:
authoriphydf <iphydf@users.noreply.github.com>2018-08-26 09:42:08 +0000
committeriphydf <iphydf@users.noreply.github.com>2018-08-26 17:32:19 +0000
commita1035cf81494c3ab22c49b01788ca8ad933c5eb0 (patch)
treefee86f8751cc93eca9702fd50c3380483ff0f86a /toxcore/ping_array.c
parent64ddb7fff21e8cfcd197ba31bbb08ee6d3964c54 (diff)
Add some tests for `ping_array`.
No timeout test here yet, because we don't yet have the ability to manipulate time at will, so we would have to actually sleep.
Diffstat (limited to 'toxcore/ping_array.c')
-rw-r--r--toxcore/ping_array.c59
1 files changed, 21 insertions, 38 deletions
diff --git a/toxcore/ping_array.c b/toxcore/ping_array.c
index 9130254e..6669b4bd 100644
--- a/toxcore/ping_array.c
+++ b/toxcore/ping_array.c
@@ -34,7 +34,6 @@
34#include "mono_time.h" 34#include "mono_time.h"
35#include "util.h" 35#include "util.h"
36 36
37
38typedef struct Ping_Array_Entry { 37typedef struct Ping_Array_Entry {
39 void *data; 38 void *data;
40 uint32_t length; 39 uint32_t length;
@@ -46,25 +45,23 @@ struct Ping_Array {
46 Ping_Array_Entry *entries; 45 Ping_Array_Entry *entries;
47 46
48 uint32_t last_deleted; /* number representing the next entry to be deleted. */ 47 uint32_t last_deleted; /* number representing the next entry to be deleted. */
49 uint32_t last_added; /* number representing the last entry to be added. */ 48 uint32_t last_added; /* number representing the last entry to be added. */
50 uint32_t total_size; /* The length of entries */ 49 uint32_t total_size; /* The length of entries */
51 uint32_t timeout; /* The timeout after which entries are cleared. */ 50 uint32_t timeout; /* The timeout after which entries are cleared. */
52}; 51};
53 52
54/* Initialize a Ping_Array.
55 * size represents the total size of the array and should be a power of 2.
56 * timeout represents the maximum timeout in seconds for the entry.
57 *
58 * return 0 on success.
59 * return -1 on failure.
60 */
61Ping_Array *ping_array_new(uint32_t size, uint32_t timeout) 53Ping_Array *ping_array_new(uint32_t size, uint32_t timeout)
62{ 54{
63 if (size == 0 || timeout == 0) { 55 if (size == 0 || timeout == 0) {
64 return nullptr; 56 return nullptr;
65 } 57 }
66 58
67 Ping_Array *empty_array = (Ping_Array *)calloc(1, sizeof(Ping_Array)); 59 if ((size & (size - 1)) != 0) {
60 // Not a power of 2.
61 return nullptr;
62 }
63
64 Ping_Array *const empty_array = (Ping_Array *)calloc(1, sizeof(Ping_Array));
68 65
69 if (empty_array == nullptr) { 66 if (empty_array == nullptr) {
70 return nullptr; 67 return nullptr;
@@ -86,19 +83,15 @@ Ping_Array *ping_array_new(uint32_t size, uint32_t timeout)
86 83
87static void clear_entry(Ping_Array *array, uint32_t index) 84static void clear_entry(Ping_Array *array, uint32_t index)
88{ 85{
86 const Ping_Array_Entry empty = {nullptr};
89 free(array->entries[index].data); 87 free(array->entries[index].data);
90 array->entries[index].data = nullptr; 88 array->entries[index] = empty;
91 array->entries[index].length = 0;
92 array->entries[index].time = 0;
93 array->entries[index].ping_id = 0;
94} 89}
95 90
96/* Free all the allocated memory in a Ping_Array.
97 */
98void ping_array_kill(Ping_Array *array) 91void ping_array_kill(Ping_Array *array)
99{ 92{
100 while (array->last_deleted != array->last_added) { 93 while (array->last_deleted != array->last_added) {
101 uint32_t index = array->last_deleted % array->total_size; 94 const uint32_t index = array->last_deleted % array->total_size;
102 clear_entry(array, index); 95 clear_entry(array, index);
103 ++array->last_deleted; 96 ++array->last_deleted;
104 } 97 }
@@ -112,7 +105,7 @@ void ping_array_kill(Ping_Array *array)
112static void ping_array_clear_timedout(Ping_Array *array, const Mono_Time *mono_time) 105static void ping_array_clear_timedout(Ping_Array *array, const Mono_Time *mono_time)
113{ 106{
114 while (array->last_deleted != array->last_added) { 107 while (array->last_deleted != array->last_added) {
115 uint32_t index = array->last_deleted % array->total_size; 108 const uint32_t index = array->last_deleted % array->total_size;
116 109
117 if (!mono_time_is_timeout(mono_time, array->entries[index].time, array->timeout)) { 110 if (!mono_time_is_timeout(mono_time, array->entries[index].time, array->timeout)) {
118 break; 111 break;
@@ -123,15 +116,11 @@ static void ping_array_clear_timedout(Ping_Array *array, const Mono_Time *mono_t
123 } 116 }
124} 117}
125 118
126/* Add a data with length to the Ping_Array list and return a ping_id. 119uint64_t ping_array_add(Ping_Array *array, const Mono_Time *mono_time, const uint8_t *data,
127 * 120 uint32_t length)
128 * return ping_id on success.
129 * return 0 on failure.
130 */
131uint64_t ping_array_add(Ping_Array *array, const Mono_Time *mono_time, const uint8_t *data, uint32_t length)
132{ 121{
133 ping_array_clear_timedout(array, mono_time); 122 ping_array_clear_timedout(array, mono_time);
134 uint32_t index = array->last_added % array->total_size; 123 const uint32_t index = array->last_added % array->total_size;
135 124
136 if (array->entries[index].data != nullptr) { 125 if (array->entries[index].data != nullptr) {
137 array->last_deleted = array->last_added - array->total_size; 126 array->last_deleted = array->last_added - array->total_size;
@@ -161,21 +150,14 @@ uint64_t ping_array_add(Ping_Array *array, const Mono_Time *mono_time, const uin
161 return ping_id; 150 return ping_id;
162} 151}
163 152
164 153int32_t ping_array_check(Ping_Array *array, const Mono_Time *mono_time, uint8_t *data,
165/* Check if ping_id is valid and not timed out. 154 size_t length, uint64_t ping_id)
166 *
167 * On success, copies the data into data of length,
168 *
169 * return length of data copied on success.
170 * return -1 on failure.
171 */
172int32_t ping_array_check(Ping_Array *array, const Mono_Time *mono_time, uint8_t *data, size_t length, uint64_t ping_id)
173{ 155{
174 if (ping_id == 0) { 156 if (ping_id == 0) {
175 return -1; 157 return -1;
176 } 158 }
177 159
178 uint32_t index = ping_id % array->total_size; 160 const uint32_t index = ping_id % array->total_size;
179 161
180 if (array->entries[index].ping_id != ping_id) { 162 if (array->entries[index].ping_id != ping_id) {
181 return -1; 163 return -1;
@@ -189,12 +171,13 @@ int32_t ping_array_check(Ping_Array *array, const Mono_Time *mono_time, uint8_t
189 return -1; 171 return -1;
190 } 172 }
191 173
174 // TODO(iphydf): This can't happen? If it indeed can't, turn it into an assert.
192 if (array->entries[index].data == nullptr) { 175 if (array->entries[index].data == nullptr) {
193 return -1; 176 return -1;
194 } 177 }
195 178
196 memcpy(data, array->entries[index].data, array->entries[index].length); 179 memcpy(data, array->entries[index].data, array->entries[index].length);
197 uint32_t len = array->entries[index].length; 180 const uint32_t len = array->entries[index].length;
198 clear_entry(array, index); 181 clear_entry(array, index);
199 return len; 182 return len;
200} 183}