diff options
author | iphydf <iphydf@users.noreply.github.com> | 2018-06-25 12:37:46 +0000 |
---|---|---|
committer | iphydf <iphydf@users.noreply.github.com> | 2018-06-29 23:24:20 +0000 |
commit | 706fad1ce88c2104009a3835ee343ff9d8ec8b79 (patch) | |
tree | b2c0d8ccb434515cbbd4e0c9e86ce21f099c11a7 | |
parent | 52f21e32518244f3008efbef073f9d3ac9e68b43 (diff) |
Add a test to try and overflow the send queue in net_crypto.
-rw-r--r-- | CMakeLists.txt | 3 | ||||
-rw-r--r-- | auto_tests/BUILD.bazel | 1 | ||||
-rw-r--r-- | auto_tests/friend_connection_test.c | 33 | ||||
-rw-r--r-- | auto_tests/overflow_recvq_test.c | 68 | ||||
-rw-r--r-- | auto_tests/overflow_sendq_test.c | 53 | ||||
-rw-r--r-- | auto_tests/run_auto_test.h | 96 | ||||
-rw-r--r-- | toxcore/Messenger.c | 6 |
7 files changed, 260 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index cd05ad70..cc55a235 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt | |||
@@ -492,6 +492,7 @@ auto_test(crypto MSVC_DONT_BUILD) | |||
492 | auto_test(dht MSVC_DONT_BUILD) | 492 | auto_test(dht MSVC_DONT_BUILD) |
493 | auto_test(encryptsave) | 493 | auto_test(encryptsave) |
494 | auto_test(file_transfer) | 494 | auto_test(file_transfer) |
495 | auto_test(friend_connection) | ||
495 | auto_test(friend_request) | 496 | auto_test(friend_request) |
496 | auto_test(invalid_proxy) | 497 | auto_test(invalid_proxy) |
497 | auto_test(invalid_tcp_proxy) | 498 | auto_test(invalid_tcp_proxy) |
@@ -501,6 +502,8 @@ auto_test(lossy_packet) | |||
501 | auto_test(messenger MSVC_DONT_BUILD) | 502 | auto_test(messenger MSVC_DONT_BUILD) |
502 | auto_test(network) | 503 | auto_test(network) |
503 | auto_test(onion) | 504 | auto_test(onion) |
505 | auto_test(overflow_recvq) | ||
506 | auto_test(overflow_sendq) | ||
504 | auto_test(save_friend) | 507 | auto_test(save_friend) |
505 | auto_test(save_load) | 508 | auto_test(save_load) |
506 | auto_test(send_message) | 509 | auto_test(send_message) |
diff --git a/auto_tests/BUILD.bazel b/auto_tests/BUILD.bazel index 7b0cab7d..4f1f1892 100644 --- a/auto_tests/BUILD.bazel +++ b/auto_tests/BUILD.bazel | |||
@@ -4,6 +4,7 @@ cc_library( | |||
4 | hdrs = [ | 4 | hdrs = [ |
5 | "check_compat.h", | 5 | "check_compat.h", |
6 | "helpers.h", | 6 | "helpers.h", |
7 | "run_auto_test.h", | ||
7 | ], | 8 | ], |
8 | ) | 9 | ) |
9 | 10 | ||
diff --git a/auto_tests/friend_connection_test.c b/auto_tests/friend_connection_test.c new file mode 100644 index 00000000..7af1b575 --- /dev/null +++ b/auto_tests/friend_connection_test.c | |||
@@ -0,0 +1,33 @@ | |||
1 | /* Tests that we can make a friend connection. | ||
2 | * | ||
3 | * This is the simplest test that brings up two toxes that can talk to each | ||
4 | * other. It's useful as a copy/pasteable starting point for testing other | ||
5 | * features. | ||
6 | */ | ||
7 | |||
8 | #ifndef _XOPEN_SOURCE | ||
9 | #define _XOPEN_SOURCE 600 | ||
10 | #endif | ||
11 | |||
12 | #include "check_compat.h" | ||
13 | |||
14 | #include "../toxcore/tox.h" | ||
15 | |||
16 | typedef struct State { | ||
17 | uint32_t index; | ||
18 | } State; | ||
19 | |||
20 | #include "run_auto_test.h" | ||
21 | |||
22 | static void friend_connection_test(Tox **toxes, State *state) | ||
23 | { | ||
24 | // Nothing to do here. When copying this test, add test-specific code here. | ||
25 | } | ||
26 | |||
27 | int main(void) | ||
28 | { | ||
29 | setvbuf(stdout, nullptr, _IONBF, 0); | ||
30 | |||
31 | run_auto_test(2, friend_connection_test); | ||
32 | return 0; | ||
33 | } | ||
diff --git a/auto_tests/overflow_recvq_test.c b/auto_tests/overflow_recvq_test.c new file mode 100644 index 00000000..3227c5f4 --- /dev/null +++ b/auto_tests/overflow_recvq_test.c | |||
@@ -0,0 +1,68 @@ | |||
1 | /* Try to overflow the net_crypto packet buffer. | ||
2 | */ | ||
3 | |||
4 | #ifndef _XOPEN_SOURCE | ||
5 | #define _XOPEN_SOURCE 600 | ||
6 | #endif | ||
7 | |||
8 | #include "check_compat.h" | ||
9 | |||
10 | #include "../toxcore/tox.h" | ||
11 | |||
12 | typedef struct State { | ||
13 | uint32_t index; | ||
14 | uint32_t recv_count; | ||
15 | } State; | ||
16 | |||
17 | #include "run_auto_test.h" | ||
18 | |||
19 | #define NUM_MSGS 40000 | ||
20 | |||
21 | static void handle_friend_message(Tox *tox, uint32_t friend_number, TOX_MESSAGE_TYPE type, | ||
22 | const uint8_t *message, size_t length, void *user_data) | ||
23 | { | ||
24 | State *state = (State *)user_data; | ||
25 | state->recv_count++; | ||
26 | } | ||
27 | |||
28 | static void net_crypto_overflow_test(Tox **toxes, State *state) | ||
29 | { | ||
30 | tox_callback_friend_message(toxes[0], handle_friend_message); | ||
31 | |||
32 | printf("sending many messages to tox0\n"); | ||
33 | |||
34 | for (uint32_t tox_index = 1; tox_index < 3; tox_index++) { | ||
35 | for (uint32_t i = 0; i < NUM_MSGS; i++) { | ||
36 | uint8_t message[128] = {0}; | ||
37 | snprintf((char *)message, sizeof(message), "%u-%u", tox_index, i); | ||
38 | |||
39 | TOX_ERR_FRIEND_SEND_MESSAGE err; | ||
40 | tox_friend_send_message(toxes[tox_index], 0, TOX_MESSAGE_TYPE_NORMAL, message, sizeof message, &err); | ||
41 | |||
42 | if (err == TOX_ERR_FRIEND_SEND_MESSAGE_SENDQ) { | ||
43 | printf("tox%u sent %u messages to friend 0\n", tox_index, i); | ||
44 | break; | ||
45 | } | ||
46 | |||
47 | ck_assert_msg(err == TOX_ERR_FRIEND_SEND_MESSAGE_OK, | ||
48 | "tox%u failed to send message number %u: %d", tox_index, i, err); | ||
49 | } | ||
50 | } | ||
51 | |||
52 | // TODO(iphydf): Wait until all messages have arrived. Currently, not all | ||
53 | // messages arrive, so this test would always fail. | ||
54 | for (uint32_t i = 0; i < 200; i++) { | ||
55 | iterate_all(3, toxes, state); | ||
56 | c_sleep(ITERATION_INTERVAL); | ||
57 | } | ||
58 | |||
59 | printf("tox%u received %u messages\n", state[0].index, state[0].recv_count); | ||
60 | } | ||
61 | |||
62 | int main(void) | ||
63 | { | ||
64 | setvbuf(stdout, nullptr, _IONBF, 0); | ||
65 | |||
66 | run_auto_test(3, net_crypto_overflow_test); | ||
67 | return 0; | ||
68 | } | ||
diff --git a/auto_tests/overflow_sendq_test.c b/auto_tests/overflow_sendq_test.c new file mode 100644 index 00000000..94f5c12a --- /dev/null +++ b/auto_tests/overflow_sendq_test.c | |||
@@ -0,0 +1,53 @@ | |||
1 | /* Try to overflow the net_crypto packet buffer. | ||
2 | */ | ||
3 | |||
4 | #ifndef _XOPEN_SOURCE | ||
5 | #define _XOPEN_SOURCE 600 | ||
6 | #endif | ||
7 | |||
8 | #include "check_compat.h" | ||
9 | |||
10 | #include "../toxcore/tox.h" | ||
11 | |||
12 | typedef struct State { | ||
13 | uint32_t index; | ||
14 | } State; | ||
15 | |||
16 | #include "run_auto_test.h" | ||
17 | |||
18 | #define NUM_MSGS 40000 | ||
19 | |||
20 | static void net_crypto_overflow_test(Tox **toxes, State *state) | ||
21 | { | ||
22 | const uint8_t message[] = {0}; | ||
23 | bool errored = false; | ||
24 | |||
25 | for (uint32_t i = 0; i < NUM_MSGS; i++) { | ||
26 | TOX_ERR_FRIEND_SEND_MESSAGE err; | ||
27 | tox_friend_send_message(toxes[0], 0, TOX_MESSAGE_TYPE_NORMAL, message, sizeof message, &err); | ||
28 | |||
29 | if (err != TOX_ERR_FRIEND_SEND_MESSAGE_OK) { | ||
30 | errored = true; | ||
31 | } | ||
32 | |||
33 | if (errored) { | ||
34 | // As soon as we get the first error, we expect the same error (SENDQ) | ||
35 | // every time we try to send. | ||
36 | ck_assert_msg(err == TOX_ERR_FRIEND_SEND_MESSAGE_SENDQ, | ||
37 | "expected SENDQ error on message %u, but got %d", i, err); | ||
38 | } else { | ||
39 | ck_assert_msg(err == TOX_ERR_FRIEND_SEND_MESSAGE_OK, | ||
40 | "failed to send message number %u: %d", i, err); | ||
41 | } | ||
42 | } | ||
43 | |||
44 | ck_assert_msg(errored, "expected SENDQ error at some point (increase NUM_MSGS?)"); | ||
45 | } | ||
46 | |||
47 | int main(void) | ||
48 | { | ||
49 | setvbuf(stdout, nullptr, _IONBF, 0); | ||
50 | |||
51 | run_auto_test(2, net_crypto_overflow_test); | ||
52 | return 0; | ||
53 | } | ||
diff --git a/auto_tests/run_auto_test.h b/auto_tests/run_auto_test.h new file mode 100644 index 00000000..6ae8ad6a --- /dev/null +++ b/auto_tests/run_auto_test.h | |||
@@ -0,0 +1,96 @@ | |||
1 | #include "helpers.h" | ||
2 | |||
3 | static bool all_connected(uint32_t tox_count, Tox **toxes) | ||
4 | { | ||
5 | for (uint32_t i = 0; i < tox_count; i++) { | ||
6 | if (tox_self_get_connection_status(toxes[i]) == TOX_CONNECTION_NONE) { | ||
7 | return false; | ||
8 | } | ||
9 | } | ||
10 | |||
11 | return true; | ||
12 | } | ||
13 | |||
14 | static bool all_friends_connected(uint32_t tox_count, Tox **toxes) | ||
15 | { | ||
16 | for (uint32_t i = 0; i < tox_count; i++) { | ||
17 | const size_t friend_count = tox_self_get_friend_list_size(toxes[i]); | ||
18 | |||
19 | for (size_t j = 0; j < friend_count; j++) { | ||
20 | if (tox_friend_get_connection_status(toxes[i], j, nullptr) == TOX_CONNECTION_NONE) { | ||
21 | return false; | ||
22 | } | ||
23 | } | ||
24 | } | ||
25 | |||
26 | return true; | ||
27 | } | ||
28 | |||
29 | static bool iterate_all(uint32_t tox_count, Tox **toxes, State *state) | ||
30 | { | ||
31 | for (uint32_t i = 0; i < tox_count; i++) { | ||
32 | tox_iterate(toxes[i], &state[i]); | ||
33 | } | ||
34 | |||
35 | return true; | ||
36 | } | ||
37 | |||
38 | static void run_auto_test(uint32_t tox_count, void test(Tox **toxes, State *state)) | ||
39 | { | ||
40 | printf("initialising %u toxes\n", tox_count); | ||
41 | Tox **toxes = (Tox **)calloc(tox_count, sizeof(Tox *)); | ||
42 | State *state = (State *)calloc(tox_count, sizeof(State)); | ||
43 | |||
44 | for (uint32_t i = 0; i < tox_count; i++) { | ||
45 | state[i].index = i; | ||
46 | toxes[i] = tox_new_log(nullptr, nullptr, &state[i].index); | ||
47 | ck_assert_msg(toxes[i], "failed to create %u tox instances", i + 1); | ||
48 | } | ||
49 | |||
50 | printf("toxes all add each other as friends\n"); | ||
51 | |||
52 | for (uint32_t i = 0; i < tox_count; i++) { | ||
53 | for (uint32_t j = 0; j < tox_count; j++) { | ||
54 | if (i != j) { | ||
55 | uint8_t public_key[TOX_PUBLIC_KEY_SIZE]; | ||
56 | tox_self_get_public_key(toxes[j], public_key); | ||
57 | tox_friend_add_norequest(toxes[i], public_key, nullptr); | ||
58 | } | ||
59 | } | ||
60 | } | ||
61 | |||
62 | |||
63 | printf("bootstrapping all toxes off toxes[0]\n"); | ||
64 | uint8_t dht_key[TOX_PUBLIC_KEY_SIZE]; | ||
65 | tox_self_get_dht_id(toxes[0], dht_key); | ||
66 | const uint16_t dht_port = tox_self_get_udp_port(toxes[0], nullptr); | ||
67 | |||
68 | for (uint32_t i = 1; i < tox_count; i++) { | ||
69 | tox_bootstrap(toxes[i], "localhost", dht_port, dht_key, nullptr); | ||
70 | } | ||
71 | |||
72 | while (!all_connected(tox_count, toxes)) { | ||
73 | iterate_all(tox_count, toxes, state); | ||
74 | |||
75 | c_sleep(ITERATION_INTERVAL); | ||
76 | } | ||
77 | |||
78 | printf("toxes are online\n"); | ||
79 | |||
80 | while (!all_friends_connected(tox_count, toxes)) { | ||
81 | iterate_all(tox_count, toxes, state); | ||
82 | |||
83 | c_sleep(ITERATION_INTERVAL); | ||
84 | } | ||
85 | |||
86 | printf("tox clients connected\n"); | ||
87 | |||
88 | test(toxes, state); | ||
89 | |||
90 | for (uint32_t i = 0; i < tox_count; i++) { | ||
91 | tox_kill(toxes[i]); | ||
92 | } | ||
93 | |||
94 | free(state); | ||
95 | free(toxes); | ||
96 | } | ||
diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index e3ceeb86..7b931bdb 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c | |||
@@ -493,18 +493,22 @@ int m_send_message_generic(Messenger *m, int32_t friendnumber, uint8_t type, con | |||
493 | uint32_t *message_id) | 493 | uint32_t *message_id) |
494 | { | 494 | { |
495 | if (type > MESSAGE_ACTION) { | 495 | if (type > MESSAGE_ACTION) { |
496 | LOGGER_ERROR(m->log, "Message type %d is invalid", type); | ||
496 | return -5; | 497 | return -5; |
497 | } | 498 | } |
498 | 499 | ||
499 | if (friend_not_valid(m, friendnumber)) { | 500 | if (friend_not_valid(m, friendnumber)) { |
501 | LOGGER_ERROR(m->log, "Friend number %d is invalid", friendnumber); | ||
500 | return -1; | 502 | return -1; |
501 | } | 503 | } |
502 | 504 | ||
503 | if (length >= MAX_CRYPTO_DATA_SIZE) { | 505 | if (length >= MAX_CRYPTO_DATA_SIZE) { |
506 | LOGGER_ERROR(m->log, "Message length %d is too large", friendnumber); | ||
504 | return -2; | 507 | return -2; |
505 | } | 508 | } |
506 | 509 | ||
507 | if (m->friendlist[friendnumber].status != FRIEND_ONLINE) { | 510 | if (m->friendlist[friendnumber].status != FRIEND_ONLINE) { |
511 | LOGGER_ERROR(m->log, "Friend %d is not online", friendnumber); | ||
508 | return -3; | 512 | return -3; |
509 | } | 513 | } |
510 | 514 | ||
@@ -519,6 +523,8 @@ int m_send_message_generic(Messenger *m, int32_t friendnumber, uint8_t type, con | |||
519 | m->friendlist[friendnumber].friendcon_id), packet, length + 1, 0); | 523 | m->friendlist[friendnumber].friendcon_id), packet, length + 1, 0); |
520 | 524 | ||
521 | if (packet_num == -1) { | 525 | if (packet_num == -1) { |
526 | LOGGER_ERROR(m->log, "Failed to write crypto packet for message of length %d to friend %d", | ||
527 | length, friendnumber); | ||
522 | return -4; | 528 | return -4; |
523 | } | 529 | } |
524 | 530 | ||