diff options
-rw-r--r-- | CMakeLists.txt | 1 | ||||
-rwxr-xr-x | other/astyle/format-source | 16 | ||||
-rw-r--r-- | testing/random_testing.cc | 25 | ||||
-rw-r--r-- | toxcore/BUILD.bazel | 9 | ||||
-rw-r--r-- | toxcore/crypto_core_test.cc | 4 | ||||
-rw-r--r-- | toxcore/ping_array.api.h | 29 | ||||
-rw-r--r-- | toxcore/ping_array.c | 59 | ||||
-rw-r--r-- | toxcore/ping_array.h | 29 | ||||
-rw-r--r-- | toxcore/ping_array_test.cc | 119 |
9 files changed, 218 insertions, 73 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index a867e1dd..95b12ce0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt | |||
@@ -362,6 +362,7 @@ unit_test(toxav ring_buffer) | |||
362 | unit_test(toxav rtp) | 362 | unit_test(toxav rtp) |
363 | unit_test(toxcore crypto_core) | 363 | unit_test(toxcore crypto_core) |
364 | unit_test(toxcore mono_time) | 364 | unit_test(toxcore mono_time) |
365 | unit_test(toxcore ping_array) | ||
365 | unit_test(toxcore util) | 366 | unit_test(toxcore util) |
366 | 367 | ||
367 | ################################################################################ | 368 | ################################################################################ |
diff --git a/other/astyle/format-source b/other/astyle/format-source index 5e139d89..550bcf07 100755 --- a/other/astyle/format-source +++ b/other/astyle/format-source | |||
@@ -49,15 +49,25 @@ if grep '<unresolved>' */*.h; then | |||
49 | exit 1 | 49 | exit 1 |
50 | fi | 50 | fi |
51 | 51 | ||
52 | CC_SOURCES=`find . '(' -name '*.cc' ')'` | ||
53 | CC_SOURCES="$CC_SOURCES toxcore/ping_array.c" | ||
54 | |||
55 | for bin in clang-format-6.0 clang-format-5.0 clang-format; do | ||
56 | if which "$bin"; then | ||
57 | "$bin" -i -style='{BasedOnStyle: Google, ColumnLimit: 100}' $CC_SOURCES | ||
58 | break | ||
59 | fi | ||
60 | done | ||
61 | |||
52 | FIND="find ." | 62 | FIND="find ." |
53 | FIND="$FIND '(' -name '*.[ch]' -or -name '*.cpp' ')'" | 63 | FIND="$FIND '(' -name '*.[ch]' ')'" |
54 | FIND="$FIND -and -not -name '*.api.h'" | 64 | FIND="$FIND -and -not -name '*.api.h'" |
55 | FIND="$FIND -and -not -wholename './super_donators/*'" | 65 | FIND="$FIND -and -not -wholename './super_donators/*'" |
56 | FIND="$FIND -and -not -wholename './third_party/*'" | 66 | FIND="$FIND -and -not -wholename './third_party/*'" |
57 | FIND="$FIND -and -not -wholename './toxencryptsave/crypto_pwhash*'" | 67 | FIND="$FIND -and -not -wholename './toxencryptsave/crypto_pwhash*'" |
58 | 68 | ||
59 | SOURCES=`eval "$FIND"` | 69 | C_SOURCES=`eval "$FIND"` |
60 | 70 | ||
61 | $ASTYLE -n --options=other/astyle/astylerc $SOURCES | 71 | $ASTYLE -n --options=other/astyle/astylerc $C_SOURCES |
62 | 72 | ||
63 | git diff --exit-code | 73 | git diff --exit-code |
diff --git a/testing/random_testing.cc b/testing/random_testing.cc index 5ea0bc9d..6211630e 100644 --- a/testing/random_testing.cc +++ b/testing/random_testing.cc | |||
@@ -283,7 +283,8 @@ bool attempt_action(Global_State *toxes, std::mt19937 *rng) { | |||
283 | int main() { | 283 | int main() { |
284 | std::vector<Action> const actions = { | 284 | std::vector<Action> const actions = { |
285 | { | 285 | { |
286 | 10, "creates a new conference", | 286 | 10, |
287 | "creates a new conference", | ||
287 | [](Local_State const &state) { | 288 | [](Local_State const &state) { |
288 | return tox_conference_get_chatlist_size(state.tox()) < MAX_CONFERENCES_PER_USER; | 289 | return tox_conference_get_chatlist_size(state.tox()) < MAX_CONFERENCES_PER_USER; |
289 | }, | 290 | }, |
@@ -294,7 +295,8 @@ int main() { | |||
294 | }, | 295 | }, |
295 | }, | 296 | }, |
296 | { | 297 | { |
297 | 10, "invites a random friend to a conference", | 298 | 10, |
299 | "invites a random friend to a conference", | ||
298 | [](Local_State const &state) { | 300 | [](Local_State const &state) { |
299 | return tox_conference_get_chatlist_size(state.tox()) != 0; | 301 | return tox_conference_get_chatlist_size(state.tox()) != 0; |
300 | }, | 302 | }, |
@@ -302,15 +304,15 @@ int main() { | |||
302 | size_t chat_count = tox_conference_get_chatlist_size(state->tox()); | 304 | size_t chat_count = tox_conference_get_chatlist_size(state->tox()); |
303 | assert(chat_count != 0); // Condition above. | 305 | assert(chat_count != 0); // Condition above. |
304 | TOX_ERR_CONFERENCE_INVITE err; | 306 | TOX_ERR_CONFERENCE_INVITE err; |
305 | tox_conference_invite( | 307 | tox_conference_invite(state->tox(), rnd->friend_selector(*rng), |
306 | state->tox(), rnd->friend_selector(*rng), | 308 | state->next_invite % chat_count, &err); |
307 | state->next_invite % chat_count, &err); | ||
308 | state->next_invite++; | 309 | state->next_invite++; |
309 | assert(err == TOX_ERR_CONFERENCE_INVITE_OK); | 310 | assert(err == TOX_ERR_CONFERENCE_INVITE_OK); |
310 | }, | 311 | }, |
311 | }, | 312 | }, |
312 | { | 313 | { |
313 | 10, "deletes the last conference", | 314 | 10, |
315 | "deletes the last conference", | ||
314 | [](Local_State const &state) { | 316 | [](Local_State const &state) { |
315 | return tox_conference_get_chatlist_size(state.tox()) != 0; | 317 | return tox_conference_get_chatlist_size(state.tox()) != 0; |
316 | }, | 318 | }, |
@@ -322,7 +324,8 @@ int main() { | |||
322 | }, | 324 | }, |
323 | }, | 325 | }, |
324 | { | 326 | { |
325 | 10, "sends a message to the last conference", | 327 | 10, |
328 | "sends a message to the last conference", | ||
326 | [](Local_State const &state) { | 329 | [](Local_State const &state) { |
327 | return tox_conference_get_chatlist_size(state.tox()) != 0; | 330 | return tox_conference_get_chatlist_size(state.tox()) != 0; |
328 | }, | 331 | }, |
@@ -344,7 +347,9 @@ int main() { | |||
344 | }, | 347 | }, |
345 | }, | 348 | }, |
346 | { | 349 | { |
347 | 10, "changes their name", [](Local_State const &state) { return true; }, | 350 | 10, |
351 | "changes their name", | ||
352 | [](Local_State const &state) { return true; }, | ||
348 | [](Local_State *state, Random *rnd, std::mt19937 *rng) { | 353 | [](Local_State *state, Random *rnd, std::mt19937 *rng) { |
349 | std::vector<uint8_t> name(rnd->name_length_selector(*rng)); | 354 | std::vector<uint8_t> name(rnd->name_length_selector(*rng)); |
350 | for (uint8_t &byte : name) { | 355 | for (uint8_t &byte : name) { |
@@ -359,7 +364,9 @@ int main() { | |||
359 | }, | 364 | }, |
360 | }, | 365 | }, |
361 | { | 366 | { |
362 | 10, "sets their name to empty", [](Local_State const &state) { return true; }, | 367 | 10, |
368 | "sets their name to empty", | ||
369 | [](Local_State const &state) { return true; }, | ||
363 | [](Local_State *state, Random *rnd, std::mt19937 *rng) { | 370 | [](Local_State *state, Random *rnd, std::mt19937 *rng) { |
364 | TOX_ERR_SET_INFO err; | 371 | TOX_ERR_SET_INFO err; |
365 | tox_self_set_name(state->tox(), nullptr, 0, &err); | 372 | tox_self_set_name(state->tox(), nullptr, 0, &err); |
diff --git a/toxcore/BUILD.bazel b/toxcore/BUILD.bazel index 6fbe016e..a34c328c 100644 --- a/toxcore/BUILD.bazel +++ b/toxcore/BUILD.bazel | |||
@@ -113,6 +113,15 @@ cc_library( | |||
113 | deps = [":network"], | 113 | deps = [":network"], |
114 | ) | 114 | ) |
115 | 115 | ||
116 | cc_test( | ||
117 | name = "ping_array_test", | ||
118 | srcs = ["ping_array_test.cc"], | ||
119 | deps = [ | ||
120 | ":ping_array", | ||
121 | "@com_google_googletest//:gtest_main", | ||
122 | ], | ||
123 | ) | ||
124 | |||
116 | cc_library( | 125 | cc_library( |
117 | name = "DHT", | 126 | name = "DHT", |
118 | srcs = [ | 127 | srcs = [ |
diff --git a/toxcore/crypto_core_test.cc b/toxcore/crypto_core_test.cc index cdc315b2..d6888b19 100644 --- a/toxcore/crypto_core_test.cc +++ b/toxcore/crypto_core_test.cc | |||
@@ -10,8 +10,10 @@ enum { | |||
10 | /** | 10 | /** |
11 | * The size of the arrays to compare. This was chosen to take around 2000 | 11 | * The size of the arrays to compare. This was chosen to take around 2000 |
12 | * CPU clocks on x86_64. | 12 | * CPU clocks on x86_64. |
13 | * | ||
14 | * This is 1MiB. | ||
13 | */ | 15 | */ |
14 | CRYPTO_TEST_MEMCMP_SIZE = 1024 * 1024, // 1 MiB | 16 | CRYPTO_TEST_MEMCMP_SIZE = 1024 * 1024, |
15 | /** | 17 | /** |
16 | * The number of times we run memcmp in the test. | 18 | * The number of times we run memcmp in the test. |
17 | * | 19 | * |
diff --git a/toxcore/ping_array.api.h b/toxcore/ping_array.api.h index 61021e24..74e2b002 100644 --- a/toxcore/ping_array.api.h +++ b/toxcore/ping_array.api.h | |||
@@ -22,10 +22,15 @@ | |||
22 | * You should have received a copy of the GNU General Public License | 22 | * You should have received a copy of the GNU General Public License |
23 | * along with Tox. If not, see <http://www.gnu.org/licenses/>. | 23 | * along with Tox. If not, see <http://www.gnu.org/licenses/>. |
24 | */ | 24 | */ |
25 | #ifndef PING_ARRAY_H | 25 | #ifndef C_TOXCORE_TOXCORE_PING_ARRAY_H |
26 | #define PING_ARRAY_H | 26 | #define C_TOXCORE_TOXCORE_PING_ARRAY_H |
27 | 27 | ||
28 | #include "network.h" | 28 | #include <stddef.h> |
29 | #include <stdint.h> | ||
30 | |||
31 | #ifdef __cplusplus | ||
32 | extern "C" { | ||
33 | #endif | ||
29 | %} | 34 | %} |
30 | 35 | ||
31 | class mono_Time { struct this; } | 36 | class mono_Time { struct this; } |
@@ -36,11 +41,11 @@ struct this; | |||
36 | 41 | ||
37 | /** | 42 | /** |
38 | * Initialize a Ping_Array. | 43 | * Initialize a Ping_Array. |
39 | * size represents the total size of the array and should be a power of 2. | ||
40 | * timeout represents the maximum timeout in seconds for the entry. | ||
41 | * | 44 | * |
42 | * return 0 on success. | 45 | * @param size represents the total size of the array and should be a power of 2. |
43 | * return -1 on failure. | 46 | * @param timeout represents the maximum timeout in seconds for the entry. |
47 | * | ||
48 | * @return 0 on success, -1 on failure. | ||
44 | */ | 49 | */ |
45 | static this new(uint32_t size, uint32_t timeout); | 50 | static this new(uint32_t size, uint32_t timeout); |
46 | 51 | ||
@@ -52,8 +57,7 @@ void kill(); | |||
52 | /** | 57 | /** |
53 | * Add a data with length to the Ping_Array list and return a ping_id. | 58 | * Add a data with length to the Ping_Array list and return a ping_id. |
54 | * | 59 | * |
55 | * return ping_id on success. | 60 | * @return ping_id on success, 0 on failure. |
56 | * return 0 on failure. | ||
57 | */ | 61 | */ |
58 | uint64_t add(const mono_Time::this *mono_time, const uint8_t *data, uint32_t length); | 62 | uint64_t add(const mono_Time::this *mono_time, const uint8_t *data, uint32_t length); |
59 | 63 | ||
@@ -62,13 +66,16 @@ uint64_t add(const mono_Time::this *mono_time, const uint8_t *data, uint32_t len | |||
62 | * | 66 | * |
63 | * On success, copies the data into data of length, | 67 | * On success, copies the data into data of length, |
64 | * | 68 | * |
65 | * return length of data copied on success. | 69 | * @return length of data copied on success, -1 on failure. |
66 | * return -1 on failure. | ||
67 | */ | 70 | */ |
68 | int32_t check(const mono_Time::this *mono_time, uint8_t[length] data, uint64_t ping_id); | 71 | int32_t check(const mono_Time::this *mono_time, uint8_t[length] data, uint64_t ping_id); |
69 | 72 | ||
70 | } | 73 | } |
71 | 74 | ||
72 | %{ | 75 | %{ |
76 | #ifdef __cplusplus | ||
77 | } // extern "C" | ||
73 | #endif | 78 | #endif |
79 | |||
80 | #endif // C_TOXCORE_TOXCORE_PING_ARRAY_H | ||
74 | %} | 81 | %} |
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 | |||
38 | typedef struct Ping_Array_Entry { | 37 | typedef 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 | */ | ||
61 | Ping_Array *ping_array_new(uint32_t size, uint32_t timeout) | 53 | Ping_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 | ||
87 | static void clear_entry(Ping_Array *array, uint32_t index) | 84 | static 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 | */ | ||
98 | void ping_array_kill(Ping_Array *array) | 91 | void 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) | |||
112 | static void ping_array_clear_timedout(Ping_Array *array, const Mono_Time *mono_time) | 105 | static 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. | 119 | uint64_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 | */ | ||
131 | uint64_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 | 153 | int32_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 | */ | ||
172 | int32_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 | } |
diff --git a/toxcore/ping_array.h b/toxcore/ping_array.h index cfa9bfcc..7bc95a42 100644 --- a/toxcore/ping_array.h +++ b/toxcore/ping_array.h | |||
@@ -21,10 +21,15 @@ | |||
21 | * You should have received a copy of the GNU General Public License | 21 | * You should have received a copy of the GNU General Public License |
22 | * along with Tox. If not, see <http://www.gnu.org/licenses/>. | 22 | * along with Tox. If not, see <http://www.gnu.org/licenses/>. |
23 | */ | 23 | */ |
24 | #ifndef PING_ARRAY_H | 24 | #ifndef C_TOXCORE_TOXCORE_PING_ARRAY_H |
25 | #define PING_ARRAY_H | 25 | #define C_TOXCORE_TOXCORE_PING_ARRAY_H |
26 | 26 | ||
27 | #include "network.h" | 27 | #include <stddef.h> |
28 | #include <stdint.h> | ||
29 | |||
30 | #ifdef __cplusplus | ||
31 | extern "C" { | ||
32 | #endif | ||
28 | 33 | ||
29 | #ifndef MONO_TIME_DEFINED | 34 | #ifndef MONO_TIME_DEFINED |
30 | #define MONO_TIME_DEFINED | 35 | #define MONO_TIME_DEFINED |
@@ -38,11 +43,11 @@ typedef struct Ping_Array Ping_Array; | |||
38 | 43 | ||
39 | /** | 44 | /** |
40 | * Initialize a Ping_Array. | 45 | * Initialize a Ping_Array. |
41 | * size represents the total size of the array and should be a power of 2. | ||
42 | * timeout represents the maximum timeout in seconds for the entry. | ||
43 | * | 46 | * |
44 | * return 0 on success. | 47 | * @param size represents the total size of the array and should be a power of 2. |
45 | * return -1 on failure. | 48 | * @param timeout represents the maximum timeout in seconds for the entry. |
49 | * | ||
50 | * @return 0 on success, -1 on failure. | ||
46 | */ | 51 | */ |
47 | struct Ping_Array *ping_array_new(uint32_t size, uint32_t timeout); | 52 | struct Ping_Array *ping_array_new(uint32_t size, uint32_t timeout); |
48 | 53 | ||
@@ -54,8 +59,7 @@ void ping_array_kill(struct Ping_Array *_array); | |||
54 | /** | 59 | /** |
55 | * Add a data with length to the Ping_Array list and return a ping_id. | 60 | * Add a data with length to the Ping_Array list and return a ping_id. |
56 | * | 61 | * |
57 | * return ping_id on success. | 62 | * @return ping_id on success, 0 on failure. |
58 | * return 0 on failure. | ||
59 | */ | 63 | */ |
60 | uint64_t ping_array_add(struct Ping_Array *_array, const struct Mono_Time *mono_time, const uint8_t *data, | 64 | uint64_t ping_array_add(struct Ping_Array *_array, const struct Mono_Time *mono_time, const uint8_t *data, |
61 | uint32_t length); | 65 | uint32_t length); |
@@ -65,10 +69,13 @@ uint64_t ping_array_add(struct Ping_Array *_array, const struct Mono_Time *mono_ | |||
65 | * | 69 | * |
66 | * On success, copies the data into data of length, | 70 | * On success, copies the data into data of length, |
67 | * | 71 | * |
68 | * return length of data copied on success. | 72 | * @return length of data copied on success, -1 on failure. |
69 | * return -1 on failure. | ||
70 | */ | 73 | */ |
71 | int32_t ping_array_check(struct Ping_Array *_array, const struct Mono_Time *mono_time, uint8_t *data, size_t length, | 74 | int32_t ping_array_check(struct Ping_Array *_array, const struct Mono_Time *mono_time, uint8_t *data, size_t length, |
72 | uint64_t ping_id); | 75 | uint64_t ping_id); |
73 | 76 | ||
77 | #ifdef __cplusplus | ||
78 | } // extern "C" | ||
74 | #endif | 79 | #endif |
80 | |||
81 | #endif // C_TOXCORE_TOXCORE_PING_ARRAY_H | ||
diff --git a/toxcore/ping_array_test.cc b/toxcore/ping_array_test.cc new file mode 100644 index 00000000..fca5009a --- /dev/null +++ b/toxcore/ping_array_test.cc | |||
@@ -0,0 +1,119 @@ | |||
1 | #include "ping_array.h" | ||
2 | |||
3 | #include <memory> | ||
4 | |||
5 | #include <gtest/gtest.h> | ||
6 | #include "mono_time.h" | ||
7 | |||
8 | namespace { | ||
9 | |||
10 | struct Ping_Array_Deleter { | ||
11 | void operator()(Ping_Array *arr) { ping_array_kill(arr); } | ||
12 | }; | ||
13 | |||
14 | using Ping_Array_Ptr = std::unique_ptr<Ping_Array, Ping_Array_Deleter>; | ||
15 | |||
16 | struct Mono_Time_Deleter { | ||
17 | void operator()(Mono_Time *arr) { mono_time_free(arr); } | ||
18 | }; | ||
19 | |||
20 | using Mono_Time_Ptr = std::unique_ptr<Mono_Time, Mono_Time_Deleter>; | ||
21 | |||
22 | TEST(PingArray, MinimumTimeoutIsOne) { | ||
23 | EXPECT_EQ(ping_array_new(1, 0), nullptr); | ||
24 | EXPECT_NE(Ping_Array_Ptr(ping_array_new(1, 1)), nullptr); | ||
25 | } | ||
26 | |||
27 | TEST(PingArray, MinimumArraySizeIsOne) { | ||
28 | EXPECT_EQ(ping_array_new(0, 1), nullptr); | ||
29 | EXPECT_NE(Ping_Array_Ptr(ping_array_new(1, 1)), nullptr); | ||
30 | } | ||
31 | |||
32 | TEST(PingArray, ArraySizeMustBePowerOfTwo) { | ||
33 | Ping_Array_Ptr arr; | ||
34 | arr.reset(ping_array_new(2, 1)); | ||
35 | EXPECT_NE(arr, nullptr); | ||
36 | arr.reset(ping_array_new(4, 1)); | ||
37 | EXPECT_NE(arr, nullptr); | ||
38 | arr.reset(ping_array_new(1024, 1)); | ||
39 | EXPECT_NE(arr, nullptr); | ||
40 | |||
41 | EXPECT_EQ(ping_array_new(1023, 1), nullptr); | ||
42 | EXPECT_EQ(ping_array_new(1234, 1), nullptr); | ||
43 | } | ||
44 | |||
45 | TEST(PingArray, StoredDataCanBeRetrieved) { | ||
46 | Ping_Array_Ptr const arr(ping_array_new(2, 1)); | ||
47 | Mono_Time_Ptr const mono_time(mono_time_new()); | ||
48 | |||
49 | uint64_t const ping_id = | ||
50 | ping_array_add(arr.get(), mono_time.get(), std::vector<uint8_t>{1, 2, 3, 4}.data(), 4); | ||
51 | EXPECT_NE(ping_id, 0); | ||
52 | |||
53 | std::vector<uint8_t> data(4); | ||
54 | EXPECT_EQ(ping_array_check(arr.get(), mono_time.get(), data.data(), data.size(), ping_id), 4); | ||
55 | EXPECT_EQ(data, std::vector<uint8_t>({1, 2, 3, 4})); | ||
56 | } | ||
57 | |||
58 | TEST(PingArray, RetrievingDataWithTooSmallOutputBufferHasNoEffect) { | ||
59 | Ping_Array_Ptr const arr(ping_array_new(2, 1)); | ||
60 | Mono_Time_Ptr const mono_time(mono_time_new()); | ||
61 | |||
62 | uint64_t const ping_id = | ||
63 | ping_array_add(arr.get(), mono_time.get(), (std::vector<uint8_t>{1, 2, 3, 4}).data(), 4); | ||
64 | EXPECT_NE(ping_id, 0); | ||
65 | |||
66 | std::vector<uint8_t> data(4); | ||
67 | EXPECT_EQ(ping_array_check(arr.get(), mono_time.get(), data.data(), 3, ping_id), -1); | ||
68 | // It doesn't write anything to the data array. | ||
69 | EXPECT_EQ(data, std::vector<uint8_t>({0, 0, 0, 0})); | ||
70 | // Afterwards, we can still read it. | ||
71 | EXPECT_EQ(ping_array_check(arr.get(), mono_time.get(), data.data(), 4, ping_id), 4); | ||
72 | EXPECT_EQ(data, std::vector<uint8_t>({1, 2, 3, 4})); | ||
73 | } | ||
74 | |||
75 | TEST(PingArray, ZeroLengthDataCanBeAdded) { | ||
76 | Ping_Array_Ptr const arr(ping_array_new(2, 1)); | ||
77 | Mono_Time_Ptr const mono_time(mono_time_new()); | ||
78 | |||
79 | uint64_t const ping_id = ping_array_add(arr.get(), mono_time.get(), nullptr, 0); | ||
80 | EXPECT_NE(ping_id, 0); | ||
81 | |||
82 | EXPECT_EQ(ping_array_check(arr.get(), mono_time.get(), nullptr, 0, ping_id), 0); | ||
83 | } | ||
84 | |||
85 | TEST(PingArray, PingId0IsInvalid) { | ||
86 | Ping_Array_Ptr const arr(ping_array_new(2, 1)); | ||
87 | Mono_Time_Ptr const mono_time(mono_time_new()); | ||
88 | |||
89 | EXPECT_EQ(ping_array_check(arr.get(), mono_time.get(), nullptr, 0, 0), -1); | ||
90 | } | ||
91 | |||
92 | // Protection against replay attacks. | ||
93 | TEST(PingArray, DataCanOnlyBeRetrievedOnce) { | ||
94 | Ping_Array_Ptr const arr(ping_array_new(2, 1)); | ||
95 | Mono_Time_Ptr const mono_time(mono_time_new()); | ||
96 | |||
97 | uint64_t const ping_id = ping_array_add(arr.get(), mono_time.get(), nullptr, 0); | ||
98 | EXPECT_NE(ping_id, 0); | ||
99 | |||
100 | EXPECT_EQ(ping_array_check(arr.get(), mono_time.get(), nullptr, 0, ping_id), 0); | ||
101 | EXPECT_EQ(ping_array_check(arr.get(), mono_time.get(), nullptr, 0, ping_id), -1); | ||
102 | } | ||
103 | |||
104 | TEST(PingArray, PingIdMustMatchOnCheck) { | ||
105 | Ping_Array_Ptr const arr(ping_array_new(1, 1)); | ||
106 | Mono_Time_Ptr const mono_time(mono_time_new()); | ||
107 | |||
108 | uint64_t const ping_id = ping_array_add(arr.get(), mono_time.get(), nullptr, 0); | ||
109 | EXPECT_NE(ping_id, 0); | ||
110 | |||
111 | uint64_t const bad_ping_id = ping_id == 1 ? 2 : 1; | ||
112 | |||
113 | // bad_ping_id will also be pointing at the same element, but won't match the | ||
114 | // actual ping_id. | ||
115 | EXPECT_EQ(ping_array_check(arr.get(), mono_time.get(), nullptr, 0, bad_ping_id), -1); | ||
116 | EXPECT_EQ(ping_array_check(arr.get(), mono_time.get(), nullptr, 0, ping_id), 0); | ||
117 | } | ||
118 | |||
119 | } // namespace | ||