Squashed 'external/toxcore/c-toxcore/' changes from 67badf694..82460b212
82460b212 feat: add ngc events 24b54722a fix: Ensure we have allocators available for the error paths. 48dbcfebc cleanup: Remove redundant `-DSODIUM_EXPORT` from definitions. 0cef46ee9 cleanup: Fix a few more clang-tidy warnings. 0c5b918e9 cleanup: Fix a few more clang-tidy warnings. 4d3c97f49 cleanup: Enforce stricter identifier naming using clang-tidy. a549807df refactor: Add `mem` module to allow tests to override allocators. 6133fb153 chore: Add devcontainer setup for codespaces. 620e07ecd chore: Set a timeout for tests started using Conan c0ec33b16 chore: Migrate Windows CI from Appveyor to Azure DevOps 8ed47f3ef fix incorrect documentation a1e245841 docs: Fix doxygen config and remove some redundant comments. b0f633185 chore: Fix the Android CI job 7469a529b fix: Add missing `#include <array>`. 2b1a6b0d2 add missing ngc constants getter declarations and definitions 2e02d5637 chore: Add missing module dependencies. REVERT: 67badf694 feat: add ngc events git-subtree-dir: external/toxcore/c-toxcore git-subtree-split: 82460b2124216af1ac9d63060de310a682a2fd15
This commit is contained in:
@ -34,20 +34,25 @@ static IP get_loopback(void)
|
||||
return ip;
|
||||
}
|
||||
|
||||
static void do_TCP_server_delay(TCP_Server *tcp_s, Mono_Time *mono_time, int delay)
|
||||
static void do_tcp_server_delay(TCP_Server *tcp_s, Mono_Time *mono_time, int delay)
|
||||
{
|
||||
c_sleep(delay);
|
||||
mono_time_update(mono_time);
|
||||
do_TCP_server(tcp_s, mono_time);
|
||||
do_tcp_server(tcp_s, mono_time);
|
||||
c_sleep(delay);
|
||||
}
|
||||
static uint16_t ports[NUM_PORTS] = {13215, 33445, 25643};
|
||||
|
||||
static void test_basic(void)
|
||||
{
|
||||
Mono_Time *mono_time = mono_time_new(nullptr, nullptr);
|
||||
const Random *rng = system_random();
|
||||
ck_assert(rng != nullptr);
|
||||
const Network *ns = system_network();
|
||||
ck_assert(ns != nullptr);
|
||||
const Memory *mem = system_memory();
|
||||
ck_assert(mem != nullptr);
|
||||
|
||||
Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr);
|
||||
Logger *logger = logger_new();
|
||||
logger_callback_log(logger, print_debug_logger, nullptr, nullptr);
|
||||
|
||||
@ -55,8 +60,7 @@ static void test_basic(void)
|
||||
uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE];
|
||||
uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE];
|
||||
crypto_new_keypair(rng, self_public_key, self_secret_key);
|
||||
const Network *ns = system_network();
|
||||
TCP_Server *tcp_s = new_TCP_server(logger, rng, ns, USE_IPV6, NUM_PORTS, ports, self_secret_key, nullptr, nullptr);
|
||||
TCP_Server *tcp_s = new_tcp_server(logger, mem, rng, ns, USE_IPV6, NUM_PORTS, ports, self_secret_key, nullptr, nullptr);
|
||||
ck_assert_msg(tcp_s != nullptr, "Failed to create a TCP relay server.");
|
||||
ck_assert_msg(tcp_server_listen_count(tcp_s) == NUM_PORTS,
|
||||
"Failed to bind a TCP relay server to all %d attempted ports.", NUM_PORTS);
|
||||
@ -70,7 +74,7 @@ static void test_basic(void)
|
||||
for (uint8_t i = 0; i < NUM_PORTS; i++) {
|
||||
sock = net_socket(ns, net_family_ipv6(), TOX_SOCK_STREAM, TOX_PROTO_TCP);
|
||||
localhost.port = net_htons(ports[i]);
|
||||
bool ret = net_connect(logger, sock, &localhost);
|
||||
bool ret = net_connect(mem, logger, sock, &localhost);
|
||||
ck_assert_msg(ret, "Failed to connect to created TCP relay server on port %d (%d).", ports[i], errno);
|
||||
|
||||
// Leave open one connection for the next test.
|
||||
@ -110,14 +114,14 @@ static void test_basic(void)
|
||||
&localhost) == TCP_CLIENT_HANDSHAKE_SIZE - 1,
|
||||
"An attempt to send the initial handshake minus last byte failed.");
|
||||
|
||||
do_TCP_server_delay(tcp_s, mono_time, 50);
|
||||
do_tcp_server_delay(tcp_s, mono_time, 50);
|
||||
|
||||
ck_assert_msg(net_send(ns, logger, sock, handshake + (TCP_CLIENT_HANDSHAKE_SIZE - 1), 1, &localhost) == 1,
|
||||
"The attempt to send the last byte of handshake failed.");
|
||||
|
||||
free(handshake);
|
||||
|
||||
do_TCP_server_delay(tcp_s, mono_time, 50);
|
||||
do_tcp_server_delay(tcp_s, mono_time, 50);
|
||||
|
||||
// Receiving server response and decrypting it
|
||||
uint8_t response[TCP_SERVER_HANDSHAKE_SIZE];
|
||||
@ -157,7 +161,7 @@ static void test_basic(void)
|
||||
|
||||
c_sleep(50);
|
||||
mono_time_update(mono_time);
|
||||
do_TCP_server(tcp_s, mono_time);
|
||||
do_tcp_server(tcp_s, mono_time);
|
||||
}
|
||||
|
||||
// Receiving the second response and verifying its validity
|
||||
@ -181,33 +185,35 @@ static void test_basic(void)
|
||||
|
||||
// Closing connections.
|
||||
kill_sock(ns, sock);
|
||||
kill_TCP_server(tcp_s);
|
||||
kill_tcp_server(tcp_s);
|
||||
|
||||
logger_kill(logger);
|
||||
mono_time_free(mono_time);
|
||||
mono_time_free(mem, mono_time);
|
||||
}
|
||||
|
||||
struct sec_TCP_con {
|
||||
Socket sock;
|
||||
const Network *ns;
|
||||
const Memory *mem;
|
||||
uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
|
||||
uint8_t recv_nonce[CRYPTO_NONCE_SIZE];
|
||||
uint8_t sent_nonce[CRYPTO_NONCE_SIZE];
|
||||
uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
|
||||
};
|
||||
|
||||
static struct sec_TCP_con *new_TCP_con(const Logger *logger, const Random *rng, const Network *ns, TCP_Server *tcp_s, Mono_Time *mono_time)
|
||||
static struct sec_TCP_con *new_tcp_con(const Logger *logger, const Memory *mem, const Random *rng, const Network *ns, TCP_Server *tcp_s, Mono_Time *mono_time)
|
||||
{
|
||||
struct sec_TCP_con *sec_c = (struct sec_TCP_con *)malloc(sizeof(struct sec_TCP_con));
|
||||
ck_assert(sec_c != nullptr);
|
||||
sec_c->ns = ns;
|
||||
sec_c->mem = mem;
|
||||
Socket sock = net_socket(ns, net_family_ipv6(), TOX_SOCK_STREAM, TOX_PROTO_TCP);
|
||||
|
||||
IP_Port localhost;
|
||||
localhost.ip = get_loopback();
|
||||
localhost.port = net_htons(ports[random_u32(rng) % NUM_PORTS]);
|
||||
|
||||
bool ok = net_connect(logger, sock, &localhost);
|
||||
bool ok = net_connect(mem, logger, sock, &localhost);
|
||||
ck_assert_msg(ok, "Failed to connect to the test TCP relay server.");
|
||||
|
||||
uint8_t f_secret_key[CRYPTO_SECRET_KEY_SIZE];
|
||||
@ -231,12 +237,12 @@ static struct sec_TCP_con *new_TCP_con(const Logger *logger, const Random *rng,
|
||||
&localhost) == TCP_CLIENT_HANDSHAKE_SIZE - 1,
|
||||
"Failed to send the first portion of the handshake to the TCP relay server.");
|
||||
|
||||
do_TCP_server_delay(tcp_s, mono_time, 50);
|
||||
do_tcp_server_delay(tcp_s, mono_time, 50);
|
||||
|
||||
ck_assert_msg(net_send(ns, logger, sock, handshake + (TCP_CLIENT_HANDSHAKE_SIZE - 1), 1, &localhost) == 1,
|
||||
"Failed to send last byte of handshake.");
|
||||
|
||||
do_TCP_server_delay(tcp_s, mono_time, 50);
|
||||
do_tcp_server_delay(tcp_s, mono_time, 50);
|
||||
|
||||
uint8_t response[TCP_SERVER_HANDSHAKE_SIZE];
|
||||
uint8_t response_plain[TCP_HANDSHAKE_PLAIN_SIZE];
|
||||
@ -251,13 +257,13 @@ static struct sec_TCP_con *new_TCP_con(const Logger *logger, const Random *rng,
|
||||
return sec_c;
|
||||
}
|
||||
|
||||
static void kill_TCP_con(struct sec_TCP_con *con)
|
||||
static void kill_tcp_con(struct sec_TCP_con *con)
|
||||
{
|
||||
kill_sock(con->ns, con->sock);
|
||||
free(con);
|
||||
}
|
||||
|
||||
static int write_packet_TCP_test_connection(const Logger *logger, struct sec_TCP_con *con, const uint8_t *data,
|
||||
static int write_packet_tcp_test_connection(const Logger *logger, struct sec_TCP_con *con, const uint8_t *data,
|
||||
uint16_t length)
|
||||
{
|
||||
VLA(uint8_t, packet, sizeof(uint16_t) + length + CRYPTO_MAC_SIZE);
|
||||
@ -281,7 +287,7 @@ static int write_packet_TCP_test_connection(const Logger *logger, struct sec_TCP
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read_packet_sec_TCP(const Logger *logger, struct sec_TCP_con *con, uint8_t *data, uint16_t length)
|
||||
static int read_packet_sec_tcp(const Logger *logger, struct sec_TCP_con *con, uint8_t *data, uint16_t length)
|
||||
{
|
||||
IP_Port localhost;
|
||||
localhost.ip = get_loopback();
|
||||
@ -297,44 +303,48 @@ static int read_packet_sec_TCP(const Logger *logger, struct sec_TCP_con *con, ui
|
||||
|
||||
static void test_some(void)
|
||||
{
|
||||
Mono_Time *mono_time = mono_time_new(nullptr, nullptr);
|
||||
const Random *rng = system_random();
|
||||
ck_assert(rng != nullptr);
|
||||
Logger *logger = logger_new();
|
||||
const Network *ns = system_network();
|
||||
ck_assert(ns != nullptr);
|
||||
const Memory *mem = system_memory();
|
||||
ck_assert(mem != nullptr);
|
||||
|
||||
Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr);
|
||||
Logger *logger = logger_new();
|
||||
|
||||
uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE];
|
||||
uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE];
|
||||
crypto_new_keypair(rng, self_public_key, self_secret_key);
|
||||
TCP_Server *tcp_s = new_TCP_server(logger, rng, ns, USE_IPV6, NUM_PORTS, ports, self_secret_key, nullptr, nullptr);
|
||||
TCP_Server *tcp_s = new_tcp_server(logger, mem, rng, ns, USE_IPV6, NUM_PORTS, ports, self_secret_key, nullptr, nullptr);
|
||||
ck_assert_msg(tcp_s != nullptr, "Failed to create TCP relay server");
|
||||
ck_assert_msg(tcp_server_listen_count(tcp_s) == NUM_PORTS, "Failed to bind to all ports.");
|
||||
|
||||
struct sec_TCP_con *con1 = new_TCP_con(logger, rng, ns, tcp_s, mono_time);
|
||||
struct sec_TCP_con *con2 = new_TCP_con(logger, rng, ns, tcp_s, mono_time);
|
||||
struct sec_TCP_con *con3 = new_TCP_con(logger, rng, ns, tcp_s, mono_time);
|
||||
struct sec_TCP_con *con1 = new_tcp_con(logger, mem, rng, ns, tcp_s, mono_time);
|
||||
struct sec_TCP_con *con2 = new_tcp_con(logger, mem, rng, ns, tcp_s, mono_time);
|
||||
struct sec_TCP_con *con3 = new_tcp_con(logger, mem, rng, ns, tcp_s, mono_time);
|
||||
|
||||
uint8_t requ_p[1 + CRYPTO_PUBLIC_KEY_SIZE];
|
||||
requ_p[0] = TCP_PACKET_ROUTING_REQUEST;
|
||||
|
||||
// Sending wrong public keys to test server response.
|
||||
memcpy(requ_p + 1, con3->public_key, CRYPTO_PUBLIC_KEY_SIZE);
|
||||
write_packet_TCP_test_connection(logger, con1, requ_p, sizeof(requ_p));
|
||||
write_packet_tcp_test_connection(logger, con1, requ_p, sizeof(requ_p));
|
||||
memcpy(requ_p + 1, con1->public_key, CRYPTO_PUBLIC_KEY_SIZE);
|
||||
write_packet_TCP_test_connection(logger, con3, requ_p, sizeof(requ_p));
|
||||
write_packet_tcp_test_connection(logger, con3, requ_p, sizeof(requ_p));
|
||||
|
||||
do_TCP_server_delay(tcp_s, mono_time, 50);
|
||||
do_tcp_server_delay(tcp_s, mono_time, 50);
|
||||
|
||||
// Testing response from connection 1
|
||||
uint8_t data[2048];
|
||||
int len = read_packet_sec_TCP(logger, con1, data, 2 + 1 + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_MAC_SIZE);
|
||||
int len = read_packet_sec_tcp(logger, con1, data, 2 + 1 + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_MAC_SIZE);
|
||||
ck_assert_msg(len == 1 + 1 + CRYPTO_PUBLIC_KEY_SIZE, "Wrong response packet length of %d.", len);
|
||||
ck_assert_msg(data[0] == TCP_PACKET_ROUTING_RESPONSE, "Wrong response packet id of %d.", data[0]);
|
||||
ck_assert_msg(data[1] == 16, "Server didn't refuse connection using wrong public key.");
|
||||
ck_assert_msg(pk_equal(data + 2, con3->public_key), "Key in response packet wrong.");
|
||||
|
||||
// Connection 3
|
||||
len = read_packet_sec_TCP(logger, con3, data, 2 + 1 + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_MAC_SIZE);
|
||||
len = read_packet_sec_tcp(logger, con3, data, 2 + 1 + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_MAC_SIZE);
|
||||
ck_assert_msg(len == 1 + 1 + CRYPTO_PUBLIC_KEY_SIZE, "Wrong response packet length of %d.", len);
|
||||
ck_assert_msg(data[0] == TCP_PACKET_ROUTING_RESPONSE, "Wrong response packet id of %d.", data[0]);
|
||||
ck_assert_msg(data[1] == 16, "Server didn't refuse connection using wrong public key.");
|
||||
@ -342,67 +352,67 @@ static void test_some(void)
|
||||
|
||||
uint8_t test_packet[512] = {16, 17, 16, 86, 99, 127, 255, 189, 78}; // What is this packet????
|
||||
|
||||
write_packet_TCP_test_connection(logger, con3, test_packet, sizeof(test_packet));
|
||||
write_packet_TCP_test_connection(logger, con3, test_packet, sizeof(test_packet));
|
||||
write_packet_TCP_test_connection(logger, con3, test_packet, sizeof(test_packet));
|
||||
write_packet_tcp_test_connection(logger, con3, test_packet, sizeof(test_packet));
|
||||
write_packet_tcp_test_connection(logger, con3, test_packet, sizeof(test_packet));
|
||||
write_packet_tcp_test_connection(logger, con3, test_packet, sizeof(test_packet));
|
||||
|
||||
do_TCP_server_delay(tcp_s, mono_time, 50);
|
||||
do_tcp_server_delay(tcp_s, mono_time, 50);
|
||||
|
||||
len = read_packet_sec_TCP(logger, con1, data, 2 + 2 + CRYPTO_MAC_SIZE);
|
||||
len = read_packet_sec_tcp(logger, con1, data, 2 + 2 + CRYPTO_MAC_SIZE);
|
||||
ck_assert_msg(len == 2, "wrong len %d", len);
|
||||
ck_assert_msg(data[0] == TCP_PACKET_CONNECTION_NOTIFICATION, "wrong packet id %u", data[0]);
|
||||
ck_assert_msg(data[1] == 16, "wrong peer id %u", data[1]);
|
||||
len = read_packet_sec_TCP(logger, con3, data, 2 + 2 + CRYPTO_MAC_SIZE);
|
||||
len = read_packet_sec_tcp(logger, con3, data, 2 + 2 + CRYPTO_MAC_SIZE);
|
||||
ck_assert_msg(len == 2, "wrong len %d", len);
|
||||
ck_assert_msg(data[0] == TCP_PACKET_CONNECTION_NOTIFICATION, "wrong packet id %u", data[0]);
|
||||
ck_assert_msg(data[1] == 16, "wrong peer id %u", data[1]);
|
||||
len = read_packet_sec_TCP(logger, con1, data, 2 + sizeof(test_packet) + CRYPTO_MAC_SIZE);
|
||||
len = read_packet_sec_tcp(logger, con1, data, 2 + sizeof(test_packet) + CRYPTO_MAC_SIZE);
|
||||
ck_assert_msg(len == sizeof(test_packet), "wrong len %d", len);
|
||||
ck_assert_msg(memcmp(data, test_packet, sizeof(test_packet)) == 0, "packet is wrong %u %u %u %u", data[0], data[1],
|
||||
data[sizeof(test_packet) - 2], data[sizeof(test_packet) - 1]);
|
||||
len = read_packet_sec_TCP(logger, con1, data, 2 + sizeof(test_packet) + CRYPTO_MAC_SIZE);
|
||||
len = read_packet_sec_tcp(logger, con1, data, 2 + sizeof(test_packet) + CRYPTO_MAC_SIZE);
|
||||
ck_assert_msg(len == sizeof(test_packet), "wrong len %d", len);
|
||||
ck_assert_msg(memcmp(data, test_packet, sizeof(test_packet)) == 0, "packet is wrong %u %u %u %u", data[0], data[1],
|
||||
data[sizeof(test_packet) - 2], data[sizeof(test_packet) - 1]);
|
||||
len = read_packet_sec_TCP(logger, con1, data, 2 + sizeof(test_packet) + CRYPTO_MAC_SIZE);
|
||||
len = read_packet_sec_tcp(logger, con1, data, 2 + sizeof(test_packet) + CRYPTO_MAC_SIZE);
|
||||
ck_assert_msg(len == sizeof(test_packet), "wrong len %d", len);
|
||||
ck_assert_msg(memcmp(data, test_packet, sizeof(test_packet)) == 0, "packet is wrong %u %u %u %u", data[0], data[1],
|
||||
data[sizeof(test_packet) - 2], data[sizeof(test_packet) - 1]);
|
||||
write_packet_TCP_test_connection(logger, con1, test_packet, sizeof(test_packet));
|
||||
write_packet_TCP_test_connection(logger, con1, test_packet, sizeof(test_packet));
|
||||
write_packet_TCP_test_connection(logger, con1, test_packet, sizeof(test_packet));
|
||||
do_TCP_server_delay(tcp_s, mono_time, 50);
|
||||
len = read_packet_sec_TCP(logger, con3, data, 2 + sizeof(test_packet) + CRYPTO_MAC_SIZE);
|
||||
write_packet_tcp_test_connection(logger, con1, test_packet, sizeof(test_packet));
|
||||
write_packet_tcp_test_connection(logger, con1, test_packet, sizeof(test_packet));
|
||||
write_packet_tcp_test_connection(logger, con1, test_packet, sizeof(test_packet));
|
||||
do_tcp_server_delay(tcp_s, mono_time, 50);
|
||||
len = read_packet_sec_tcp(logger, con3, data, 2 + sizeof(test_packet) + CRYPTO_MAC_SIZE);
|
||||
ck_assert_msg(len == sizeof(test_packet), "wrong len %d", len);
|
||||
ck_assert_msg(memcmp(data, test_packet, sizeof(test_packet)) == 0, "packet is wrong %u %u %u %u", data[0], data[1],
|
||||
data[sizeof(test_packet) - 2], data[sizeof(test_packet) - 1]);
|
||||
len = read_packet_sec_TCP(logger, con3, data, 2 + sizeof(test_packet) + CRYPTO_MAC_SIZE);
|
||||
len = read_packet_sec_tcp(logger, con3, data, 2 + sizeof(test_packet) + CRYPTO_MAC_SIZE);
|
||||
ck_assert_msg(len == sizeof(test_packet), "wrong len %d", len);
|
||||
ck_assert_msg(memcmp(data, test_packet, sizeof(test_packet)) == 0, "packet is wrong %u %u %u %u", data[0], data[1],
|
||||
data[sizeof(test_packet) - 2], data[sizeof(test_packet) - 1]);
|
||||
len = read_packet_sec_TCP(logger, con3, data, 2 + sizeof(test_packet) + CRYPTO_MAC_SIZE);
|
||||
len = read_packet_sec_tcp(logger, con3, data, 2 + sizeof(test_packet) + CRYPTO_MAC_SIZE);
|
||||
ck_assert_msg(len == sizeof(test_packet), "wrong len %d", len);
|
||||
ck_assert_msg(memcmp(data, test_packet, sizeof(test_packet)) == 0, "packet is wrong %u %u %u %u", data[0], data[1],
|
||||
data[sizeof(test_packet) - 2], data[sizeof(test_packet) - 1]);
|
||||
|
||||
uint8_t ping_packet[1 + sizeof(uint64_t)] = {TCP_PACKET_PING, 8, 6, 9, 67};
|
||||
write_packet_TCP_test_connection(logger, con1, ping_packet, sizeof(ping_packet));
|
||||
write_packet_tcp_test_connection(logger, con1, ping_packet, sizeof(ping_packet));
|
||||
|
||||
do_TCP_server_delay(tcp_s, mono_time, 50);
|
||||
do_tcp_server_delay(tcp_s, mono_time, 50);
|
||||
|
||||
len = read_packet_sec_TCP(logger, con1, data, 2 + sizeof(ping_packet) + CRYPTO_MAC_SIZE);
|
||||
len = read_packet_sec_tcp(logger, con1, data, 2 + sizeof(ping_packet) + CRYPTO_MAC_SIZE);
|
||||
ck_assert_msg(len == sizeof(ping_packet), "wrong len %d", len);
|
||||
ck_assert_msg(data[0] == TCP_PACKET_PONG, "wrong packet id %u", data[0]);
|
||||
ck_assert_msg(memcmp(ping_packet + 1, data + 1, sizeof(uint64_t)) == 0, "wrong packet data");
|
||||
|
||||
// Kill off the connections
|
||||
kill_TCP_server(tcp_s);
|
||||
kill_TCP_con(con1);
|
||||
kill_TCP_con(con2);
|
||||
kill_TCP_con(con3);
|
||||
kill_tcp_server(tcp_s);
|
||||
kill_tcp_con(con1);
|
||||
kill_tcp_con(con2);
|
||||
kill_tcp_con(con3);
|
||||
|
||||
logger_kill(logger);
|
||||
mono_time_free(mono_time);
|
||||
mono_time_free(mem, mono_time);
|
||||
}
|
||||
|
||||
static int response_callback_good;
|
||||
@ -488,16 +498,20 @@ static int oob_data_callback(void *object, const uint8_t *public_key, const uint
|
||||
|
||||
static void test_client(void)
|
||||
{
|
||||
Mono_Time *mono_time = mono_time_new(nullptr, nullptr);
|
||||
const Random *rng = system_random();
|
||||
ck_assert(rng != nullptr);
|
||||
const Network *ns = system_network();
|
||||
ck_assert(ns != nullptr);
|
||||
const Memory *mem = system_memory();
|
||||
ck_assert(mem != nullptr);
|
||||
|
||||
Logger *logger = logger_new();
|
||||
Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr);
|
||||
|
||||
uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE];
|
||||
uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE];
|
||||
crypto_new_keypair(rng, self_public_key, self_secret_key);
|
||||
const Network *ns = system_network();
|
||||
TCP_Server *tcp_s = new_TCP_server(logger, rng, ns, USE_IPV6, NUM_PORTS, ports, self_secret_key, nullptr, nullptr);
|
||||
TCP_Server *tcp_s = new_tcp_server(logger, mem, rng, ns, USE_IPV6, NUM_PORTS, ports, self_secret_key, nullptr, nullptr);
|
||||
ck_assert_msg(tcp_s != nullptr, "Failed to create a TCP relay server.");
|
||||
ck_assert_msg(tcp_server_listen_count(tcp_s) == NUM_PORTS, "Failed to bind the relay server to all ports.");
|
||||
|
||||
@ -509,9 +523,8 @@ static void test_client(void)
|
||||
ip_port_tcp_s.port = net_htons(ports[random_u32(rng) % NUM_PORTS]);
|
||||
ip_port_tcp_s.ip = get_loopback();
|
||||
|
||||
TCP_Client_Connection *conn = new_TCP_connection(logger, mono_time, rng, ns, &ip_port_tcp_s, self_public_key, f_public_key,
|
||||
f_secret_key, nullptr);
|
||||
do_TCP_connection(logger, mono_time, conn, nullptr);
|
||||
TCP_Client_Connection *conn = new_tcp_connection(logger, mem, mono_time, rng, ns, &ip_port_tcp_s, self_public_key, f_public_key, f_secret_key, nullptr);
|
||||
do_tcp_connection(logger, mono_time, conn, nullptr);
|
||||
c_sleep(50);
|
||||
|
||||
// The connection status should be unconfirmed here because we have finished
|
||||
@ -519,22 +532,22 @@ static void test_client(void)
|
||||
ck_assert_msg(tcp_con_status(conn) == TCP_CLIENT_UNCONFIRMED, "Wrong connection status. Expected: %d, is: %d.",
|
||||
TCP_CLIENT_UNCONFIRMED, tcp_con_status(conn));
|
||||
|
||||
do_TCP_server_delay(tcp_s, mono_time, 50); // Now let the server handle requests...
|
||||
do_tcp_server_delay(tcp_s, mono_time, 50); // Now let the server handle requests...
|
||||
|
||||
const uint8_t LOOP_SIZE = 3;
|
||||
const uint8_t loop_size = 3;
|
||||
|
||||
for (uint8_t i = 0; i < LOOP_SIZE; i++) {
|
||||
for (uint8_t i = 0; i < loop_size; i++) {
|
||||
mono_time_update(mono_time);
|
||||
do_TCP_connection(logger, mono_time, conn, nullptr); // Run the connection loop.
|
||||
do_tcp_connection(logger, mono_time, conn, nullptr); // Run the connection loop.
|
||||
|
||||
// The status of the connection should continue to be TCP_CLIENT_CONFIRMED after multiple subsequent do_TCP_connection() calls.
|
||||
// The status of the connection should continue to be TCP_CLIENT_CONFIRMED after multiple subsequent do_tcp_connection() calls.
|
||||
ck_assert_msg(tcp_con_status(conn) == TCP_CLIENT_CONFIRMED, "Wrong connection status. Expected: %d, is: %d",
|
||||
TCP_CLIENT_CONFIRMED, tcp_con_status(conn));
|
||||
|
||||
c_sleep(i == LOOP_SIZE - 1 ? 0 : 500); // Sleep for 500ms on all except third loop.
|
||||
c_sleep(i == loop_size - 1 ? 0 : 500); // Sleep for 500ms on all except third loop.
|
||||
}
|
||||
|
||||
do_TCP_server_delay(tcp_s, mono_time, 50);
|
||||
do_tcp_server_delay(tcp_s, mono_time, 50);
|
||||
|
||||
// And still after the server runs again.
|
||||
ck_assert_msg(tcp_con_status(conn) == TCP_CLIENT_CONFIRMED, "Wrong status. Expected: %d, is: %d", TCP_CLIENT_CONFIRMED,
|
||||
@ -544,7 +557,7 @@ static void test_client(void)
|
||||
uint8_t f2_secret_key[CRYPTO_SECRET_KEY_SIZE];
|
||||
crypto_new_keypair(rng, f2_public_key, f2_secret_key);
|
||||
ip_port_tcp_s.port = net_htons(ports[random_u32(rng) % NUM_PORTS]);
|
||||
TCP_Client_Connection *conn2 = new_TCP_connection(logger, mono_time, rng, ns, &ip_port_tcp_s, self_public_key, f2_public_key,
|
||||
TCP_Client_Connection *conn2 = new_tcp_connection(logger, mem, mono_time, rng, ns, &ip_port_tcp_s, self_public_key, f2_public_key,
|
||||
f2_secret_key, nullptr);
|
||||
|
||||
// The client should call this function (defined earlier) during the routing process.
|
||||
@ -559,13 +572,13 @@ static void test_client(void)
|
||||
// These integers will increment per successful callback.
|
||||
oob_data_callback_good = response_callback_good = status_callback_good = data_callback_good = 0;
|
||||
|
||||
do_TCP_connection(logger, mono_time, conn, nullptr);
|
||||
do_TCP_connection(logger, mono_time, conn2, nullptr);
|
||||
do_tcp_connection(logger, mono_time, conn, nullptr);
|
||||
do_tcp_connection(logger, mono_time, conn2, nullptr);
|
||||
|
||||
do_TCP_server_delay(tcp_s, mono_time, 50);
|
||||
do_tcp_server_delay(tcp_s, mono_time, 50);
|
||||
|
||||
do_TCP_connection(logger, mono_time, conn, nullptr);
|
||||
do_TCP_connection(logger, mono_time, conn2, nullptr);
|
||||
do_tcp_connection(logger, mono_time, conn, nullptr);
|
||||
do_tcp_connection(logger, mono_time, conn2, nullptr);
|
||||
c_sleep(50);
|
||||
|
||||
uint8_t data[5] = {1, 2, 3, 4, 5};
|
||||
@ -574,10 +587,10 @@ static void test_client(void)
|
||||
send_routing_request(logger, conn, f2_public_key);
|
||||
send_routing_request(logger, conn2, f_public_key);
|
||||
|
||||
do_TCP_server_delay(tcp_s, mono_time, 50);
|
||||
do_tcp_server_delay(tcp_s, mono_time, 50);
|
||||
|
||||
do_TCP_connection(logger, mono_time, conn, nullptr);
|
||||
do_TCP_connection(logger, mono_time, conn2, nullptr);
|
||||
do_tcp_connection(logger, mono_time, conn, nullptr);
|
||||
do_tcp_connection(logger, mono_time, conn2, nullptr);
|
||||
|
||||
// All callback methods save data should have run during the above network prodding.
|
||||
ck_assert_msg(oob_data_callback_good == 1, "OOB callback not called");
|
||||
@ -588,42 +601,46 @@ static void test_client(void)
|
||||
ck_assert_msg(status_callback_connection_id == response_callback_connection_id,
|
||||
"Status and response callback connection IDs are not equal.");
|
||||
|
||||
do_TCP_server_delay(tcp_s, mono_time, 50);
|
||||
do_tcp_server_delay(tcp_s, mono_time, 50);
|
||||
|
||||
ck_assert_msg(send_data(logger, conn2, 0, data, 5) == 1, "Failed a send_data() call.");
|
||||
|
||||
do_TCP_server_delay(tcp_s, mono_time, 50);
|
||||
do_tcp_server_delay(tcp_s, mono_time, 50);
|
||||
|
||||
do_TCP_connection(logger, mono_time, conn, nullptr);
|
||||
do_TCP_connection(logger, mono_time, conn2, nullptr);
|
||||
do_tcp_connection(logger, mono_time, conn, nullptr);
|
||||
do_tcp_connection(logger, mono_time, conn2, nullptr);
|
||||
ck_assert_msg(data_callback_good == 1, "Data callback was not called.");
|
||||
status_callback_good = 0;
|
||||
send_disconnect_request(logger, conn2, 0);
|
||||
|
||||
do_TCP_server_delay(tcp_s, mono_time, 50);
|
||||
do_tcp_server_delay(tcp_s, mono_time, 50);
|
||||
|
||||
do_TCP_connection(logger, mono_time, conn, nullptr);
|
||||
do_TCP_connection(logger, mono_time, conn2, nullptr);
|
||||
do_tcp_connection(logger, mono_time, conn, nullptr);
|
||||
do_tcp_connection(logger, mono_time, conn2, nullptr);
|
||||
ck_assert_msg(status_callback_good == 1, "Status callback not called");
|
||||
ck_assert_msg(status_callback_status == 1, "Wrong status callback status.");
|
||||
|
||||
// Kill off all connections and servers.
|
||||
kill_TCP_server(tcp_s);
|
||||
kill_TCP_connection(conn);
|
||||
kill_TCP_connection(conn2);
|
||||
kill_tcp_server(tcp_s);
|
||||
kill_tcp_connection(conn);
|
||||
kill_tcp_connection(conn2);
|
||||
|
||||
logger_kill(logger);
|
||||
mono_time_free(mono_time);
|
||||
mono_time_free(mem, mono_time);
|
||||
}
|
||||
|
||||
// Test how the client handles servers that don't respond.
|
||||
static void test_client_invalid(void)
|
||||
{
|
||||
Mono_Time *mono_time = mono_time_new(nullptr, nullptr);
|
||||
const Random *rng = system_random();
|
||||
ck_assert(rng != nullptr);
|
||||
Logger *logger = logger_new();
|
||||
const Network *ns = system_network();
|
||||
ck_assert(ns != nullptr);
|
||||
const Memory *mem = system_memory();
|
||||
ck_assert(mem != nullptr);
|
||||
|
||||
Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr);
|
||||
Logger *logger = logger_new();
|
||||
|
||||
uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE];
|
||||
uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE];
|
||||
@ -636,12 +653,12 @@ static void test_client_invalid(void)
|
||||
|
||||
ip_port_tcp_s.port = net_htons(ports[random_u32(rng) % NUM_PORTS]);
|
||||
ip_port_tcp_s.ip = get_loopback();
|
||||
TCP_Client_Connection *conn = new_TCP_connection(logger, mono_time, rng, ns, &ip_port_tcp_s,
|
||||
TCP_Client_Connection *conn = new_tcp_connection(logger, mem, mono_time, rng, ns, &ip_port_tcp_s,
|
||||
self_public_key, f_public_key, f_secret_key, nullptr);
|
||||
|
||||
// Run the client's main loop but not the server.
|
||||
mono_time_update(mono_time);
|
||||
do_TCP_connection(logger, mono_time, conn, nullptr);
|
||||
do_tcp_connection(logger, mono_time, conn, nullptr);
|
||||
c_sleep(50);
|
||||
|
||||
// After 50ms of no response...
|
||||
@ -650,20 +667,20 @@ static void test_client_invalid(void)
|
||||
// After 5s...
|
||||
c_sleep(5000);
|
||||
mono_time_update(mono_time);
|
||||
do_TCP_connection(logger, mono_time, conn, nullptr);
|
||||
do_tcp_connection(logger, mono_time, conn, nullptr);
|
||||
ck_assert_msg(tcp_con_status(conn) == TCP_CLIENT_CONNECTING, "Wrong status. Expected: %d, is: %d.",
|
||||
TCP_CLIENT_CONNECTING, tcp_con_status(conn));
|
||||
// 11s... (Should wait for 10 before giving up.)
|
||||
c_sleep(6000);
|
||||
mono_time_update(mono_time);
|
||||
do_TCP_connection(logger, mono_time, conn, nullptr);
|
||||
do_tcp_connection(logger, mono_time, conn, nullptr);
|
||||
ck_assert_msg(tcp_con_status(conn) == TCP_CLIENT_DISCONNECTED, "Wrong status. Expected: %d, is: %d.",
|
||||
TCP_CLIENT_DISCONNECTED, tcp_con_status(conn));
|
||||
|
||||
kill_TCP_connection(conn);
|
||||
kill_tcp_connection(conn);
|
||||
|
||||
logger_kill(logger);
|
||||
mono_time_free(mono_time);
|
||||
mono_time_free(mem, mono_time);
|
||||
}
|
||||
|
||||
#include "../toxcore/TCP_connection.h"
|
||||
@ -694,27 +711,31 @@ static int tcp_data_callback(void *object, int id, const uint8_t *data, uint16_t
|
||||
|
||||
static void test_tcp_connection(void)
|
||||
{
|
||||
Mono_Time *mono_time = mono_time_new(nullptr, nullptr);
|
||||
Logger *logger = logger_new();
|
||||
const Random *rng = system_random();
|
||||
ck_assert(rng != nullptr);
|
||||
const Network *ns = system_network();
|
||||
ck_assert(ns != nullptr);
|
||||
const Memory *mem = system_memory();
|
||||
ck_assert(mem != nullptr);
|
||||
|
||||
Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr);
|
||||
Logger *logger = logger_new();
|
||||
|
||||
tcp_data_callback_called = 0;
|
||||
uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE];
|
||||
uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE];
|
||||
crypto_new_keypair(rng, self_public_key, self_secret_key);
|
||||
TCP_Server *tcp_s = new_TCP_server(logger, rng, ns, USE_IPV6, NUM_PORTS, ports, self_secret_key, nullptr, nullptr);
|
||||
TCP_Server *tcp_s = new_tcp_server(logger, mem, rng, ns, USE_IPV6, NUM_PORTS, ports, self_secret_key, nullptr, nullptr);
|
||||
ck_assert_msg(pk_equal(tcp_server_public_key(tcp_s), self_public_key), "Wrong public key");
|
||||
|
||||
TCP_Proxy_Info proxy_info;
|
||||
proxy_info.proxy_type = TCP_PROXY_NONE;
|
||||
crypto_new_keypair(rng, self_public_key, self_secret_key);
|
||||
TCP_Connections *tc_1 = new_tcp_connections(logger, rng, ns, mono_time, self_secret_key, &proxy_info);
|
||||
TCP_Connections *tc_1 = new_tcp_connections(logger, mem, rng, ns, mono_time, self_secret_key, &proxy_info);
|
||||
ck_assert_msg(pk_equal(tcp_connections_public_key(tc_1), self_public_key), "Wrong public key");
|
||||
|
||||
crypto_new_keypair(rng, self_public_key, self_secret_key);
|
||||
TCP_Connections *tc_2 = new_tcp_connections(logger, rng, ns, mono_time, self_secret_key, &proxy_info);
|
||||
TCP_Connections *tc_2 = new_tcp_connections(logger, mem, rng, ns, mono_time, self_secret_key, &proxy_info);
|
||||
ck_assert_msg(pk_equal(tcp_connections_public_key(tc_2), self_public_key), "Wrong public key");
|
||||
|
||||
IP_Port ip_port_tcp_s;
|
||||
@ -736,17 +757,17 @@ static void test_tcp_connection(void)
|
||||
ck_assert_msg(new_tcp_connection_to(tc_2, tcp_connections_public_key(tc_1), 123) == -1,
|
||||
"Managed to read same connection\n");
|
||||
|
||||
do_TCP_server_delay(tcp_s, mono_time, 50);
|
||||
do_tcp_server_delay(tcp_s, mono_time, 50);
|
||||
|
||||
do_tcp_connections(logger, tc_1, nullptr);
|
||||
do_tcp_connections(logger, tc_2, nullptr);
|
||||
|
||||
do_TCP_server_delay(tcp_s, mono_time, 50);
|
||||
do_tcp_server_delay(tcp_s, mono_time, 50);
|
||||
|
||||
do_tcp_connections(logger, tc_1, nullptr);
|
||||
do_tcp_connections(logger, tc_2, nullptr);
|
||||
|
||||
do_TCP_server_delay(tcp_s, mono_time, 50);
|
||||
do_tcp_server_delay(tcp_s, mono_time, 50);
|
||||
|
||||
do_tcp_connections(logger, tc_1, nullptr);
|
||||
do_tcp_connections(logger, tc_2, nullptr);
|
||||
@ -755,7 +776,7 @@ static void test_tcp_connection(void)
|
||||
ck_assert_msg(ret == 0, "could not send packet.");
|
||||
set_packet_tcp_connection_callback(tc_2, &tcp_data_callback, (void *) 120397);
|
||||
|
||||
do_TCP_server_delay(tcp_s, mono_time, 50);
|
||||
do_tcp_server_delay(tcp_s, mono_time, 50);
|
||||
|
||||
do_tcp_connections(logger, tc_1, nullptr);
|
||||
do_tcp_connections(logger, tc_2, nullptr);
|
||||
@ -764,7 +785,7 @@ static void test_tcp_connection(void)
|
||||
ck_assert_msg(tcp_connection_to_online_tcp_relays(tc_1, 0) == 1, "Wrong number of connected relays");
|
||||
ck_assert_msg(kill_tcp_connection_to(tc_1, 0) == 0, "could not kill connection to\n");
|
||||
|
||||
do_TCP_server_delay(tcp_s, mono_time, 50);
|
||||
do_tcp_server_delay(tcp_s, mono_time, 50);
|
||||
|
||||
do_tcp_connections(logger, tc_1, nullptr);
|
||||
do_tcp_connections(logger, tc_2, nullptr);
|
||||
@ -772,12 +793,12 @@ static void test_tcp_connection(void)
|
||||
ck_assert_msg(send_packet_tcp_connection(tc_1, 0, (const uint8_t *)"Gentoo", 6) == -1, "could send packet.");
|
||||
ck_assert_msg(kill_tcp_connection_to(tc_2, 0) == 0, "could not kill connection to\n");
|
||||
|
||||
kill_TCP_server(tcp_s);
|
||||
kill_tcp_server(tcp_s);
|
||||
kill_tcp_connections(tc_1);
|
||||
kill_tcp_connections(tc_2);
|
||||
|
||||
logger_kill(logger);
|
||||
mono_time_free(mono_time);
|
||||
mono_time_free(mem, mono_time);
|
||||
}
|
||||
|
||||
static bool tcp_oobdata_callback_called;
|
||||
@ -803,11 +824,15 @@ static int tcp_oobdata_callback(void *object, const uint8_t *public_key, unsigne
|
||||
|
||||
static void test_tcp_connection2(void)
|
||||
{
|
||||
Mono_Time *mono_time = mono_time_new(nullptr, nullptr);
|
||||
Logger *logger = logger_new();
|
||||
const Random *rng = system_random();
|
||||
ck_assert(rng != nullptr);
|
||||
const Network *ns = system_network();
|
||||
ck_assert(ns != nullptr);
|
||||
const Memory *mem = system_memory();
|
||||
ck_assert(mem != nullptr);
|
||||
|
||||
Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr);
|
||||
Logger *logger = logger_new();
|
||||
|
||||
tcp_oobdata_callback_called = 0;
|
||||
tcp_data_callback_called = 0;
|
||||
@ -815,17 +840,17 @@ static void test_tcp_connection2(void)
|
||||
uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE];
|
||||
uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE];
|
||||
crypto_new_keypair(rng, self_public_key, self_secret_key);
|
||||
TCP_Server *tcp_s = new_TCP_server(logger, rng, ns, USE_IPV6, NUM_PORTS, ports, self_secret_key, nullptr, nullptr);
|
||||
TCP_Server *tcp_s = new_tcp_server(logger, mem, rng, ns, USE_IPV6, NUM_PORTS, ports, self_secret_key, nullptr, nullptr);
|
||||
ck_assert_msg(pk_equal(tcp_server_public_key(tcp_s), self_public_key), "Wrong public key");
|
||||
|
||||
TCP_Proxy_Info proxy_info;
|
||||
proxy_info.proxy_type = TCP_PROXY_NONE;
|
||||
crypto_new_keypair(rng, self_public_key, self_secret_key);
|
||||
TCP_Connections *tc_1 = new_tcp_connections(logger, rng, ns, mono_time, self_secret_key, &proxy_info);
|
||||
TCP_Connections *tc_1 = new_tcp_connections(logger, mem, rng, ns, mono_time, self_secret_key, &proxy_info);
|
||||
ck_assert_msg(pk_equal(tcp_connections_public_key(tc_1), self_public_key), "Wrong public key");
|
||||
|
||||
crypto_new_keypair(rng, self_public_key, self_secret_key);
|
||||
TCP_Connections *tc_2 = new_tcp_connections(logger, rng, ns, mono_time, self_secret_key, &proxy_info);
|
||||
TCP_Connections *tc_2 = new_tcp_connections(logger, mem, rng, ns, mono_time, self_secret_key, &proxy_info);
|
||||
ck_assert_msg(pk_equal(tcp_connections_public_key(tc_2), self_public_key), "Wrong public key");
|
||||
|
||||
IP_Port ip_port_tcp_s;
|
||||
@ -841,17 +866,17 @@ static void test_tcp_connection2(void)
|
||||
ck_assert_msg(add_tcp_relay_global(tc_2, &ip_port_tcp_s, tcp_server_public_key(tcp_s)) == 0,
|
||||
"Could not add global relay");
|
||||
|
||||
do_TCP_server_delay(tcp_s, mono_time, 50);
|
||||
do_tcp_server_delay(tcp_s, mono_time, 50);
|
||||
|
||||
do_tcp_connections(logger, tc_1, nullptr);
|
||||
do_tcp_connections(logger, tc_2, nullptr);
|
||||
|
||||
do_TCP_server_delay(tcp_s, mono_time, 50);
|
||||
do_tcp_server_delay(tcp_s, mono_time, 50);
|
||||
|
||||
do_tcp_connections(logger, tc_1, nullptr);
|
||||
do_tcp_connections(logger, tc_2, nullptr);
|
||||
|
||||
do_TCP_server_delay(tcp_s, mono_time, 50);
|
||||
do_tcp_server_delay(tcp_s, mono_time, 50);
|
||||
|
||||
do_tcp_connections(logger, tc_1, nullptr);
|
||||
do_tcp_connections(logger, tc_2, nullptr);
|
||||
@ -861,14 +886,14 @@ static void test_tcp_connection2(void)
|
||||
set_oob_packet_tcp_connection_callback(tc_2, &tcp_oobdata_callback, tc_2);
|
||||
set_packet_tcp_connection_callback(tc_1, &tcp_data_callback, (void *) 120397);
|
||||
|
||||
do_TCP_server_delay(tcp_s, mono_time, 50);
|
||||
do_tcp_server_delay(tcp_s, mono_time, 50);
|
||||
|
||||
do_tcp_connections(logger, tc_1, nullptr);
|
||||
do_tcp_connections(logger, tc_2, nullptr);
|
||||
|
||||
ck_assert_msg(tcp_oobdata_callback_called, "could not recv packet.");
|
||||
|
||||
do_TCP_server_delay(tcp_s, mono_time, 50);
|
||||
do_tcp_server_delay(tcp_s, mono_time, 50);
|
||||
|
||||
do_tcp_connections(logger, tc_1, nullptr);
|
||||
do_tcp_connections(logger, tc_2, nullptr);
|
||||
@ -876,15 +901,15 @@ static void test_tcp_connection2(void)
|
||||
ck_assert_msg(tcp_data_callback_called, "could not recv packet.");
|
||||
ck_assert_msg(kill_tcp_connection_to(tc_1, 0) == 0, "could not kill connection to\n");
|
||||
|
||||
kill_TCP_server(tcp_s);
|
||||
kill_tcp_server(tcp_s);
|
||||
kill_tcp_connections(tc_1);
|
||||
kill_tcp_connections(tc_2);
|
||||
|
||||
logger_kill(logger);
|
||||
mono_time_free(mono_time);
|
||||
mono_time_free(mem, mono_time);
|
||||
}
|
||||
|
||||
static void TCP_suite(void)
|
||||
static void tcp_suite(void)
|
||||
{
|
||||
test_basic();
|
||||
test_some();
|
||||
@ -897,6 +922,6 @@ static void TCP_suite(void)
|
||||
int main(void)
|
||||
{
|
||||
setvbuf(stdout, nullptr, _IONBF, 0);
|
||||
TCP_suite();
|
||||
tcp_suite();
|
||||
return 0;
|
||||
}
|
||||
|
Reference in New Issue
Block a user