Merge commit '83e200df43eb790719c40103099c8d70e37c0477'
This commit is contained in:
commit
260d3b7818
@ -90,16 +90,6 @@ jobs:
|
||||
with:
|
||||
file: other/docker/compcert/Dockerfile
|
||||
|
||||
build-alpine-s390x:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
- name: Docker Build
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
file: other/docker/alpine-s390x/Dockerfile
|
||||
|
||||
cimplefmt:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
16
external/toxcore/c-toxcore/.github/workflows/post-submit.yml
vendored
Normal file
16
external/toxcore/c-toxcore/.github/workflows/post-submit.yml
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
name: post-submit
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
|
||||
jobs:
|
||||
build-alpine-s390x:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
- name: Docker Build
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
file: other/docker/alpine-s390x/Dockerfile
|
1
external/toxcore/c-toxcore/CMakeLists.txt
vendored
1
external/toxcore/c-toxcore/CMakeLists.txt
vendored
@ -453,6 +453,7 @@ unit_test(toxcore bin_pack)
|
||||
unit_test(toxcore crypto_core)
|
||||
unit_test(toxcore group_announce)
|
||||
unit_test(toxcore group_moderation)
|
||||
unit_test(toxcore list)
|
||||
unit_test(toxcore mem)
|
||||
unit_test(toxcore mono_time)
|
||||
unit_test(toxcore ping_array)
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "auto_test_support.h"
|
||||
#include "../toxcore/tox_private.h"
|
||||
|
||||
typedef struct State {
|
||||
size_t peer_joined_count;
|
||||
@ -42,6 +43,22 @@ typedef struct State {
|
||||
|
||||
#define PEER_LIMIT 20
|
||||
|
||||
static void print_ip(Tox *tox, uint32_t groupnumber, uint32_t peer_id)
|
||||
{
|
||||
Tox_Err_Group_Peer_Query err;
|
||||
size_t length = tox_group_peer_get_ip_address_size(tox, groupnumber, peer_id, &err);
|
||||
|
||||
ck_assert_msg(err == TOX_ERR_GROUP_PEER_QUERY_OK, "failed to get ip address size: error %d", err);
|
||||
|
||||
uint8_t ip_str[TOX_GROUP_PEER_IP_STRING_MAX_LENGTH];
|
||||
tox_group_peer_get_ip_address(tox, groupnumber, peer_id, ip_str, &err);
|
||||
ip_str[length] = '\0';
|
||||
|
||||
ck_assert_msg(err == TOX_ERR_GROUP_PEER_QUERY_OK, "failed to get ip address: error %d", err);
|
||||
|
||||
fprintf(stderr, "%s\n", ip_str);
|
||||
}
|
||||
|
||||
static bool all_group_peers_connected(AutoTox *autotoxes, uint32_t tox_count, uint32_t groupnumber, size_t name_length)
|
||||
{
|
||||
for (size_t i = 0; i < tox_count; ++i) {
|
||||
@ -119,6 +136,9 @@ static void group_peer_join_handler(Tox *tox, uint32_t groupnumber, uint32_t pee
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s joined with IP: ", peer_name);
|
||||
print_ip(tox, groupnumber, peer_id);
|
||||
|
||||
state->peer_id = peer_id;
|
||||
++state->peer_joined_count;
|
||||
}
|
||||
@ -178,6 +198,11 @@ static void group_peer_self_join_handler(Tox *tox, uint32_t groupnumber, void *u
|
||||
ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "%d", query_err);
|
||||
ck_assert(memcmp(topic, TOPIC, TOPIC_LEN) == 0);
|
||||
|
||||
uint32_t peer_id = tox_group_self_get_peer_id(tox, groupnumber, nullptr);
|
||||
|
||||
fprintf(stderr, "self joined with IP: ");
|
||||
print_ip(tox, groupnumber, peer_id);
|
||||
|
||||
++state->self_joined_count;
|
||||
}
|
||||
|
||||
@ -341,6 +366,7 @@ static void group_announce_test(AutoTox *autotoxes)
|
||||
ck_assert(memcmp(tox0_pk_query, tox0_self_pk, TOX_GROUP_PEER_PUBLIC_KEY_SIZE) == 0);
|
||||
|
||||
fprintf(stderr, "Peer 0 disconnecting...\n");
|
||||
|
||||
// tox 0 disconnects then reconnects
|
||||
Tox_Err_Group_Disconnect d_err;
|
||||
tox_group_disconnect(tox0, groupnumber, &d_err);
|
||||
|
@ -53,7 +53,7 @@ static int handle_test_1(void *object, const IP_Port *source, const uint8_t *pac
|
||||
res_packet[0] = NET_PACKET_ANNOUNCE_RESPONSE;
|
||||
memcpy(res_packet + 1, res_message, sizeof(res_message));
|
||||
|
||||
if (send_onion_response(onion->net, source, res_packet, sizeof(res_packet),
|
||||
if (send_onion_response(onion->log, onion->net, source, res_packet, sizeof(res_packet),
|
||||
packet + sizeof(res_packet)) == -1) {
|
||||
return 1;
|
||||
}
|
||||
@ -293,7 +293,7 @@ static void test_basic(void)
|
||||
uint64_t s;
|
||||
memcpy(&s, sb_data, sizeof(uint64_t));
|
||||
memcpy(test_3_pub_key, nodes[3].public_key, CRYPTO_PUBLIC_KEY_SIZE);
|
||||
int ret = send_announce_request(onion1->net, rng, &path, &nodes[3],
|
||||
int ret = send_announce_request(log1, onion1->net, rng, &path, &nodes[3],
|
||||
dht_get_self_public_key(onion1->dht),
|
||||
dht_get_self_secret_key(onion1->dht),
|
||||
zeroes,
|
||||
@ -315,7 +315,7 @@ static void test_basic(void)
|
||||
memcpy(onion_announce_entry_public_key(onion2_a, 1), dht_get_self_public_key(onion2->dht), CRYPTO_PUBLIC_KEY_SIZE);
|
||||
onion_announce_entry_set_time(onion2_a, 1, mono_time_get(mono_time2));
|
||||
networking_registerhandler(onion1->net, NET_PACKET_ONION_DATA_RESPONSE, &handle_test_4, onion1);
|
||||
send_announce_request(onion1->net, rng, &path, &nodes[3],
|
||||
send_announce_request(log1, onion1->net, rng, &path, &nodes[3],
|
||||
dht_get_self_public_key(onion1->dht),
|
||||
dht_get_self_secret_key(onion1->dht),
|
||||
test_3_ping_id,
|
||||
@ -340,7 +340,7 @@ static void test_basic(void)
|
||||
ck_assert_msg((onion3 != nullptr), "Onion failed initializing.");
|
||||
|
||||
random_nonce(rng, nonce);
|
||||
ret = send_data_request(onion3->net, rng, &path, &nodes[3].ip_port,
|
||||
ret = send_data_request(log3, onion3->net, rng, &path, &nodes[3].ip_port,
|
||||
dht_get_self_public_key(onion1->dht),
|
||||
dht_get_self_public_key(onion1->dht),
|
||||
nonce, (const uint8_t *)"Install gentoo", sizeof("Install gentoo"));
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "../toxcore/tox.h"
|
||||
#include "../toxcore/tox_dispatch.h"
|
||||
#include "../toxcore/tox_events.h"
|
||||
#include "../toxcore/tox_unpack.h"
|
||||
#include "auto_test_support.h"
|
||||
#include "check_compat.h"
|
||||
|
||||
@ -160,9 +161,22 @@ static void test_tox_events(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void fake_test_unpack(void)
|
||||
{
|
||||
// TODO(Green-Sky): add proper unpack tests and/or implement ngc events
|
||||
(void)tox_unpack_group_privacy_state;
|
||||
(void)tox_unpack_group_privacy_state;
|
||||
(void)tox_unpack_group_voice_state;
|
||||
(void)tox_unpack_group_topic_lock;
|
||||
(void)tox_unpack_group_join_fail;
|
||||
(void)tox_unpack_group_mod_event;
|
||||
(void)tox_unpack_group_exit_type;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
setvbuf(stdout, nullptr, _IONBF, 0);
|
||||
test_tox_events();
|
||||
fake_test_unpack();
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,15 +1,16 @@
|
||||
###########################################################
|
||||
# Builder image: we compile the code here (static build)
|
||||
FROM alpine:3.18.5 AS build
|
||||
FROM alpine:3.19.0 AS build
|
||||
|
||||
RUN ["apk", "--no-cache", "add",\
|
||||
"build-base",\
|
||||
"clang",\
|
||||
"cmake",\
|
||||
"linux-headers",\
|
||||
"libconfig-dev",\
|
||||
"libconfig-static",\
|
||||
"libsodium-dev",\
|
||||
"libsodium-static",\
|
||||
"musl-dev",\
|
||||
"ninja",\
|
||||
"python3"\
|
||||
]
|
||||
@ -34,9 +35,9 @@ COPY CMakeLists.txt so.version ./
|
||||
COPY other/bootstrap_daemon/CMakeLists.txt other/bootstrap_daemon/CMakeLists.txt
|
||||
COPY testing/CMakeLists.txt testing/CMakeLists.txt
|
||||
|
||||
RUN cmake -B_build -H. \
|
||||
RUN CC=clang cmake -B_build -H. \
|
||||
-GNinja \
|
||||
-DCMAKE_C_FLAGS="-DTCP_SERVER_USE_EPOLL -fstack-protector-all -fisolate-erroneous-paths-attribute" \
|
||||
-DCMAKE_C_FLAGS="-DTCP_SERVER_USE_EPOLL -fsanitize=alignment,return,returns-nonnull-attribute,vla-bound,unreachable,float-cast-overflow,null -fsanitize-trap=all -fstack-protector-all" \
|
||||
-DCMAKE_UNITY_BUILD=ON \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DFULLY_STATIC=ON \
|
||||
|
@ -1 +1 @@
|
||||
5aac1df4d6c1de289e8e9f646d06099c84fd4d9b80d19f45e3254eec3ece2bff /usr/local/bin/tox-bootstrapd
|
||||
21cf23b1a2e46712663dc4f8daa322991af51b9e82626a127cf1bc8dc583b598 /usr/local/bin/tox-bootstrapd
|
||||
|
22
external/toxcore/c-toxcore/testing/BUILD.bazel
vendored
22
external/toxcore/c-toxcore/testing/BUILD.bazel
vendored
@ -22,6 +22,28 @@ sh_test(
|
||||
tags = ["haskell"],
|
||||
)
|
||||
|
||||
sh_test(
|
||||
name = "c_test",
|
||||
size = "small",
|
||||
srcs = ["//hs-tokstyle/tools:check-c"],
|
||||
args = [
|
||||
"--cc=$(CC)",
|
||||
"-Iexternal/libsodium/include",
|
||||
"-Iexternal/libvpx",
|
||||
"-Iexternal/opus/include",
|
||||
"-Ihs-tokstyle/include",
|
||||
] + ["$(locations %s)" % f for f in CIMPLE_FILES],
|
||||
data = CIMPLE_FILES + [
|
||||
"//c-toxcore/third_party:headers",
|
||||
"//hs-tokstyle:headers",
|
||||
"@libsodium//:headers",
|
||||
"@libvpx//:headers",
|
||||
"@opus//:headers",
|
||||
],
|
||||
tags = ["haskell"],
|
||||
toolchains = ["@rules_cc//cc:current_cc_toolchain"],
|
||||
)
|
||||
|
||||
sh_test(
|
||||
name = "cimplefmt_test",
|
||||
size = "small",
|
||||
|
@ -7,3 +7,9 @@ cc_library(
|
||||
copts = ["-DCMP_NO_FLOAT"],
|
||||
visibility = ["//c-toxcore:__subpackages__"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "headers",
|
||||
srcs = ["cmp/cmp.h"],
|
||||
visibility = ["//c-toxcore:__subpackages__"],
|
||||
)
|
||||
|
1
external/toxcore/c-toxcore/toxav/msi.c
vendored
1
external/toxcore/c-toxcore/toxav/msi.c
vendored
@ -821,6 +821,7 @@ static void handle_pop(MSICall *call, const MSIMessage *msg)
|
||||
switch (call->state) {
|
||||
case MSI_CALL_INACTIVE: {
|
||||
LOGGER_FATAL(call->session->messenger->log, "Handling what should be impossible case");
|
||||
break;
|
||||
}
|
||||
|
||||
case MSI_CALL_ACTIVE: {
|
||||
|
@ -201,6 +201,7 @@ cc_library(
|
||||
":attributes",
|
||||
":ccompat",
|
||||
":mem",
|
||||
":util",
|
||||
"@pthread",
|
||||
],
|
||||
)
|
||||
@ -230,6 +231,7 @@ cc_library(
|
||||
deps = [
|
||||
":ccompat",
|
||||
":crypto_core",
|
||||
":logger",
|
||||
":mem",
|
||||
":mono_time",
|
||||
],
|
||||
|
20
external/toxcore/c-toxcore/toxcore/DHT.c
vendored
20
external/toxcore/c-toxcore/toxcore/DHT.c
vendored
@ -1828,7 +1828,9 @@ static uint8_t do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, co
|
||||
++not_kill;
|
||||
|
||||
if (mono_time_is_timeout(dht->mono_time, assoc->last_pinged, PING_INTERVAL)) {
|
||||
dht_getnodes(dht, &assoc->ip_port, client->public_key, public_key);
|
||||
const IP_Port *target = &assoc->ip_port;
|
||||
const uint8_t *target_key = client->public_key;
|
||||
dht_getnodes(dht, target, target_key, public_key);
|
||||
assoc->last_pinged = temp_time;
|
||||
}
|
||||
|
||||
@ -1861,7 +1863,9 @@ static uint8_t do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, co
|
||||
rand_node += random_range_u32(dht->rng, num_nodes - (rand_node + 1));
|
||||
}
|
||||
|
||||
dht_getnodes(dht, &assoc_list[rand_node]->ip_port, client_list[rand_node]->public_key, public_key);
|
||||
const IP_Port *target = &assoc_list[rand_node]->ip_port;
|
||||
const uint8_t *target_key = client_list[rand_node]->public_key;
|
||||
dht_getnodes(dht, target, target_key, public_key);
|
||||
|
||||
*lastgetnode = temp_time;
|
||||
++*bootstrap_times;
|
||||
@ -1890,8 +1894,7 @@ static void do_dht_friends(DHT *dht)
|
||||
dht_friend->num_to_bootstrap = 0;
|
||||
|
||||
do_ping_and_sendnode_requests(dht, &dht_friend->lastgetnode, dht_friend->public_key, dht_friend->client_list,
|
||||
MAX_FRIEND_CLIENTS,
|
||||
&dht_friend->bootstrap_times, true);
|
||||
MAX_FRIEND_CLIENTS, &dht_friend->bootstrap_times, true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2634,6 +2637,7 @@ DHT *new_dht(const Logger *log, const Memory *mem, const Random *rng, const Netw
|
||||
DHT *const dht = (DHT *)mem_alloc(mem, sizeof(DHT));
|
||||
|
||||
if (dht == nullptr) {
|
||||
LOGGER_ERROR(log, "failed to allocate DHT struct (%ld bytes)", (unsigned long)sizeof(DHT));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -2651,6 +2655,7 @@ DHT *new_dht(const Logger *log, const Memory *mem, const Random *rng, const Netw
|
||||
dht->ping = ping_new(mem, mono_time, rng, dht);
|
||||
|
||||
if (dht->ping == nullptr) {
|
||||
LOGGER_ERROR(log, "failed to initialise ping");
|
||||
kill_dht(dht);
|
||||
return nullptr;
|
||||
}
|
||||
@ -2667,10 +2672,11 @@ DHT *new_dht(const Logger *log, const Memory *mem, const Random *rng, const Netw
|
||||
|
||||
crypto_new_keypair(rng, dht->self_public_key, dht->self_secret_key);
|
||||
|
||||
dht->shared_keys_recv = shared_key_cache_new(mono_time, mem, dht->self_secret_key, KEYS_TIMEOUT, MAX_KEYS_PER_SLOT);
|
||||
dht->shared_keys_sent = shared_key_cache_new(mono_time, mem, dht->self_secret_key, KEYS_TIMEOUT, MAX_KEYS_PER_SLOT);
|
||||
dht->shared_keys_recv = shared_key_cache_new(log, mono_time, mem, dht->self_secret_key, KEYS_TIMEOUT, MAX_KEYS_PER_SLOT);
|
||||
dht->shared_keys_sent = shared_key_cache_new(log, mono_time, mem, dht->self_secret_key, KEYS_TIMEOUT, MAX_KEYS_PER_SLOT);
|
||||
|
||||
if (dht->shared_keys_recv == nullptr || dht->shared_keys_sent == nullptr) {
|
||||
LOGGER_ERROR(log, "failed to initialise shared key cache");
|
||||
kill_dht(dht);
|
||||
return nullptr;
|
||||
}
|
||||
@ -2679,6 +2685,7 @@ DHT *new_dht(const Logger *log, const Memory *mem, const Random *rng, const Netw
|
||||
dht->dht_ping_array = ping_array_new(mem, DHT_PING_ARRAY_SIZE, PING_TIMEOUT);
|
||||
|
||||
if (dht->dht_ping_array == nullptr) {
|
||||
LOGGER_ERROR(log, "failed to initialise ping array");
|
||||
kill_dht(dht);
|
||||
return nullptr;
|
||||
}
|
||||
@ -2691,6 +2698,7 @@ DHT *new_dht(const Logger *log, const Memory *mem, const Random *rng, const Netw
|
||||
|
||||
uint32_t token; // We don't intend to delete these ever, but need to pass the token
|
||||
if (dht_addfriend(dht, random_public_key_bytes, nullptr, nullptr, 0, &token) != 0) {
|
||||
LOGGER_ERROR(log, "failed to add initial random seed DHT friends");
|
||||
kill_dht(dht);
|
||||
return nullptr;
|
||||
}
|
||||
|
11
external/toxcore/c-toxcore/toxcore/Messenger.c
vendored
11
external/toxcore/c-toxcore/toxcore/Messenger.c
vendored
@ -3583,6 +3583,7 @@ Messenger *new_messenger(Mono_Time *mono_time, const Memory *mem, const Random *
|
||||
mem_delete(mem, m);
|
||||
|
||||
if (error != nullptr && net_err == 1) {
|
||||
LOGGER_WARNING(m->log, "network initialisation failed (no ports available)");
|
||||
*error = MESSENGER_ERROR_PORT;
|
||||
}
|
||||
|
||||
@ -3602,6 +3603,8 @@ Messenger *new_messenger(Mono_Time *mono_time, const Memory *mem, const Random *
|
||||
m->net_crypto = new_net_crypto(m->log, m->mem, m->rng, m->ns, m->mono_time, m->dht, &options->proxy_info);
|
||||
|
||||
if (m->net_crypto == nullptr) {
|
||||
LOGGER_WARNING(m->log, "net_crypto initialisation failed");
|
||||
|
||||
kill_dht(m->dht);
|
||||
kill_networking(m->net);
|
||||
friendreq_kill(m->fr);
|
||||
@ -3614,6 +3617,8 @@ Messenger *new_messenger(Mono_Time *mono_time, const Memory *mem, const Random *
|
||||
m->group_announce = new_gca_list();
|
||||
|
||||
if (m->group_announce == nullptr) {
|
||||
LOGGER_WARNING(m->log, "DHT group chats initialisation failed");
|
||||
|
||||
kill_net_crypto(m->net_crypto);
|
||||
kill_dht(m->dht);
|
||||
kill_networking(m->net);
|
||||
@ -3642,6 +3647,8 @@ Messenger *new_messenger(Mono_Time *mono_time, const Memory *mem, const Random *
|
||||
|
||||
if ((options->dht_announcements_enabled && (m->forwarding == nullptr || m->announce == nullptr)) ||
|
||||
m->onion == nullptr || m->onion_a == nullptr || m->onion_c == nullptr || m->fr_c == nullptr) {
|
||||
LOGGER_WARNING(m->log, "onion initialisation failed");
|
||||
|
||||
kill_onion(m->onion);
|
||||
kill_onion_announce(m->onion_a);
|
||||
kill_onion_client(m->onion_c);
|
||||
@ -3666,6 +3673,8 @@ Messenger *new_messenger(Mono_Time *mono_time, const Memory *mem, const Random *
|
||||
m->group_handler = new_dht_groupchats(m);
|
||||
|
||||
if (m->group_handler == nullptr) {
|
||||
LOGGER_WARNING(m->log, "conferences initialisation failed");
|
||||
|
||||
kill_onion(m->onion);
|
||||
kill_onion_announce(m->onion_a);
|
||||
kill_onion_client(m->onion_c);
|
||||
@ -3690,6 +3699,8 @@ Messenger *new_messenger(Mono_Time *mono_time, const Memory *mem, const Random *
|
||||
m->onion, m->forwarding);
|
||||
|
||||
if (m->tcp_server == nullptr) {
|
||||
LOGGER_WARNING(m->log, "TCP server initialisation failed");
|
||||
|
||||
kill_onion(m->onion);
|
||||
kill_onion_announce(m->onion_a);
|
||||
#ifndef VANILLA_NACL
|
||||
|
@ -201,7 +201,11 @@ int read_tcp_packet(
|
||||
const uint16_t count = net_socket_data_recv_buffer(ns, sock);
|
||||
|
||||
if (count < length) {
|
||||
if (count != 0) {
|
||||
// Only log when there are some bytes available, as empty buffer
|
||||
// is a very common case and this spams our logs.
|
||||
LOGGER_TRACE(logger, "recv buffer has %d bytes, but requested %d bytes", count, length);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -120,7 +120,7 @@ bool tcp_get_random_conn_ip_port(const TCP_Connections *tcp_c, IP_Port *ip_port)
|
||||
* return -1 on failure.
|
||||
*/
|
||||
non_null()
|
||||
int tcp_send_onion_request(TCP_Connections *tcp_c, unsigned int tcp_connections_number, const uint8_t *data,
|
||||
int tcp_send_onion_request(TCP_Connections *tcp_c, uint32_t tcp_connections_number, const uint8_t *data,
|
||||
uint16_t length);
|
||||
|
||||
/** @brief Set if we want TCP_connection to allocate some connection for onion use.
|
||||
|
@ -660,7 +660,7 @@ Announcements *new_announcements(const Logger *log, const Memory *mem, const Ran
|
||||
announce->public_key = dht_get_self_public_key(announce->dht);
|
||||
announce->secret_key = dht_get_self_secret_key(announce->dht);
|
||||
new_hmac_key(announce->rng, announce->hmac_key);
|
||||
announce->shared_keys = shared_key_cache_new(mono_time, mem, announce->secret_key, KEYS_TIMEOUT, MAX_KEYS_PER_SLOT);
|
||||
announce->shared_keys = shared_key_cache_new(log, mono_time, mem, announce->secret_key, KEYS_TIMEOUT, MAX_KEYS_PER_SLOT);
|
||||
if (announce->shared_keys == nullptr) {
|
||||
free(announce);
|
||||
return nullptr;
|
||||
|
57
external/toxcore/c-toxcore/toxcore/group_chats.c
vendored
57
external/toxcore/c-toxcore/toxcore/group_chats.c
vendored
@ -3517,6 +3517,63 @@ int gc_get_peer_public_key_by_peer_id(const GC_Chat *chat, uint32_t peer_id, uin
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @brief Puts a string of the IP associated with `ip_port` in `ip_str` if the
|
||||
* connection is direct, otherwise puts a placeholder in the buffer indicating that
|
||||
* the IP cannot be displayed.
|
||||
*/
|
||||
non_null()
|
||||
static void get_gc_ip_ntoa(const IP_Port *ip_port, Ip_Ntoa *ip_str)
|
||||
{
|
||||
net_ip_ntoa(&ip_port->ip, ip_str);
|
||||
|
||||
if (!ip_str->ip_is_valid) {
|
||||
ip_str->buf[0] = '-';
|
||||
ip_str->buf[1] = '\0';
|
||||
ip_str->length = 1;
|
||||
}
|
||||
}
|
||||
|
||||
int gc_get_peer_ip_address_size(const GC_Chat *chat, uint32_t peer_id)
|
||||
{
|
||||
const int peer_number = get_peer_number_of_peer_id(chat, peer_id);
|
||||
const GC_Connection *gconn = get_gc_connection(chat, peer_number);
|
||||
|
||||
if (gconn == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
const IP_Port *ip_port = peer_number == 0 ? &chat->self_ip_port : &gconn->addr.ip_port;
|
||||
|
||||
Ip_Ntoa ip_str;
|
||||
get_gc_ip_ntoa(ip_port, &ip_str);
|
||||
|
||||
return ip_str.length;
|
||||
}
|
||||
|
||||
int gc_get_peer_ip_address(const GC_Chat *chat, uint32_t peer_id, uint8_t *ip_addr)
|
||||
{
|
||||
const int peer_number = get_peer_number_of_peer_id(chat, peer_id);
|
||||
const GC_Connection *gconn = get_gc_connection(chat, peer_number);
|
||||
|
||||
if (gconn == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ip_addr == nullptr) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
const IP_Port *ip_port = peer_number == 0 ? &chat->self_ip_port : &gconn->addr.ip_port;
|
||||
|
||||
Ip_Ntoa ip_str;
|
||||
get_gc_ip_ntoa(ip_port, &ip_str);
|
||||
|
||||
assert(ip_str.length <= IP_NTOA_LEN);
|
||||
memcpy(ip_addr, ip_str.buf, ip_str.length);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int gc_get_peer_connection_status(const GC_Chat *chat, uint32_t peer_id)
|
||||
{
|
||||
const int peer_number = get_peer_number_of_peer_id(chat, peer_id);
|
||||
|
23
external/toxcore/c-toxcore/toxcore/group_chats.h
vendored
23
external/toxcore/c-toxcore/toxcore/group_chats.h
vendored
@ -390,6 +390,29 @@ int gc_get_peer_nick_size(const GC_Chat *chat, uint32_t peer_id);
|
||||
non_null(1) nullable(3)
|
||||
int gc_get_peer_public_key_by_peer_id(const GC_Chat *chat, uint32_t peer_id, uint8_t *public_key);
|
||||
|
||||
/** @brief Returns the length of the IP address for the peer designated by `peer_id`.
|
||||
* Returns -1 if peer_id is invalid.
|
||||
*/
|
||||
non_null()
|
||||
int gc_get_peer_ip_address_size(const GC_Chat *chat, uint32_t peer_id);
|
||||
|
||||
/** @brief Copies peer_id's IP address to `ip_addr`.
|
||||
*
|
||||
* If the peer is forcing TCP connections this will be a placeholder value indicating
|
||||
* that their real IP address is unknown to us.
|
||||
*
|
||||
* If `peer_id` designates ourself, it will write either our own IP address or a
|
||||
* placeholder value, depending on whether or not we're forcing TCP connections.
|
||||
*
|
||||
* `ip_addr` should have room for at least IP_NTOA_LEN bytes.
|
||||
*
|
||||
* Returns 0 on success.
|
||||
* Returns -1 if peer_id is invalid or doesn't correspond to a valid peer connection.
|
||||
* Returns -2 if `ip_addr` is null.
|
||||
*/
|
||||
non_null(1) nullable(3)
|
||||
int gc_get_peer_ip_address(const GC_Chat *chat, uint32_t peer_id, uint8_t *ip_addr);
|
||||
|
||||
/** @brief Gets the connection status for peer associated with `peer_id`.
|
||||
*
|
||||
* If `peer_id` designates ourself, the return value indicates whether we're capable
|
||||
|
5
external/toxcore/c-toxcore/toxcore/logger.c
vendored
5
external/toxcore/c-toxcore/toxcore/logger.c
vendored
@ -117,3 +117,8 @@ void logger_write(const Logger *log, Logger_Level level, const char *file, int l
|
||||
|
||||
log->callback(log->context, level, file, line, func, msg, log->userdata);
|
||||
}
|
||||
|
||||
void logger_abort(void)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
5
external/toxcore/c-toxcore/toxcore/logger.h
vendored
5
external/toxcore/c-toxcore/toxcore/logger.h
vendored
@ -67,6 +67,9 @@ void logger_write(
|
||||
const Logger *log, Logger_Level level, const char *file, int line, const char *func,
|
||||
const char *format, ...);
|
||||
|
||||
/* @brief Terminate the program with a signal. */
|
||||
void logger_abort(void);
|
||||
|
||||
|
||||
#define LOGGER_WRITE(log, level, ...) \
|
||||
do { \
|
||||
@ -85,7 +88,7 @@ void logger_write(
|
||||
#define LOGGER_FATAL(log, ...) \
|
||||
do { \
|
||||
LOGGER_ERROR(log, __VA_ARGS__); \
|
||||
abort(); \
|
||||
logger_abort(); \
|
||||
} while (0)
|
||||
|
||||
#define LOGGER_ASSERT(log, cond, ...) \
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <time.h>
|
||||
|
||||
#include "ccompat.h"
|
||||
#include "util.h"
|
||||
|
||||
/** don't call into system billions of times for no reason */
|
||||
struct Mono_Time {
|
||||
@ -165,7 +166,9 @@ Mono_Time *mono_time_new(const Memory *mem, mono_time_current_time_cb *current_t
|
||||
// Maximum reproducibility. Never return time = 0.
|
||||
mono_time->base_time = 1;
|
||||
#else
|
||||
mono_time->base_time = (uint64_t)time(nullptr) * 1000ULL - current_time_monotonic(mono_time);
|
||||
// Never return time = 0 in case time() returns 0 (e.g. on microcontrollers
|
||||
// without battery-powered RTC or ones where NTP didn't initialise it yet).
|
||||
mono_time->base_time = max_u64(1, (uint64_t)time(nullptr)) * 1000ULL - current_time_monotonic(mono_time);
|
||||
#endif
|
||||
|
||||
mono_time_update(mono_time);
|
||||
|
@ -2,6 +2,9 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
namespace {
|
||||
|
||||
TEST(MonoTime, UnixTimeIncreasesOverTime)
|
||||
@ -41,6 +44,24 @@ TEST(MonoTime, IsTimeout)
|
||||
mono_time_free(mem, mono_time);
|
||||
}
|
||||
|
||||
TEST(MonoTime, IsTimeoutReal)
|
||||
{
|
||||
const Memory *mem = system_memory();
|
||||
Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr);
|
||||
ASSERT_NE(mono_time, nullptr);
|
||||
|
||||
uint64_t const start = mono_time_get(mono_time);
|
||||
EXPECT_FALSE(mono_time_is_timeout(mono_time, start, 5));
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
mono_time_update(mono_time);
|
||||
|
||||
// should still not have timed out (5sec) after sleeping ~100ms
|
||||
EXPECT_FALSE(mono_time_is_timeout(mono_time, start, 5));
|
||||
|
||||
mono_time_free(mem, mono_time);
|
||||
}
|
||||
|
||||
TEST(MonoTime, CustomTime)
|
||||
{
|
||||
const Memory *mem = system_memory();
|
||||
|
23
external/toxcore/c-toxcore/toxcore/network.c
vendored
23
external/toxcore/c-toxcore/toxcore/network.c
vendored
@ -1,5 +1,5 @@
|
||||
/* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Copyright © 2016-2018 The TokTok team.
|
||||
* Copyright © 2016-2023 The TokTok team.
|
||||
* Copyright © 2013 Tox project.
|
||||
*/
|
||||
|
||||
@ -778,7 +778,7 @@ static void loglogdata(const Logger *log, const char *message, const uint8_t *bu
|
||||
Ip_Ntoa ip_str;
|
||||
const int error = net_error();
|
||||
char *strerror = net_new_strerror(error);
|
||||
LOGGER_TRACE(log, "[%02x = %-20s] %s %3u%c %s:%u (%u: %s) | %08x%08x...%02x",
|
||||
LOGGER_TRACE(log, "[%02x = %-21s] %s %3u%c %s:%u (%u: %s) | %08x%08x...%02x",
|
||||
buffer[0], net_packet_type_name((Net_Packet_Type)buffer[0]), message,
|
||||
min_u16(buflen, 999), 'E',
|
||||
net_ip_ntoa(&ip_port->ip, &ip_str), net_ntohs(ip_port->port), error,
|
||||
@ -786,14 +786,14 @@ static void loglogdata(const Logger *log, const char *message, const uint8_t *bu
|
||||
net_kill_strerror(strerror);
|
||||
} else if ((res > 0) && ((size_t)res <= buflen)) {
|
||||
Ip_Ntoa ip_str;
|
||||
LOGGER_TRACE(log, "[%02x = %-20s] %s %3u%c %s:%u (%u: %s) | %08x%08x...%02x",
|
||||
LOGGER_TRACE(log, "[%02x = %-21s] %s %3u%c %s:%u (%u: %s) | %08x%08x...%02x",
|
||||
buffer[0], net_packet_type_name((Net_Packet_Type)buffer[0]), message,
|
||||
min_u16(res, 999), (size_t)res < buflen ? '<' : '=',
|
||||
net_ip_ntoa(&ip_port->ip, &ip_str), net_ntohs(ip_port->port), 0, "OK",
|
||||
data_0(buflen, buffer), data_1(buflen, buffer), buffer[buflen - 1]);
|
||||
} else { /* empty or overwrite */
|
||||
Ip_Ntoa ip_str;
|
||||
LOGGER_TRACE(log, "[%02x = %-20s] %s %lu%c%u %s:%u (%u: %s) | %08x%08x...%02x",
|
||||
LOGGER_TRACE(log, "[%02x = %-21s] %s %lu%c%u %s:%u (%u: %s) | %08x%08x...%02x",
|
||||
buffer[0], net_packet_type_name((Net_Packet_Type)buffer[0]), message,
|
||||
res, res == 0 ? '!' : '>', buflen,
|
||||
net_ip_ntoa(&ip_port->ip, &ip_str), net_ntohs(ip_port->port), 0, "OK",
|
||||
@ -1514,30 +1514,29 @@ void ipport_copy(IP_Port *target, const IP_Port *source)
|
||||
*target = *source;
|
||||
}
|
||||
|
||||
/** @brief Converts IP into a string.
|
||||
*
|
||||
* Writes error message into the buffer on error.
|
||||
*
|
||||
* @param ip_str contains a buffer of the required size.
|
||||
*
|
||||
* @return Pointer to the buffer inside `ip_str` containing the IP string.
|
||||
*/
|
||||
const char *net_ip_ntoa(const IP *ip, Ip_Ntoa *ip_str)
|
||||
{
|
||||
assert(ip_str != nullptr);
|
||||
|
||||
ip_str->ip_is_valid = false;
|
||||
|
||||
if (ip == nullptr) {
|
||||
snprintf(ip_str->buf, sizeof(ip_str->buf), "(IP invalid: NULL)");
|
||||
ip_str->length = (uint16_t)strlen(ip_str->buf);
|
||||
return ip_str->buf;
|
||||
}
|
||||
|
||||
if (!ip_parse_addr(ip, ip_str->buf, sizeof(ip_str->buf))) {
|
||||
snprintf(ip_str->buf, sizeof(ip_str->buf), "(IP invalid, family %u)", ip->family.value);
|
||||
ip_str->length = (uint16_t)strlen(ip_str->buf);
|
||||
return ip_str->buf;
|
||||
}
|
||||
|
||||
/* brute force protection against lacking termination */
|
||||
ip_str->buf[sizeof(ip_str->buf) - 1] = '\0';
|
||||
ip_str->length = (uint16_t)strlen(ip_str->buf);
|
||||
ip_str->ip_is_valid = true;
|
||||
|
||||
return ip_str->buf;
|
||||
}
|
||||
|
||||
|
7
external/toxcore/c-toxcore/toxcore/network.h
vendored
7
external/toxcore/c-toxcore/toxcore/network.h
vendored
@ -343,11 +343,14 @@ bool ipv6_ipv4_in_v6(const IP6 *a);
|
||||
/** this would be TOX_INET6_ADDRSTRLEN, but it might be too short for the error message */
|
||||
#define IP_NTOA_LEN 96 // TODO(irungentoo): magic number. Why not INET6_ADDRSTRLEN ?
|
||||
|
||||
/** Contains a null terminated string of an IP address. */
|
||||
typedef struct Ip_Ntoa {
|
||||
char buf[IP_NTOA_LEN];
|
||||
char buf[IP_NTOA_LEN]; // a string formatted IP address or an error message.
|
||||
uint16_t length; // the length of the string (not including the null byte).
|
||||
bool ip_is_valid; // if this is false `buf` will contain an error message.
|
||||
} Ip_Ntoa;
|
||||
|
||||
/** @brief Converts IP into a string.
|
||||
/** @brief Converts IP into a null terminated string.
|
||||
*
|
||||
* Writes error message into the buffer on error.
|
||||
*
|
||||
|
60
external/toxcore/c-toxcore/toxcore/onion.c
vendored
60
external/toxcore/c-toxcore/toxcore/onion.c
vendored
@ -283,22 +283,27 @@ int create_onion_packet_tcp(const Random *rng, uint8_t *packet, uint16_t max_pac
|
||||
* return -1 on failure.
|
||||
* return 0 on success.
|
||||
*/
|
||||
int send_onion_response(const Networking_Core *net, const IP_Port *dest, const uint8_t *data, uint16_t length,
|
||||
int send_onion_response(const Logger *log, const Networking_Core *net,
|
||||
const IP_Port *dest, const uint8_t *data, uint16_t length,
|
||||
const uint8_t *ret)
|
||||
{
|
||||
if (length > ONION_RESPONSE_MAX_DATA_SIZE || length == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
VLA(uint8_t, packet, 1 + RETURN_3 + length);
|
||||
const uint16_t packet_size = 1 + RETURN_3 + length;
|
||||
VLA(uint8_t, packet, packet_size);
|
||||
packet[0] = NET_PACKET_ONION_RECV_3;
|
||||
memcpy(packet + 1, ret, RETURN_3);
|
||||
memcpy(packet + 1 + RETURN_3, data, length);
|
||||
|
||||
if ((uint32_t)sendpacket(net, dest, packet, SIZEOF_VLA(packet)) != SIZEOF_VLA(packet)) {
|
||||
if ((uint16_t)sendpacket(net, dest, packet, packet_size) != packet_size) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
Ip_Ntoa ip_str;
|
||||
LOGGER_TRACE(log, "forwarded onion RECV_3 to %s:%d (%02x in %02x, %d bytes)",
|
||||
net_ip_ntoa(&dest->ip, &ip_str), net_ntohs(dest->port), data[0], packet[0], packet_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -309,28 +314,42 @@ static int handle_send_initial(void *object, const IP_Port *source, const uint8_
|
||||
Onion *onion = (Onion *)object;
|
||||
|
||||
if (length > ONION_MAX_PACKET_SIZE) {
|
||||
LOGGER_TRACE(onion->log, "invalid initial onion packet length: %u (max: %u)",
|
||||
length, ONION_MAX_PACKET_SIZE);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (length <= 1 + SEND_1) {
|
||||
LOGGER_TRACE(onion->log, "initial onion packet cannot contain SEND_1 packet: %u <= %u",
|
||||
length, 1 + SEND_1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
change_symmetric_key(onion);
|
||||
|
||||
const int nonce_start = 1;
|
||||
const int public_key_start = nonce_start + CRYPTO_NONCE_SIZE;
|
||||
const int ciphertext_start = public_key_start + CRYPTO_PUBLIC_KEY_SIZE;
|
||||
|
||||
const int ciphertext_length = length - ciphertext_start;
|
||||
const int plaintext_length = ciphertext_length - CRYPTO_MAC_SIZE;
|
||||
|
||||
uint8_t plain[ONION_MAX_PACKET_SIZE];
|
||||
const uint8_t *public_key = packet + 1 + CRYPTO_NONCE_SIZE;
|
||||
const uint8_t *public_key = &packet[public_key_start];
|
||||
const uint8_t *shared_key = shared_key_cache_lookup(onion->shared_keys_1, public_key);
|
||||
|
||||
if (shared_key == nullptr) {
|
||||
/* Error looking up/deriving the shared key */
|
||||
LOGGER_TRACE(onion->log, "shared onion key lookup failed for pk %02x%02x...",
|
||||
public_key[0], public_key[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE,
|
||||
length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE), plain);
|
||||
const int len = decrypt_data_symmetric(
|
||||
shared_key, &packet[nonce_start], &packet[ciphertext_start], ciphertext_length, plain);
|
||||
|
||||
if (len != length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_MAC_SIZE)) {
|
||||
if (len != plaintext_length) {
|
||||
LOGGER_TRACE(onion->log, "decrypt failed: %d != %d", len, plaintext_length);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -339,7 +358,9 @@ static int handle_send_initial(void *object, const IP_Port *source, const uint8_
|
||||
|
||||
int onion_send_1(const Onion *onion, const uint8_t *plain, uint16_t len, const IP_Port *source, const uint8_t *nonce)
|
||||
{
|
||||
if (len > ONION_MAX_PACKET_SIZE + SIZE_IPPORT - (1 + CRYPTO_NONCE_SIZE + ONION_RETURN_1)) {
|
||||
const uint16_t max_len = ONION_MAX_PACKET_SIZE + SIZE_IPPORT - (1 + CRYPTO_NONCE_SIZE + ONION_RETURN_1);
|
||||
if (len > max_len) {
|
||||
LOGGER_TRACE(onion->log, "invalid SEND_1 length: %d > %d", len, max_len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -376,6 +397,9 @@ int onion_send_1(const Onion *onion, const uint8_t *plain, uint16_t len, const I
|
||||
return 1;
|
||||
}
|
||||
|
||||
Ip_Ntoa ip_str;
|
||||
LOGGER_TRACE(onion->log, "forwarded onion packet to %s:%d, level 1 (%02x in %02x, %d bytes)",
|
||||
net_ip_ntoa(&send_to.ip, &ip_str), net_ntohs(send_to.port), plain[0], data[0], data_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -439,6 +463,9 @@ static int handle_send_1(void *object, const IP_Port *source, const uint8_t *pac
|
||||
return 1;
|
||||
}
|
||||
|
||||
Ip_Ntoa ip_str;
|
||||
LOGGER_TRACE(onion->log, "forwarded onion packet to %s:%d, level 2 (%02x in %02x, %d bytes)",
|
||||
net_ip_ntoa(&send_to.ip, &ip_str), net_ntohs(send_to.port), packet[0], data[0], data_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -509,6 +536,9 @@ static int handle_send_2(void *object, const IP_Port *source, const uint8_t *pac
|
||||
return 1;
|
||||
}
|
||||
|
||||
Ip_Ntoa ip_str;
|
||||
LOGGER_TRACE(onion->log, "forwarded onion packet to %s:%d, level 3 (%02x in %02x, %d bytes)",
|
||||
net_ip_ntoa(&send_to.ip, &ip_str), net_ntohs(send_to.port), packet[0], data[0], data_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -546,6 +576,7 @@ static int handle_recv_3(void *object, const IP_Port *source, const uint8_t *pac
|
||||
IP_Port send_to;
|
||||
|
||||
if (ipport_unpack(&send_to, plain, len, false) == -1) {
|
||||
LOGGER_DEBUG(onion->log, "failed to unpack IP/Port");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -559,6 +590,9 @@ static int handle_recv_3(void *object, const IP_Port *source, const uint8_t *pac
|
||||
return 1;
|
||||
}
|
||||
|
||||
Ip_Ntoa ip_str;
|
||||
LOGGER_TRACE(onion->log, "forwarded onion RECV_2 to %s:%d (%02x in %02x, %d bytes)",
|
||||
net_ip_ntoa(&send_to.ip, &ip_str), net_ntohs(send_to.port), packet[0], data[0], data_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -608,6 +642,9 @@ static int handle_recv_2(void *object, const IP_Port *source, const uint8_t *pac
|
||||
return 1;
|
||||
}
|
||||
|
||||
Ip_Ntoa ip_str;
|
||||
LOGGER_TRACE(onion->log, "forwarded onion RECV_1 to %s:%d (%02x in %02x, %d bytes)",
|
||||
net_ip_ntoa(&send_to.ip, &ip_str), net_ntohs(send_to.port), packet[0], data[0], data_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -644,6 +681,7 @@ static int handle_recv_1(void *object, const IP_Port *source, const uint8_t *pac
|
||||
IP_Port send_to;
|
||||
|
||||
if (ipport_unpack(&send_to, plain, len, true) == -1) {
|
||||
LOGGER_DEBUG(onion->log, "failed to unpack IP/Port");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -690,9 +728,9 @@ Onion *new_onion(const Logger *log, const Memory *mem, const Mono_Time *mono_tim
|
||||
onion->timestamp = mono_time_get(onion->mono_time);
|
||||
|
||||
const uint8_t *secret_key = dht_get_self_secret_key(dht);
|
||||
onion->shared_keys_1 = shared_key_cache_new(mono_time, mem, secret_key, KEYS_TIMEOUT, MAX_KEYS_PER_SLOT);
|
||||
onion->shared_keys_2 = shared_key_cache_new(mono_time, mem, secret_key, KEYS_TIMEOUT, MAX_KEYS_PER_SLOT);
|
||||
onion->shared_keys_3 = shared_key_cache_new(mono_time, mem, secret_key, KEYS_TIMEOUT, MAX_KEYS_PER_SLOT);
|
||||
onion->shared_keys_1 = shared_key_cache_new(log, mono_time, mem, secret_key, KEYS_TIMEOUT, MAX_KEYS_PER_SLOT);
|
||||
onion->shared_keys_2 = shared_key_cache_new(log, mono_time, mem, secret_key, KEYS_TIMEOUT, MAX_KEYS_PER_SLOT);
|
||||
onion->shared_keys_3 = shared_key_cache_new(log, mono_time, mem, secret_key, KEYS_TIMEOUT, MAX_KEYS_PER_SLOT);
|
||||
|
||||
if (onion->shared_keys_1 == nullptr ||
|
||||
onion->shared_keys_2 == nullptr ||
|
||||
|
3
external/toxcore/c-toxcore/toxcore/onion.h
vendored
3
external/toxcore/c-toxcore/toxcore/onion.h
vendored
@ -127,7 +127,8 @@ int create_onion_packet_tcp(const Random *rng, uint8_t *packet, uint16_t max_pac
|
||||
* return 0 on success.
|
||||
*/
|
||||
non_null()
|
||||
int send_onion_response(const Networking_Core *net, const IP_Port *dest, const uint8_t *data, uint16_t length,
|
||||
int send_onion_response(const Logger *log, const Networking_Core *net,
|
||||
const IP_Port *dest, const uint8_t *data, uint16_t length,
|
||||
const uint8_t *ret);
|
||||
|
||||
/** @brief Function to handle/send received decrypted versions of the packet created by create_onion_packet.
|
||||
|
@ -186,7 +186,8 @@ int create_data_request(const Random *rng, uint8_t *packet, uint16_t max_packet_
|
||||
* return -1 on failure.
|
||||
* return 0 on success.
|
||||
*/
|
||||
int send_announce_request(const Networking_Core *net, const Random *rng,
|
||||
int send_announce_request(
|
||||
const Logger *log, const Networking_Core *net, const Random *rng,
|
||||
const Onion_Path *path, const Node_format *dest,
|
||||
const uint8_t *public_key, const uint8_t *secret_key,
|
||||
const uint8_t *ping_id, const uint8_t *client_id,
|
||||
@ -230,7 +231,8 @@ int send_announce_request(const Networking_Core *net, const Random *rng,
|
||||
* return -1 on failure.
|
||||
* return 0 on success.
|
||||
*/
|
||||
int send_data_request(const Networking_Core *net, const Random *rng, const Onion_Path *path, const IP_Port *dest,
|
||||
int send_data_request(
|
||||
const Logger *log, const Networking_Core *net, const Random *rng, const Onion_Path *path, const IP_Port *dest,
|
||||
const uint8_t *public_key, const uint8_t *encrypt_public_key, const uint8_t *nonce,
|
||||
const uint8_t *data, uint16_t length)
|
||||
{
|
||||
@ -549,7 +551,7 @@ static int handle_announce_request_common(
|
||||
ONION_ANNOUNCE_SENDBACK_DATA_LENGTH);
|
||||
memcpy(data + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH, nonce, CRYPTO_NONCE_SIZE);
|
||||
|
||||
if (send_onion_response(onion_a->net, source, data,
|
||||
if (send_onion_response(onion_a->log, onion_a->net, source, data,
|
||||
1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_NONCE_SIZE + len,
|
||||
packet + (length - ONION_RETURN_3)) == -1) {
|
||||
mem_delete(onion_a->mem, response);
|
||||
@ -634,7 +636,7 @@ static int handle_data_request(void *object, const IP_Port *source, const uint8_
|
||||
data[0] = NET_PACKET_ONION_DATA_RESPONSE;
|
||||
memcpy(data + 1, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, length - (1 + CRYPTO_PUBLIC_KEY_SIZE + ONION_RETURN_3));
|
||||
|
||||
if (send_onion_response(onion_a->net, &onion_a->entries[index].ret_ip_port, data, SIZEOF_VLA(data),
|
||||
if (send_onion_response(onion_a->log, onion_a->net, &onion_a->entries[index].ret_ip_port, data, SIZEOF_VLA(data),
|
||||
onion_a->entries[index].ret) == -1) {
|
||||
return 1;
|
||||
}
|
||||
@ -665,7 +667,7 @@ Onion_Announce *new_onion_announce(const Logger *log, const Memory *mem, const R
|
||||
onion_a->extra_data_object = nullptr;
|
||||
new_hmac_key(rng, onion_a->hmac_key);
|
||||
|
||||
onion_a->shared_keys_recv = shared_key_cache_new(mono_time, mem, dht_get_self_secret_key(dht), KEYS_TIMEOUT, MAX_KEYS_PER_SLOT);
|
||||
onion_a->shared_keys_recv = shared_key_cache_new(log, mono_time, mem, dht_get_self_secret_key(dht), KEYS_TIMEOUT, MAX_KEYS_PER_SLOT);
|
||||
if (onion_a->shared_keys_recv == nullptr) {
|
||||
kill_onion_announce(onion_a);
|
||||
return nullptr;
|
||||
|
@ -94,7 +94,8 @@ int create_data_request(const Random *rng, uint8_t *packet, uint16_t max_packet_
|
||||
* return 0 on success.
|
||||
*/
|
||||
non_null()
|
||||
int send_announce_request(const Networking_Core *net, const Random *rng,
|
||||
int send_announce_request(
|
||||
const Logger *log, const Networking_Core *net, const Random *rng,
|
||||
const Onion_Path *path, const Node_format *dest,
|
||||
const uint8_t *public_key, const uint8_t *secret_key,
|
||||
const uint8_t *ping_id, const uint8_t *client_id,
|
||||
@ -117,7 +118,8 @@ int send_announce_request(const Networking_Core *net, const Random *rng,
|
||||
* return 0 on success.
|
||||
*/
|
||||
non_null()
|
||||
int send_data_request(const Networking_Core *net, const Random *rng, const Onion_Path *path, const IP_Port *dest,
|
||||
int send_data_request(
|
||||
const Logger *log, const Networking_Core *net, const Random *rng, const Onion_Path *path, const IP_Port *dest,
|
||||
const uint8_t *public_key, const uint8_t *encrypt_public_key, const uint8_t *nonce,
|
||||
const uint8_t *data, uint16_t length);
|
||||
|
||||
|
109
external/toxcore/c-toxcore/toxcore/onion_client.c
vendored
109
external/toxcore/c-toxcore/toxcore/onion_client.c
vendored
@ -582,6 +582,7 @@ static int new_sendback(Onion_Client *onion_c, uint32_t num, const uint8_t *publ
|
||||
*sendback = ping_array_add(onion_c->announce_ping_array, onion_c->mono_time, onion_c->rng, data, sizeof(data));
|
||||
|
||||
if (*sendback == 0) {
|
||||
LOGGER_TRACE(onion_c->logger, "generating sendback in announce ping array failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -624,6 +625,7 @@ static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, con
|
||||
const uint8_t *dest_pubkey, const uint8_t *ping_id, uint32_t pathnum)
|
||||
{
|
||||
if (num > onion_c->num_friends) {
|
||||
LOGGER_TRACE(onion_c->logger, "not sending announce to out of bounds friend %u (num friends: %u)", num, onion_c->num_friends);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -632,10 +634,12 @@ static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, con
|
||||
|
||||
if (num == 0) {
|
||||
if (random_path(onion_c, &onion_c->onion_paths_self, pathnum, &path) == -1) {
|
||||
LOGGER_TRACE(onion_c->logger, "cannot find path to self");
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if (random_path(onion_c, &onion_c->onion_paths_friends, pathnum, &path) == -1) {
|
||||
LOGGER_TRACE(onion_c->logger, "cannot find path to friend");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -682,9 +686,13 @@ static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, con
|
||||
}
|
||||
|
||||
if (len == -1) {
|
||||
LOGGER_TRACE(onion_c->logger, "failed to create announce request");
|
||||
return -1;
|
||||
}
|
||||
|
||||
Ip_Ntoa ip_str;
|
||||
LOGGER_TRACE(onion_c->logger, "sending onion packet to %s:%d (%02x, %d bytes)",
|
||||
net_ip_ntoa(&dest->ip, &ip_str), net_ntohs(dest->port), request[0], len);
|
||||
return send_onion_packet_tcp_udp(onion_c, &path, dest, request, len);
|
||||
}
|
||||
|
||||
@ -934,6 +942,8 @@ static int handle_announce_response(void *object, const IP_Port *source, const u
|
||||
Onion_Client *onion_c = (Onion_Client *)object;
|
||||
|
||||
if (length < ONION_ANNOUNCE_RESPONSE_MIN_SIZE || length > ONION_ANNOUNCE_RESPONSE_MAX_SIZE) {
|
||||
LOGGER_TRACE(onion_c->logger, "invalid announce response length: %u (min: %u, max: %u)",
|
||||
length, (unsigned int)ONION_ANNOUNCE_RESPONSE_MIN_SIZE, (unsigned int)ONION_ANNOUNCE_RESPONSE_MAX_SIZE);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -949,30 +959,37 @@ static int handle_announce_response(void *object, const IP_Port *source, const u
|
||||
uint8_t plain[1 + ONION_PING_ID_SIZE + ONION_ANNOUNCE_RESPONSE_MAX_SIZE - ONION_ANNOUNCE_RESPONSE_MIN_SIZE];
|
||||
const int plain_size = 1 + ONION_PING_ID_SIZE + length - ONION_ANNOUNCE_RESPONSE_MIN_SIZE;
|
||||
int len;
|
||||
const uint16_t nonce_start = 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH;
|
||||
const uint16_t ciphertext_start = nonce_start + CRYPTO_NONCE_SIZE;
|
||||
const uint16_t ciphertext_size = length - ciphertext_start;
|
||||
|
||||
if (num == 0) {
|
||||
len = decrypt_data(public_key, nc_get_self_secret_key(onion_c->c),
|
||||
packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH,
|
||||
packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_NONCE_SIZE,
|
||||
length - (1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_NONCE_SIZE), plain);
|
||||
&packet[nonce_start], &packet[ciphertext_start], ciphertext_size, plain);
|
||||
} else {
|
||||
if (!onion_c->friends_list[num - 1].is_valid) {
|
||||
LOGGER_TRACE(onion_c->logger, "friend number %lu is invalid", (unsigned long)(num - 1));
|
||||
return 1;
|
||||
}
|
||||
|
||||
len = decrypt_data(public_key, onion_c->friends_list[num - 1].temp_secret_key,
|
||||
packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH,
|
||||
packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_NONCE_SIZE,
|
||||
length - (1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_NONCE_SIZE), plain);
|
||||
&packet[nonce_start], &packet[ciphertext_start], ciphertext_size, plain);
|
||||
}
|
||||
|
||||
if (len < 0) {
|
||||
// This happens a lot, so don't log it.
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((uint32_t)len != plain_size) {
|
||||
LOGGER_WARNING(onion_c->logger, "decrypted size (%lu) is not the expected plain text size (%lu)", (unsigned long)len, (unsigned long)plain_size);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const uint32_t path_used = set_path_timeouts(onion_c, num, path_num);
|
||||
|
||||
if (client_add_to_list(onion_c, num, public_key, &ip_port, plain[0], plain + 1, path_used) == -1) {
|
||||
LOGGER_WARNING(onion_c->logger, "failed to add client to list");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -989,10 +1006,12 @@ static int handle_announce_response(void *object, const IP_Port *source, const u
|
||||
plain_size - 2 - ONION_PING_ID_SIZE, false);
|
||||
|
||||
if (num_nodes < 0) {
|
||||
LOGGER_WARNING(onion_c->logger, "no nodes to unpack in onion response");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (client_ping_nodes(onion_c, num, nodes, num_nodes, source) == -1) {
|
||||
LOGGER_WARNING(onion_c->logger, "pinging %d nodes failed", num_nodes);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@ -1011,6 +1030,8 @@ static int handle_announce_response(void *object, const IP_Port *source, const u
|
||||
|
||||
// TODO(irungentoo): LAN vs non LAN ips?, if we are connected only to LAN, are we offline?
|
||||
onion_c->last_packet_recv = mono_time_get(onion_c->mono_time);
|
||||
LOGGER_TRACE(onion_c->logger, "onion has received a packet at %llu",
|
||||
(unsigned long long)onion_c->last_packet_recv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1023,6 +1044,8 @@ static int handle_announce_response_old(void *object, const IP_Port *source, con
|
||||
Onion_Client *onion_c = (Onion_Client *)object;
|
||||
|
||||
if (length < ONION_ANNOUNCE_RESPONSE_MIN_SIZE || length > ONION_ANNOUNCE_RESPONSE_MAX_SIZE) {
|
||||
LOGGER_TRACE(onion_c->logger, "invalid announce response length: %u (min: %u, max: %u)",
|
||||
length, (unsigned int)ONION_ANNOUNCE_RESPONSE_MIN_SIZE, (unsigned int)ONION_ANNOUNCE_RESPONSE_MAX_SIZE);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1039,30 +1062,37 @@ static int handle_announce_response_old(void *object, const IP_Port *source, con
|
||||
|
||||
VLA(uint8_t, plain, 1 + ONION_PING_ID_SIZE + len_nodes);
|
||||
int len;
|
||||
const uint16_t nonce_start = 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH;
|
||||
const uint16_t ciphertext_start = nonce_start + CRYPTO_NONCE_SIZE;
|
||||
const uint16_t ciphertext_size = length - ciphertext_start;
|
||||
|
||||
if (num == 0) {
|
||||
len = decrypt_data(public_key, nc_get_self_secret_key(onion_c->c),
|
||||
packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH,
|
||||
packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_NONCE_SIZE,
|
||||
length - (1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_NONCE_SIZE), plain);
|
||||
&packet[nonce_start], &packet[ciphertext_start], ciphertext_size, plain);
|
||||
} else {
|
||||
if (!onion_c->friends_list[num - 1].is_valid) {
|
||||
LOGGER_TRACE(onion_c->logger, "friend number %lu is invalid", (unsigned long)(num - 1));
|
||||
return 1;
|
||||
}
|
||||
|
||||
len = decrypt_data(public_key, onion_c->friends_list[num - 1].temp_secret_key,
|
||||
packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH,
|
||||
packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_NONCE_SIZE,
|
||||
length - (1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_NONCE_SIZE), plain);
|
||||
&packet[nonce_start], &packet[ciphertext_start], ciphertext_size, plain);
|
||||
}
|
||||
|
||||
if (len < 0) {
|
||||
// This happens a lot, so don't log it.
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((uint32_t)len != SIZEOF_VLA(plain)) {
|
||||
LOGGER_WARNING(onion_c->logger, "decrypted size (%lu) is not the expected plain text size (%lu)", (unsigned long)len, (unsigned long)SIZEOF_VLA(plain));
|
||||
return 1;
|
||||
}
|
||||
|
||||
const uint32_t path_used = set_path_timeouts(onion_c, num, path_num);
|
||||
|
||||
if (client_add_to_list(onion_c, num, public_key, &ip_port, plain[0], plain + 1, path_used) == -1) {
|
||||
LOGGER_WARNING(onion_c->logger, "failed to add client to list");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1071,16 +1101,21 @@ static int handle_announce_response_old(void *object, const IP_Port *source, con
|
||||
const int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, nullptr, plain + 1 + ONION_PING_ID_SIZE, len_nodes, false);
|
||||
|
||||
if (num_nodes <= 0) {
|
||||
LOGGER_WARNING(onion_c->logger, "no nodes to unpack in onion response");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (client_ping_nodes(onion_c, num, nodes, num_nodes, source) == -1) {
|
||||
LOGGER_WARNING(onion_c->logger, "pinging %d nodes failed", num_nodes);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(irungentoo): LAN vs non LAN ips?, if we are connected only to LAN, are we offline?
|
||||
onion_c->last_packet_recv = mono_time_get(onion_c->mono_time);
|
||||
LOGGER_TRACE(onion_c->logger, "onion has received a packet at %llu",
|
||||
(unsigned long long)onion_c->last_packet_recv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1378,6 +1413,7 @@ static int handle_dht_dhtpk(void *object, const IP_Port *source, const uint8_t *
|
||||
|
||||
return handle_dhtpk_announce(onion_c, packet, plain, len, userdata);
|
||||
}
|
||||
|
||||
/** @brief Send the packets to tell our friends what our DHT public key is.
|
||||
*
|
||||
* if onion_dht_both is 0, use only the onion to send the packet.
|
||||
@ -1857,6 +1893,18 @@ void onion_group_announce_register(Onion_Client *onion_c, onion_group_announce_c
|
||||
#define TIME_TO_STABLE (ONION_NODE_PING_INTERVAL * 6)
|
||||
#define ANNOUNCE_INTERVAL_STABLE (ONION_NODE_PING_INTERVAL * 8)
|
||||
|
||||
non_null()
|
||||
static bool key_list_contains(const uint8_t *const *keys, uint16_t keys_size, const uint8_t *public_key)
|
||||
{
|
||||
for (uint16_t i = 0; i < keys_size; ++i) {
|
||||
if (memeq(keys[i], CRYPTO_PUBLIC_KEY_SIZE, public_key, CRYPTO_PUBLIC_KEY_SIZE)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
non_null()
|
||||
static void do_announce(Onion_Client *onion_c)
|
||||
{
|
||||
@ -1945,9 +1993,27 @@ static void do_announce(Onion_Client *onion_c)
|
||||
return;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < (MAX_ONION_CLIENTS_ANNOUNCE / 2); ++i) {
|
||||
// Don't send announces to the same node twice. If we don't have many nodes,
|
||||
// the random selection below may have overlaps. This ensures that we deduplicate
|
||||
// nodes before sending packets to save some bandwidth.
|
||||
const uint8_t *targets[MAX_ONION_CLIENTS_ANNOUNCE / 2];
|
||||
unsigned int targets_count = 0;
|
||||
|
||||
for (unsigned int i = 0; i < MAX_ONION_CLIENTS_ANNOUNCE / 2; ++i) {
|
||||
const uint32_t num = random_range_u32(onion_c->rng, num_nodes);
|
||||
client_send_announce_request(onion_c, 0, &path_nodes[num].ip_port, path_nodes[num].public_key, nullptr, -1);
|
||||
const Node_format *target = &path_nodes[num];
|
||||
|
||||
if (!key_list_contains(targets, targets_count, target->public_key)) {
|
||||
client_send_announce_request(onion_c, 0, &target->ip_port, target->public_key, nullptr, -1);
|
||||
|
||||
targets[targets_count] = target->public_key;
|
||||
++targets_count;
|
||||
assert(targets_count <= MAX_ONION_CLIENTS_ANNOUNCE / 2);
|
||||
} else {
|
||||
Ip_Ntoa ip_str;
|
||||
LOGGER_TRACE(onion_c->logger, "not sending repeated announce request to %s:%d",
|
||||
net_ip_ntoa(&target->ip_port.ip, &ip_str), net_ntohs(target->ip_port.port));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1959,22 +2025,25 @@ static void do_announce(Onion_Client *onion_c)
|
||||
non_null()
|
||||
static bool onion_isconnected(Onion_Client *onion_c)
|
||||
{
|
||||
unsigned int num = 0;
|
||||
unsigned int live = 0;
|
||||
unsigned int announced = 0;
|
||||
|
||||
if (mono_time_is_timeout(onion_c->mono_time, onion_c->last_packet_recv, ONION_OFFLINE_TIMEOUT)) {
|
||||
LOGGER_TRACE(onion_c->logger, "onion is NOT connected: last packet received at %llu (timeout=%u)",
|
||||
(unsigned long long)onion_c->last_packet_recv, ONION_OFFLINE_TIMEOUT);
|
||||
onion_c->last_populated = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (onion_c->path_nodes_index == 0) {
|
||||
LOGGER_TRACE(onion_c->logger, "onion is NOT connected: no path nodes available");
|
||||
onion_c->last_populated = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < MAX_ONION_CLIENTS_ANNOUNCE; ++i) {
|
||||
if (!onion_node_timed_out(&onion_c->clients_announce_list[i], onion_c->mono_time)) {
|
||||
++num;
|
||||
++live;
|
||||
|
||||
if (onion_c->clients_announce_list[i].is_stored != 0) {
|
||||
++announced;
|
||||
@ -1990,14 +2059,18 @@ static bool onion_isconnected(Onion_Client *onion_c)
|
||||
|
||||
/* Consider ourselves online if we are announced to half or more nodes
|
||||
* we are connected to */
|
||||
if (num != 0 && announced != 0) {
|
||||
if ((num / 2) <= announced && (pnodes / 2) <= num) {
|
||||
if (live != 0 && announced != 0) {
|
||||
if ((live / 2) <= announced && (pnodes / 2) <= live) {
|
||||
LOGGER_TRACE(onion_c->logger, "onion is connected: %u live nodes, %u announced, %d path nodes",
|
||||
live, announced, pnodes);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
onion_c->last_populated = 0;
|
||||
|
||||
LOGGER_TRACE(onion_c->logger, "onion is NOT connected: %u live nodes, %u announced, %d path nodes",
|
||||
live, announced, pnodes);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -24,12 +24,13 @@ struct Shared_Key_Cache {
|
||||
uint64_t timeout; /** After this time (in seconds), a key is erased on the next housekeeping cycle */
|
||||
const Mono_Time *mono_time;
|
||||
const Memory *mem;
|
||||
const Logger *log;
|
||||
uint8_t keys_per_slot;
|
||||
};
|
||||
|
||||
non_null()
|
||||
static bool shared_key_is_empty(const Shared_Key *k) {
|
||||
assert(k != nullptr);
|
||||
static bool shared_key_is_empty(const Logger *log, const Shared_Key *k) {
|
||||
LOGGER_ASSERT(log, k != nullptr, "shared key must not be NULL");
|
||||
/*
|
||||
* Since time can never be 0, we use that to determine if a key slot is empty.
|
||||
* Additionally this allows us to use crypto_memzero and leave the slot in a valid state.
|
||||
@ -38,12 +39,12 @@ static bool shared_key_is_empty(const Shared_Key *k) {
|
||||
}
|
||||
|
||||
non_null()
|
||||
static void shared_key_set_empty(Shared_Key *k) {
|
||||
static void shared_key_set_empty(const Logger *log, Shared_Key *k) {
|
||||
crypto_memzero(k, sizeof (Shared_Key));
|
||||
assert(shared_key_is_empty(k));
|
||||
LOGGER_ASSERT(log, shared_key_is_empty(log, k), "shared key must be empty after clearing it");
|
||||
}
|
||||
|
||||
Shared_Key_Cache *shared_key_cache_new(const Mono_Time *mono_time, const Memory *mem, const uint8_t *self_secret_key, uint64_t timeout, uint8_t keys_per_slot)
|
||||
Shared_Key_Cache *shared_key_cache_new(const Logger *log, const Mono_Time *mono_time, const Memory *mem, const uint8_t *self_secret_key, uint64_t timeout, uint8_t keys_per_slot)
|
||||
{
|
||||
if (mono_time == nullptr || self_secret_key == nullptr || timeout == 0 || keys_per_slot == 0) {
|
||||
return nullptr;
|
||||
@ -52,7 +53,7 @@ Shared_Key_Cache *shared_key_cache_new(const Mono_Time *mono_time, const Memory
|
||||
// Time must not be zero, since we use that as special value for empty slots
|
||||
if (mono_time_get(mono_time) == 0) {
|
||||
// Fail loudly in debug environments
|
||||
assert(false);
|
||||
LOGGER_FATAL(log, "time must not be zero (mono_time not initialised?)");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -64,6 +65,7 @@ Shared_Key_Cache *shared_key_cache_new(const Mono_Time *mono_time, const Memory
|
||||
res->self_secret_key = self_secret_key;
|
||||
res->mono_time = mono_time;
|
||||
res->mem = mem;
|
||||
res->log = log;
|
||||
res->keys_per_slot = keys_per_slot;
|
||||
// We take one byte from the public key for each bucket and store keys_per_slot elements there
|
||||
const size_t cache_size = 256 * keys_per_slot;
|
||||
@ -106,7 +108,7 @@ const uint8_t *shared_key_cache_lookup(Shared_Key_Cache *cache, const uint8_t pu
|
||||
|
||||
// Perform lookup
|
||||
for(size_t i = 0; i < cache->keys_per_slot; ++i) {
|
||||
if (shared_key_is_empty(&bucket_start[i])) {
|
||||
if (shared_key_is_empty(cache->log, &bucket_start[i])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -119,13 +121,13 @@ const uint8_t *shared_key_cache_lookup(Shared_Key_Cache *cache, const uint8_t pu
|
||||
|
||||
// Perform housekeeping for this bucket
|
||||
for (size_t i = 0; i < cache->keys_per_slot; ++i) {
|
||||
if (shared_key_is_empty(&bucket_start[i])) {
|
||||
if (shared_key_is_empty(cache->log, &bucket_start[i])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const bool timed_out = (bucket_start[i].time_last_requested + cache->timeout) < cur_time;
|
||||
if (timed_out) {
|
||||
shared_key_set_empty(&bucket_start[i]);
|
||||
shared_key_set_empty(cache->log, &bucket_start[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <stdint.h> // uint*_t
|
||||
|
||||
#include "crypto_core.h"
|
||||
#include "logger.h"
|
||||
#include "mem.h"
|
||||
#include "mono_time.h"
|
||||
|
||||
@ -27,7 +28,8 @@ typedef struct Shared_Key_Cache Shared_Key_Cache;
|
||||
* @return nullptr on error.
|
||||
*/
|
||||
non_null()
|
||||
Shared_Key_Cache *shared_key_cache_new(const Mono_Time *mono_time, const Memory *mem,
|
||||
Shared_Key_Cache *shared_key_cache_new(
|
||||
const Logger *log, const Mono_Time *mono_time, const Memory *mem,
|
||||
const uint8_t *self_secret_key,
|
||||
uint64_t timeout, uint8_t keys_per_slot);
|
||||
|
||||
|
6
external/toxcore/c-toxcore/toxcore/tox.c
vendored
6
external/toxcore/c-toxcore/toxcore/tox.c
vendored
@ -43,6 +43,8 @@ static_assert(FILE_ID_LENGTH == CRYPTO_SYMMETRIC_KEY_SIZE,
|
||||
"FILE_ID_LENGTH is assumed to be equal to CRYPTO_SYMMETRIC_KEY_SIZE");
|
||||
static_assert(TOX_DHT_NODE_IP_STRING_SIZE == IP_NTOA_LEN,
|
||||
"TOX_DHT_NODE_IP_STRING_SIZE is assumed to be equal to IP_NTOA_LEN");
|
||||
static_assert(TOX_GROUP_PEER_IP_STRING_MAX_LENGTH == IP_NTOA_LEN,
|
||||
"TOX_GROUP_PEER_IP_STRING_MAX_LENGTH is assumed to be equal to IP_NTOA_LEN");
|
||||
static_assert(TOX_DHT_NODE_PUBLIC_KEY_SIZE == CRYPTO_PUBLIC_KEY_SIZE,
|
||||
"TOX_DHT_NODE_PUBLIC_KEY_SIZE is assumed to be equal to CRYPTO_PUBLIC_KEY_SIZE");
|
||||
static_assert(TOX_FILE_ID_LENGTH == CRYPTO_SYMMETRIC_KEY_SIZE,
|
||||
@ -2810,7 +2812,7 @@ uint16_t tox_self_get_udp_port(const Tox *tox, Tox_Err_Get_Port *error)
|
||||
{
|
||||
assert(tox != nullptr);
|
||||
tox_lock(tox);
|
||||
const uint16_t port = net_htons(net_port(tox->m->net));
|
||||
const uint16_t port = tox->m == nullptr || tox->m->net == nullptr ? 0 : net_htons(net_port(tox->m->net));
|
||||
tox_unlock(tox);
|
||||
|
||||
if (port == 0) {
|
||||
@ -2827,7 +2829,7 @@ uint16_t tox_self_get_tcp_port(const Tox *tox, Tox_Err_Get_Port *error)
|
||||
assert(tox != nullptr);
|
||||
tox_lock(tox);
|
||||
|
||||
if (tox->m->tcp_server != nullptr) {
|
||||
if (tox->m != nullptr && tox->m->tcp_server != nullptr) {
|
||||
SET_ERROR_PARAMETER(error, TOX_ERR_GET_PORT_OK);
|
||||
const uint16_t ret = tox->m->options.tcp_server_port;
|
||||
tox_unlock(tox);
|
||||
|
142
external/toxcore/c-toxcore/toxcore/tox.h
vendored
142
external/toxcore/c-toxcore/toxcore/tox.h
vendored
@ -373,6 +373,8 @@ typedef enum Tox_User_Status {
|
||||
|
||||
} Tox_User_Status;
|
||||
|
||||
const char *tox_user_status_to_string(Tox_User_Status value);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Represents message types for tox_friend_send_message and conference
|
||||
@ -393,6 +395,8 @@ typedef enum Tox_Message_Type {
|
||||
|
||||
} Tox_Message_Type;
|
||||
|
||||
const char *tox_message_type_to_string(Tox_Message_Type value);
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
@ -422,6 +426,8 @@ typedef enum Tox_Proxy_Type {
|
||||
|
||||
} Tox_Proxy_Type;
|
||||
|
||||
const char *tox_proxy_type_to_string(Tox_Proxy_Type value);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Type of savedata to create the Tox instance from.
|
||||
@ -445,6 +451,8 @@ typedef enum Tox_Savedata_Type {
|
||||
|
||||
} Tox_Savedata_Type;
|
||||
|
||||
const char *tox_savedata_type_to_string(Tox_Savedata_Type value);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Severity level of log messages.
|
||||
@ -478,6 +486,8 @@ typedef enum Tox_Log_Level {
|
||||
|
||||
} Tox_Log_Level;
|
||||
|
||||
const char *tox_log_level_to_string(Tox_Log_Level value);
|
||||
|
||||
|
||||
/**
|
||||
* @brief This event is triggered when the toxcore library logs an events_alloc message.
|
||||
@ -791,6 +801,8 @@ typedef enum Tox_Err_Options_New {
|
||||
|
||||
} Tox_Err_Options_New;
|
||||
|
||||
const char *tox_err_options_new_to_string(Tox_Err_Options_New value);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Allocates a new Tox_Options object and initialises it with the default
|
||||
@ -883,6 +895,8 @@ typedef enum Tox_Err_New {
|
||||
|
||||
} Tox_Err_New;
|
||||
|
||||
const char *tox_err_new_to_string(Tox_Err_New value);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Creates and initialises a new Tox instance with the options passed.
|
||||
@ -962,6 +976,8 @@ typedef enum Tox_Err_Bootstrap {
|
||||
|
||||
} Tox_Err_Bootstrap;
|
||||
|
||||
const char *tox_err_bootstrap_to_string(Tox_Err_Bootstrap value);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Sends a "get nodes" request to the given bootstrap node with IP, port,
|
||||
@ -1029,6 +1045,8 @@ typedef enum Tox_Connection {
|
||||
|
||||
} Tox_Connection;
|
||||
|
||||
const char *tox_connection_to_string(Tox_Connection value);
|
||||
|
||||
/**
|
||||
* @brief Return whether we are connected to the DHT.
|
||||
*
|
||||
@ -1155,6 +1173,8 @@ typedef enum Tox_Err_Set_Info {
|
||||
|
||||
} Tox_Err_Set_Info;
|
||||
|
||||
const char *tox_err_set_info_to_string(Tox_Err_Set_Info value);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the nickname for the Tox client.
|
||||
@ -1297,6 +1317,8 @@ typedef enum Tox_Err_Friend_Add {
|
||||
|
||||
} Tox_Err_Friend_Add;
|
||||
|
||||
const char *tox_err_friend_add_to_string(Tox_Err_Friend_Add value);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Add a friend to the friend list and send a friend request.
|
||||
@ -1358,6 +1380,8 @@ typedef enum Tox_Err_Friend_Delete {
|
||||
|
||||
} Tox_Err_Friend_Delete;
|
||||
|
||||
const char *tox_err_friend_delete_to_string(Tox_Err_Friend_Delete value);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Remove a friend from the friend list.
|
||||
@ -1398,6 +1422,8 @@ typedef enum Tox_Err_Friend_By_Public_Key {
|
||||
|
||||
} Tox_Err_Friend_By_Public_Key;
|
||||
|
||||
const char *tox_err_friend_by_public_key_to_string(Tox_Err_Friend_By_Public_Key value);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Return the friend number associated with that Public Key.
|
||||
@ -1445,6 +1471,8 @@ typedef enum Tox_Err_Friend_Get_Public_Key {
|
||||
|
||||
} Tox_Err_Friend_Get_Public_Key;
|
||||
|
||||
const char *tox_err_friend_get_public_key_to_string(Tox_Err_Friend_Get_Public_Key value);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Copies the Public Key associated with a given friend number to a byte array.
|
||||
@ -1472,6 +1500,8 @@ typedef enum Tox_Err_Friend_Get_Last_Online {
|
||||
|
||||
} Tox_Err_Friend_Get_Last_Online;
|
||||
|
||||
const char *tox_err_friend_get_last_online_to_string(Tox_Err_Friend_Get_Last_Online value);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Return a unix-time timestamp of the last time the friend associated with a given
|
||||
@ -1514,6 +1544,8 @@ typedef enum Tox_Err_Friend_Query {
|
||||
|
||||
} Tox_Err_Friend_Query;
|
||||
|
||||
const char *tox_err_friend_query_to_string(Tox_Err_Friend_Query value);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Return the length of the friend's name.
|
||||
@ -1726,6 +1758,8 @@ typedef enum Tox_Err_Set_Typing {
|
||||
|
||||
} Tox_Err_Set_Typing;
|
||||
|
||||
const char *tox_err_set_typing_to_string(Tox_Err_Set_Typing value);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the client's typing status for a friend.
|
||||
@ -1778,6 +1812,8 @@ typedef enum Tox_Err_Friend_Send_Message {
|
||||
|
||||
} Tox_Err_Friend_Send_Message;
|
||||
|
||||
const char *tox_err_friend_send_message_to_string(Tox_Err_Friend_Send_Message value);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Send a text chat message to an online friend.
|
||||
@ -1960,6 +1996,8 @@ typedef enum Tox_File_Control {
|
||||
|
||||
} Tox_File_Control;
|
||||
|
||||
const char *tox_file_control_to_string(Tox_File_Control value);
|
||||
|
||||
|
||||
typedef enum Tox_Err_File_Control {
|
||||
|
||||
@ -2006,6 +2044,8 @@ typedef enum Tox_Err_File_Control {
|
||||
|
||||
} Tox_Err_File_Control;
|
||||
|
||||
const char *tox_err_file_control_to_string(Tox_Err_File_Control value);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Sends a file control command to a friend for a given file transfer.
|
||||
@ -2082,6 +2122,8 @@ typedef enum Tox_Err_File_Seek {
|
||||
|
||||
} Tox_Err_File_Seek;
|
||||
|
||||
const char *tox_err_file_seek_to_string(Tox_Err_File_Seek value);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Sends a file seek control command to a friend for a given file transfer.
|
||||
@ -2120,6 +2162,8 @@ typedef enum Tox_Err_File_Get {
|
||||
|
||||
} Tox_Err_File_Get;
|
||||
|
||||
const char *tox_err_file_get_to_string(Tox_Err_File_Get value);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Copy the file id associated to the file transfer to a byte array.
|
||||
@ -2177,6 +2221,8 @@ typedef enum Tox_Err_File_Send {
|
||||
|
||||
} Tox_Err_File_Send;
|
||||
|
||||
const char *tox_err_file_send_to_string(Tox_Err_File_Send value);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Send a file transmission request.
|
||||
@ -2291,6 +2337,8 @@ typedef enum Tox_Err_File_Send_Chunk {
|
||||
|
||||
} Tox_Err_File_Send_Chunk;
|
||||
|
||||
const char *tox_err_file_send_chunk_to_string(Tox_Err_File_Send_Chunk value);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Send a chunk of file data to a friend.
|
||||
@ -2438,6 +2486,8 @@ typedef enum Tox_Conference_Type {
|
||||
|
||||
} Tox_Conference_Type;
|
||||
|
||||
const char *tox_conference_type_to_string(Tox_Conference_Type value);
|
||||
|
||||
|
||||
/**
|
||||
* The invitation will remain valid until the inviting friend goes offline
|
||||
@ -2571,6 +2621,8 @@ typedef enum Tox_Err_Conference_New {
|
||||
|
||||
} Tox_Err_Conference_New;
|
||||
|
||||
const char *tox_err_conference_new_to_string(Tox_Err_Conference_New value);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Creates a new conference.
|
||||
@ -2597,6 +2649,8 @@ typedef enum Tox_Err_Conference_Delete {
|
||||
|
||||
} Tox_Err_Conference_Delete;
|
||||
|
||||
const char *tox_err_conference_delete_to_string(Tox_Err_Conference_Delete value);
|
||||
|
||||
|
||||
/**
|
||||
* @brief This function deletes a conference.
|
||||
@ -2634,6 +2688,8 @@ typedef enum Tox_Err_Conference_Peer_Query {
|
||||
|
||||
} Tox_Err_Conference_Peer_Query;
|
||||
|
||||
const char *tox_err_conference_peer_query_to_string(Tox_Err_Conference_Peer_Query value);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Return the number of online peers in the conference.
|
||||
@ -2742,6 +2798,8 @@ typedef enum Tox_Err_Conference_Set_Max_Offline {
|
||||
|
||||
} Tox_Err_Conference_Set_Max_Offline;
|
||||
|
||||
const char *tox_err_conference_set_max_offline_to_string(Tox_Err_Conference_Set_Max_Offline value);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set maximum number of offline peers to store, overriding the default.
|
||||
@ -2773,6 +2831,8 @@ typedef enum Tox_Err_Conference_Invite {
|
||||
|
||||
} Tox_Err_Conference_Invite;
|
||||
|
||||
const char *tox_err_conference_invite_to_string(Tox_Err_Conference_Invite value);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Invites a friend to a conference.
|
||||
@ -2824,6 +2884,8 @@ typedef enum Tox_Err_Conference_Join {
|
||||
|
||||
} Tox_Err_Conference_Join;
|
||||
|
||||
const char *tox_err_conference_join_to_string(Tox_Err_Conference_Join value);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Joins a conference that the client has been invited to.
|
||||
@ -2874,6 +2936,8 @@ typedef enum Tox_Err_Conference_Send_Message {
|
||||
|
||||
} Tox_Err_Conference_Send_Message;
|
||||
|
||||
const char *tox_err_conference_send_message_to_string(Tox_Err_Conference_Send_Message value);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Send a text chat message to the conference.
|
||||
@ -2921,6 +2985,8 @@ typedef enum Tox_Err_Conference_Title {
|
||||
|
||||
} Tox_Err_Conference_Title;
|
||||
|
||||
const char *tox_err_conference_title_to_string(Tox_Err_Conference_Title value);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Return the length of the conference title.
|
||||
@ -3000,6 +3066,8 @@ typedef enum Tox_Err_Conference_Get_Type {
|
||||
|
||||
} Tox_Err_Conference_Get_Type;
|
||||
|
||||
const char *tox_err_conference_get_type_to_string(Tox_Err_Conference_Get_Type value);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the type (text or A/V) for the conference.
|
||||
@ -3037,6 +3105,8 @@ typedef enum Tox_Err_Conference_By_Id {
|
||||
|
||||
} Tox_Err_Conference_By_Id;
|
||||
|
||||
const char *tox_err_conference_by_id_to_string(Tox_Err_Conference_By_Id value);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Return the conference number associated with the specified id.
|
||||
@ -3078,6 +3148,8 @@ typedef enum Tox_Err_Conference_By_Uid {
|
||||
|
||||
} Tox_Err_Conference_By_Uid;
|
||||
|
||||
const char *tox_err_conference_by_uid_to_string(Tox_Err_Conference_By_Uid value);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Return the conference number associated with the specified uid.
|
||||
@ -3141,6 +3213,8 @@ typedef enum Tox_Err_Friend_Custom_Packet {
|
||||
|
||||
} Tox_Err_Friend_Custom_Packet;
|
||||
|
||||
const char *tox_err_friend_custom_packet_to_string(Tox_Err_Friend_Custom_Packet value);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Send a custom lossy packet to a friend.
|
||||
@ -3237,6 +3311,8 @@ typedef enum Tox_Err_Get_Port {
|
||||
|
||||
} Tox_Err_Get_Port;
|
||||
|
||||
const char *tox_err_get_port_to_string(Tox_Err_Get_Port value);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Writes the temporary DHT public key of this instance to a byte array.
|
||||
@ -3382,6 +3458,8 @@ typedef enum Tox_Group_Privacy_State {
|
||||
|
||||
} Tox_Group_Privacy_State;
|
||||
|
||||
const char *tox_group_privacy_state_to_string(Tox_Group_Privacy_State value);
|
||||
|
||||
|
||||
/**
|
||||
* Represents the state of the group topic lock.
|
||||
@ -3400,6 +3478,8 @@ typedef enum Tox_Group_Topic_Lock {
|
||||
|
||||
} Tox_Group_Topic_Lock;
|
||||
|
||||
const char *tox_group_topic_lock_to_string(Tox_Group_Topic_Lock value);
|
||||
|
||||
/**
|
||||
* Represents the group voice state, which determines which Group Roles have permission to speak
|
||||
* in the group chat. The voice state does not have any effect private messages or topic setting.
|
||||
@ -3421,6 +3501,8 @@ typedef enum Tox_Group_Voice_State {
|
||||
TOX_GROUP_VOICE_STATE_FOUNDER,
|
||||
} Tox_Group_Voice_State;
|
||||
|
||||
const char *tox_group_voice_state_to_string(Tox_Group_Voice_State value);
|
||||
|
||||
/**
|
||||
* Represents group roles.
|
||||
*
|
||||
@ -3453,6 +3535,8 @@ typedef enum Tox_Group_Role {
|
||||
|
||||
} Tox_Group_Role;
|
||||
|
||||
const char *tox_group_role_to_string(Tox_Group_Role value);
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
@ -3498,6 +3582,8 @@ typedef enum Tox_Err_Group_New {
|
||||
|
||||
} Tox_Err_Group_New;
|
||||
|
||||
const char *tox_err_group_new_to_string(Tox_Err_Group_New value);
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new group chat.
|
||||
@ -3564,6 +3650,8 @@ typedef enum Tox_Err_Group_Join {
|
||||
|
||||
} Tox_Err_Group_Join;
|
||||
|
||||
const char *tox_err_group_join_to_string(Tox_Err_Group_Join value);
|
||||
|
||||
|
||||
/**
|
||||
* Joins a group chat with specified Chat ID.
|
||||
@ -3599,6 +3687,8 @@ typedef enum Tox_Err_Group_Is_Connected {
|
||||
|
||||
} Tox_Err_Group_Is_Connected;
|
||||
|
||||
const char *tox_err_group_is_connected_to_string(Tox_Err_Group_Is_Connected value);
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the group chat is currently connected or attempting to connect to other peers
|
||||
@ -3626,6 +3716,8 @@ typedef enum Tox_Err_Group_Disconnect {
|
||||
TOX_ERR_GROUP_DISCONNECT_ALREADY_DISCONNECTED,
|
||||
} Tox_Err_Group_Disconnect;
|
||||
|
||||
const char *tox_err_group_disconnect_to_string(Tox_Err_Group_Disconnect value);
|
||||
|
||||
|
||||
/**
|
||||
* Disconnects from a group chat while retaining the group state and credentials.
|
||||
@ -3655,6 +3747,8 @@ typedef enum Tox_Err_Group_Reconnect {
|
||||
|
||||
} Tox_Err_Group_Reconnect;
|
||||
|
||||
const char *tox_err_group_reconnect_to_string(Tox_Err_Group_Reconnect value);
|
||||
|
||||
|
||||
/**
|
||||
* Reconnects to a group.
|
||||
@ -3691,6 +3785,8 @@ typedef enum Tox_Err_Group_Leave {
|
||||
TOX_ERR_GROUP_LEAVE_FAIL_SEND,
|
||||
} Tox_Err_Group_Leave;
|
||||
|
||||
const char *tox_err_group_leave_to_string(Tox_Err_Group_Leave value);
|
||||
|
||||
|
||||
/**
|
||||
* Leaves a group.
|
||||
@ -3735,6 +3831,8 @@ typedef enum Tox_Err_Group_Self_Query {
|
||||
|
||||
} Tox_Err_Group_Self_Query;
|
||||
|
||||
const char *tox_err_group_self_query_to_string(Tox_Err_Group_Self_Query value);
|
||||
|
||||
|
||||
/**
|
||||
* Error codes for self name setting.
|
||||
@ -3768,6 +3866,8 @@ typedef enum Tox_Err_Group_Self_Name_Set {
|
||||
|
||||
} Tox_Err_Group_Self_Name_Set;
|
||||
|
||||
const char *tox_err_group_self_name_set_to_string(Tox_Err_Group_Self_Name_Set value);
|
||||
|
||||
|
||||
/**
|
||||
* Set the client's nickname for the group instance designated by the given group number.
|
||||
@ -3831,6 +3931,8 @@ typedef enum Tox_Err_Group_Self_Status_Set {
|
||||
|
||||
} Tox_Err_Group_Self_Status_Set;
|
||||
|
||||
const char *tox_err_group_self_status_set_to_string(Tox_Err_Group_Self_Status_Set value);
|
||||
|
||||
|
||||
/**
|
||||
* Set the client's status for the group instance. Status must be a Tox_User_Status.
|
||||
@ -3906,6 +4008,8 @@ typedef enum Tox_Err_Group_Peer_Query {
|
||||
|
||||
} Tox_Err_Group_Peer_Query;
|
||||
|
||||
const char *tox_err_group_peer_query_to_string(Tox_Err_Group_Peer_Query value);
|
||||
|
||||
|
||||
/**
|
||||
* Return the length of the peer's name. If the group number or ID is invalid, the
|
||||
@ -4054,6 +4158,8 @@ typedef enum Tox_Err_Group_State_Queries {
|
||||
|
||||
} Tox_Err_Group_State_Queries;
|
||||
|
||||
const char *tox_err_group_state_queries_to_string(Tox_Err_Group_State_Queries value);
|
||||
|
||||
|
||||
/**
|
||||
* Error codes for group topic setting.
|
||||
@ -4097,6 +4203,8 @@ typedef enum Tox_Err_Group_Topic_Set {
|
||||
|
||||
} Tox_Err_Group_Topic_Set;
|
||||
|
||||
const char *tox_err_group_topic_set_to_string(Tox_Err_Group_Topic_Set value);
|
||||
|
||||
|
||||
/**
|
||||
* Set the group topic and broadcast it to the rest of the group.
|
||||
@ -4384,6 +4492,8 @@ typedef enum Tox_Err_Group_Send_Message {
|
||||
|
||||
} Tox_Err_Group_Send_Message;
|
||||
|
||||
const char *tox_err_group_send_message_to_string(Tox_Err_Group_Send_Message value);
|
||||
|
||||
|
||||
/**
|
||||
* Send a text chat message to the group.
|
||||
@ -4458,6 +4568,8 @@ typedef enum Tox_Err_Group_Send_Private_Message {
|
||||
|
||||
} Tox_Err_Group_Send_Private_Message;
|
||||
|
||||
const char *tox_err_group_send_private_message_to_string(Tox_Err_Group_Send_Private_Message value);
|
||||
|
||||
|
||||
/**
|
||||
* Send a text chat message to the specified peer in the specified group.
|
||||
@ -4516,6 +4628,8 @@ typedef enum Tox_Err_Group_Send_Custom_Packet {
|
||||
|
||||
} Tox_Err_Group_Send_Custom_Packet;
|
||||
|
||||
const char *tox_err_group_send_custom_packet_to_string(Tox_Err_Group_Send_Custom_Packet value);
|
||||
|
||||
|
||||
/**
|
||||
* Send a custom packet to the group.
|
||||
@ -4592,6 +4706,8 @@ typedef enum Tox_Err_Group_Send_Custom_Private_Packet {
|
||||
|
||||
} Tox_Err_Group_Send_Custom_Private_Packet;
|
||||
|
||||
const char *tox_err_group_send_custom_private_packet_to_string(Tox_Err_Group_Send_Custom_Private_Packet value);
|
||||
|
||||
/**
|
||||
* Send a custom private packet to a designated peer in the group.
|
||||
*
|
||||
@ -4743,6 +4859,8 @@ typedef enum Tox_Err_Group_Invite_Friend {
|
||||
|
||||
} Tox_Err_Group_Invite_Friend;
|
||||
|
||||
const char *tox_err_group_invite_friend_to_string(Tox_Err_Group_Invite_Friend value);
|
||||
|
||||
|
||||
/**
|
||||
* Invite a friend to a group.
|
||||
@ -4801,6 +4919,8 @@ typedef enum Tox_Err_Group_Invite_Accept {
|
||||
|
||||
} Tox_Err_Group_Invite_Accept;
|
||||
|
||||
const char *tox_err_group_invite_accept_to_string(Tox_Err_Group_Invite_Accept value);
|
||||
|
||||
|
||||
/**
|
||||
* Accept an invite to a group chat that the client previously received from a friend. The invite
|
||||
@ -4891,6 +5011,8 @@ typedef enum Tox_Group_Exit_Type {
|
||||
|
||||
} Tox_Group_Exit_Type;
|
||||
|
||||
const char *tox_group_exit_type_to_string(Tox_Group_Exit_Type value);
|
||||
|
||||
|
||||
/**
|
||||
* @param group_number The group number of the group in which a peer has left.
|
||||
@ -4951,6 +5073,8 @@ typedef enum Tox_Group_Join_Fail {
|
||||
|
||||
} Tox_Group_Join_Fail;
|
||||
|
||||
const char *tox_group_join_fail_to_string(Tox_Group_Join_Fail value);
|
||||
|
||||
|
||||
/**
|
||||
* @param group_number The group number of the group for which the join has failed.
|
||||
@ -5014,6 +5138,8 @@ typedef enum Tox_Err_Group_Founder_Set_Password {
|
||||
|
||||
} Tox_Err_Group_Founder_Set_Password;
|
||||
|
||||
const char *tox_err_group_founder_set_password_to_string(Tox_Err_Group_Founder_Set_Password value);
|
||||
|
||||
|
||||
/**
|
||||
* Set or unset the group password.
|
||||
@ -5070,6 +5196,8 @@ typedef enum Tox_Err_Group_Founder_Set_Topic_Lock {
|
||||
|
||||
} Tox_Err_Group_Founder_Set_Topic_Lock;
|
||||
|
||||
const char *tox_err_group_founder_set_topic_lock_to_string(Tox_Err_Group_Founder_Set_Topic_Lock value);
|
||||
|
||||
|
||||
/**
|
||||
* Set the group topic lock state.
|
||||
@ -5123,6 +5251,8 @@ typedef enum Tox_Err_Group_Founder_Set_Voice_State {
|
||||
|
||||
} Tox_Err_Group_Founder_Set_Voice_State;
|
||||
|
||||
const char *tox_err_group_founder_set_voice_state_to_string(Tox_Err_Group_Founder_Set_Voice_State value);
|
||||
|
||||
/**
|
||||
* Set the group voice state.
|
||||
*
|
||||
@ -5175,6 +5305,8 @@ typedef enum Tox_Err_Group_Founder_Set_Privacy_State {
|
||||
|
||||
} Tox_Err_Group_Founder_Set_Privacy_State;
|
||||
|
||||
const char *tox_err_group_founder_set_privacy_state_to_string(Tox_Err_Group_Founder_Set_Privacy_State value);
|
||||
|
||||
/**
|
||||
* Set the group privacy state.
|
||||
*
|
||||
@ -5227,6 +5359,8 @@ typedef enum Tox_Err_Group_Founder_Set_Peer_Limit {
|
||||
|
||||
} Tox_Err_Group_Founder_Set_Peer_Limit;
|
||||
|
||||
const char *tox_err_group_founder_set_peer_limit_to_string(Tox_Err_Group_Founder_Set_Peer_Limit value);
|
||||
|
||||
|
||||
/**
|
||||
* Set the group peer limit.
|
||||
@ -5275,6 +5409,8 @@ typedef enum Tox_Err_Group_Set_Ignore {
|
||||
|
||||
} Tox_Err_Group_Set_Ignore;
|
||||
|
||||
const char *tox_err_group_set_ignore_to_string(Tox_Err_Group_Set_Ignore value);
|
||||
|
||||
|
||||
/**
|
||||
* Ignore or unignore a peer.
|
||||
@ -5329,6 +5465,8 @@ typedef enum Tox_Err_Group_Mod_Set_Role {
|
||||
|
||||
} Tox_Err_Group_Mod_Set_Role;
|
||||
|
||||
const char *tox_err_group_mod_set_role_to_string(Tox_Err_Group_Mod_Set_Role value);
|
||||
|
||||
|
||||
/**
|
||||
* Set a peer's role.
|
||||
@ -5385,6 +5523,8 @@ typedef enum Tox_Err_Group_Mod_Kick_Peer {
|
||||
|
||||
} Tox_Err_Group_Mod_Kick_Peer;
|
||||
|
||||
const char *tox_err_group_mod_kick_peer_to_string(Tox_Err_Group_Mod_Kick_Peer value);
|
||||
|
||||
|
||||
/**
|
||||
* Kick a peer.
|
||||
@ -5428,6 +5568,8 @@ typedef enum Tox_Group_Mod_Event {
|
||||
|
||||
} Tox_Group_Mod_Event;
|
||||
|
||||
const char *tox_group_mod_event_to_string(Tox_Group_Mod_Event value);
|
||||
|
||||
|
||||
/**
|
||||
* @param group_number The group number of the group the event is intended for.
|
||||
|
1394
external/toxcore/c-toxcore/toxcore/tox_api.c
vendored
1394
external/toxcore/c-toxcore/toxcore/tox_api.c
vendored
File diff suppressed because it is too large
Load Diff
55
external/toxcore/c-toxcore/toxcore/tox_private.c
vendored
55
external/toxcore/c-toxcore/toxcore/tox_private.c
vendored
@ -11,6 +11,7 @@
|
||||
#include <assert.h>
|
||||
|
||||
#include "ccompat.h"
|
||||
#include "group_chats.h"
|
||||
#include "mem.h"
|
||||
#include "network.h"
|
||||
#include "tox_struct.h"
|
||||
@ -166,3 +167,57 @@ uint16_t tox_dht_get_num_closelist_announce_capable(const Tox *tox){
|
||||
return num_cap;
|
||||
}
|
||||
|
||||
#ifndef VANILLA_NACL
|
||||
size_t tox_group_peer_get_ip_address_size(const Tox *tox, uint32_t group_number, uint32_t peer_id,
|
||||
Tox_Err_Group_Peer_Query *error)
|
||||
{
|
||||
assert(tox != nullptr);
|
||||
|
||||
tox_lock(tox);
|
||||
const GC_Chat *chat = gc_get_group(tox->m->group_handler, group_number);
|
||||
|
||||
if (chat == nullptr) {
|
||||
SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_PEER_QUERY_GROUP_NOT_FOUND);
|
||||
tox_unlock(tox);
|
||||
return -1;
|
||||
}
|
||||
|
||||
const int ret = gc_get_peer_ip_address_size(chat, peer_id);
|
||||
tox_unlock(tox);
|
||||
|
||||
if (ret == -1) {
|
||||
SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_PEER_QUERY_PEER_NOT_FOUND);
|
||||
return -1;
|
||||
} else {
|
||||
SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_PEER_QUERY_OK);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
bool tox_group_peer_get_ip_address(const Tox *tox, uint32_t group_number, uint32_t peer_id, uint8_t *ip_addr,
|
||||
Tox_Err_Group_Peer_Query *error)
|
||||
{
|
||||
assert(tox != nullptr);
|
||||
|
||||
tox_lock(tox);
|
||||
const GC_Chat *chat = gc_get_group(tox->m->group_handler, group_number);
|
||||
|
||||
if (chat == nullptr) {
|
||||
SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_PEER_QUERY_GROUP_NOT_FOUND);
|
||||
tox_unlock(tox);
|
||||
return false;
|
||||
}
|
||||
|
||||
const int ret = gc_get_peer_ip_address(chat, peer_id, ip_addr);
|
||||
tox_unlock(tox);
|
||||
|
||||
if (ret == -1) {
|
||||
SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_PEER_QUERY_PEER_NOT_FOUND);
|
||||
return false;
|
||||
}
|
||||
|
||||
SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_PEER_QUERY_OK);
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif /* VANILLA_NACL */
|
||||
|
45
external/toxcore/c-toxcore/toxcore/tox_private.h
vendored
45
external/toxcore/c-toxcore/toxcore/tox_private.h
vendored
@ -156,6 +156,51 @@ uint16_t tox_dht_get_num_closelist(const Tox *tox);
|
||||
*/
|
||||
uint16_t tox_dht_get_num_closelist_announce_capable(const Tox *tox);
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* :: DHT groupchat queries.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* Maximum size of a peer IP address string.
|
||||
*/
|
||||
#define TOX_GROUP_PEER_IP_STRING_MAX_LENGTH 96
|
||||
|
||||
uint32_t tox_group_peer_ip_string_max_length(void);
|
||||
|
||||
/**
|
||||
* Return the length of the peer's IP address in string form. If the group number or ID
|
||||
* is invalid, the return value is unspecified.
|
||||
*
|
||||
* @param group_number The group number of the group we wish to query.
|
||||
* @param peer_id The ID of the peer whose IP address length we want to retrieve.
|
||||
*/
|
||||
size_t tox_group_peer_get_ip_address_size(const Tox *tox, uint32_t group_number, uint32_t peer_id,
|
||||
Tox_Err_Group_Peer_Query *error);
|
||||
/**
|
||||
* Write the IP address associated with the designated peer_id for the designated group number
|
||||
* to ip_addr.
|
||||
*
|
||||
* If the peer is forcing TCP connections a placeholder value will be written instead,
|
||||
* indicating that their real IP address is unknown to us.
|
||||
*
|
||||
* If `peer_id` designates ourself, it will write either our own IP address or a placeholder value,
|
||||
* depending on whether or not we're forcing TCP connections.
|
||||
*
|
||||
* Call tox_group_peer_get_ip_address_size to determine the allocation size for the `ip_addr` parameter.
|
||||
*
|
||||
* @param group_number The group number of the group we wish to query.
|
||||
* @param peer_id The ID of the peer whose public key we wish to retrieve.
|
||||
* @param ip_addr A valid memory region large enough to store the IP address string.
|
||||
* If this parameter is NULL, this function call has no effect.
|
||||
*
|
||||
* @return true on success.
|
||||
*/
|
||||
bool tox_group_peer_get_ip_address(const Tox *tox, uint32_t group_number, uint32_t peer_id, uint8_t *ip_addr,
|
||||
Tox_Err_Group_Peer_Query *error);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
95
external/toxcore/c-toxcore/toxcore/tox_unpack.c
vendored
95
external/toxcore/c-toxcore/toxcore/tox_unpack.c
vendored
@ -130,6 +130,17 @@ bool tox_unpack_user_status(Bin_Unpack *bu, Tox_User_Status *val)
|
||||
return true;
|
||||
}
|
||||
|
||||
static Tox_Group_Privacy_State tox_group_privacy_state_from_int(uint32_t value)
|
||||
{
|
||||
switch (value) {
|
||||
case 0:
|
||||
return TOX_GROUP_PRIVACY_STATE_PUBLIC;
|
||||
case 1:
|
||||
return TOX_GROUP_PRIVACY_STATE_PRIVATE;
|
||||
default:
|
||||
return TOX_GROUP_PRIVACY_STATE_PRIVATE;
|
||||
}
|
||||
}
|
||||
bool tox_unpack_group_privacy_state(Bin_Unpack *bu, Tox_Group_Privacy_State *val)
|
||||
{
|
||||
uint32_t u32;
|
||||
@ -138,10 +149,22 @@ bool tox_unpack_group_privacy_state(Bin_Unpack *bu, Tox_Group_Privacy_State *val
|
||||
return false;
|
||||
}
|
||||
|
||||
*val = (Tox_Group_Privacy_State)u32;
|
||||
*val = tox_group_privacy_state_from_int(u32);
|
||||
return true;
|
||||
}
|
||||
|
||||
static Tox_Group_Voice_State tox_group_voice_state_from_int(uint32_t value)
|
||||
{
|
||||
switch (value) {
|
||||
case 0:
|
||||
return TOX_GROUP_VOICE_STATE_ALL;
|
||||
case 1:
|
||||
return TOX_GROUP_VOICE_STATE_MODERATOR;
|
||||
case 2:
|
||||
return TOX_GROUP_VOICE_STATE_FOUNDER;
|
||||
default:
|
||||
return TOX_GROUP_VOICE_STATE_FOUNDER;
|
||||
}
|
||||
}
|
||||
bool tox_unpack_group_voice_state(Bin_Unpack *bu, Tox_Group_Voice_State *val)
|
||||
{
|
||||
uint32_t u32;
|
||||
@ -150,10 +173,21 @@ bool tox_unpack_group_voice_state(Bin_Unpack *bu, Tox_Group_Voice_State *val)
|
||||
return false;
|
||||
}
|
||||
|
||||
*val = (Tox_Group_Voice_State)u32;
|
||||
*val = tox_group_voice_state_from_int(u32);
|
||||
return true;
|
||||
}
|
||||
|
||||
static Tox_Group_Topic_Lock tox_group_topic_lock_from_int(uint32_t value)
|
||||
{
|
||||
switch (value) {
|
||||
case 0:
|
||||
return TOX_GROUP_TOPIC_LOCK_ENABLED;
|
||||
case 1:
|
||||
return TOX_GROUP_TOPIC_LOCK_DISABLED;
|
||||
default:
|
||||
return TOX_GROUP_TOPIC_LOCK_ENABLED;
|
||||
}
|
||||
}
|
||||
bool tox_unpack_group_topic_lock(Bin_Unpack *bu, Tox_Group_Topic_Lock *val)
|
||||
{
|
||||
uint32_t u32;
|
||||
@ -162,10 +196,23 @@ bool tox_unpack_group_topic_lock(Bin_Unpack *bu, Tox_Group_Topic_Lock *val)
|
||||
return false;
|
||||
}
|
||||
|
||||
*val = (Tox_Group_Topic_Lock)u32;
|
||||
*val = tox_group_topic_lock_from_int(u32);
|
||||
return true;
|
||||
}
|
||||
|
||||
static Tox_Group_Join_Fail tox_group_join_fail_from_int(uint32_t value)
|
||||
{
|
||||
switch (value) {
|
||||
case 0:
|
||||
return TOX_GROUP_JOIN_FAIL_PEER_LIMIT;
|
||||
case 1:
|
||||
return TOX_GROUP_JOIN_FAIL_INVALID_PASSWORD;
|
||||
case 2:
|
||||
return TOX_GROUP_JOIN_FAIL_UNKNOWN;
|
||||
default:
|
||||
return TOX_GROUP_JOIN_FAIL_UNKNOWN;
|
||||
}
|
||||
}
|
||||
bool tox_unpack_group_join_fail(Bin_Unpack *bu, Tox_Group_Join_Fail *val)
|
||||
{
|
||||
uint32_t u32;
|
||||
@ -174,10 +221,25 @@ bool tox_unpack_group_join_fail(Bin_Unpack *bu, Tox_Group_Join_Fail *val)
|
||||
return false;
|
||||
}
|
||||
|
||||
*val = (Tox_Group_Join_Fail)u32;
|
||||
*val = tox_group_join_fail_from_int(u32);
|
||||
return true;
|
||||
}
|
||||
|
||||
static Tox_Group_Mod_Event tox_group_mod_event_from_int(uint32_t value)
|
||||
{
|
||||
switch (value) {
|
||||
case 0:
|
||||
return TOX_GROUP_MOD_EVENT_KICK;
|
||||
case 1:
|
||||
return TOX_GROUP_MOD_EVENT_OBSERVER;
|
||||
case 2:
|
||||
return TOX_GROUP_MOD_EVENT_USER;
|
||||
case 3:
|
||||
return TOX_GROUP_MOD_EVENT_MODERATOR;
|
||||
default:
|
||||
return TOX_GROUP_MOD_EVENT_MODERATOR;
|
||||
}
|
||||
}
|
||||
bool tox_unpack_group_mod_event(Bin_Unpack *bu, Tox_Group_Mod_Event *val)
|
||||
{
|
||||
uint32_t u32;
|
||||
@ -186,10 +248,29 @@ bool tox_unpack_group_mod_event(Bin_Unpack *bu, Tox_Group_Mod_Event *val)
|
||||
return false;
|
||||
}
|
||||
|
||||
*val = (Tox_Group_Mod_Event)u32;
|
||||
*val = tox_group_mod_event_from_int(u32);
|
||||
return true;
|
||||
}
|
||||
|
||||
static Tox_Group_Exit_Type tox_group_exit_type_from_int(uint32_t value)
|
||||
{
|
||||
switch (value) {
|
||||
case 0:
|
||||
return TOX_GROUP_EXIT_TYPE_QUIT;
|
||||
case 1:
|
||||
return TOX_GROUP_EXIT_TYPE_TIMEOUT;
|
||||
case 2:
|
||||
return TOX_GROUP_EXIT_TYPE_DISCONNECTED;
|
||||
case 3:
|
||||
return TOX_GROUP_EXIT_TYPE_SELF_DISCONNECTED;
|
||||
case 4:
|
||||
return TOX_GROUP_EXIT_TYPE_KICK;
|
||||
case 5:
|
||||
return TOX_GROUP_EXIT_TYPE_SYNC_ERROR;
|
||||
default:
|
||||
return TOX_GROUP_EXIT_TYPE_QUIT;
|
||||
}
|
||||
}
|
||||
bool tox_unpack_group_exit_type(Bin_Unpack *bu, Tox_Group_Exit_Type *val)
|
||||
{
|
||||
uint32_t u32;
|
||||
@ -198,6 +279,6 @@ bool tox_unpack_group_exit_type(Bin_Unpack *bu, Tox_Group_Exit_Type *val)
|
||||
return false;
|
||||
}
|
||||
|
||||
*val = (Tox_Group_Exit_Type)u32;
|
||||
*val = tox_group_exit_type_from_int(u32);
|
||||
return true;
|
||||
}
|
||||
|
4
external/toxcore/c-toxcore/toxcore/util.c
vendored
4
external/toxcore/c-toxcore/toxcore/util.c
vendored
@ -107,6 +107,10 @@ int64_t min_s64(int64_t a, int64_t b)
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
uint8_t max_u08(uint8_t a, uint8_t b)
|
||||
{
|
||||
return a > b ? a : b;
|
||||
}
|
||||
uint16_t max_u16(uint16_t a, uint16_t b)
|
||||
{
|
||||
return a > b ? a : b;
|
||||
|
1
external/toxcore/c-toxcore/toxcore/util.h
vendored
1
external/toxcore/c-toxcore/toxcore/util.h
vendored
@ -53,6 +53,7 @@ int16_t min_s16(int16_t a, int16_t b);
|
||||
int32_t min_s32(int32_t a, int32_t b);
|
||||
int64_t min_s64(int64_t a, int64_t b);
|
||||
|
||||
uint8_t max_u08(uint8_t a, uint8_t b);
|
||||
uint16_t max_u16(uint16_t a, uint16_t b);
|
||||
uint32_t max_u32(uint32_t a, uint32_t b);
|
||||
uint64_t max_u64(uint64_t a, uint64_t b);
|
||||
|
Loading…
Reference in New Issue
Block a user