Squashed 'external/toxcore/c-toxcore/' changes from e58eb27a8..1828c5356
1828c5356 fix(toxav): remove extra copy of video frame on encode b66b8ded6 refactor: improve group stability, moderation determinism, and DHT dual-stack handling 4fbd7c10a fix(toxav): fix heap buffer overflow in RTP video packet handling 809fe8c78 refactor(tox): make the `#define` consts int literals. 50d242a37 refactor(toxav): improve MSI safety and testability da1c13a2f fix(toxav): harden video processing and fix large frame handling 472825288 fix(toxav): fix multiple logic bugs in audio module dc963d9a9 fix(toxav): fix multiple bugs in bandwidth controller and add tests 3bf5778ef refactor(toxav): split out RTP module and add exhaustive unit tests b79b7d436 fix(autotools): add tox_log_level.h to public headers list ea2e34ff2 chore: Disable cirrus. We're out of quota again. b449ea2ed chore(ci): update azure runner image to windows-2022 windows-2019 is EOL e115b136d refactor: Make add_to_list non-recursive. REVERT: e58eb27a8 fix(toxav): remove extra copy of video frame on encode Tested and works, but there might be alignment issues and other stuff. git-subtree-dir: external/toxcore/c-toxcore git-subtree-split: 1828c5356b2daf1d5f680854e776d74b181d268c
This commit is contained in:
@@ -591,9 +591,18 @@ static bool client_or_ip_port_in_list(const Logger *_Nonnull log, const Mono_Tim
|
||||
|
||||
LOGGER_DEBUG(log, "coipil[%u]: switching public_key (ipv%d)", index, ip_version);
|
||||
|
||||
/* kill the other address, if it was set */
|
||||
const IPPTsPng empty_ipptspng = {{{{0}}}};
|
||||
*assoc = empty_ipptspng;
|
||||
/* kill the other address, if it was set.
|
||||
* We just updated `assoc` (which is either assoc4 or assoc6) with the new public_key.
|
||||
* If there was an association for the other IP version, it's now invalid for this new identity.
|
||||
*/
|
||||
if (ip_version == 4) {
|
||||
const IPPTsPng empty_ipptspng = {{{{0}}}};
|
||||
list[index].assoc6 = empty_ipptspng;
|
||||
} else {
|
||||
const IPPTsPng empty_ipptspng = {{{{0}}}};
|
||||
list[index].assoc4 = empty_ipptspng;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -601,27 +610,30 @@ bool add_to_list(
|
||||
Node_format *nodes_list, uint32_t length, const uint8_t pk[CRYPTO_PUBLIC_KEY_SIZE],
|
||||
const IP_Port *ip_port, const uint8_t cmp_pk[CRYPTO_PUBLIC_KEY_SIZE])
|
||||
{
|
||||
uint8_t pk_cur[CRYPTO_PUBLIC_KEY_SIZE];
|
||||
memcpy(pk_cur, pk, CRYPTO_PUBLIC_KEY_SIZE);
|
||||
IP_Port ip_port_cur = *ip_port;
|
||||
|
||||
bool inserted = false;
|
||||
|
||||
for (uint32_t i = 0; i < length; ++i) {
|
||||
Node_format *node = &nodes_list[i];
|
||||
|
||||
if (id_closest(cmp_pk, node->public_key, pk) == 2) {
|
||||
if (id_closest(cmp_pk, node->public_key, pk_cur) == 2) {
|
||||
uint8_t pk_bak[CRYPTO_PUBLIC_KEY_SIZE];
|
||||
memcpy(pk_bak, node->public_key, CRYPTO_PUBLIC_KEY_SIZE);
|
||||
|
||||
const IP_Port ip_port_bak = node->ip_port;
|
||||
memcpy(node->public_key, pk, CRYPTO_PUBLIC_KEY_SIZE);
|
||||
|
||||
node->ip_port = *ip_port;
|
||||
memcpy(node->public_key, pk_cur, CRYPTO_PUBLIC_KEY_SIZE);
|
||||
node->ip_port = ip_port_cur;
|
||||
|
||||
if (i != length - 1) {
|
||||
add_to_list(nodes_list, length, pk_bak, &ip_port_bak, cmp_pk);
|
||||
}
|
||||
|
||||
return true;
|
||||
memcpy(pk_cur, pk_bak, CRYPTO_PUBLIC_KEY_SIZE);
|
||||
ip_port_cur = ip_port_bak;
|
||||
inserted = true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return inserted;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -638,12 +650,6 @@ static void get_close_nodes_inner(uint64_t cur_time, const uint8_t *_Nonnull pub
|
||||
|
||||
for (uint32_t i = 0; i < client_list_length; ++i) {
|
||||
const Client_data *const client = &client_list[i];
|
||||
|
||||
/* node already in list? */
|
||||
if (index_of_node_pk(nodes_list, MAX_SENT_NODES, client->public_key) != UINT32_MAX) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const IPPTsPng *ipptp;
|
||||
|
||||
if (net_family_is_ipv4(sa_family)) {
|
||||
@@ -674,6 +680,11 @@ static void get_close_nodes_inner(uint64_t cur_time, const uint8_t *_Nonnull pub
|
||||
|
||||
#endif /* CHECK_ANNOUNCE_NODE */
|
||||
|
||||
/* node already in list? */
|
||||
if (index_of_node_pk(nodes_list, num_nodes, client->public_key) != UINT32_MAX) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (num_nodes < MAX_SENT_NODES) {
|
||||
memcpy(nodes_list[num_nodes].public_key, client->public_key, CRYPTO_PUBLIC_KEY_SIZE);
|
||||
nodes_list[num_nodes].ip_port = ipptp->ip_port;
|
||||
@@ -2009,7 +2020,7 @@ static uint32_t foreach_ip_port(const DHT *_Nonnull dht, const DHT_Friend *_Nonn
|
||||
static bool send_packet_to_friend(const DHT *_Nonnull dht, const IP_Port *_Nonnull ip_port, uint32_t *_Nonnull n, void *_Nonnull userdata)
|
||||
{
|
||||
const Packet *packet = (const Packet *)userdata;
|
||||
const int retval = send_packet(dht->net, ip_port, *packet);
|
||||
const int retval = net_send_packet(dht->net, ip_port, *packet);
|
||||
|
||||
if ((uint32_t)retval == packet->length) {
|
||||
++*n;
|
||||
@@ -2078,7 +2089,7 @@ static uint32_t routeone_to_friend(const DHT *_Nonnull dht, const uint8_t *_Nonn
|
||||
}
|
||||
|
||||
const uint32_t rand_idx = random_range_u32(dht->rng, n);
|
||||
const int retval = send_packet(dht->net, &ip_list[rand_idx], *packet);
|
||||
const int retval = net_send_packet(dht->net, &ip_list[rand_idx], *packet);
|
||||
|
||||
if ((unsigned int)retval == packet->length) {
|
||||
return 1;
|
||||
|
||||
@@ -2,6 +2,7 @@ lib_LTLIBRARIES += libtoxcore.la
|
||||
|
||||
libtoxcore_la_include_HEADERS = \
|
||||
../toxcore/tox.h \
|
||||
../toxcore/tox_log_level.h \
|
||||
../toxcore/tox_options.h
|
||||
|
||||
libtoxcore_la_includedir = $(includedir)/tox
|
||||
|
||||
@@ -142,12 +142,7 @@ bool crypto_memunlock(void *data, size_t length)
|
||||
|
||||
bool pk_equal(const uint8_t pk1[CRYPTO_PUBLIC_KEY_SIZE], const uint8_t pk2[CRYPTO_PUBLIC_KEY_SIZE])
|
||||
{
|
||||
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
||||
// Hope that this is better for the fuzzer
|
||||
return memcmp(pk1, pk2, CRYPTO_PUBLIC_KEY_SIZE) == 0;
|
||||
#else
|
||||
return crypto_verify_32(pk1, pk2) == 0;
|
||||
#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
|
||||
}
|
||||
|
||||
void pk_copy(uint8_t dest[CRYPTO_PUBLIC_KEY_SIZE], const uint8_t src[CRYPTO_PUBLIC_KEY_SIZE])
|
||||
@@ -167,12 +162,7 @@ bool crypto_sha512_eq(const uint8_t cksum1[CRYPTO_SHA512_SIZE], const uint8_t ck
|
||||
|
||||
bool crypto_sha256_eq(const uint8_t cksum1[CRYPTO_SHA256_SIZE], const uint8_t cksum2[CRYPTO_SHA256_SIZE])
|
||||
{
|
||||
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
||||
// Hope that this is better for the fuzzer
|
||||
return memcmp(cksum1, cksum2, CRYPTO_SHA256_SIZE) == 0;
|
||||
#else
|
||||
return crypto_verify_32(cksum1, cksum2) == 0;
|
||||
#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
|
||||
}
|
||||
|
||||
uint8_t random_u08(const Random *rng)
|
||||
|
||||
@@ -3717,6 +3717,10 @@ Group_Chats *new_groupchats(const Mono_Time *mono_time, const Memory *mem, Messe
|
||||
/** main groupchats loop. */
|
||||
void do_groupchats(Group_Chats *g_c, void *userdata)
|
||||
{
|
||||
if (g_c == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint16_t i = 0; i < g_c->num_chats; ++i) {
|
||||
Group_c *g = get_group_c(g_c, i);
|
||||
|
||||
|
||||
@@ -1759,11 +1759,6 @@ static bool unpack_gc_sync_announce(GC_Chat *_Nonnull chat, const uint8_t *_Nonn
|
||||
static int handle_gc_sync_response(const GC_Session *_Nonnull c, GC_Chat *_Nonnull chat, uint32_t peer_number, const uint8_t *_Nullable data,
|
||||
uint16_t length, void *_Nullable userdata)
|
||||
{
|
||||
if (chat->connection_state == CS_CONNECTED && get_gc_confirmed_numpeers(chat) >= chat->shared_state.maxpeers
|
||||
&& !peer_is_founder(chat, peer_number)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (length > 0) {
|
||||
if (!unpack_gc_sync_announce(chat, data, length)) {
|
||||
return -1;
|
||||
@@ -1778,6 +1773,14 @@ static int handle_gc_sync_response(const GC_Session *_Nonnull c, GC_Chat *_Nonnu
|
||||
return -2;
|
||||
}
|
||||
|
||||
/* If the group is full, we only allow already confirmed peers to sync.
|
||||
* This prevents disconnecting existing peers during re-syncing.
|
||||
*/
|
||||
if (!gconn->confirmed && get_gc_confirmed_numpeers(chat) >= chat->shared_state.maxpeers
|
||||
&& !peer_is_founder(chat, peer_number)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!send_gc_peer_exchange(chat, gconn)) {
|
||||
LOGGER_WARNING(chat->log, "Failed to send peer exchange on sync response");
|
||||
}
|
||||
@@ -2200,7 +2203,7 @@ static int handle_gc_invite_request(GC_Chat *_Nonnull chat, uint32_t peer_number
|
||||
|
||||
uint8_t invite_error;
|
||||
|
||||
if (get_gc_confirmed_numpeers(chat) >= chat->shared_state.maxpeers && !peer_is_founder(chat, peer_number)) {
|
||||
if (!gconn->confirmed && get_gc_confirmed_numpeers(chat) >= chat->shared_state.maxpeers && !peer_is_founder(chat, peer_number)) {
|
||||
invite_error = GJ_GROUP_FULL;
|
||||
goto FAILED_INVITE;
|
||||
}
|
||||
@@ -3828,12 +3831,6 @@ static bool handle_gc_topic_validate(const GC_Chat *_Nonnull chat, const GC_Peer
|
||||
return true;
|
||||
}
|
||||
|
||||
if (chat->topic_prev_checksum == topic_info->checksum &&
|
||||
!mono_time_is_timeout(chat->mono_time, chat->topic_time_set, GC_CONFIRMED_PEER_TIMEOUT)) {
|
||||
LOGGER_DEBUG(chat->log, "Topic reversion (probable sync error)");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -3893,11 +3890,17 @@ static int handle_gc_topic(const GC_Session *_Nonnull c, GC_Chat *_Nonnull chat,
|
||||
chat->topic_info = topic_info;
|
||||
memcpy(chat->topic_sig, signature, SIGNATURE_SIZE);
|
||||
|
||||
if (!skip_callback && chat->connection_state == CS_CONNECTED && c->topic_change != nullptr) {
|
||||
const int setter_peer_number = get_peer_number_of_sig_pk(chat, topic_info.public_sig_key);
|
||||
const GC_Peer_Id peer_id = setter_peer_number >= 0 ? chat->group[setter_peer_number].peer_id : gc_unknown_peer_id();
|
||||
if (!skip_callback && chat->connection_state == CS_CONNECTED) {
|
||||
if (gc_get_self_role(chat) == GR_FOUNDER) {
|
||||
broadcast_gc_topic(chat);
|
||||
}
|
||||
|
||||
c->topic_change(c->messenger, chat->group_number, peer_id, topic_info.topic, topic_info.length, userdata);
|
||||
if (c->topic_change != nullptr) {
|
||||
const int setter_peer_number = get_peer_number_of_sig_pk(chat, topic_info.public_sig_key);
|
||||
const GC_Peer_Id peer_id = setter_peer_number >= 0 ? chat->group[setter_peer_number].peer_id : gc_unknown_peer_id();
|
||||
|
||||
c->topic_change(c->messenger, chat->group_number, peer_id, topic_info.topic, topic_info.length, userdata);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -5530,7 +5533,9 @@ static bool send_gc_handshake_packet(const GC_Chat *_Nonnull chat, GC_Connection
|
||||
}
|
||||
|
||||
if (ret != length && gconn->tcp_relays_count == 0) {
|
||||
LOGGER_WARNING(chat->log, "UDP handshake failed and no TCP relays to fall back on");
|
||||
Ip_Ntoa ip_str;
|
||||
LOGGER_WARNING(chat->log, "UDP handshake failed and no TCP relays to fall back on. ret: %d, target: %s:%u",
|
||||
ret, net_ip_ntoa(&gconn->addr.ip_port.ip, &ip_str), net_ntohs(gconn->addr.ip_port.port));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -5588,7 +5593,8 @@ static bool send_gc_oob_handshake_request(const GC_Chat *chat, const GC_Connecti
|
||||
* Returns peer_number of new connected peer on success.
|
||||
* Returns -1 on failure.
|
||||
*/
|
||||
static int handle_gc_handshake_response(const GC_Chat *_Nonnull chat, const uint8_t *_Nonnull sender_pk, const uint8_t *_Nonnull data, uint16_t length)
|
||||
static int handle_gc_handshake_response(const GC_Chat *_Nonnull chat, const IP_Port *_Nullable ipp,
|
||||
const uint8_t *_Nonnull sender_pk, const uint8_t *_Nonnull data, uint16_t length)
|
||||
{
|
||||
// this should be checked at lower level; this is a redundant defense check. Ideally we should
|
||||
// guarantee that this can never happen in the future.
|
||||
@@ -5609,6 +5615,11 @@ static int handle_gc_handshake_response(const GC_Chat *_Nonnull chat, const uint
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ipp != nullptr) {
|
||||
gcc_set_ip_port(gconn, ipp);
|
||||
gconn->last_received_direct_time = mono_time_get(chat->mono_time);
|
||||
}
|
||||
|
||||
const uint8_t *sender_session_pk = data;
|
||||
|
||||
gcc_make_session_shared_key(gconn, sender_session_pk);
|
||||
@@ -5666,7 +5677,7 @@ static bool send_gc_handshake_response(const GC_Chat *_Nonnull chat, GC_Connecti
|
||||
* Return new peer's peer_number on success.
|
||||
* Return -1 on failure.
|
||||
*/
|
||||
#define GC_NEW_PEER_CONNECTION_LIMIT 10
|
||||
#define GC_NEW_PEER_CONNECTION_LIMIT 32
|
||||
static int handle_gc_handshake_request(GC_Chat *_Nonnull chat, const IP_Port *_Nullable ipp, const uint8_t *_Nonnull sender_pk,
|
||||
const uint8_t *_Nonnull data, uint16_t length)
|
||||
{
|
||||
@@ -5682,14 +5693,6 @@ static int handle_gc_handshake_request(GC_Chat *_Nonnull chat, const IP_Port *_N
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (chat->connection_o_metre >= GC_NEW_PEER_CONNECTION_LIMIT) {
|
||||
chat->block_handshakes = true;
|
||||
LOGGER_DEBUG(chat->log, "Handshake overflow. Blocking handshakes.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
++chat->connection_o_metre;
|
||||
|
||||
const uint8_t *public_sig_key = data + ENC_PUBLIC_KEY_SIZE;
|
||||
|
||||
const uint8_t request_type = data[ENC_PUBLIC_KEY_SIZE + SIG_PUBLIC_KEY_SIZE];
|
||||
@@ -5715,18 +5718,18 @@ static int handle_gc_handshake_request(GC_Chat *_Nonnull chat, const IP_Port *_N
|
||||
|
||||
if (gconn->handshaked) {
|
||||
gconn->handshaked = false;
|
||||
LOGGER_DEBUG(chat->log, "Handshaked peer sent a handshake request");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// peers sent handshake request at same time so the closer peer becomes the requestor
|
||||
// and ignores the request packet while further peer continues on with the response
|
||||
if (gconn->self_is_closer) {
|
||||
LOGGER_DEBUG(chat->log, "Simultaneous handshake requests; other peer is closer");
|
||||
return 0;
|
||||
LOGGER_DEBUG(chat->log, "Handshaked peer %d sent a handshake request; re-handshaking", peer_number);
|
||||
}
|
||||
}
|
||||
|
||||
if (chat->connection_o_metre >= GC_NEW_PEER_CONNECTION_LIMIT) {
|
||||
chat->block_handshakes = true;
|
||||
LOGGER_DEBUG(chat->log, "Handshake overflow. Blocking handshakes.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
++chat->connection_o_metre;
|
||||
|
||||
GC_Connection *gconn = get_gc_connection(chat, peer_number);
|
||||
|
||||
if (gconn == nullptr) {
|
||||
@@ -5734,7 +5737,10 @@ static int handle_gc_handshake_request(GC_Chat *_Nonnull chat, const IP_Port *_N
|
||||
return -1;
|
||||
}
|
||||
|
||||
gcc_set_ip_port(gconn, ipp);
|
||||
if (ipp != nullptr) {
|
||||
gcc_set_ip_port(gconn, ipp);
|
||||
gconn->last_received_direct_time = mono_time_get(chat->mono_time);
|
||||
}
|
||||
|
||||
Node_format node[GCA_MAX_ANNOUNCED_TCP_RELAYS];
|
||||
const int processed = ENC_PUBLIC_KEY_SIZE + SIG_PUBLIC_KEY_SIZE + 1 + 1;
|
||||
@@ -5824,7 +5830,7 @@ static int handle_gc_handshake_packet(GC_Chat *_Nonnull chat, const uint8_t *_No
|
||||
if (handshake_type == GH_REQUEST) {
|
||||
peer_number = handle_gc_handshake_request(chat, ipp, sender_pk, real_data, real_len);
|
||||
} else if (handshake_type == GH_RESPONSE) {
|
||||
peer_number = handle_gc_handshake_response(chat, sender_pk, real_data, real_len);
|
||||
peer_number = handle_gc_handshake_response(chat, ipp, sender_pk, real_data, real_len);
|
||||
} else {
|
||||
mem_delete(chat->mem, data);
|
||||
return -1;
|
||||
@@ -5832,16 +5838,6 @@ static int handle_gc_handshake_packet(GC_Chat *_Nonnull chat, const uint8_t *_No
|
||||
|
||||
mem_delete(chat->mem, data);
|
||||
|
||||
GC_Connection *gconn = get_gc_connection(chat, peer_number);
|
||||
|
||||
if (gconn == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (direct_conn) {
|
||||
gconn->last_received_direct_time = mono_time_get(chat->mono_time);
|
||||
}
|
||||
|
||||
return peer_number;
|
||||
}
|
||||
|
||||
@@ -6718,6 +6714,7 @@ int peer_add(GC_Chat *chat, const IP_Port *ipp, const uint8_t *public_key)
|
||||
gconn->last_received_packet_time = tm;
|
||||
gconn->last_key_rotation = tm;
|
||||
gconn->tcp_connection_num = tcp_connection_num;
|
||||
gconn->friend_number = -1;
|
||||
gconn->last_sent_ip_time = tm;
|
||||
gconn->last_sent_ping_time = tm - (GC_PING_TIMEOUT / 2) + (peer_number % (GC_PING_TIMEOUT / 2));
|
||||
gconn->self_is_closer = id_closest(get_chat_id(&chat->chat_public_key),
|
||||
@@ -6820,13 +6817,26 @@ static void do_peer_connections(const GC_Session *_Nonnull c, GC_Chat *_Nonnull
|
||||
* load peers from our saved peers list and initiate handshake requests with them.
|
||||
*/
|
||||
#define LOAD_PEERS_TIMEOUT (GC_UNCONFIRMED_PEER_TIMEOUT + 10)
|
||||
static void do_handshakes(GC_Chat *_Nonnull chat)
|
||||
static bool copy_friend_ip_port_to_gconn(const Messenger *_Nonnull m, int friend_number, GC_Connection *_Nonnull gconn);
|
||||
|
||||
static void do_handshakes(const GC_Session *_Nonnull c, GC_Chat *_Nonnull chat)
|
||||
{
|
||||
for (uint32_t i = 1; i < chat->numpeers; ++i) {
|
||||
GC_Connection *gconn = get_gc_connection(chat, i);
|
||||
assert(gconn != nullptr);
|
||||
|
||||
if (gconn->handshaked || gconn->pending_delete) {
|
||||
if (gconn->pending_delete) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If we don't have an IP/port for this peer yet, try to get it from the messenger friend connection.
|
||||
* This might happen if the friend's DHT IP/port was not yet known when we handled the invite.
|
||||
*/
|
||||
if (!gconn->handshaked && !gcc_ip_port_is_set(gconn) && gconn->friend_number != -1) {
|
||||
copy_friend_ip_port_to_gconn(c->messenger, gconn->friend_number, gconn);
|
||||
}
|
||||
|
||||
if (gconn->handshaked) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -7028,10 +7038,12 @@ static void do_gc_tcp(const GC_Session *_Nonnull c, GC_Chat *_Nonnull chat, void
|
||||
set_tcp_connection_to_status(chat->tcp_conn, gconn->tcp_connection_num, tcp_set);
|
||||
}
|
||||
|
||||
const uint32_t main_tcp_connected_count = tcp_connected_relays_count(nc_get_tcp_c(c->messenger->net_crypto));
|
||||
|
||||
if (mono_time_is_timeout(chat->mono_time, chat->last_checked_tcp_relays, TCP_RELAYS_CHECK_INTERVAL)
|
||||
&& tcp_connected_relays_count(chat->tcp_conn) != chat->connected_tcp_relays) {
|
||||
&& main_tcp_connected_count != chat->connected_tcp_relays) {
|
||||
add_tcp_relays_to_chat(c, chat);
|
||||
chat->connected_tcp_relays = tcp_connected_relays_count(chat->tcp_conn);
|
||||
chat->connected_tcp_relays = main_tcp_connected_count;
|
||||
chat->last_checked_tcp_relays = mono_time_get(chat->mono_time);
|
||||
}
|
||||
}
|
||||
@@ -7130,7 +7142,7 @@ void do_gc(GC_Session *c, void *userdata)
|
||||
if (state != CS_DISCONNECTED) {
|
||||
do_peer_connections(c, chat, userdata);
|
||||
do_gc_tcp(c, chat, userdata);
|
||||
do_handshakes(chat);
|
||||
do_handshakes(c, chat);
|
||||
do_self_connection(c, chat);
|
||||
}
|
||||
|
||||
@@ -7298,6 +7310,7 @@ static int create_new_group(const Memory *_Nonnull mem, GC_Session *_Nonnull c,
|
||||
const int group_number = get_new_group_index(mem, c);
|
||||
|
||||
if (group_number == -1) {
|
||||
LOGGER_DEBUG(c->messenger->log, "get_new_group_index failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -7328,16 +7341,19 @@ static int create_new_group(const Memory *_Nonnull mem, GC_Session *_Nonnull c,
|
||||
init_gc_moderation(chat);
|
||||
|
||||
if (!init_gc_tcp_connection(c, chat)) {
|
||||
LOGGER_DEBUG(chat->log, "init_gc_tcp_connection failed");
|
||||
group_delete(c, chat);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (peer_add(chat, nullptr, chat->self_public_key.enc) != 0) { /* you are always peer_number/index 0 */
|
||||
LOGGER_DEBUG(chat->log, "peer_add failed");
|
||||
group_delete(c, chat);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!self_gc_set_nick(chat, nick, (uint16_t)nick_length)) {
|
||||
LOGGER_DEBUG(chat->log, "self_gc_set_nick failed");
|
||||
group_delete(c, chat);
|
||||
return -1;
|
||||
}
|
||||
@@ -7517,7 +7533,12 @@ int gc_group_add(GC_Session *c, Group_Privacy_State privacy_state,
|
||||
|
||||
crypto_memlock(&chat->chat_secret_key, sizeof(chat->chat_secret_key));
|
||||
|
||||
create_extended_keypair(&chat->chat_public_key, &chat->chat_secret_key, chat->rng);
|
||||
/* Ensure we have a valid keypair for the group. */
|
||||
if (!create_extended_keypair(&chat->chat_public_key, &chat->chat_secret_key, chat->rng)) {
|
||||
crypto_memunlock(&chat->chat_secret_key, sizeof(chat->chat_secret_key));
|
||||
group_delete(c, chat);
|
||||
return -3;
|
||||
}
|
||||
|
||||
if (!init_gc_shared_state_founder(chat, privacy_state, group_name, group_name_length)) {
|
||||
group_delete(c, chat);
|
||||
@@ -7893,7 +7914,11 @@ int handle_gc_invite_confirmed_packet(const GC_Session *c, int friend_number, co
|
||||
nullptr, data + ENC_PUBLIC_KEY_SIZE + CHAT_ID_SIZE,
|
||||
length - GC_JOIN_DATA_LENGTH, true);
|
||||
|
||||
const bool copy_ip_port_result = copy_friend_ip_port_to_gconn(c->messenger, friend_number, gconn);
|
||||
bool has_ip_port = gcc_ip_port_is_set(gconn);
|
||||
if (!has_ip_port) {
|
||||
has_ip_port = copy_friend_ip_port_to_gconn(c->messenger, friend_number, gconn);
|
||||
}
|
||||
gconn->friend_number = friend_number;
|
||||
|
||||
uint32_t tcp_relays_added = 0;
|
||||
|
||||
@@ -7903,7 +7928,7 @@ int handle_gc_invite_confirmed_packet(const GC_Session *c, int friend_number, co
|
||||
LOGGER_WARNING(chat->log, "Invite confirm packet did not contain any TCP relays");
|
||||
}
|
||||
|
||||
if (tcp_relays_added == 0 && !copy_ip_port_result) {
|
||||
if (tcp_relays_added == 0 && !has_ip_port) {
|
||||
LOGGER_ERROR(chat->log, "Got invalid connection info from peer");
|
||||
return -5;
|
||||
}
|
||||
@@ -7957,11 +7982,15 @@ bool handle_gc_invite_accepted_packet(const GC_Session *c, int friend_number, co
|
||||
}
|
||||
|
||||
Node_format tcp_relays[GCC_MAX_TCP_SHARED_RELAYS];
|
||||
const uint32_t num_tcp_relays = tcp_copy_connected_relays(chat->tcp_conn, tcp_relays, GCC_MAX_TCP_SHARED_RELAYS);
|
||||
const uint32_t num_tcp_relays = tcp_copy_connected_relays(nc_get_tcp_c(m->net_crypto), tcp_relays, GCC_MAX_TCP_SHARED_RELAYS);
|
||||
|
||||
const bool copy_ip_port_result = copy_friend_ip_port_to_gconn(m, friend_number, gconn);
|
||||
bool has_ip_port = gcc_ip_port_is_set(gconn);
|
||||
if (!has_ip_port) {
|
||||
has_ip_port = copy_friend_ip_port_to_gconn(m, friend_number, gconn);
|
||||
}
|
||||
gconn->friend_number = friend_number;
|
||||
|
||||
if (num_tcp_relays == 0 && !copy_ip_port_result) {
|
||||
if (num_tcp_relays == 0 && !has_ip_port) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -7974,7 +8003,7 @@ bool handle_gc_invite_accepted_packet(const GC_Session *c, int friend_number, co
|
||||
if (num_tcp_relays > 0) {
|
||||
const uint32_t tcp_relays_added = add_gc_tcp_relays(chat, gconn, tcp_relays, num_tcp_relays);
|
||||
|
||||
if (tcp_relays_added == 0 && !copy_ip_port_result) {
|
||||
if (tcp_relays_added == 0 && !has_ip_port) {
|
||||
LOGGER_ERROR(chat->log, "Got invalid connection info from peer");
|
||||
return false;
|
||||
}
|
||||
@@ -7982,7 +8011,7 @@ bool handle_gc_invite_accepted_packet(const GC_Session *c, int friend_number, co
|
||||
const int nodes_len = pack_nodes(chat->log, out_data + len, sizeof(out_data) - len, tcp_relays,
|
||||
(uint16_t)num_tcp_relays);
|
||||
|
||||
if (nodes_len <= 0 && !copy_ip_port_result) {
|
||||
if (nodes_len <= 0 && !has_ip_port) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -112,6 +112,7 @@ typedef struct GC_Connection {
|
||||
uint8_t session_shared_key[CRYPTO_SHARED_KEY_SIZE]; /* made with our session sk and peer's session pk */
|
||||
|
||||
int tcp_connection_num;
|
||||
int32_t friend_number; /* The messenger friend number associated with this group connection. Used to discover the peer's IP/port if it wasn't available during the initial invite. */
|
||||
uint64_t last_sent_tcp_relays_time; /* the last time we attempted to send this peer our tcp relays */
|
||||
uint16_t tcp_relay_share_index;
|
||||
uint64_t last_received_direct_time; /* the last time we received a direct UDP packet from this connection */
|
||||
|
||||
@@ -556,7 +556,7 @@ void gcc_resend_packets(const GC_Chat *chat, GC_Connection *gconn)
|
||||
const uint16_t start = gconn->send_array_start;
|
||||
const uint16_t end = gconn->send_message_id % GCC_BUFFER_SIZE;
|
||||
|
||||
GC_Message_Array_Entry *array_entry = &gconn->send_array[start];
|
||||
const GC_Message_Array_Entry *array_entry = &gconn->send_array[start];
|
||||
|
||||
if (array_entry_is_empty(array_entry)) {
|
||||
return;
|
||||
@@ -569,23 +569,23 @@ void gcc_resend_packets(const GC_Chat *chat, GC_Connection *gconn)
|
||||
}
|
||||
|
||||
for (uint16_t i = start; i != end; i = (i + 1) % GCC_BUFFER_SIZE) {
|
||||
array_entry = &gconn->send_array[i];
|
||||
GC_Message_Array_Entry *const array_entry_loop = &gconn->send_array[i];
|
||||
|
||||
if (array_entry_is_empty(array_entry)) {
|
||||
if (array_entry_is_empty(array_entry_loop)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tm == array_entry->last_send_try) {
|
||||
if (tm == array_entry_loop->last_send_try) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const uint64_t delta = array_entry->last_send_try - array_entry->time_added;
|
||||
array_entry->last_send_try = tm;
|
||||
const uint64_t delta = array_entry_loop->last_send_try - array_entry_loop->time_added;
|
||||
array_entry_loop->last_send_try = tm;
|
||||
|
||||
/* if this occurrs less than once per second this won't be reliable */
|
||||
if (delta > 1 && is_power_of_2(delta)) {
|
||||
gcc_encrypt_and_send_lossless_packet(chat, gconn, array_entry->data, array_entry->data_length,
|
||||
array_entry->message_id, array_entry->packet_type);
|
||||
gcc_encrypt_and_send_lossless_packet(chat, gconn, array_entry_loop->data, array_entry_loop->data_length,
|
||||
array_entry_loop->message_id, array_entry_loop->packet_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "group_moderation.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
@@ -23,6 +24,30 @@
|
||||
#include "network.h"
|
||||
#include "util.h"
|
||||
|
||||
static int compare_signatures(const void *a, const void *b)
|
||||
{
|
||||
return memcmp(a, b, SIGNATURE_SIZE);
|
||||
}
|
||||
|
||||
static int compare_sig_pks(const void *a, const void *b)
|
||||
{
|
||||
return memcmp(a, b, SIG_PUBLIC_KEY_SIZE);
|
||||
}
|
||||
|
||||
static int compare_sanctions(const void *a, const void *b)
|
||||
{
|
||||
const Mod_Sanction *sa = (const Mod_Sanction *)a;
|
||||
const Mod_Sanction *sb = (const Mod_Sanction *)b;
|
||||
return memcmp(sa->signature, sb->signature, SIGNATURE_SIZE);
|
||||
}
|
||||
|
||||
static int compare_mod_pointers(const void *a, const void *b)
|
||||
{
|
||||
const uint8_t *const *mod_a = (const uint8_t *const *)a;
|
||||
const uint8_t *const *mod_b = (const uint8_t *const *)b;
|
||||
return memcmp(*mod_a, *mod_b, SIG_PUBLIC_KEY_SIZE);
|
||||
}
|
||||
|
||||
static_assert(MOD_SANCTIONS_CREDS_SIZE <= MAX_PACKET_SIZE_NO_HEADERS,
|
||||
"MOD_SANCTIONS_CREDS_SIZE must be <= the maximum allowed payload size");
|
||||
static_assert(MOD_MAX_NUM_SANCTIONS * MOD_SANCTION_PACKED_SIZE + MOD_SANCTIONS_CREDS_SIZE <= MAX_PACKET_SIZE_NO_HEADERS,
|
||||
@@ -34,6 +59,7 @@ static_assert(MOD_MAX_NUM_MODERATORS <= MOD_MAX_NUM_MODERATORS_LIMIT,
|
||||
static_assert(MOD_MAX_NUM_SANCTIONS <= MOD_MAX_NUM_SANCTIONS_LIMIT,
|
||||
"MOD_MAX_NUM_SANCTIONS must be <= MOD_MAX_NUM_SANCTIONS_LIMIT");
|
||||
|
||||
/** @brief Returns the size in bytes of the packed moderation list. */
|
||||
uint16_t mod_list_packed_size(const Moderation *_Nonnull moderation)
|
||||
{
|
||||
return moderation->num_mods * MOD_LIST_ENTRY_SIZE;
|
||||
@@ -76,6 +102,8 @@ int mod_list_unpack(Moderation *_Nonnull moderation, const uint8_t *_Nonnull dat
|
||||
moderation->mod_list = tmp_list;
|
||||
moderation->num_mods = num_mods;
|
||||
|
||||
qsort(moderation->mod_list, moderation->num_mods, sizeof(uint8_t *), compare_mod_pointers);
|
||||
|
||||
return unpacked_len;
|
||||
}
|
||||
|
||||
@@ -110,6 +138,8 @@ bool mod_list_make_hash(const Moderation *_Nonnull moderation, uint8_t *_Nonnull
|
||||
|
||||
mod_list_pack(moderation, data);
|
||||
|
||||
qsort(data, moderation->num_mods, SIG_PUBLIC_KEY_SIZE, compare_sig_pks);
|
||||
|
||||
mod_list_get_data_hash(hash, data, data_buf_size);
|
||||
|
||||
mem_delete(moderation->mem, data);
|
||||
@@ -176,6 +206,8 @@ bool mod_list_remove_index(Moderation *_Nonnull moderation, uint16_t index)
|
||||
|
||||
moderation->mod_list = tmp_list;
|
||||
|
||||
qsort(moderation->mod_list, moderation->num_mods, sizeof(uint8_t *), compare_mod_pointers);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -221,6 +253,8 @@ bool mod_list_add_entry(Moderation *_Nonnull moderation, const uint8_t *_Nonnull
|
||||
tmp_list[moderation->num_mods] = entry;
|
||||
++moderation->num_mods;
|
||||
|
||||
qsort(moderation->mod_list, moderation->num_mods, sizeof(uint8_t *), compare_mod_pointers);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -430,6 +464,8 @@ static bool sanctions_list_make_hash(const Memory *_Nonnull mem, const Mod_Sanct
|
||||
memcpy(&data[i * SIGNATURE_SIZE], sanctions[i].signature, SIGNATURE_SIZE);
|
||||
}
|
||||
|
||||
qsort(data, num_sanctions, SIGNATURE_SIZE, compare_signatures);
|
||||
|
||||
memcpy(&data[sig_data_size], &new_version, sizeof(uint32_t));
|
||||
crypto_sha256(hash, data, data_buf_size);
|
||||
|
||||
@@ -594,6 +630,8 @@ static bool sanctions_apply_new(Moderation *_Nonnull moderation, Mod_Sanction *_
|
||||
moderation->sanctions_creds = *new_creds;
|
||||
}
|
||||
|
||||
qsort(new_sanctions, num_sanctions, sizeof(Mod_Sanction), compare_sanctions);
|
||||
|
||||
sanctions_list_cleanup(moderation);
|
||||
moderation->sanctions = new_sanctions;
|
||||
moderation->num_sanctions = num_sanctions;
|
||||
@@ -805,7 +843,8 @@ bool sanctions_list_make_entry(Moderation *_Nonnull moderation, const uint8_t *_
|
||||
|
||||
memcpy(sanction->setter_public_sig_key, moderation->self_public_sig_key, SIG_PUBLIC_KEY_SIZE);
|
||||
|
||||
sanction->time_set = (uint64_t)time(nullptr);
|
||||
/* Use a stable non-zero value to ensure deterministic signatures and hashes. */
|
||||
sanction->time_set = 1;
|
||||
sanction->type = type;
|
||||
|
||||
if (!sanctions_list_sign_entry(moderation, sanction)) {
|
||||
|
||||
@@ -85,12 +85,12 @@ typedef enum Packet_Id {
|
||||
#define CRYPTO_MIN_QUEUE_LENGTH 64
|
||||
|
||||
/** Maximum total size of packets that net_crypto sends. */
|
||||
#define MAX_CRYPTO_PACKET_SIZE (uint16_t)1400
|
||||
#define MAX_CRYPTO_PACKET_SIZE 1400
|
||||
|
||||
#define CRYPTO_DATA_PACKET_MIN_SIZE (uint16_t)(1 + sizeof(uint16_t) + (sizeof(uint32_t) + sizeof(uint32_t)) + CRYPTO_MAC_SIZE)
|
||||
#define CRYPTO_DATA_PACKET_MIN_SIZE (1 + sizeof(uint16_t) + (sizeof(uint32_t) + sizeof(uint32_t)) + CRYPTO_MAC_SIZE)
|
||||
|
||||
/** Max size of data in packets */
|
||||
#define MAX_CRYPTO_DATA_SIZE (uint16_t)(MAX_CRYPTO_PACKET_SIZE - CRYPTO_DATA_PACKET_MIN_SIZE)
|
||||
#define MAX_CRYPTO_DATA_SIZE (MAX_CRYPTO_PACKET_SIZE - CRYPTO_DATA_PACKET_MIN_SIZE)
|
||||
|
||||
/** Interval in ms between sending cookie request/handshake packets. */
|
||||
#define CRYPTO_SEND_PACKET_INTERVAL 1000
|
||||
|
||||
@@ -838,7 +838,7 @@ uint16_t net_port(const Networking_Core *net)
|
||||
/* Basic network functions:
|
||||
*/
|
||||
|
||||
int send_packet(const Networking_Core *net, const IP_Port *ip_port, Packet packet)
|
||||
int net_send_packet(const Networking_Core *net, const IP_Port *ip_port, Packet packet)
|
||||
{
|
||||
IP_Port ipp_copy = *ip_port;
|
||||
|
||||
@@ -919,12 +919,12 @@ int send_packet(const Networking_Core *net, const IP_Port *ip_port, Packet packe
|
||||
/**
|
||||
* Function to send packet(data) of length length to ip_port.
|
||||
*
|
||||
* @deprecated Use send_packet instead.
|
||||
* @deprecated Use net_send_packet instead.
|
||||
*/
|
||||
int sendpacket(const Networking_Core *net, const IP_Port *ip_port, const uint8_t *data, uint16_t length)
|
||||
{
|
||||
const Packet packet = {data, length};
|
||||
return send_packet(net, ip_port, packet);
|
||||
return net_send_packet(net, ip_port, packet);
|
||||
}
|
||||
|
||||
/** @brief Function to receive data
|
||||
|
||||
@@ -448,7 +448,7 @@ bool set_socket_dualstack(const Network *_Nonnull ns, Socket sock);
|
||||
/**
|
||||
* An outgoing network packet.
|
||||
*
|
||||
* Use `send_packet` to send it to an IP/port endpoint.
|
||||
* Use `net_send_packet` to send it to an IP/port endpoint.
|
||||
*/
|
||||
typedef struct Packet {
|
||||
const uint8_t *_Nonnull data;
|
||||
@@ -458,12 +458,12 @@ typedef struct Packet {
|
||||
/**
|
||||
* Function to send a network packet to a given IP/port.
|
||||
*/
|
||||
int send_packet(const Networking_Core *_Nonnull net, const IP_Port *_Nonnull ip_port, Packet packet);
|
||||
int net_send_packet(const Networking_Core *_Nonnull net, const IP_Port *_Nonnull ip_port, Packet packet);
|
||||
|
||||
/**
|
||||
* Function to send packet(data) of length length to ip_port.
|
||||
*
|
||||
* @deprecated Use send_packet instead.
|
||||
* @deprecated Use net_send_packet instead.
|
||||
*/
|
||||
int sendpacket(const Networking_Core *_Nonnull net, const IP_Port *_Nonnull ip_port, const uint8_t *_Nonnull data, uint16_t length);
|
||||
|
||||
|
||||
@@ -239,7 +239,7 @@ uint32_t tox_conference_id_size(void);
|
||||
/**
|
||||
* @brief The size of the nospam in bytes when written in a Tox address.
|
||||
*/
|
||||
#define TOX_NOSPAM_SIZE (sizeof(uint32_t))
|
||||
#define TOX_NOSPAM_SIZE 4
|
||||
|
||||
uint32_t tox_nospam_size(void);
|
||||
|
||||
@@ -253,7 +253,7 @@ uint32_t tox_nospam_size(void);
|
||||
* byte is an XOR of all the even bytes (0, 2, 4, ...), the second byte is an
|
||||
* XOR of all the odd bytes (1, 3, 5, ...) of the Public Key and nospam.
|
||||
*/
|
||||
#define TOX_ADDRESS_SIZE (TOX_PUBLIC_KEY_SIZE + TOX_NOSPAM_SIZE + sizeof(uint16_t))
|
||||
#define TOX_ADDRESS_SIZE 38
|
||||
|
||||
uint32_t tox_address_size(void);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user