summaryrefslogtreecommitdiff
path: root/protocols
diff options
context:
space:
mode:
Diffstat (limited to 'protocols')
-rw-r--r--protocols/Tox/libtox/libtox.vcxproj8
-rw-r--r--protocols/Tox/libtox/libtox.vcxproj.filters12
-rw-r--r--protocols/Tox/libtox/src/third_party/cmp/cmp.c1436
-rw-r--r--protocols/Tox/libtox/src/third_party/cmp/cmp.h108
-rw-r--r--protocols/Tox/libtox/src/toxcore/DHT.c482
-rw-r--r--protocols/Tox/libtox/src/toxcore/DHT.h99
-rw-r--r--protocols/Tox/libtox/src/toxcore/LAN_discovery.c67
-rw-r--r--protocols/Tox/libtox/src/toxcore/LAN_discovery.h3
-rw-r--r--protocols/Tox/libtox/src/toxcore/Messenger.c463
-rw-r--r--protocols/Tox/libtox/src/toxcore/Messenger.h45
-rw-r--r--protocols/Tox/libtox/src/toxcore/TCP_client.c164
-rw-r--r--protocols/Tox/libtox/src/toxcore/TCP_client.h20
-rw-r--r--protocols/Tox/libtox/src/toxcore/TCP_common.c81
-rw-r--r--protocols/Tox/libtox/src/toxcore/TCP_common.h70
-rw-r--r--protocols/Tox/libtox/src/toxcore/TCP_connection.c128
-rw-r--r--protocols/Tox/libtox/src/toxcore/TCP_connection.h22
-rw-r--r--protocols/Tox/libtox/src/toxcore/TCP_server.c234
-rw-r--r--protocols/Tox/libtox/src/toxcore/TCP_server.h16
-rw-r--r--protocols/Tox/libtox/src/toxcore/announce.c67
-rw-r--r--protocols/Tox/libtox/src/toxcore/announce.h13
-rw-r--r--protocols/Tox/libtox/src/toxcore/attributes.h12
-rw-r--r--protocols/Tox/libtox/src/toxcore/bin_pack.c72
-rw-r--r--protocols/Tox/libtox/src/toxcore/bin_pack.h120
-rw-r--r--protocols/Tox/libtox/src/toxcore/bin_unpack.c54
-rw-r--r--protocols/Tox/libtox/src/toxcore/bin_unpack.h54
-rw-r--r--protocols/Tox/libtox/src/toxcore/ccompat.c2
-rw-r--r--protocols/Tox/libtox/src/toxcore/ccompat.h19
-rw-r--r--protocols/Tox/libtox/src/toxcore/crypto_core.c228
-rw-r--r--protocols/Tox/libtox/src/toxcore/crypto_core.h162
-rw-r--r--protocols/Tox/libtox/src/toxcore/crypto_core_pack.c66
-rw-r--r--protocols/Tox/libtox/src/toxcore/crypto_core_pack.h31
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/conference_connected.c165
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/conference_invite.c180
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/conference_message.c180
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/conference_peer_list_changed.c172
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/conference_peer_name.c179
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/conference_title.c179
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/dht_get_nodes_response.c223
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/events_alloc.c74
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/events_alloc.h200
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/file_chunk_request.c166
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/file_recv.c179
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/file_recv_chunk.c181
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/file_recv_control.c168
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/friend_connection_status.c182
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/friend_lossless_packet.c177
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/friend_lossy_packet.c174
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/friend_message.c187
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/friend_name.c177
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/friend_read_receipt.c161
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/friend_request.c178
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/friend_status.c168
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/friend_status_message.c180
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/friend_typing.c163
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_custom_packet.c235
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_custom_private_packet.c235
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_invite.c263
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_join_fail.c191
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_message.c271
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_moderation.c225
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_password.c218
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_peer_exit.c299
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_peer_join.c189
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_peer_limit.c189
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_peer_name.c235
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_peer_status.c208
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_privacy_state.c191
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_private_message.c254
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_self_join.c167
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_topic.c235
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_topic_lock.c191
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_voice_state.c191
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/self_connection_status.c169
-rw-r--r--protocols/Tox/libtox/src/toxcore/forwarding.c11
-rw-r--r--protocols/Tox/libtox/src/toxcore/forwarding.h15
-rw-r--r--protocols/Tox/libtox/src/toxcore/friend_connection.c82
-rw-r--r--protocols/Tox/libtox/src/toxcore/friend_connection.h23
-rw-r--r--protocols/Tox/libtox/src/toxcore/friend_requests.c24
-rw-r--r--protocols/Tox/libtox/src/toxcore/friend_requests.h7
-rw-r--r--protocols/Tox/libtox/src/toxcore/group.c113
-rw-r--r--protocols/Tox/libtox/src/toxcore/group.h11
-rw-r--r--protocols/Tox/libtox/src/toxcore/group_announce.c52
-rw-r--r--protocols/Tox/libtox/src/toxcore/group_announce.h15
-rw-r--r--protocols/Tox/libtox/src/toxcore/group_chats.c772
-rw-r--r--protocols/Tox/libtox/src/toxcore/group_chats.h67
-rw-r--r--protocols/Tox/libtox/src/toxcore/group_common.h88
-rw-r--r--protocols/Tox/libtox/src/toxcore/group_connection.c109
-rw-r--r--protocols/Tox/libtox/src/toxcore/group_connection.h26
-rw-r--r--protocols/Tox/libtox/src/toxcore/group_moderation.c83
-rw-r--r--protocols/Tox/libtox/src/toxcore/group_moderation.h8
-rw-r--r--protocols/Tox/libtox/src/toxcore/group_onion_announce.c12
-rw-r--r--protocols/Tox/libtox/src/toxcore/group_onion_announce.h4
-rw-r--r--protocols/Tox/libtox/src/toxcore/group_pack.c141
-rw-r--r--protocols/Tox/libtox/src/toxcore/group_pack.h12
-rw-r--r--protocols/Tox/libtox/src/toxcore/list.c14
-rw-r--r--protocols/Tox/libtox/src/toxcore/list.h10
-rw-r--r--protocols/Tox/libtox/src/toxcore/logger.c13
-rw-r--r--protocols/Tox/libtox/src/toxcore/logger.h10
-rw-r--r--protocols/Tox/libtox/src/toxcore/mem.c89
-rw-r--r--protocols/Tox/libtox/src/toxcore/mem.h86
-rw-r--r--protocols/Tox/libtox/src/toxcore/mono_time.c189
-rw-r--r--protocols/Tox/libtox/src/toxcore/mono_time.h32
-rw-r--r--protocols/Tox/libtox/src/toxcore/net_crypto.c191
-rw-r--r--protocols/Tox/libtox/src/toxcore/net_crypto.h61
-rw-r--r--protocols/Tox/libtox/src/toxcore/network.c593
-rw-r--r--protocols/Tox/libtox/src/toxcore/network.h173
-rw-r--r--protocols/Tox/libtox/src/toxcore/onion.c129
-rw-r--r--protocols/Tox/libtox/src/toxcore/onion.h14
-rw-r--r--protocols/Tox/libtox/src/toxcore/onion_announce.c82
-rw-r--r--protocols/Tox/libtox/src/toxcore/onion_announce.h29
-rw-r--r--protocols/Tox/libtox/src/toxcore/onion_client.c255
-rw-r--r--protocols/Tox/libtox/src/toxcore/onion_client.h34
-rw-r--r--protocols/Tox/libtox/src/toxcore/ping.c23
-rw-r--r--protocols/Tox/libtox/src/toxcore/ping.h12
-rw-r--r--protocols/Tox/libtox/src/toxcore/ping_array.c32
-rw-r--r--protocols/Tox/libtox/src/toxcore/ping_array.h9
-rw-r--r--protocols/Tox/libtox/src/toxcore/shared_key_cache.c70
-rw-r--r--protocols/Tox/libtox/src/toxcore/shared_key_cache.h16
-rw-r--r--protocols/Tox/libtox/src/toxcore/state.c18
-rw-r--r--protocols/Tox/libtox/src/toxcore/state.h7
-rw-r--r--protocols/Tox/libtox/src/toxcore/timed_auth.c15
-rw-r--r--protocols/Tox/libtox/src/toxcore/timed_auth.h3
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox.c496
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox.h887
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox_api.c1594
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox_dispatch.c641
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox_dispatch.h126
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox_event.c1087
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox_event.h260
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox_events.c266
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox_events.h373
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox_pack.c55
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox_pack.h24
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox_private.c89
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox_private.h70
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox_struct.h11
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox_unpack.c332
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox_unpack.h18
-rw-r--r--protocols/Tox/libtox/src/toxcore/util.c43
-rw-r--r--protocols/Tox/libtox/src/toxcore/util.h30
-rw-r--r--protocols/Tox/libtox/src/toxencryptsave/defines.h2
-rw-r--r--protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.c36
-rw-r--r--protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.h50
143 files changed, 15959 insertions, 6922 deletions
diff --git a/protocols/Tox/libtox/libtox.vcxproj b/protocols/Tox/libtox/libtox.vcxproj
index 497525dfe8..4c86a4fef8 100644
--- a/protocols/Tox/libtox/libtox.vcxproj
+++ b/protocols/Tox/libtox/libtox.vcxproj
@@ -55,6 +55,9 @@
<ClCompile Include="src\toxcore\crypto_core.c">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
+ <ClCompile Include="src\toxcore\crypto_core_pack.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
<ClCompile Include="src\toxcore\DHT.c">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
@@ -163,6 +166,9 @@
<ClCompile Include="src\toxcore\logger.c">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
+ <ClCompile Include="src\toxcore\mem.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
<ClCompile Include="src\toxcore\Messenger.c">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
@@ -242,6 +248,7 @@
<ClInclude Include="src\toxcore\bin_unpack.h" />
<ClInclude Include="src\toxcore\ccompat.h" />
<ClInclude Include="src\toxcore\crypto_core.h" />
+ <ClInclude Include="src\toxcore\crypto_core_pack.h" />
<ClInclude Include="src\toxcore\DHT.h" />
<ClInclude Include="src\toxcore\events\events_alloc.h" />
<ClInclude Include="src\toxcore\forwarding.h" />
@@ -253,6 +260,7 @@
<ClInclude Include="src\toxcore\LAN_discovery.h" />
<ClInclude Include="src\toxcore\list.h" />
<ClInclude Include="src\toxcore\logger.h" />
+ <ClInclude Include="src\toxcore\mem.h" />
<ClInclude Include="src\toxcore\Messenger.h" />
<ClInclude Include="src\toxcore\mono_time.h" />
<ClInclude Include="src\toxcore\network.h" />
diff --git a/protocols/Tox/libtox/libtox.vcxproj.filters b/protocols/Tox/libtox/libtox.vcxproj.filters
index 3e640dc5ff..fd34edfa20 100644
--- a/protocols/Tox/libtox/libtox.vcxproj.filters
+++ b/protocols/Tox/libtox/libtox.vcxproj.filters
@@ -210,6 +210,12 @@
<ClCompile Include="src\third_party\cmp\cmp.c">
<Filter>Source Files\third_party</Filter>
</ClCompile>
+ <ClCompile Include="src\toxcore\mem.c">
+ <Filter>Source Files\toxcore</Filter>
+ </ClCompile>
+ <ClCompile Include="src\toxcore\crypto_core_pack.c">
+ <Filter>Source Files\toxcore</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\toxcore\announce.h">
@@ -332,6 +338,12 @@
<ClInclude Include="src\third_party\cmp\cmp.h">
<Filter>Source Files\third_party</Filter>
</ClInclude>
+ <ClInclude Include="src\toxcore\mem.h">
+ <Filter>Source Files\toxcore</Filter>
+ </ClInclude>
+ <ClInclude Include="src\toxcore\crypto_core_pack.h">
+ <Filter>Source Files\toxcore</Filter>
+ </ClInclude>
</ItemGroup>
<Import Project="$(ProjectDir)..\..\..\build\vc.common\common.filters" />
</Project> \ No newline at end of file
diff --git a/protocols/Tox/libtox/src/third_party/cmp/cmp.c b/protocols/Tox/libtox/src/third_party/cmp/cmp.c
index 405b5780b2..c312efd6c7 100644
--- a/protocols/Tox/libtox/src/third_party/cmp/cmp.c
+++ b/protocols/Tox/libtox/src/third_party/cmp/cmp.c
@@ -1,31 +1,16 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2020 Charles Gunyon
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-*/
-
+/* SPDX-License-Identifier: MIT
+ * Copyright © 2020-2024 Charles Gunyon.
+ */
#include "cmp.h"
-static const uint32_t version = 20;
-static const uint32_t mp_version = 5;
+#ifdef __cplusplus
+#define CMP_NULL nullptr
+#else
+#define CMP_NULL NULL
+#endif /* __cplusplus */
+
+static const uint32_t cmp_version_ = 20;
+static const uint32_t cmp_mp_version_ = 5;
enum {
POSITIVE_FIXNUM_MARKER = 0x00,
@@ -72,67 +57,69 @@ enum {
FIXSTR_SIZE = 0x1F
};
-enum {
- ERROR_NONE,
- STR_DATA_LENGTH_TOO_LONG_ERROR,
- BIN_DATA_LENGTH_TOO_LONG_ERROR,
- ARRAY_LENGTH_TOO_LONG_ERROR,
- MAP_LENGTH_TOO_LONG_ERROR,
- INPUT_VALUE_TOO_LARGE_ERROR,
- FIXED_VALUE_WRITING_ERROR,
- TYPE_MARKER_READING_ERROR,
- TYPE_MARKER_WRITING_ERROR,
- DATA_READING_ERROR,
- DATA_WRITING_ERROR,
- EXT_TYPE_READING_ERROR,
- EXT_TYPE_WRITING_ERROR,
- INVALID_TYPE_ERROR,
- LENGTH_READING_ERROR,
- LENGTH_WRITING_ERROR,
- SKIP_DEPTH_LIMIT_EXCEEDED_ERROR,
- INTERNAL_ERROR,
- DISABLED_FLOATING_POINT_ERROR,
- ERROR_MAX
-};
-
-static const char * const cmp_error_messages[ERROR_MAX + 1] = {
- "No Error",
- "Specified string data length is too long (> 0xFFFFFFFF)",
- "Specified binary data length is too long (> 0xFFFFFFFF)",
- "Specified array length is too long (> 0xFFFFFFFF)",
- "Specified map length is too long (> 0xFFFFFFFF)",
- "Input value is too large",
- "Error writing fixed value",
- "Error reading type marker",
- "Error writing type marker",
- "Error reading packed data",
- "Error writing packed data",
- "Error reading ext type",
- "Error writing ext type",
- "Invalid type",
- "Error reading size",
- "Error writing size",
- "Depth limit exceeded while skipping",
- "Internal error",
- "Floating point operations disabled",
- "Max Error"
-};
+typedef enum cmp_error_t {
+ CMP_ERROR_NONE,
+ CMP_ERROR_STR_DATA_LENGTH_TOO_LONG,
+ CMP_ERROR_BIN_DATA_LENGTH_TOO_LONG,
+ CMP_ERROR_ARRAY_LENGTH_TOO_LONG,
+ CMP_ERROR_MAP_LENGTH_TOO_LONG,
+ CMP_ERROR_INPUT_VALUE_TOO_LARGE,
+ CMP_ERROR_FIXED_VALUE_WRITING,
+ CMP_ERROR_TYPE_MARKER_READING,
+ CMP_ERROR_TYPE_MARKER_WRITING,
+ CMP_ERROR_DATA_READING,
+ CMP_ERROR_DATA_WRITING,
+ CMP_ERROR_EXT_TYPE_READING,
+ CMP_ERROR_EXT_TYPE_WRITING,
+ CMP_ERROR_INVALID_TYPE,
+ CMP_ERROR_LENGTH_READING,
+ CMP_ERROR_LENGTH_WRITING,
+ CMP_ERROR_SKIP_DEPTH_LIMIT_EXCEEDED,
+ CMP_ERROR_INTERNAL,
+ CMP_ERROR_DISABLED_FLOATING_POINT,
+ CMP_ERROR_MAX
+} cmp_error_t;
+
+static const char *cmp_error_message(cmp_error_t error) {
+ switch (error) {
+ case CMP_ERROR_NONE: return "No Error";
+ case CMP_ERROR_STR_DATA_LENGTH_TOO_LONG: return "Specified string data length is too long (> 0xFFFFFFFF)";
+ case CMP_ERROR_BIN_DATA_LENGTH_TOO_LONG: return "Specified binary data length is too long (> 0xFFFFFFFF)";
+ case CMP_ERROR_ARRAY_LENGTH_TOO_LONG: return "Specified array length is too long (> 0xFFFFFFFF)";
+ case CMP_ERROR_MAP_LENGTH_TOO_LONG: return "Specified map length is too long (> 0xFFFFFFFF)";
+ case CMP_ERROR_INPUT_VALUE_TOO_LARGE: return "Input value is too large";
+ case CMP_ERROR_FIXED_VALUE_WRITING: return "Error writing fixed value";
+ case CMP_ERROR_TYPE_MARKER_READING: return "Error reading type marker";
+ case CMP_ERROR_TYPE_MARKER_WRITING: return "Error writing type marker";
+ case CMP_ERROR_DATA_READING: return "Error reading packed data";
+ case CMP_ERROR_DATA_WRITING: return "Error writing packed data";
+ case CMP_ERROR_EXT_TYPE_READING: return "Error reading ext type";
+ case CMP_ERROR_EXT_TYPE_WRITING: return "Error writing ext type";
+ case CMP_ERROR_INVALID_TYPE: return "Invalid type";
+ case CMP_ERROR_LENGTH_READING: return "Error reading size";
+ case CMP_ERROR_LENGTH_WRITING: return "Error writing size";
+ case CMP_ERROR_SKIP_DEPTH_LIMIT_EXCEEDED: return "Depth limit exceeded while skipping";
+ case CMP_ERROR_INTERNAL: return "Internal error";
+ case CMP_ERROR_DISABLED_FLOATING_POINT: return "Floating point operations disabled";
+ case CMP_ERROR_MAX: return "Max Error";
+ }
+ return "";
+}
+static bool is_bigendian(void) {
#ifdef WORDS_BIGENDIAN
-#define is_bigendian() (WORDS_BIGENDIAN)
+ return WORDS_BIGENDIAN;
#else
-static const int32_t _i = 1;
-#define is_bigendian() ((*(const char *)&_i) == 0)
-#endif
+ const int32_t i_ = 1;
+ const char *i_bytes = (const char *)&i_;
+ return *i_bytes == 0;
+#endif /* WORDS_BIGENDIAN */
+}
static uint16_t be16(uint16_t x) {
- char *b = (char *)&x;
-
- if (!is_bigendian()) {
- char swap = b[0];
- b[0] = b[1];
- b[1] = swap;
- }
+ if (!is_bigendian())
+ return ((x >> 8) & 0x00ff)
+ | ((x << 8) & 0xff00);
return x;
}
@@ -142,17 +129,8 @@ static int16_t sbe16(int16_t x) {
}
static uint32_t be32(uint32_t x) {
- char *b = (char *)&x;
-
- if (!is_bigendian()) {
- char swap = b[0];
- b[0] = b[3];
- b[3] = swap;
-
- swap = b[1];
- b[1] = b[2];
- b[2] = swap;
- }
+ if (!is_bigendian())
+ return ((uint32_t)be16((uint16_t)(x & 0xffff)) << 16) | (uint32_t)be16((uint16_t)(x >> 16));
return x;
}
@@ -162,27 +140,8 @@ static int32_t sbe32(int32_t x) {
}
static uint64_t be64(uint64_t x) {
- char *b = (char *)&x;
-
- if (!is_bigendian()) {
- char swap;
-
- swap = b[0];
- b[0] = b[7];
- b[7] = swap;
-
- swap = b[1];
- b[1] = b[6];
- b[6] = swap;
-
- swap = b[2];
- b[2] = b[5];
- b[5] = swap;
-
- swap = b[3];
- b[3] = b[4];
- b[4] = swap;
- }
+ if (!is_bigendian())
+ return ((uint64_t)be32((uint32_t)(x & 0xffffffff)) << 32) | (uint64_t)be32((uint32_t)(x >> 32));
return x;
}
@@ -193,7 +152,7 @@ static int64_t sbe64(int64_t x) {
#ifndef CMP_NO_FLOAT
static float decode_befloat(const char *b) {
- float f = 0.;
+ float f = 0.0;
char *fb = (char *)&f;
if (!is_bigendian()) {
@@ -213,7 +172,7 @@ static float decode_befloat(const char *b) {
}
static double decode_bedouble(const char *b) {
- double d = 0.;
+ double d = 0.0;
char *db = (char *)&d;
if (!is_bigendian()) {
@@ -246,18 +205,17 @@ static bool read_byte(cmp_ctx_t *ctx, uint8_t *x) {
}
static bool write_byte(cmp_ctx_t *ctx, uint8_t x) {
- return (ctx->write(ctx, &x, sizeof(uint8_t)) == (sizeof(uint8_t)));
+ return ctx->write(ctx, &x, sizeof(uint8_t)) == sizeof(uint8_t);
}
static bool skip_bytes(cmp_ctx_t *ctx, size_t count) {
- if (ctx->skip) {
+ if (ctx->skip != CMP_NULL) {
return ctx->skip(ctx, count);
}
else {
- uint8_t floor;
size_t i;
-
- for (i = 0; i < count; i++) {
+ for (i = 0; i < count; ++i) {
+ uint8_t floor;
if (!ctx->read(ctx, &floor, sizeof(uint8_t))) {
return false;
}
@@ -272,7 +230,7 @@ static bool read_type_marker(cmp_ctx_t *ctx, uint8_t *marker) {
return true;
}
- ctx->error = TYPE_MARKER_READING_ERROR;
+ ctx->error = CMP_ERROR_TYPE_MARKER_READING;
return false;
}
@@ -280,7 +238,7 @@ static bool write_type_marker(cmp_ctx_t *ctx, uint8_t marker) {
if (write_byte(ctx, marker))
return true;
- ctx->error = TYPE_MARKER_WRITING_ERROR;
+ ctx->error = CMP_ERROR_TYPE_MARKER_WRITING;
return false;
}
@@ -288,7 +246,7 @@ static bool write_fixed_value(cmp_ctx_t *ctx, uint8_t value) {
if (write_byte(ctx, value))
return true;
- ctx->error = FIXED_VALUE_WRITING_ERROR;
+ ctx->error = CMP_ERROR_FIXED_VALUE_WRITING;
return false;
}
@@ -319,101 +277,133 @@ static bool type_marker_to_cmp_type(uint8_t type_marker, uint8_t *cmp_type) {
}
switch (type_marker) {
- case NIL_MARKER:
+ case NIL_MARKER: {
*cmp_type = CMP_TYPE_NIL;
return true;
- case FALSE_MARKER:
+ }
+ case FALSE_MARKER: {
*cmp_type = CMP_TYPE_BOOLEAN;
return true;
- case TRUE_MARKER:
+ }
+ case TRUE_MARKER: {
*cmp_type = CMP_TYPE_BOOLEAN;
return true;
- case BIN8_MARKER:
+ }
+ case BIN8_MARKER: {
*cmp_type = CMP_TYPE_BIN8;
return true;
- case BIN16_MARKER:
+ }
+ case BIN16_MARKER: {
*cmp_type = CMP_TYPE_BIN16;
return true;
- case BIN32_MARKER:
+ }
+ case BIN32_MARKER: {
*cmp_type = CMP_TYPE_BIN32;
return true;
- case EXT8_MARKER:
+ }
+ case EXT8_MARKER: {
*cmp_type = CMP_TYPE_EXT8;
return true;
- case EXT16_MARKER:
+ }
+ case EXT16_MARKER: {
*cmp_type = CMP_TYPE_EXT16;
return true;
- case EXT32_MARKER:
+ }
+ case EXT32_MARKER: {
*cmp_type = CMP_TYPE_EXT32;
return true;
- case FLOAT_MARKER:
+ }
+ case FLOAT_MARKER: {
*cmp_type = CMP_TYPE_FLOAT;
return true;
- case DOUBLE_MARKER:
+ }
+ case DOUBLE_MARKER: {
*cmp_type = CMP_TYPE_DOUBLE;
return true;
- case U8_MARKER:
+ }
+ case U8_MARKER: {
*cmp_type = CMP_TYPE_UINT8;
return true;
- case U16_MARKER:
+ }
+ case U16_MARKER: {
*cmp_type = CMP_TYPE_UINT16;
return true;
- case U32_MARKER:
+ }
+ case U32_MARKER: {
*cmp_type = CMP_TYPE_UINT32;
return true;
- case U64_MARKER:
+ }
+ case U64_MARKER: {
*cmp_type = CMP_TYPE_UINT64;
return true;
- case S8_MARKER:
+ }
+ case S8_MARKER: {
*cmp_type = CMP_TYPE_SINT8;
return true;
- case S16_MARKER:
+ }
+ case S16_MARKER: {
*cmp_type = CMP_TYPE_SINT16;
return true;
- case S32_MARKER:
+ }
+ case S32_MARKER: {
*cmp_type = CMP_TYPE_SINT32;
return true;
- case S64_MARKER:
+ }
+ case S64_MARKER: {
*cmp_type = CMP_TYPE_SINT64;
return true;
- case FIXEXT1_MARKER:
+ }
+ case FIXEXT1_MARKER: {
*cmp_type = CMP_TYPE_FIXEXT1;
return true;
- case FIXEXT2_MARKER:
+ }
+ case FIXEXT2_MARKER: {
*cmp_type = CMP_TYPE_FIXEXT2;
return true;
- case FIXEXT4_MARKER:
+ }
+ case FIXEXT4_MARKER: {
*cmp_type = CMP_TYPE_FIXEXT4;
return true;
- case FIXEXT8_MARKER:
+ }
+ case FIXEXT8_MARKER: {
*cmp_type = CMP_TYPE_FIXEXT8;
return true;
- case FIXEXT16_MARKER:
+ }
+ case FIXEXT16_MARKER: {
*cmp_type = CMP_TYPE_FIXEXT16;
return true;
- case STR8_MARKER:
+ }
+ case STR8_MARKER: {
*cmp_type = CMP_TYPE_STR8;
return true;
- case STR16_MARKER:
+ }
+ case STR16_MARKER: {
*cmp_type = CMP_TYPE_STR16;
return true;
- case STR32_MARKER:
+ }
+ case STR32_MARKER: {
*cmp_type = CMP_TYPE_STR32;
return true;
- case ARRAY16_MARKER:
+ }
+ case ARRAY16_MARKER: {
*cmp_type = CMP_TYPE_ARRAY16;
return true;
- case ARRAY32_MARKER:
+ }
+ case ARRAY32_MARKER: {
*cmp_type = CMP_TYPE_ARRAY32;
return true;
- case MAP16_MARKER:
+ }
+ case MAP16_MARKER: {
*cmp_type = CMP_TYPE_MAP16;
return true;
- case MAP32_MARKER:
+ }
+ case MAP32_MARKER: {
*cmp_type = CMP_TYPE_MAP32;
return true;
- default:
+ }
+ default: {
return false;
+ }
}
}
@@ -425,277 +415,325 @@ static bool read_type_size(cmp_ctx_t *ctx, uint8_t type_marker,
uint32_t u32temp = 0;
switch (cmp_type) {
- case CMP_TYPE_POSITIVE_FIXNUM:
+ case CMP_TYPE_POSITIVE_FIXNUM: {
*size = 0;
return true;
- case CMP_TYPE_FIXMAP:
- *size = (type_marker & FIXMAP_SIZE);
+ }
+ case CMP_TYPE_FIXMAP: {
+ *size = type_marker & FIXMAP_SIZE;
return true;
- case CMP_TYPE_FIXARRAY:
- *size = (type_marker & FIXARRAY_SIZE);
+ }
+ case CMP_TYPE_FIXARRAY: {
+ *size = type_marker & FIXARRAY_SIZE;
return true;
- case CMP_TYPE_FIXSTR:
- *size = (type_marker & FIXSTR_SIZE);
+ }
+ case CMP_TYPE_FIXSTR: {
+ *size = type_marker & FIXSTR_SIZE;
return true;
- case CMP_TYPE_NIL:
+ }
+ case CMP_TYPE_NIL: {
*size = 0;
return true;
- case CMP_TYPE_BOOLEAN:
+ }
+ case CMP_TYPE_BOOLEAN: {
*size = 0;
return true;
- case CMP_TYPE_BIN8:
+ }
+ case CMP_TYPE_BIN8: {
if (!ctx->read(ctx, &u8temp, sizeof(uint8_t))) {
- ctx->error = LENGTH_READING_ERROR;
+ ctx->error = CMP_ERROR_LENGTH_READING;
return false;
}
*size = u8temp;
return true;
- case CMP_TYPE_BIN16:
+ }
+ case CMP_TYPE_BIN16: {
if (!ctx->read(ctx, &u16temp, sizeof(uint16_t))) {
- ctx->error = LENGTH_READING_ERROR;
+ ctx->error = CMP_ERROR_LENGTH_READING;
return false;
}
*size = be16(u16temp);
return true;
- case CMP_TYPE_BIN32:
+ }
+ case CMP_TYPE_BIN32: {
if (!ctx->read(ctx, &u32temp, sizeof(uint32_t))) {
- ctx->error = LENGTH_READING_ERROR;
+ ctx->error = CMP_ERROR_LENGTH_READING;
return false;
}
*size = be32(u32temp);
return true;
- case CMP_TYPE_EXT8:
+ }
+ case CMP_TYPE_EXT8: {
if (!ctx->read(ctx, &u8temp, sizeof(uint8_t))) {
- ctx->error = LENGTH_READING_ERROR;
+ ctx->error = CMP_ERROR_LENGTH_READING;
return false;
}
*size = u8temp;
return true;
- case CMP_TYPE_EXT16:
+ }
+ case CMP_TYPE_EXT16: {
if (!ctx->read(ctx, &u16temp, sizeof(uint16_t))) {
- ctx->error = LENGTH_READING_ERROR;
+ ctx->error = CMP_ERROR_LENGTH_READING;
return false;
}
*size = be16(u16temp);
return true;
- case CMP_TYPE_EXT32:
+ }
+ case CMP_TYPE_EXT32: {
if (!ctx->read(ctx, &u32temp, sizeof(uint32_t))) {
- ctx->error = LENGTH_READING_ERROR;
+ ctx->error = CMP_ERROR_LENGTH_READING;
return false;
}
*size = be32(u32temp);
return true;
- case CMP_TYPE_FLOAT:
+ }
+ case CMP_TYPE_FLOAT: {
*size = 4;
return true;
- case CMP_TYPE_DOUBLE:
+ }
+ case CMP_TYPE_DOUBLE: {
*size = 8;
return true;
- case CMP_TYPE_UINT8:
+ }
+ case CMP_TYPE_UINT8: {
*size = 1;
return true;
- case CMP_TYPE_UINT16:
+ }
+ case CMP_TYPE_UINT16: {
*size = 2;
return true;
- case CMP_TYPE_UINT32:
+ }
+ case CMP_TYPE_UINT32: {
*size = 4;
return true;
- case CMP_TYPE_UINT64:
+ }
+ case CMP_TYPE_UINT64: {
*size = 8;
return true;
- case CMP_TYPE_SINT8:
+ }
+ case CMP_TYPE_SINT8: {
*size = 1;
return true;
- case CMP_TYPE_SINT16:
+ }
+ case CMP_TYPE_SINT16: {
*size = 2;
return true;
- case CMP_TYPE_SINT32:
+ }
+ case CMP_TYPE_SINT32: {
*size = 4;
return true;
- case CMP_TYPE_SINT64:
+ }
+ case CMP_TYPE_SINT64: {
*size = 8;
return true;
- case CMP_TYPE_FIXEXT1:
+ }
+ case CMP_TYPE_FIXEXT1: {
*size = 1;
return true;
- case CMP_TYPE_FIXEXT2:
+ }
+ case CMP_TYPE_FIXEXT2: {
*size = 2;
return true;
- case CMP_TYPE_FIXEXT4:
+ }
+ case CMP_TYPE_FIXEXT4: {
*size = 4;
return true;
- case CMP_TYPE_FIXEXT8:
+ }
+ case CMP_TYPE_FIXEXT8: {
*size = 8;
return true;
- case CMP_TYPE_FIXEXT16:
+ }
+ case CMP_TYPE_FIXEXT16: {
*size = 16;
return true;
- case CMP_TYPE_STR8:
+ }
+ case CMP_TYPE_STR8: {
if (!ctx->read(ctx, &u8temp, sizeof(uint8_t))) {
- ctx->error = DATA_READING_ERROR;
+ ctx->error = CMP_ERROR_DATA_READING;
return false;
}
*size = u8temp;
return true;
- case CMP_TYPE_STR16:
+ }
+ case CMP_TYPE_STR16: {
if (!ctx->read(ctx, &u16temp, sizeof(uint16_t))) {
- ctx->error = DATA_READING_ERROR;
+ ctx->error = CMP_ERROR_DATA_READING;
return false;
}
*size = be16(u16temp);
return true;
- case CMP_TYPE_STR32:
+ }
+ case CMP_TYPE_STR32: {
if (!ctx->read(ctx, &u32temp, sizeof(uint32_t))) {
- ctx->error = DATA_READING_ERROR;
+ ctx->error = CMP_ERROR_DATA_READING;
return false;
}
*size = be32(u32temp);
return true;
- case CMP_TYPE_ARRAY16:
+ }
+ case CMP_TYPE_ARRAY16: {
if (!ctx->read(ctx, &u16temp, sizeof(uint16_t))) {
- ctx->error = DATA_READING_ERROR;
+ ctx->error = CMP_ERROR_DATA_READING;
return false;
}
*size = be16(u16temp);
return true;
- case CMP_TYPE_ARRAY32:
+ }
+ case CMP_TYPE_ARRAY32: {
if (!ctx->read(ctx, &u32temp, sizeof(uint32_t))) {
- ctx->error = DATA_READING_ERROR;
+ ctx->error = CMP_ERROR_DATA_READING;
return false;
}
*size = be32(u32temp);
return true;
- case CMP_TYPE_MAP16:
+ }
+ case CMP_TYPE_MAP16: {
if (!ctx->read(ctx, &u16temp, sizeof(uint16_t))) {
- ctx->error = DATA_READING_ERROR;
+ ctx->error = CMP_ERROR_DATA_READING;
return false;
}
*size = be16(u16temp);
return true;
- case CMP_TYPE_MAP32:
+ }
+ case CMP_TYPE_MAP32: {
if (!ctx->read(ctx, &u32temp, sizeof(uint32_t))) {
- ctx->error = DATA_READING_ERROR;
+ ctx->error = CMP_ERROR_DATA_READING;
return false;
}
*size = be32(u32temp);
return true;
- case CMP_TYPE_NEGATIVE_FIXNUM:
+ }
+ case CMP_TYPE_NEGATIVE_FIXNUM: {
*size = 0;
return true;
- default:
- ctx->error = INVALID_TYPE_ERROR;
+ }
+ default: {
+ ctx->error = CMP_ERROR_INVALID_TYPE;
return false;
+ }
}
}
static bool read_obj_data(cmp_ctx_t *ctx, uint8_t type_marker,
cmp_object_t *obj) {
switch (obj->type) {
- case CMP_TYPE_POSITIVE_FIXNUM:
+ case CMP_TYPE_POSITIVE_FIXNUM: {
obj->as.u8 = type_marker;
return true;
- case CMP_TYPE_NEGATIVE_FIXNUM:
+ }
+ case CMP_TYPE_NEGATIVE_FIXNUM: {
obj->as.s8 = (int8_t)type_marker;
return true;
- case CMP_TYPE_NIL:
+ }
+ case CMP_TYPE_NIL: {
obj->as.u8 = 0;
return true;
- case CMP_TYPE_BOOLEAN:
+ }
+ case CMP_TYPE_BOOLEAN: {
switch (type_marker) {
- case TRUE_MARKER:
+ case TRUE_MARKER: {
obj->as.boolean = true;
return true;
- case FALSE_MARKER:
+ }
+ case FALSE_MARKER: {
obj->as.boolean = false;
return true;
+ }
default:
break;
}
- ctx->error = INTERNAL_ERROR;
+ ctx->error = CMP_ERROR_INTERNAL;
return false;
- case CMP_TYPE_UINT8:
+ }
+ case CMP_TYPE_UINT8: {
if (!ctx->read(ctx, &obj->as.u8, sizeof(uint8_t))) {
- ctx->error = DATA_READING_ERROR;
+ ctx->error = CMP_ERROR_DATA_READING;
return false;
}
return true;
- case CMP_TYPE_UINT16:
+ }
+ case CMP_TYPE_UINT16: {
if (!ctx->read(ctx, &obj->as.u16, sizeof(uint16_t))) {
- ctx->error = DATA_READING_ERROR;
+ ctx->error = CMP_ERROR_DATA_READING;
return false;
}
obj->as.u16 = be16(obj->as.u16);
return true;
- case CMP_TYPE_UINT32:
+ }
+ case CMP_TYPE_UINT32: {
if (!ctx->read(ctx, &obj->as.u32, sizeof(uint32_t))) {
- ctx->error = DATA_READING_ERROR;
+ ctx->error = CMP_ERROR_DATA_READING;
return false;
}
obj->as.u32 = be32(obj->as.u32);
return true;
- case CMP_TYPE_UINT64:
+ }
+ case CMP_TYPE_UINT64: {
if (!ctx->read(ctx, &obj->as.u64, sizeof(uint64_t))) {
- ctx->error = DATA_READING_ERROR;
+ ctx->error = CMP_ERROR_DATA_READING;
return false;
}
obj->as.u64 = be64(obj->as.u64);
return true;
- case CMP_TYPE_SINT8:
+ }
+ case CMP_TYPE_SINT8: {
if (!ctx->read(ctx, &obj->as.s8, sizeof(int8_t))) {
- ctx->error = DATA_READING_ERROR;
+ ctx->error = CMP_ERROR_DATA_READING;
return false;
}
return true;
- case CMP_TYPE_SINT16:
+ }
+ case CMP_TYPE_SINT16: {
if (!ctx->read(ctx, &obj->as.s16, sizeof(int16_t))) {
- ctx->error = DATA_READING_ERROR;
+ ctx->error = CMP_ERROR_DATA_READING;
return false;
}
obj->as.s16 = sbe16(obj->as.s16);
return true;
- case CMP_TYPE_SINT32:
+ }
+ case CMP_TYPE_SINT32: {
if (!ctx->read(ctx, &obj->as.s32, sizeof(int32_t))) {
- ctx->error = DATA_READING_ERROR;
+ ctx->error = CMP_ERROR_DATA_READING;
return false;
}
obj->as.s32 = sbe32(obj->as.s32);
return true;
- case CMP_TYPE_SINT64:
+ }
+ case CMP_TYPE_SINT64: {
if (!ctx->read(ctx, &obj->as.s64, sizeof(int64_t))) {
- ctx->error = DATA_READING_ERROR;
+ ctx->error = CMP_ERROR_DATA_READING;
return false;
}
obj->as.s64 = sbe64(obj->as.s64);
return true;
- case CMP_TYPE_FLOAT:
- {
+ }
+ case CMP_TYPE_FLOAT: {
#ifndef CMP_NO_FLOAT
char bytes[4];
if (!ctx->read(ctx, bytes, 4)) {
- ctx->error = DATA_READING_ERROR;
+ ctx->error = CMP_ERROR_DATA_READING;
return false;
}
obj->as.flt = decode_befloat(bytes);
return true;
#else /* CMP_NO_FLOAT */
- ctx->error = DISABLED_FLOATING_POINT_ERROR;
+ ctx->error = CMP_ERROR_DISABLED_FLOATING_POINT;
return false;
#endif /* CMP_NO_FLOAT */
}
- case CMP_TYPE_DOUBLE:
- {
+ case CMP_TYPE_DOUBLE: {
#ifndef CMP_NO_FLOAT
char bytes[8];
if (!ctx->read(ctx, bytes, 8)) {
- ctx->error = DATA_READING_ERROR;
+ ctx->error = CMP_ERROR_DATA_READING;
return false;
}
obj->as.dbl = decode_bedouble(bytes);
return true;
#else /* CMP_NO_FLOAT */
- ctx->error = DISABLED_FLOATING_POINT_ERROR;
+ ctx->error = CMP_ERROR_DISABLED_FLOATING_POINT;
return false;
#endif /* CMP_NO_FLOAT */
}
@@ -716,80 +754,88 @@ static bool read_obj_data(cmp_ctx_t *ctx, uint8_t type_marker,
case CMP_TYPE_MAP16:
case CMP_TYPE_MAP32:
return read_type_size(ctx, type_marker, obj->type, &obj->as.map_size);
- case CMP_TYPE_FIXEXT1:
+ case CMP_TYPE_FIXEXT1: {
if (!ctx->read(ctx, &obj->as.ext.type, sizeof(int8_t))) {
- ctx->error = EXT_TYPE_READING_ERROR;
+ ctx->error = CMP_ERROR_EXT_TYPE_READING;
return false;
}
obj->as.ext.size = 1;
return true;
- case CMP_TYPE_FIXEXT2:
+ }
+ case CMP_TYPE_FIXEXT2: {
if (!ctx->read(ctx, &obj->as.ext.type, sizeof(int8_t))) {
- ctx->error = EXT_TYPE_READING_ERROR;
+ ctx->error = CMP_ERROR_EXT_TYPE_READING;
return false;
}
obj->as.ext.size = 2;
return true;
- case CMP_TYPE_FIXEXT4:
+ }
+ case CMP_TYPE_FIXEXT4: {
if (!ctx->read(ctx, &obj->as.ext.type, sizeof(int8_t))) {
- ctx->error = EXT_TYPE_READING_ERROR;
+ ctx->error = CMP_ERROR_EXT_TYPE_READING;
return false;
}
obj->as.ext.size = 4;
return true;
- case CMP_TYPE_FIXEXT8:
+ }
+ case CMP_TYPE_FIXEXT8: {
if (!ctx->read(ctx, &obj->as.ext.type, sizeof(int8_t))) {
- ctx->error = EXT_TYPE_READING_ERROR;
+ ctx->error = CMP_ERROR_EXT_TYPE_READING;
return false;
}
obj->as.ext.size = 8;
return true;
- case CMP_TYPE_FIXEXT16:
+ }
+ case CMP_TYPE_FIXEXT16: {
if (!ctx->read(ctx, &obj->as.ext.type, sizeof(int8_t))) {
- ctx->error = EXT_TYPE_READING_ERROR;
+ ctx->error = CMP_ERROR_EXT_TYPE_READING;
return false;
}
obj->as.ext.size = 16;
return true;
- case CMP_TYPE_EXT8:
+ }
+ case CMP_TYPE_EXT8: {
if (!read_type_size(ctx, type_marker, obj->type, &obj->as.ext.size)) {
return false;
}
if (!ctx->read(ctx, &obj->as.ext.type, sizeof(int8_t))) {
- ctx->error = EXT_TYPE_READING_ERROR;
+ ctx->error = CMP_ERROR_EXT_TYPE_READING;
return false;
}
return true;
- case CMP_TYPE_EXT16:
+ }
+ case CMP_TYPE_EXT16: {
if (!read_type_size(ctx, type_marker, obj->type, &obj->as.ext.size)) {
return false;
}
if (!ctx->read(ctx, &obj->as.ext.type, sizeof(int8_t))) {
- ctx->error = EXT_TYPE_READING_ERROR;
+ ctx->error = CMP_ERROR_EXT_TYPE_READING;
return false;
}
return true;
- case CMP_TYPE_EXT32:
+ }
+ case CMP_TYPE_EXT32: {
if (!read_type_size(ctx, type_marker, obj->type, &obj->as.ext.size)) {
return false;
}
if (!ctx->read(ctx, &obj->as.ext.type, sizeof(int8_t))) {
- ctx->error = EXT_TYPE_READING_ERROR;
+ ctx->error = CMP_ERROR_EXT_TYPE_READING;
return false;
}
return true;
+ }
default:
break;
}
- ctx->error = INVALID_TYPE_ERROR;
+ ctx->error = CMP_ERROR_INVALID_TYPE;
return false;
}
-void cmp_init(cmp_ctx_t *ctx, void *buf, cmp_reader read,
- cmp_skipper skip,
- cmp_writer write) {
- ctx->error = ERROR_NONE;
+void cmp_init(cmp_ctx_t *ctx, void *buf, cmp_reader *read,
+ cmp_skipper *skip,
+ cmp_writer *write) {
+ ctx->error = CMP_ERROR_NONE;
ctx->buf = buf;
ctx->read = read;
ctx->skip = skip;
@@ -797,17 +843,16 @@ void cmp_init(cmp_ctx_t *ctx, void *buf, cmp_reader read,
}
uint32_t cmp_version(void) {
- return version;
+ return cmp_version_;
}
uint32_t cmp_mp_version(void) {
- return mp_version;
+ return cmp_mp_version_;
}
-const char* cmp_strerror(cmp_ctx_t *ctx) {
- if (ctx->error > ERROR_NONE && ctx->error < ERROR_MAX)
- return cmp_error_messages[ctx->error];
-
+const char* cmp_strerror(const cmp_ctx_t *ctx) {
+ if (ctx->error > CMP_ERROR_NONE && ctx->error < CMP_ERROR_MAX)
+ return cmp_error_message((cmp_error_t)ctx->error);
return "";
}
@@ -815,7 +860,7 @@ bool cmp_write_pfix(cmp_ctx_t *ctx, uint8_t c) {
if (c <= 0x7F)
return write_fixed_value(ctx, c);
- ctx->error = INPUT_VALUE_TOO_LARGE_ERROR;
+ ctx->error = CMP_ERROR_INPUT_VALUE_TOO_LARGE;
return false;
}
@@ -823,7 +868,7 @@ bool cmp_write_nfix(cmp_ctx_t *ctx, int8_t c) {
if (c >= -32 && c <= -1)
return write_fixed_value(ctx, (uint8_t)c);
- ctx->error = INPUT_VALUE_TOO_LARGE_ERROR;
+ ctx->error = CMP_ERROR_INPUT_VALUE_TOO_LARGE;
return false;
}
@@ -833,7 +878,7 @@ bool cmp_write_sfix(cmp_ctx_t *ctx, int8_t c) {
if (c >= -32 && c <= -1)
return cmp_write_nfix(ctx, c);
- ctx->error = INPUT_VALUE_TOO_LARGE_ERROR;
+ ctx->error = CMP_ERROR_INPUT_VALUE_TOO_LARGE;
return false;
}
@@ -841,7 +886,7 @@ bool cmp_write_s8(cmp_ctx_t *ctx, int8_t c) {
if (!write_type_marker(ctx, S8_MARKER))
return false;
- return ctx->write(ctx, &c, sizeof(int8_t));
+ return ctx->write(ctx, &c, sizeof(int8_t)) == sizeof(int8_t);
}
bool cmp_write_s16(cmp_ctx_t *ctx, int16_t s) {
@@ -850,7 +895,7 @@ bool cmp_write_s16(cmp_ctx_t *ctx, int16_t s) {
s = sbe16(s);
- return ctx->write(ctx, &s, sizeof(int16_t));
+ return ctx->write(ctx, &s, sizeof(int16_t)) == sizeof(int16_t);
}
bool cmp_write_s32(cmp_ctx_t *ctx, int32_t i) {
@@ -859,7 +904,7 @@ bool cmp_write_s32(cmp_ctx_t *ctx, int32_t i) {
i = sbe32(i);
- return ctx->write(ctx, &i, sizeof(int32_t));
+ return ctx->write(ctx, &i, sizeof(int32_t)) == sizeof(int32_t);
}
bool cmp_write_s64(cmp_ctx_t *ctx, int64_t l) {
@@ -868,19 +913,19 @@ bool cmp_write_s64(cmp_ctx_t *ctx, int64_t l) {
l = sbe64(l);
- return ctx->write(ctx, &l, sizeof(int64_t));
+ return ctx->write(ctx, &l, sizeof(int64_t)) == sizeof(int64_t);
}
bool cmp_write_integer(cmp_ctx_t *ctx, int64_t d) {
if (d >= 0)
return cmp_write_uinteger(ctx, (uint64_t)d);
- if (d >= -32)
+ if (d >= -0x20)
return cmp_write_nfix(ctx, (int8_t)d);
- if (d >= -128)
+ if (d >= -0x80)
return cmp_write_s8(ctx, (int8_t)d);
- if (d >= -32768)
+ if (d >= -0x8000)
return cmp_write_s16(ctx, (int16_t)d);
- if (d >= (-2147483647 - 1))
+ if (d >= -INT64_C(0x80000000))
return cmp_write_s32(ctx, (int32_t)d);
return cmp_write_s64(ctx, d);
@@ -894,7 +939,7 @@ bool cmp_write_u8(cmp_ctx_t *ctx, uint8_t c) {
if (!write_type_marker(ctx, U8_MARKER))
return false;
- return ctx->write(ctx, &c, sizeof(uint8_t));
+ return ctx->write(ctx, &c, sizeof(uint8_t)) == sizeof(uint8_t);
}
bool cmp_write_u16(cmp_ctx_t *ctx, uint16_t s) {
@@ -903,7 +948,7 @@ bool cmp_write_u16(cmp_ctx_t *ctx, uint16_t s) {
s = be16(s);
- return ctx->write(ctx, &s, sizeof(uint16_t));
+ return ctx->write(ctx, &s, sizeof(uint16_t)) == sizeof(uint16_t);
}
bool cmp_write_u32(cmp_ctx_t *ctx, uint32_t i) {
@@ -912,7 +957,7 @@ bool cmp_write_u32(cmp_ctx_t *ctx, uint32_t i) {
i = be32(i);
- return ctx->write(ctx, &i, sizeof(uint32_t));
+ return ctx->write(ctx, &i, sizeof(uint32_t)) == sizeof(uint32_t);
}
bool cmp_write_u64(cmp_ctx_t *ctx, uint64_t l) {
@@ -921,7 +966,7 @@ bool cmp_write_u64(cmp_ctx_t *ctx, uint64_t l) {
l = be64(l);
- return ctx->write(ctx, &l, sizeof(uint64_t));
+ return ctx->write(ctx, &l, sizeof(uint64_t)) == sizeof(uint64_t);
}
bool cmp_write_uinteger(cmp_ctx_t *ctx, uint64_t u) {
@@ -950,15 +995,16 @@ bool cmp_write_float(cmp_ctx_t *ctx, float f) {
if (!is_bigendian()) {
char swapped[sizeof(float)];
char *fbuf = (char *)&f;
- size_t i;
- for (i = 0; i < sizeof(float); i++)
+ size_t i;
+ for (i = 0; i < sizeof(float); ++i) {
swapped[i] = fbuf[sizeof(float) - i - 1];
+ }
- return ctx->write(ctx, swapped, sizeof(float));
+ return ctx->write(ctx, swapped, sizeof(float)) == sizeof(float);
}
- return ctx->write(ctx, &f, sizeof(float));
+ return ctx->write(ctx, &f, sizeof(float)) == sizeof(float);
}
bool cmp_write_double(cmp_ctx_t *ctx, double d) {
@@ -969,20 +1015,21 @@ bool cmp_write_double(cmp_ctx_t *ctx, double d) {
if (!is_bigendian()) {
char swapped[sizeof(double)];
char *dbuf = (char *)&d;
- size_t i;
- for (i = 0; i < sizeof(double); i++)
+ size_t i;
+ for (i = 0; i < sizeof(double); ++i) {
swapped[i] = dbuf[sizeof(double) - i - 1];
+ }
- return ctx->write(ctx, swapped, sizeof(double));
+ return ctx->write(ctx, swapped, sizeof(double)) == sizeof(double);
}
- return ctx->write(ctx, &d, sizeof(double));
+ return ctx->write(ctx, &d, sizeof(double)) == sizeof(double);
}
bool cmp_write_decimal(cmp_ctx_t *ctx, double d) {
- float f = (float)d;
- double df = (double)f;
+ const float f = (float)d;
+ const double df = (double)f;
if (df == d)
return cmp_write_float(ctx, f);
@@ -1011,17 +1058,14 @@ bool cmp_write_bool(cmp_ctx_t *ctx, bool b) {
}
bool cmp_write_u8_as_bool(cmp_ctx_t *ctx, uint8_t b) {
- if (b)
- return cmp_write_true(ctx);
-
- return cmp_write_false(ctx);
+ return cmp_write_bool(ctx, b != 0);
}
bool cmp_write_fixstr_marker(cmp_ctx_t *ctx, uint8_t size) {
if (size <= FIXSTR_SIZE)
return write_fixed_value(ctx, FIXSTR_MARKER | size);
- ctx->error = INPUT_VALUE_TOO_LARGE_ERROR;
+ ctx->error = CMP_ERROR_INPUT_VALUE_TOO_LARGE;
return false;
}
@@ -1032,10 +1076,10 @@ bool cmp_write_fixstr(cmp_ctx_t *ctx, const char *data, uint8_t size) {
if (size == 0)
return true;
- if (ctx->write(ctx, data, size))
+ if (ctx->write(ctx, data, size) == size)
return true;
- ctx->error = DATA_WRITING_ERROR;
+ ctx->error = CMP_ERROR_DATA_WRITING;
return false;
}
@@ -1043,10 +1087,10 @@ bool cmp_write_str8_marker(cmp_ctx_t *ctx, uint8_t size) {
if (!write_type_marker(ctx, STR8_MARKER))
return false;
- if (ctx->write(ctx, &size, sizeof(uint8_t)))
+ if (ctx->write(ctx, &size, sizeof(uint8_t)) == sizeof(uint8_t))
return true;
- ctx->error = LENGTH_WRITING_ERROR;
+ ctx->error = CMP_ERROR_LENGTH_WRITING;
return false;
}
@@ -1057,10 +1101,10 @@ bool cmp_write_str8(cmp_ctx_t *ctx, const char *data, uint8_t size) {
if (size == 0)
return true;
- if (ctx->write(ctx, data, size))
+ if (ctx->write(ctx, data, size) == size)
return true;
- ctx->error = DATA_WRITING_ERROR;
+ ctx->error = CMP_ERROR_DATA_WRITING;
return false;
}
@@ -1070,10 +1114,10 @@ bool cmp_write_str16_marker(cmp_ctx_t *ctx, uint16_t size) {
size = be16(size);
- if (ctx->write(ctx, &size, sizeof(uint16_t)))
+ if (ctx->write(ctx, &size, sizeof(uint16_t)) == sizeof(uint16_t))
return true;
- ctx->error = LENGTH_WRITING_ERROR;
+ ctx->error = CMP_ERROR_LENGTH_WRITING;
return false;
}
@@ -1084,10 +1128,10 @@ bool cmp_write_str16(cmp_ctx_t *ctx, const char *data, uint16_t size) {
if (size == 0)
return true;
- if (ctx->write(ctx, data, size))
+ if (ctx->write(ctx, data, size) == size)
return true;
- ctx->error = DATA_WRITING_ERROR;
+ ctx->error = CMP_ERROR_DATA_WRITING;
return false;
}
@@ -1097,10 +1141,10 @@ bool cmp_write_str32_marker(cmp_ctx_t *ctx, uint32_t size) {
size = be32(size);
- if (ctx->write(ctx, &size, sizeof(uint32_t)))
+ if (ctx->write(ctx, &size, sizeof(uint32_t)) == sizeof(uint32_t))
return true;
- ctx->error = LENGTH_WRITING_ERROR;
+ ctx->error = CMP_ERROR_LENGTH_WRITING;
return false;
}
@@ -1111,10 +1155,10 @@ bool cmp_write_str32(cmp_ctx_t *ctx, const char *data, uint32_t size) {
if (size == 0)
return true;
- if (ctx->write(ctx, data, size))
+ if (ctx->write(ctx, data, size) == size)
return true;
- ctx->error = DATA_WRITING_ERROR;
+ ctx->error = CMP_ERROR_DATA_WRITING;
return false;
}
@@ -1162,10 +1206,10 @@ bool cmp_write_bin8_marker(cmp_ctx_t *ctx, uint8_t size) {
if (!write_type_marker(ctx, BIN8_MARKER))
return false;
- if (ctx->write(ctx, &size, sizeof(uint8_t)))
+ if (ctx->write(ctx, &size, sizeof(uint8_t)) == sizeof(uint8_t))
return true;
- ctx->error = LENGTH_WRITING_ERROR;
+ ctx->error = CMP_ERROR_LENGTH_WRITING;
return false;
}
@@ -1176,10 +1220,10 @@ bool cmp_write_bin8(cmp_ctx_t *ctx, const void *data, uint8_t size) {
if (size == 0)
return true;
- if (ctx->write(ctx, data, size))
+ if (ctx->write(ctx, data, size) == size)
return true;
- ctx->error = DATA_WRITING_ERROR;
+ ctx->error = CMP_ERROR_DATA_WRITING;
return false;
}
@@ -1189,10 +1233,10 @@ bool cmp_write_bin16_marker(cmp_ctx_t *ctx, uint16_t size) {
size = be16(size);
- if (ctx->write(ctx, &size, sizeof(uint16_t)))
+ if (ctx->write(ctx, &size, sizeof(uint16_t)) == sizeof(uint16_t))
return true;
- ctx->error = LENGTH_WRITING_ERROR;
+ ctx->error = CMP_ERROR_LENGTH_WRITING;
return false;
}
@@ -1203,10 +1247,10 @@ bool cmp_write_bin16(cmp_ctx_t *ctx, const void *data, uint16_t size) {
if (size == 0)
return true;
- if (ctx->write(ctx, data, size))
+ if (ctx->write(ctx, data, size) == size)
return true;
- ctx->error = DATA_WRITING_ERROR;
+ ctx->error = CMP_ERROR_DATA_WRITING;
return false;
}
@@ -1216,10 +1260,10 @@ bool cmp_write_bin32_marker(cmp_ctx_t *ctx, uint32_t size) {
size = be32(size);
- if (ctx->write(ctx, &size, sizeof(uint32_t)))
+ if (ctx->write(ctx, &size, sizeof(uint32_t)) == sizeof(uint32_t))
return true;
- ctx->error = LENGTH_WRITING_ERROR;
+ ctx->error = CMP_ERROR_LENGTH_WRITING;
return false;
}
@@ -1230,10 +1274,10 @@ bool cmp_write_bin32(cmp_ctx_t *ctx, const void *data, uint32_t size) {
if (size == 0)
return true;
- if (ctx->write(ctx, data, size))
+ if (ctx->write(ctx, data, size) == size)
return true;
- ctx->error = DATA_WRITING_ERROR;
+ ctx->error = CMP_ERROR_DATA_WRITING;
return false;
}
@@ -1259,7 +1303,7 @@ bool cmp_write_fixarray(cmp_ctx_t *ctx, uint8_t size) {
if (size <= FIXARRAY_SIZE)
return write_fixed_value(ctx, FIXARRAY_MARKER | size);
- ctx->error = INPUT_VALUE_TOO_LARGE_ERROR;
+ ctx->error = CMP_ERROR_INPUT_VALUE_TOO_LARGE;
return false;
}
@@ -1269,10 +1313,10 @@ bool cmp_write_array16(cmp_ctx_t *ctx, uint16_t size) {
size = be16(size);
- if (ctx->write(ctx, &size, sizeof(uint16_t)))
+ if (ctx->write(ctx, &size, sizeof(uint16_t)) == sizeof(uint16_t))
return true;
- ctx->error = LENGTH_WRITING_ERROR;
+ ctx->error = CMP_ERROR_LENGTH_WRITING;
return false;
}
@@ -1282,10 +1326,10 @@ bool cmp_write_array32(cmp_ctx_t *ctx, uint32_t size) {
size = be32(size);
- if (ctx->write(ctx, &size, sizeof(uint32_t)))
+ if (ctx->write(ctx, &size, sizeof(uint32_t)) == sizeof(uint32_t))
return true;
- ctx->error = LENGTH_WRITING_ERROR;
+ ctx->error = CMP_ERROR_LENGTH_WRITING;
return false;
}
@@ -1302,7 +1346,7 @@ bool cmp_write_fixmap(cmp_ctx_t *ctx, uint8_t size) {
if (size <= FIXMAP_SIZE)
return write_fixed_value(ctx, FIXMAP_MARKER | size);
- ctx->error = INPUT_VALUE_TOO_LARGE_ERROR;
+ ctx->error = CMP_ERROR_INPUT_VALUE_TOO_LARGE;
return false;
}
@@ -1312,10 +1356,10 @@ bool cmp_write_map16(cmp_ctx_t *ctx, uint16_t size) {
size = be16(size);
- if (ctx->write(ctx, &size, sizeof(uint16_t)))
+ if (ctx->write(ctx, &size, sizeof(uint16_t)) == sizeof(uint16_t))
return true;
- ctx->error = LENGTH_WRITING_ERROR;
+ ctx->error = CMP_ERROR_LENGTH_WRITING;
return false;
}
@@ -1325,10 +1369,10 @@ bool cmp_write_map32(cmp_ctx_t *ctx, uint32_t size) {
size = be32(size);
- if (ctx->write(ctx, &size, sizeof(uint32_t)))
+ if (ctx->write(ctx, &size, sizeof(uint32_t)) == sizeof(uint32_t))
return true;
- ctx->error = LENGTH_WRITING_ERROR;
+ ctx->error = CMP_ERROR_LENGTH_WRITING;
return false;
}
@@ -1345,10 +1389,10 @@ bool cmp_write_fixext1_marker(cmp_ctx_t *ctx, int8_t type) {
if (!write_type_marker(ctx, FIXEXT1_MARKER))
return false;
- if (ctx->write(ctx, &type, sizeof(int8_t)))
+ if (ctx->write(ctx, &type, sizeof(int8_t)) == sizeof(int8_t))
return true;
- ctx->error = EXT_TYPE_WRITING_ERROR;
+ ctx->error = CMP_ERROR_EXT_TYPE_WRITING;
return false;
}
@@ -1356,10 +1400,10 @@ bool cmp_write_fixext1(cmp_ctx_t *ctx, int8_t type, const void *data) {
if (!cmp_write_fixext1_marker(ctx, type))
return false;
- if (ctx->write(ctx, data, 1))
+ if (ctx->write(ctx, data, 1) == 1)
return true;
- ctx->error = DATA_WRITING_ERROR;
+ ctx->error = CMP_ERROR_DATA_WRITING;
return false;
}
@@ -1367,10 +1411,10 @@ bool cmp_write_fixext2_marker(cmp_ctx_t *ctx, int8_t type) {
if (!write_type_marker(ctx, FIXEXT2_MARKER))
return false;
- if (ctx->write(ctx, &type, sizeof(int8_t)))
+ if (ctx->write(ctx, &type, sizeof(int8_t)) == sizeof(int8_t))
return true;
- ctx->error = EXT_TYPE_WRITING_ERROR;
+ ctx->error = CMP_ERROR_EXT_TYPE_WRITING;
return false;
}
@@ -1378,10 +1422,10 @@ bool cmp_write_fixext2(cmp_ctx_t *ctx, int8_t type, const void *data) {
if (!cmp_write_fixext2_marker(ctx, type))
return false;
- if (ctx->write(ctx, data, 2))
+ if (ctx->write(ctx, data, 2) == 2)
return true;
- ctx->error = DATA_WRITING_ERROR;
+ ctx->error = CMP_ERROR_DATA_WRITING;
return false;
}
@@ -1389,10 +1433,10 @@ bool cmp_write_fixext4_marker(cmp_ctx_t *ctx, int8_t type) {
if (!write_type_marker(ctx, FIXEXT4_MARKER))
return false;
- if (ctx->write(ctx, &type, sizeof(int8_t)))
+ if (ctx->write(ctx, &type, sizeof(int8_t)) == sizeof(int8_t))
return true;
- ctx->error = EXT_TYPE_WRITING_ERROR;
+ ctx->error = CMP_ERROR_EXT_TYPE_WRITING;
return false;
}
@@ -1400,10 +1444,10 @@ bool cmp_write_fixext4(cmp_ctx_t *ctx, int8_t type, const void *data) {
if (!cmp_write_fixext4_marker(ctx, type))
return false;
- if (ctx->write(ctx, data, 4))
+ if (ctx->write(ctx, data, 4) == 4)
return true;
- ctx->error = DATA_WRITING_ERROR;
+ ctx->error = CMP_ERROR_DATA_WRITING;
return false;
}
@@ -1411,10 +1455,10 @@ bool cmp_write_fixext8_marker(cmp_ctx_t *ctx, int8_t type) {
if (!write_type_marker(ctx, FIXEXT8_MARKER))
return false;
- if (ctx->write(ctx, &type, sizeof(int8_t)))
+ if (ctx->write(ctx, &type, sizeof(int8_t)) == sizeof(int8_t))
return true;
- ctx->error = EXT_TYPE_WRITING_ERROR;
+ ctx->error = CMP_ERROR_EXT_TYPE_WRITING;
return false;
}
@@ -1422,10 +1466,10 @@ bool cmp_write_fixext8(cmp_ctx_t *ctx, int8_t type, const void *data) {
if (!cmp_write_fixext8_marker(ctx, type))
return false;
- if (ctx->write(ctx, data, 8))
+ if (ctx->write(ctx, data, 8) == 8)
return true;
- ctx->error = DATA_WRITING_ERROR;
+ ctx->error = CMP_ERROR_DATA_WRITING;
return false;
}
@@ -1433,10 +1477,10 @@ bool cmp_write_fixext16_marker(cmp_ctx_t *ctx, int8_t type) {
if (!write_type_marker(ctx, FIXEXT16_MARKER))
return false;
- if (ctx->write(ctx, &type, sizeof(int8_t)))
+ if (ctx->write(ctx, &type, sizeof(int8_t)) == sizeof(int8_t))
return true;
- ctx->error = EXT_TYPE_WRITING_ERROR;
+ ctx->error = CMP_ERROR_EXT_TYPE_WRITING;
return false;
}
@@ -1444,10 +1488,10 @@ bool cmp_write_fixext16(cmp_ctx_t *ctx, int8_t type, const void *data) {
if (!cmp_write_fixext16_marker(ctx, type))
return false;
- if (ctx->write(ctx, data, 16))
+ if (ctx->write(ctx, data, 16) == 16)
return true;
- ctx->error = DATA_WRITING_ERROR;
+ ctx->error = CMP_ERROR_DATA_WRITING;
return false;
}
@@ -1455,15 +1499,15 @@ bool cmp_write_ext8_marker(cmp_ctx_t *ctx, int8_t type, uint8_t size) {
if (!write_type_marker(ctx, EXT8_MARKER))
return false;
- if (!ctx->write(ctx, &size, sizeof(uint8_t))) {
- ctx->error = LENGTH_WRITING_ERROR;
+ if (ctx->write(ctx, &size, sizeof(uint8_t)) != sizeof(uint8_t)) {
+ ctx->error = CMP_ERROR_LENGTH_WRITING;
return false;
}
- if (ctx->write(ctx, &type, sizeof(int8_t)))
+ if (ctx->write(ctx, &type, sizeof(int8_t)) == sizeof(int8_t))
return true;
- ctx->error = EXT_TYPE_WRITING_ERROR;
+ ctx->error = CMP_ERROR_EXT_TYPE_WRITING;
return false;
}
@@ -1471,10 +1515,10 @@ bool cmp_write_ext8(cmp_ctx_t *ctx, int8_t type, uint8_t size, const void *data)
if (!cmp_write_ext8_marker(ctx, type, size))
return false;
- if (ctx->write(ctx, data, size))
+ if (ctx->write(ctx, data, size) == size)
return true;
- ctx->error = DATA_WRITING_ERROR;
+ ctx->error = CMP_ERROR_DATA_WRITING;
return false;
}
@@ -1484,15 +1528,15 @@ bool cmp_write_ext16_marker(cmp_ctx_t *ctx, int8_t type, uint16_t size) {
size = be16(size);
- if (!ctx->write(ctx, &size, sizeof(uint16_t))) {
- ctx->error = LENGTH_WRITING_ERROR;
+ if (ctx->write(ctx, &size, sizeof(uint16_t)) != sizeof(uint16_t)) {
+ ctx->error = CMP_ERROR_LENGTH_WRITING;
return false;
}
- if (ctx->write(ctx, &type, sizeof(int8_t)))
+ if (ctx->write(ctx, &type, sizeof(int8_t)) == sizeof(int8_t))
return true;
- ctx->error = EXT_TYPE_WRITING_ERROR;
+ ctx->error = CMP_ERROR_EXT_TYPE_WRITING;
return false;
}
@@ -1500,10 +1544,10 @@ bool cmp_write_ext16(cmp_ctx_t *ctx, int8_t type, uint16_t size, const void *dat
if (!cmp_write_ext16_marker(ctx, type, size))
return false;
- if (ctx->write(ctx, data, size))
+ if (ctx->write(ctx, data, size) == size)
return true;
- ctx->error = DATA_WRITING_ERROR;
+ ctx->error = CMP_ERROR_DATA_WRITING;
return false;
}
@@ -1513,15 +1557,15 @@ bool cmp_write_ext32_marker(cmp_ctx_t *ctx, int8_t type, uint32_t size) {
size = be32(size);
- if (!ctx->write(ctx, &size, sizeof(uint32_t))) {
- ctx->error = LENGTH_WRITING_ERROR;
+ if (ctx->write(ctx, &size, sizeof(uint32_t)) != sizeof(uint32_t)) {
+ ctx->error = CMP_ERROR_LENGTH_WRITING;
return false;
}
- if (ctx->write(ctx, &type, sizeof(int8_t)))
+ if (ctx->write(ctx, &type, sizeof(int8_t)) == sizeof(int8_t))
return true;
- ctx->error = EXT_TYPE_WRITING_ERROR;
+ ctx->error = CMP_ERROR_EXT_TYPE_WRITING;
return false;
}
@@ -1529,10 +1573,10 @@ bool cmp_write_ext32(cmp_ctx_t *ctx, int8_t type, uint32_t size, const void *dat
if (!cmp_write_ext32_marker(ctx, type, size))
return false;
- if (ctx->write(ctx, data, size))
+ if (ctx->write(ctx, data, size) == size)
return true;
- ctx->error = DATA_WRITING_ERROR;
+ ctx->error = CMP_ERROR_DATA_WRITING;
return false;
}
@@ -1586,10 +1630,11 @@ bool cmp_write_object(cmp_ctx_t *ctx, const cmp_object_t *obj) {
return cmp_write_fixstr_marker(ctx, (uint8_t)obj->as.str_size);
case CMP_TYPE_NIL:
return cmp_write_nil(ctx);
- case CMP_TYPE_BOOLEAN:
+ case CMP_TYPE_BOOLEAN: {
if (obj->as.boolean)
return cmp_write_true(ctx);
return cmp_write_false(ctx);
+ }
case CMP_TYPE_BIN8:
return cmp_write_bin8_marker(ctx, (uint8_t)obj->as.bin_size);
case CMP_TYPE_BIN16:
@@ -1606,20 +1651,22 @@ bool cmp_write_object(cmp_ctx_t *ctx, const cmp_object_t *obj) {
);
case CMP_TYPE_EXT32:
return cmp_write_ext32_marker(ctx, obj->as.ext.type, obj->as.ext.size);
- case CMP_TYPE_FLOAT:
+ case CMP_TYPE_FLOAT: {
#ifndef CMP_NO_FLOAT
return cmp_write_float(ctx, obj->as.flt);
#else /* CMP_NO_FLOAT */
- ctx->error = DISABLED_FLOATING_POINT_ERROR;
+ ctx->error = CMP_ERROR_DISABLED_FLOATING_POINT;
return false;
#endif /* CMP_NO_FLOAT */
- case CMP_TYPE_DOUBLE:
+ }
+ case CMP_TYPE_DOUBLE: {
#ifndef CMP_NO_FLOAT
return cmp_write_double(ctx, obj->as.dbl);
#else /* CMP_NO_FLOAT */
- ctx->error = DISABLED_FLOATING_POINT_ERROR;
+ ctx->error = CMP_ERROR_DISABLED_FLOATING_POINT;
return false;
-#endif
+#endif /* CMP_NO_FLOAT */
+ }
case CMP_TYPE_UINT8:
return cmp_write_u8(ctx, obj->as.u8);
case CMP_TYPE_UINT16:
@@ -1662,9 +1709,10 @@ bool cmp_write_object(cmp_ctx_t *ctx, const cmp_object_t *obj) {
return cmp_write_map32(ctx, obj->as.map_size);
case CMP_TYPE_NEGATIVE_FIXNUM:
return cmp_write_nfix(ctx, obj->as.s8);
- default:
- ctx->error = INVALID_TYPE_ERROR;
+ default: {
+ ctx->error = CMP_ERROR_INVALID_TYPE;
return false;
+ }
}
}
@@ -1680,10 +1728,11 @@ bool cmp_write_object_v4(cmp_ctx_t *ctx, const cmp_object_t *obj) {
return cmp_write_fixstr_marker(ctx, (uint8_t)obj->as.str_size);
case CMP_TYPE_NIL:
return cmp_write_nil(ctx);
- case CMP_TYPE_BOOLEAN:
+ case CMP_TYPE_BOOLEAN: {
if (obj->as.boolean)
return cmp_write_true(ctx);
return cmp_write_false(ctx);
+ }
case CMP_TYPE_EXT8:
return cmp_write_ext8_marker(ctx, obj->as.ext.type, (uint8_t)obj->as.ext.size);
case CMP_TYPE_EXT16:
@@ -1692,20 +1741,22 @@ bool cmp_write_object_v4(cmp_ctx_t *ctx, const cmp_object_t *obj) {
);
case CMP_TYPE_EXT32:
return cmp_write_ext32_marker(ctx, obj->as.ext.type, obj->as.ext.size);
- case CMP_TYPE_FLOAT:
+ case CMP_TYPE_FLOAT: {
#ifndef CMP_NO_FLOAT
return cmp_write_float(ctx, obj->as.flt);
#else /* CMP_NO_FLOAT */
- ctx->error = DISABLED_FLOATING_POINT_ERROR;
+ ctx->error = CMP_ERROR_DISABLED_FLOATING_POINT;
return false;
-#endif
- case CMP_TYPE_DOUBLE:
+#endif /* CMP_NO_FLOAT */
+ }
+ case CMP_TYPE_DOUBLE: {
#ifndef CMP_NO_FLOAT
return cmp_write_double(ctx, obj->as.dbl);
#else
- ctx->error = DISABLED_FLOATING_POINT_ERROR;
+ ctx->error = CMP_ERROR_DISABLED_FLOATING_POINT;
return false;
-#endif
+#endif /* CMP_NO_FLOAT */
+ }
case CMP_TYPE_UINT8:
return cmp_write_u8(ctx, obj->as.u8);
case CMP_TYPE_UINT16:
@@ -1746,9 +1797,10 @@ bool cmp_write_object_v4(cmp_ctx_t *ctx, const cmp_object_t *obj) {
return cmp_write_map32(ctx, obj->as.map_size);
case CMP_TYPE_NEGATIVE_FIXNUM:
return cmp_write_nfix(ctx, obj->as.s8);
- default:
- ctx->error = INVALID_TYPE_ERROR;
+ default: {
+ ctx->error = CMP_ERROR_INVALID_TYPE;
return false;
+ }
}
}
@@ -1759,7 +1811,7 @@ bool cmp_read_pfix(cmp_ctx_t *ctx, uint8_t *c) {
return false;
if (obj.type != CMP_TYPE_POSITIVE_FIXNUM) {
- ctx->error = INVALID_TYPE_ERROR;
+ ctx->error = CMP_ERROR_INVALID_TYPE;
return false;
}
@@ -1774,7 +1826,7 @@ bool cmp_read_nfix(cmp_ctx_t *ctx, int8_t *c) {
return false;
if (obj.type != CMP_TYPE_NEGATIVE_FIXNUM) {
- ctx->error = INVALID_TYPE_ERROR;
+ ctx->error = CMP_ERROR_INVALID_TYPE;
return false;
}
@@ -1790,12 +1842,14 @@ bool cmp_read_sfix(cmp_ctx_t *ctx, int8_t *c) {
switch (obj.type) {
case CMP_TYPE_POSITIVE_FIXNUM:
- case CMP_TYPE_NEGATIVE_FIXNUM:
+ case CMP_TYPE_NEGATIVE_FIXNUM: {
*c = obj.as.s8;
return true;
- default:
- ctx->error = INVALID_TYPE_ERROR;
+ }
+ default: {
+ ctx->error = CMP_ERROR_INVALID_TYPE;
return false;
+ }
}
}
@@ -1806,7 +1860,7 @@ bool cmp_read_s8(cmp_ctx_t *ctx, int8_t *c) {
return false;
if (obj.type != CMP_TYPE_SINT8) {
- ctx->error = INVALID_TYPE_ERROR;
+ ctx->error = CMP_ERROR_INVALID_TYPE;
return false;
}
@@ -1821,7 +1875,7 @@ bool cmp_read_s16(cmp_ctx_t *ctx, int16_t *s) {
return false;
if (obj.type != CMP_TYPE_SINT16) {
- ctx->error = INVALID_TYPE_ERROR;
+ ctx->error = CMP_ERROR_INVALID_TYPE;
return false;
}
@@ -1836,7 +1890,7 @@ bool cmp_read_s32(cmp_ctx_t *ctx, int32_t *i) {
return false;
if (obj.type != CMP_TYPE_SINT32) {
- ctx->error = INVALID_TYPE_ERROR;
+ ctx->error = CMP_ERROR_INVALID_TYPE;
return false;
}
@@ -1851,7 +1905,7 @@ bool cmp_read_s64(cmp_ctx_t *ctx, int64_t *l) {
return false;
if (obj.type != CMP_TYPE_SINT64) {
- ctx->error = INVALID_TYPE_ERROR;
+ ctx->error = CMP_ERROR_INVALID_TYPE;
return false;
}
@@ -1868,20 +1922,22 @@ bool cmp_read_char(cmp_ctx_t *ctx, int8_t *c) {
switch (obj.type) {
case CMP_TYPE_POSITIVE_FIXNUM:
case CMP_TYPE_NEGATIVE_FIXNUM:
- case CMP_TYPE_SINT8:
+ case CMP_TYPE_SINT8: {
*c = obj.as.s8;
return true;
- case CMP_TYPE_UINT8:
+ }
+ case CMP_TYPE_UINT8: {
if (obj.as.u8 <= 127) {
*c = (int8_t)obj.as.u8;
return true;
}
break;
+ }
default:
break;
}
- ctx->error = INVALID_TYPE_ERROR;
+ ctx->error = CMP_ERROR_INVALID_TYPE;
return false;
}
@@ -1894,26 +1950,30 @@ bool cmp_read_short(cmp_ctx_t *ctx, int16_t *s) {
switch (obj.type) {
case CMP_TYPE_POSITIVE_FIXNUM:
case CMP_TYPE_NEGATIVE_FIXNUM:
- case CMP_TYPE_SINT8:
+ case CMP_TYPE_SINT8: {
*s = obj.as.s8;
return true;
- case CMP_TYPE_UINT8:
+ }
+ case CMP_TYPE_UINT8: {
*s = obj.as.u8;
return true;
- case CMP_TYPE_SINT16:
+ }
+ case CMP_TYPE_SINT16: {
*s = obj.as.s16;
return true;
- case CMP_TYPE_UINT16:
- if (obj.as.u16 <= 32767) {
+ }
+ case CMP_TYPE_UINT16: {
+ if (obj.as.u16 <= 0x7fff) {
*s = (int16_t)obj.as.u16;
return true;
}
break;
+ }
default:
break;
}
- ctx->error = INVALID_TYPE_ERROR;
+ ctx->error = CMP_ERROR_INVALID_TYPE;
return false;
}
@@ -1926,32 +1986,38 @@ bool cmp_read_int(cmp_ctx_t *ctx, int32_t *i) {
switch (obj.type) {
case CMP_TYPE_POSITIVE_FIXNUM:
case CMP_TYPE_NEGATIVE_FIXNUM:
- case CMP_TYPE_SINT8:
+ case CMP_TYPE_SINT8: {
*i = obj.as.s8;
return true;
- case CMP_TYPE_UINT8:
+ }
+ case CMP_TYPE_UINT8: {
*i = obj.as.u8;
return true;
- case CMP_TYPE_SINT16:
+ }
+ case CMP_TYPE_SINT16: {
*i = obj.as.s16;
return true;
- case CMP_TYPE_UINT16:
+ }
+ case CMP_TYPE_UINT16: {
*i = obj.as.u16;
return true;
- case CMP_TYPE_SINT32:
+ }
+ case CMP_TYPE_SINT32: {
*i = obj.as.s32;
return true;
- case CMP_TYPE_UINT32:
- if (obj.as.u32 <= 2147483647) {
+ }
+ case CMP_TYPE_UINT32: {
+ if (obj.as.u32 <= 0x7fffffff) {
*i = (int32_t)obj.as.u32;
return true;
}
break;
+ }
default:
break;
}
- ctx->error = INVALID_TYPE_ERROR;
+ ctx->error = CMP_ERROR_INVALID_TYPE;
return false;
}
@@ -1964,38 +2030,46 @@ bool cmp_read_long(cmp_ctx_t *ctx, int64_t *d) {
switch (obj.type) {
case CMP_TYPE_POSITIVE_FIXNUM:
case CMP_TYPE_NEGATIVE_FIXNUM:
- case CMP_TYPE_SINT8:
+ case CMP_TYPE_SINT8: {
*d = obj.as.s8;
return true;
- case CMP_TYPE_UINT8:
+ }
+ case CMP_TYPE_UINT8: {
*d = obj.as.u8;
return true;
- case CMP_TYPE_SINT16:
+ }
+ case CMP_TYPE_SINT16: {
*d = obj.as.s16;
return true;
- case CMP_TYPE_UINT16:
+ }
+ case CMP_TYPE_UINT16: {
*d = obj.as.u16;
return true;
- case CMP_TYPE_SINT32:
+ }
+ case CMP_TYPE_SINT32: {
*d = obj.as.s32;
return true;
- case CMP_TYPE_UINT32:
+ }
+ case CMP_TYPE_UINT32: {
*d = obj.as.u32;
return true;
- case CMP_TYPE_SINT64:
+ }
+ case CMP_TYPE_SINT64: {
*d = obj.as.s64;
return true;
- case CMP_TYPE_UINT64:
- if (obj.as.u64 <= 9223372036854775807) {
+ }
+ case CMP_TYPE_UINT64: {
+ if (obj.as.u64 <= UINT64_C(0x7fffffffffffffff)) {
*d = (int64_t)obj.as.u64;
return true;
}
break;
+ }
default:
break;
}
- ctx->error = INVALID_TYPE_ERROR;
+ ctx->error = CMP_ERROR_INVALID_TYPE;
return false;
}
@@ -2014,7 +2088,7 @@ bool cmp_read_u8(cmp_ctx_t *ctx, uint8_t *c) {
return false;
if (obj.type != CMP_TYPE_UINT8) {
- ctx->error = INVALID_TYPE_ERROR;
+ ctx->error = CMP_ERROR_INVALID_TYPE;
return false;
}
@@ -2029,7 +2103,7 @@ bool cmp_read_u16(cmp_ctx_t *ctx, uint16_t *s) {
return false;
if (obj.type != CMP_TYPE_UINT16) {
- ctx->error = INVALID_TYPE_ERROR;
+ ctx->error = CMP_ERROR_INVALID_TYPE;
return false;
}
@@ -2044,7 +2118,7 @@ bool cmp_read_u32(cmp_ctx_t *ctx, uint32_t *i) {
return false;
if (obj.type != CMP_TYPE_UINT32) {
- ctx->error = INVALID_TYPE_ERROR;
+ ctx->error = CMP_ERROR_INVALID_TYPE;
return false;
}
@@ -2059,7 +2133,7 @@ bool cmp_read_u64(cmp_ctx_t *ctx, uint64_t *l) {
return false;
if (obj.type != CMP_TYPE_UINT64) {
- ctx->error = INVALID_TYPE_ERROR;
+ ctx->error = CMP_ERROR_INVALID_TYPE;
return false;
}
@@ -2075,21 +2149,23 @@ bool cmp_read_uchar(cmp_ctx_t *ctx, uint8_t *c) {
switch (obj.type) {
case CMP_TYPE_POSITIVE_FIXNUM:
- case CMP_TYPE_UINT8:
+ case CMP_TYPE_UINT8: {
*c = obj.as.u8;
return true;
+ }
case CMP_TYPE_NEGATIVE_FIXNUM:
- case CMP_TYPE_SINT8:
+ case CMP_TYPE_SINT8: {
if (obj.as.s8 >= 0) {
*c = (uint8_t)obj.as.s8;
return true;
}
break;
+ }
default:
break;
}
- ctx->error = INVALID_TYPE_ERROR;
+ ctx->error = CMP_ERROR_INVALID_TYPE;
return false;
}
@@ -2101,30 +2177,34 @@ bool cmp_read_ushort(cmp_ctx_t *ctx, uint16_t *s) {
switch (obj.type) {
case CMP_TYPE_POSITIVE_FIXNUM:
- case CMP_TYPE_UINT8:
+ case CMP_TYPE_UINT8: {
*s = obj.as.u8;
return true;
- case CMP_TYPE_UINT16:
+ }
+ case CMP_TYPE_UINT16: {
*s = obj.as.u16;
return true;
+ }
case CMP_TYPE_NEGATIVE_FIXNUM:
- case CMP_TYPE_SINT8:
+ case CMP_TYPE_SINT8: {
if (obj.as.s8 >= 0) {
*s = (uint8_t)obj.as.s8;
return true;
}
break;
- case CMP_TYPE_SINT16:
+ }
+ case CMP_TYPE_SINT16: {
if (obj.as.s16 >= 0) {
*s = (uint16_t)obj.as.s16;
return true;
}
break;
+ }
default:
break;
}
- ctx->error = INVALID_TYPE_ERROR;
+ ctx->error = CMP_ERROR_INVALID_TYPE;
return false;
}
@@ -2136,39 +2216,45 @@ bool cmp_read_uint(cmp_ctx_t *ctx, uint32_t *i) {
switch (obj.type) {
case CMP_TYPE_POSITIVE_FIXNUM:
- case CMP_TYPE_UINT8:
+ case CMP_TYPE_UINT8: {
*i = obj.as.u8;
return true;
- case CMP_TYPE_UINT16:
+ }
+ case CMP_TYPE_UINT16: {
*i = obj.as.u16;
return true;
- case CMP_TYPE_UINT32:
+ }
+ case CMP_TYPE_UINT32: {
*i = obj.as.u32;
return true;
+ }
case CMP_TYPE_NEGATIVE_FIXNUM:
- case CMP_TYPE_SINT8:
+ case CMP_TYPE_SINT8: {
if (obj.as.s8 >= 0) {
*i = (uint8_t)obj.as.s8;
return true;
}
break;
- case CMP_TYPE_SINT16:
+ }
+ case CMP_TYPE_SINT16: {
if (obj.as.s16 >= 0) {
*i = (uint16_t)obj.as.s16;
return true;
}
break;
- case CMP_TYPE_SINT32:
+ }
+ case CMP_TYPE_SINT32: {
if (obj.as.s32 >= 0) {
*i = (uint32_t)obj.as.s32;
return true;
}
break;
+ }
default:
break;
}
- ctx->error = INVALID_TYPE_ERROR;
+ ctx->error = CMP_ERROR_INVALID_TYPE;
return false;
}
@@ -2180,48 +2266,56 @@ bool cmp_read_ulong(cmp_ctx_t *ctx, uint64_t *u) {
switch (obj.type) {
case CMP_TYPE_POSITIVE_FIXNUM:
- case CMP_TYPE_UINT8:
+ case CMP_TYPE_UINT8: {
*u = obj.as.u8;
return true;
- case CMP_TYPE_UINT16:
+ }
+ case CMP_TYPE_UINT16: {
*u = obj.as.u16;
return true;
- case CMP_TYPE_UINT32:
+ }
+ case CMP_TYPE_UINT32: {
*u = obj.as.u32;
return true;
- case CMP_TYPE_UINT64:
+ }
+ case CMP_TYPE_UINT64: {
*u = obj.as.u64;
return true;
+ }
case CMP_TYPE_NEGATIVE_FIXNUM:
- case CMP_TYPE_SINT8:
+ case CMP_TYPE_SINT8: {
if (obj.as.s8 >= 0) {
*u = (uint8_t)obj.as.s8;
return true;
}
break;
- case CMP_TYPE_SINT16:
+ }
+ case CMP_TYPE_SINT16: {
if (obj.as.s16 >= 0) {
*u = (uint16_t)obj.as.s16;
return true;
}
break;
- case CMP_TYPE_SINT32:
+ }
+ case CMP_TYPE_SINT32: {
if (obj.as.s32 >= 0) {
*u = (uint32_t)obj.as.s32;
return true;
}
break;
- case CMP_TYPE_SINT64:
+ }
+ case CMP_TYPE_SINT64: {
if (obj.as.s64 >= 0) {
*u = (uint64_t)obj.as.s64;
return true;
}
break;
+ }
default:
break;
}
- ctx->error = INVALID_TYPE_ERROR;
+ ctx->error = CMP_ERROR_INVALID_TYPE;
return false;
}
@@ -2237,7 +2331,7 @@ bool cmp_read_float(cmp_ctx_t *ctx, float *f) {
return false;
if (obj.type != CMP_TYPE_FLOAT) {
- ctx->error = INVALID_TYPE_ERROR;
+ ctx->error = CMP_ERROR_INVALID_TYPE;
return false;
}
@@ -2253,7 +2347,7 @@ bool cmp_read_double(cmp_ctx_t *ctx, double *d) {
return false;
if (obj.type != CMP_TYPE_DOUBLE) {
- ctx->error = INVALID_TYPE_ERROR;
+ ctx->error = CMP_ERROR_INVALID_TYPE;
return false;
}
@@ -2269,15 +2363,18 @@ bool cmp_read_decimal(cmp_ctx_t *ctx, double *d) {
return false;
switch (obj.type) {
- case CMP_TYPE_FLOAT:
+ case CMP_TYPE_FLOAT: {
*d = (double)obj.as.flt;
return true;
- case CMP_TYPE_DOUBLE:
+ }
+ case CMP_TYPE_DOUBLE: {
*d = obj.as.dbl;
return true;
- default:
- ctx->error = INVALID_TYPE_ERROR;
+ }
+ default: {
+ ctx->error = CMP_ERROR_INVALID_TYPE;
return false;
+ }
}
}
#endif /* CMP_NO_FLOAT */
@@ -2291,7 +2388,7 @@ bool cmp_read_nil(cmp_ctx_t *ctx) {
if (obj.type == CMP_TYPE_NIL)
return true;
- ctx->error = INVALID_TYPE_ERROR;
+ ctx->error = CMP_ERROR_INVALID_TYPE;
return false;
}
@@ -2302,14 +2399,15 @@ bool cmp_read_bool(cmp_ctx_t *ctx, bool *b) {
return false;
if (obj.type != CMP_TYPE_BOOLEAN) {
- ctx->error = INVALID_TYPE_ERROR;
+ ctx->error = CMP_ERROR_INVALID_TYPE;
return false;
}
- if (obj.as.boolean)
+ if (obj.as.boolean) {
*b = true;
- else
+ } else {
*b = false;
+ }
return true;
}
@@ -2321,14 +2419,15 @@ bool cmp_read_bool_as_u8(cmp_ctx_t *ctx, uint8_t *b) {
return false;
if (obj.type != CMP_TYPE_BOOLEAN) {
- ctx->error = INVALID_TYPE_ERROR;
+ ctx->error = CMP_ERROR_INVALID_TYPE;
return false;
}
- if (obj.as.boolean)
+ if (obj.as.boolean) {
*b = 1;
- else
+ } else {
*b = 0;
+ }
return true;
}
@@ -2343,12 +2442,14 @@ bool cmp_read_str_size(cmp_ctx_t *ctx, uint32_t *size) {
case CMP_TYPE_FIXSTR:
case CMP_TYPE_STR8:
case CMP_TYPE_STR16:
- case CMP_TYPE_STR32:
+ case CMP_TYPE_STR32: {
*size = obj.as.str_size;
return true;
- default:
- ctx->error = INVALID_TYPE_ERROR;
+ }
+ default: {
+ ctx->error = CMP_ERROR_INVALID_TYPE;
return false;
+ }
}
}
@@ -2360,12 +2461,12 @@ bool cmp_read_str(cmp_ctx_t *ctx, char *data, uint32_t *size) {
if (str_size >= *size) {
*size = str_size;
- ctx->error = STR_DATA_LENGTH_TOO_LONG_ERROR;
+ ctx->error = CMP_ERROR_STR_DATA_LENGTH_TOO_LONG;
return false;
}
if (!ctx->read(ctx, data, str_size)) {
- ctx->error = DATA_READING_ERROR;
+ ctx->error = CMP_ERROR_DATA_READING;
return false;
}
@@ -2384,12 +2485,14 @@ bool cmp_read_bin_size(cmp_ctx_t *ctx, uint32_t *size) {
switch (obj.type) {
case CMP_TYPE_BIN8:
case CMP_TYPE_BIN16:
- case CMP_TYPE_BIN32:
+ case CMP_TYPE_BIN32: {
*size = obj.as.bin_size;
return true;
- default:
- ctx->error = INVALID_TYPE_ERROR;
+ }
+ default: {
+ ctx->error = CMP_ERROR_INVALID_TYPE;
return false;
+ }
}
}
@@ -2400,12 +2503,12 @@ bool cmp_read_bin(cmp_ctx_t *ctx, void *data, uint32_t *size) {
return false;
if (bin_size > *size) {
- ctx->error = BIN_DATA_LENGTH_TOO_LONG_ERROR;
+ ctx->error = CMP_ERROR_BIN_DATA_LENGTH_TOO_LONG;
return false;
}
if (!ctx->read(ctx, data, bin_size)) {
- ctx->error = DATA_READING_ERROR;
+ ctx->error = CMP_ERROR_DATA_READING;
return false;
}
@@ -2422,12 +2525,14 @@ bool cmp_read_array(cmp_ctx_t *ctx, uint32_t *size) {
switch (obj.type) {
case CMP_TYPE_FIXARRAY:
case CMP_TYPE_ARRAY16:
- case CMP_TYPE_ARRAY32:
+ case CMP_TYPE_ARRAY32: {
*size = obj.as.array_size;
return true;
- default:
- ctx->error = INVALID_TYPE_ERROR;
+ }
+ default: {
+ ctx->error = CMP_ERROR_INVALID_TYPE;
return false;
+ }
}
}
@@ -2440,12 +2545,14 @@ bool cmp_read_map(cmp_ctx_t *ctx, uint32_t *size) {
switch (obj.type) {
case CMP_TYPE_FIXMAP:
case CMP_TYPE_MAP16:
- case CMP_TYPE_MAP32:
+ case CMP_TYPE_MAP32: {
*size = obj.as.map_size;
return true;
- default:
- ctx->error = INVALID_TYPE_ERROR;
+ }
+ default: {
+ ctx->error = CMP_ERROR_INVALID_TYPE;
return false;
+ }
}
}
@@ -2456,7 +2563,7 @@ bool cmp_read_fixext1_marker(cmp_ctx_t *ctx, int8_t *type) {
return false;
if (obj.type != CMP_TYPE_FIXEXT1) {
- ctx->error = INVALID_TYPE_ERROR;
+ ctx->error = CMP_ERROR_INVALID_TYPE;
return false;
}
@@ -2471,7 +2578,7 @@ bool cmp_read_fixext1(cmp_ctx_t *ctx, int8_t *type, void *data) {
if (ctx->read(ctx, data, 1))
return true;
- ctx->error = DATA_READING_ERROR;
+ ctx->error = CMP_ERROR_DATA_READING;
return false;
}
@@ -2482,7 +2589,7 @@ bool cmp_read_fixext2_marker(cmp_ctx_t *ctx, int8_t *type) {
return false;
if (obj.type != CMP_TYPE_FIXEXT2) {
- ctx->error = INVALID_TYPE_ERROR;
+ ctx->error = CMP_ERROR_INVALID_TYPE;
return false;
}
@@ -2497,7 +2604,7 @@ bool cmp_read_fixext2(cmp_ctx_t *ctx, int8_t *type, void *data) {
if (ctx->read(ctx, data, 2))
return true;
- ctx->error = DATA_READING_ERROR;
+ ctx->error = CMP_ERROR_DATA_READING;
return false;
}
@@ -2508,7 +2615,7 @@ bool cmp_read_fixext4_marker(cmp_ctx_t *ctx, int8_t *type) {
return false;
if (obj.type != CMP_TYPE_FIXEXT4) {
- ctx->error = INVALID_TYPE_ERROR;
+ ctx->error = CMP_ERROR_INVALID_TYPE;
return false;
}
@@ -2523,7 +2630,7 @@ bool cmp_read_fixext4(cmp_ctx_t *ctx, int8_t *type, void *data) {
if (ctx->read(ctx, data, 4))
return true;
- ctx->error = DATA_READING_ERROR;
+ ctx->error = CMP_ERROR_DATA_READING;
return false;
}
@@ -2534,7 +2641,7 @@ bool cmp_read_fixext8_marker(cmp_ctx_t *ctx, int8_t *type) {
return false;
if (obj.type != CMP_TYPE_FIXEXT8) {
- ctx->error = INVALID_TYPE_ERROR;
+ ctx->error = CMP_ERROR_INVALID_TYPE;
return false;
}
@@ -2549,7 +2656,7 @@ bool cmp_read_fixext8(cmp_ctx_t *ctx, int8_t *type, void *data) {
if (ctx->read(ctx, data, 8))
return true;
- ctx->error = DATA_READING_ERROR;
+ ctx->error = CMP_ERROR_DATA_READING;
return false;
}
@@ -2560,7 +2667,7 @@ bool cmp_read_fixext16_marker(cmp_ctx_t *ctx, int8_t *type) {
return false;
if (obj.type != CMP_TYPE_FIXEXT16) {
- ctx->error = INVALID_TYPE_ERROR;
+ ctx->error = CMP_ERROR_INVALID_TYPE;
return false;
}
@@ -2575,7 +2682,7 @@ bool cmp_read_fixext16(cmp_ctx_t *ctx, int8_t *type, void *data) {
if (ctx->read(ctx, data, 16))
return true;
- ctx->error = DATA_READING_ERROR;
+ ctx->error = CMP_ERROR_DATA_READING;
return false;
}
@@ -2586,7 +2693,7 @@ bool cmp_read_ext8_marker(cmp_ctx_t *ctx, int8_t *type, uint8_t *size) {
return false;
if (obj.type != CMP_TYPE_EXT8) {
- ctx->error = INVALID_TYPE_ERROR;
+ ctx->error = CMP_ERROR_INVALID_TYPE;
return false;
}
@@ -2603,7 +2710,7 @@ bool cmp_read_ext8(cmp_ctx_t *ctx, int8_t *type, uint8_t *size, void *data) {
if (ctx->read(ctx, data, *size))
return true;
- ctx->error = DATA_READING_ERROR;
+ ctx->error = CMP_ERROR_DATA_READING;
return false;
}
@@ -2614,7 +2721,7 @@ bool cmp_read_ext16_marker(cmp_ctx_t *ctx, int8_t *type, uint16_t *size) {
return false;
if (obj.type != CMP_TYPE_EXT16) {
- ctx->error = INVALID_TYPE_ERROR;
+ ctx->error = CMP_ERROR_INVALID_TYPE;
return false;
}
@@ -2631,7 +2738,7 @@ bool cmp_read_ext16(cmp_ctx_t *ctx, int8_t *type, uint16_t *size, void *data) {
if (ctx->read(ctx, data, *size))
return true;
- ctx->error = DATA_READING_ERROR;
+ ctx->error = CMP_ERROR_DATA_READING;
return false;
}
@@ -2642,7 +2749,7 @@ bool cmp_read_ext32_marker(cmp_ctx_t *ctx, int8_t *type, uint32_t *size) {
return false;
if (obj.type != CMP_TYPE_EXT32) {
- ctx->error = INVALID_TYPE_ERROR;
+ ctx->error = CMP_ERROR_INVALID_TYPE;
return false;
}
@@ -2659,7 +2766,7 @@ bool cmp_read_ext32(cmp_ctx_t *ctx, int8_t *type, uint32_t *size, void *data) {
if (ctx->read(ctx, data, *size))
return true;
- ctx->error = DATA_READING_ERROR;
+ ctx->error = CMP_ERROR_DATA_READING;
return false;
}
@@ -2677,13 +2784,15 @@ bool cmp_read_ext_marker(cmp_ctx_t *ctx, int8_t *type, uint32_t *size) {
case CMP_TYPE_FIXEXT16:
case CMP_TYPE_EXT8:
case CMP_TYPE_EXT16:
- case CMP_TYPE_EXT32:
+ case CMP_TYPE_EXT32: {
*type = obj.as.ext.type;
*size = obj.as.ext.size;
return true;
- default:
- ctx->error = INVALID_TYPE_ERROR;
+ }
+ default: {
+ ctx->error = CMP_ERROR_INVALID_TYPE;
return false;
+ }
}
}
@@ -2694,7 +2803,7 @@ bool cmp_read_ext(cmp_ctx_t *ctx, int8_t *type, uint32_t *size, void *data) {
if (ctx->read(ctx, data, *size))
return true;
- ctx->error = DATA_READING_ERROR;
+ ctx->error = CMP_ERROR_DATA_READING;
return false;
}
@@ -2705,7 +2814,7 @@ bool cmp_read_object(cmp_ctx_t *ctx, cmp_object_t *obj) {
return false;
if (!type_marker_to_cmp_type(type_marker, &obj->type)) {
- ctx->error = INVALID_TYPE_ERROR;
+ ctx->error = CMP_ERROR_INVALID_TYPE;
return false;
}
@@ -2722,7 +2831,7 @@ bool cmp_skip_object(cmp_ctx_t *ctx, cmp_object_t *obj) {
}
if (!type_marker_to_cmp_type(type_marker, &cmp_type)) {
- ctx->error = INVALID_TYPE_ERROR;
+ ctx->error = CMP_ERROR_INVALID_TYPE;
return false;
}
@@ -2732,22 +2841,23 @@ bool cmp_skip_object(cmp_ctx_t *ctx, cmp_object_t *obj) {
case CMP_TYPE_ARRAY32:
case CMP_TYPE_FIXMAP:
case CMP_TYPE_MAP16:
- case CMP_TYPE_MAP32:
+ case CMP_TYPE_MAP32: {
obj->type = cmp_type;
if (!read_obj_data(ctx, type_marker, obj)) {
return false;
}
- ctx->error = SKIP_DEPTH_LIMIT_EXCEEDED_ERROR;
+ ctx->error = CMP_ERROR_SKIP_DEPTH_LIMIT_EXCEEDED;
return false;
- default:
+ }
+ default: {
if (!read_type_size(ctx, type_marker, cmp_type, &size)) {
return false;
}
- if (size) {
+ if (size != 0) {
switch (cmp_type) {
case CMP_TYPE_FIXEXT1:
case CMP_TYPE_FIXEXT2:
@@ -2756,15 +2866,17 @@ bool cmp_skip_object(cmp_ctx_t *ctx, cmp_object_t *obj) {
case CMP_TYPE_FIXEXT16:
case CMP_TYPE_EXT8:
case CMP_TYPE_EXT16:
- case CMP_TYPE_EXT32:
- size++;
+ case CMP_TYPE_EXT32: {
+ ++size;
break;
+ }
default:
break;
}
skip_bytes(ctx, size);
}
+ }
}
return true;
@@ -2774,7 +2886,7 @@ bool cmp_skip_object_flat(cmp_ctx_t *ctx, cmp_object_t *obj) {
size_t element_count = 1;
bool in_container = false;
- while (element_count) {
+ while (element_count != 0) {
uint8_t type_marker = 0;
uint8_t cmp_type;
uint32_t size = 0;
@@ -2784,7 +2896,7 @@ bool cmp_skip_object_flat(cmp_ctx_t *ctx, cmp_object_t *obj) {
}
if (!type_marker_to_cmp_type(type_marker, &cmp_type)) {
- ctx->error = INVALID_TYPE_ERROR;
+ ctx->error = CMP_ERROR_INVALID_TYPE;
return false;
}
@@ -2794,7 +2906,7 @@ bool cmp_skip_object_flat(cmp_ctx_t *ctx, cmp_object_t *obj) {
case CMP_TYPE_ARRAY32:
case CMP_TYPE_FIXMAP:
case CMP_TYPE_MAP16:
- case CMP_TYPE_MAP32:
+ case CMP_TYPE_MAP32: {
if (in_container) {
obj->type = cmp_type;
@@ -2802,19 +2914,20 @@ bool cmp_skip_object_flat(cmp_ctx_t *ctx, cmp_object_t *obj) {
return false;
}
- ctx->error = SKIP_DEPTH_LIMIT_EXCEEDED_ERROR;
+ ctx->error = CMP_ERROR_SKIP_DEPTH_LIMIT_EXCEEDED;
return false;
}
in_container = true;
break;
- default:
+ }
+ default: {
if (!read_type_size(ctx, type_marker, cmp_type, &size)) {
return false;
}
- if (size) {
+ if (size != 0) {
switch (cmp_type) {
case CMP_TYPE_FIXEXT1:
case CMP_TYPE_FIXEXT2:
@@ -2823,36 +2936,40 @@ bool cmp_skip_object_flat(cmp_ctx_t *ctx, cmp_object_t *obj) {
case CMP_TYPE_FIXEXT16:
case CMP_TYPE_EXT8:
case CMP_TYPE_EXT16:
- case CMP_TYPE_EXT32:
- size++;
+ case CMP_TYPE_EXT32: {
+ ++size;
break;
+ }
default:
break;
}
skip_bytes(ctx, size);
}
+ }
}
- element_count--;
+ --element_count;
switch (cmp_type) {
case CMP_TYPE_FIXARRAY:
case CMP_TYPE_ARRAY16:
- case CMP_TYPE_ARRAY32:
+ case CMP_TYPE_ARRAY32: {
if (!read_type_size(ctx, type_marker, cmp_type, &size)) {
return false;
}
element_count += size;
break;
+ }
case CMP_TYPE_FIXMAP:
case CMP_TYPE_MAP16:
- case CMP_TYPE_MAP32:
+ case CMP_TYPE_MAP32: {
if (!read_type_size(ctx, type_marker, cmp_type, &size)) {
return false;
}
element_count += ((size_t)size) * 2;
break;
+ }
default:
break;
}
@@ -2864,7 +2981,7 @@ bool cmp_skip_object_flat(cmp_ctx_t *ctx, cmp_object_t *obj) {
bool cmp_skip_object_no_limit(cmp_ctx_t *ctx) {
size_t element_count = 1;
- while (element_count) {
+ while (element_count != 0) {
uint8_t type_marker = 0;
uint8_t cmp_type = 0;
uint32_t size = 0;
@@ -2874,7 +2991,7 @@ bool cmp_skip_object_no_limit(cmp_ctx_t *ctx) {
}
if (!type_marker_to_cmp_type(type_marker, &cmp_type)) {
- ctx->error = INVALID_TYPE_ERROR;
+ ctx->error = CMP_ERROR_INVALID_TYPE;
return false;
}
@@ -2886,12 +3003,12 @@ bool cmp_skip_object_no_limit(cmp_ctx_t *ctx) {
case CMP_TYPE_MAP16:
case CMP_TYPE_MAP32:
break;
- default:
+ default: {
if (!read_type_size(ctx, type_marker, cmp_type, &size)) {
return false;
}
- if (size) {
+ if (size != 0) {
switch (cmp_type) {
case CMP_TYPE_FIXEXT1:
case CMP_TYPE_FIXEXT2:
@@ -2900,128 +3017,40 @@ bool cmp_skip_object_no_limit(cmp_ctx_t *ctx) {
case CMP_TYPE_FIXEXT16:
case CMP_TYPE_EXT8:
case CMP_TYPE_EXT16:
- case CMP_TYPE_EXT32:
- size++;
+ case CMP_TYPE_EXT32: {
+ ++size;
break;
+ }
default:
break;
}
skip_bytes(ctx, size);
}
+ }
}
- element_count--;
-
- switch (cmp_type) {
- case CMP_TYPE_FIXARRAY:
- case CMP_TYPE_ARRAY16:
- case CMP_TYPE_ARRAY32:
- if (!read_type_size(ctx, type_marker, cmp_type, &size)) {
- return false;
- }
- element_count += size;
- break;
- case CMP_TYPE_FIXMAP:
- case CMP_TYPE_MAP16:
- case CMP_TYPE_MAP32:
- if (!read_type_size(ctx, type_marker, cmp_type, &size)) {
- return false;
- }
- element_count += ((size_t)size) * 2;
- break;
- default:
- break;
- }
- }
-
- return true;
-}
-
-bool cmp_skip_object_limit(cmp_ctx_t *ctx, cmp_object_t *obj, uint32_t limit) {
- size_t element_count = 1;
- uint32_t depth = 0;
-
- while (element_count) {
- uint8_t type_marker = 0;
- uint8_t cmp_type;
- uint32_t size = 0;
-
- if (!read_type_marker(ctx, &type_marker)) {
- return false;
- }
-
- if (!type_marker_to_cmp_type(type_marker, &cmp_type)) {
- ctx->error = INVALID_TYPE_ERROR;
- return false;
- }
-
- switch (cmp_type) {
- case CMP_TYPE_FIXARRAY:
- case CMP_TYPE_ARRAY16:
- case CMP_TYPE_ARRAY32:
- case CMP_TYPE_FIXMAP:
- case CMP_TYPE_MAP16:
- case CMP_TYPE_MAP32:
- depth++;
-
- if (depth > limit) {
- obj->type = cmp_type;
-
- if (!read_obj_data(ctx, type_marker, obj)) {
- return false;
- }
-
- ctx->error = SKIP_DEPTH_LIMIT_EXCEEDED_ERROR;
-
- return false;
- }
-
- break;
- default:
- if (!read_type_size(ctx, type_marker, cmp_type, &size)) {
- return false;
- }
-
- if (size) {
- switch (cmp_type) {
- case CMP_TYPE_FIXEXT1:
- case CMP_TYPE_FIXEXT2:
- case CMP_TYPE_FIXEXT4:
- case CMP_TYPE_FIXEXT8:
- case CMP_TYPE_FIXEXT16:
- case CMP_TYPE_EXT8:
- case CMP_TYPE_EXT16:
- case CMP_TYPE_EXT32:
- size++;
- break;
- default:
- break;
- }
-
- skip_bytes(ctx, size);
- }
- }
-
- element_count--;
+ --element_count;
switch (cmp_type) {
case CMP_TYPE_FIXARRAY:
case CMP_TYPE_ARRAY16:
- case CMP_TYPE_ARRAY32:
+ case CMP_TYPE_ARRAY32: {
if (!read_type_size(ctx, type_marker, cmp_type, &size)) {
return false;
}
element_count += size;
break;
+ }
case CMP_TYPE_FIXMAP:
case CMP_TYPE_MAP16:
- case CMP_TYPE_MAP32:
+ case CMP_TYPE_MAP32: {
if (!read_type_size(ctx, type_marker, cmp_type, &size)) {
return false;
}
element_count += ((size_t)size) * 2;
break;
+ }
default:
break;
}
@@ -3224,10 +3253,11 @@ bool cmp_object_as_char(const cmp_object_t *obj, int8_t *c) {
switch (obj->type) {
case CMP_TYPE_POSITIVE_FIXNUM:
case CMP_TYPE_NEGATIVE_FIXNUM:
- case CMP_TYPE_SINT8:
+ case CMP_TYPE_SINT8: {
*c = obj->as.s8;
return true;
- case CMP_TYPE_UINT8:
+ }
+ case CMP_TYPE_UINT8: {
if (obj->as.u8 <= 127) {
*c = obj->as.s8;
return true;
@@ -3235,8 +3265,9 @@ bool cmp_object_as_char(const cmp_object_t *obj, int8_t *c) {
else {
return false;
}
+ }
default:
- return false;
+ return false;
}
}
@@ -3244,25 +3275,29 @@ bool cmp_object_as_short(const cmp_object_t *obj, int16_t *s) {
switch (obj->type) {
case CMP_TYPE_POSITIVE_FIXNUM:
case CMP_TYPE_NEGATIVE_FIXNUM:
- case CMP_TYPE_SINT8:
+ case CMP_TYPE_SINT8: {
*s = obj->as.s8;
return true;
- case CMP_TYPE_UINT8:
+ }
+ case CMP_TYPE_UINT8: {
*s = obj->as.u8;
return true;
- case CMP_TYPE_SINT16:
+ }
+ case CMP_TYPE_SINT16: {
*s = obj->as.s16;
return true;
- case CMP_TYPE_UINT16:
- if (obj->as.u16 <= 32767) {
+ }
+ case CMP_TYPE_UINT16: {
+ if (obj->as.u16 <= 0x7fff) {
*s = (int16_t)obj->as.u16;
return true;
}
else {
return false;
}
+ }
default:
- return false;
+ return false;
}
}
@@ -3270,31 +3305,37 @@ bool cmp_object_as_int(const cmp_object_t *obj, int32_t *i) {
switch (obj->type) {
case CMP_TYPE_POSITIVE_FIXNUM:
case CMP_TYPE_NEGATIVE_FIXNUM:
- case CMP_TYPE_SINT8:
+ case CMP_TYPE_SINT8: {
*i = obj->as.s8;
return true;
- case CMP_TYPE_UINT8:
+ }
+ case CMP_TYPE_UINT8: {
*i = obj->as.u8;
return true;
- case CMP_TYPE_SINT16:
+ }
+ case CMP_TYPE_SINT16: {
*i = obj->as.s16;
return true;
- case CMP_TYPE_UINT16:
+ }
+ case CMP_TYPE_UINT16: {
*i = obj->as.u16;
return true;
- case CMP_TYPE_SINT32:
+ }
+ case CMP_TYPE_SINT32: {
*i = obj->as.s32;
return true;
- case CMP_TYPE_UINT32:
- if (obj->as.u32 <= 2147483647) {
+ }
+ case CMP_TYPE_UINT32: {
+ if (obj->as.u32 <= 0x7fffffff) {
*i = (int32_t)obj->as.u32;
return true;
}
else {
return false;
}
+ }
default:
- return false;
+ return false;
}
}
@@ -3302,37 +3343,45 @@ bool cmp_object_as_long(const cmp_object_t *obj, int64_t *d) {
switch (obj->type) {
case CMP_TYPE_POSITIVE_FIXNUM:
case CMP_TYPE_NEGATIVE_FIXNUM:
- case CMP_TYPE_SINT8:
+ case CMP_TYPE_SINT8: {
*d = obj->as.s8;
return true;
- case CMP_TYPE_UINT8:
+ }
+ case CMP_TYPE_UINT8: {
*d = obj->as.u8;
return true;
- case CMP_TYPE_SINT16:
+ }
+ case CMP_TYPE_SINT16: {
*d = obj->as.s16;
return true;
- case CMP_TYPE_UINT16:
+ }
+ case CMP_TYPE_UINT16: {
*d = obj->as.u16;
return true;
- case CMP_TYPE_SINT32:
+ }
+ case CMP_TYPE_SINT32: {
*d = obj->as.s32;
return true;
- case CMP_TYPE_UINT32:
+ }
+ case CMP_TYPE_UINT32: {
*d = obj->as.u32;
return true;
- case CMP_TYPE_SINT64:
+ }
+ case CMP_TYPE_SINT64: {
*d = obj->as.s64;
return true;
- case CMP_TYPE_UINT64:
- if (obj->as.u64 <= 9223372036854775807) {
+ }
+ case CMP_TYPE_UINT64: {
+ if (obj->as.u64 <= UINT64_C(0x7fffffffffffffff)) {
*d = (int64_t)obj->as.u64;
return true;
}
else {
return false;
}
+ }
default:
- return false;
+ return false;
}
}
@@ -3343,62 +3392,72 @@ bool cmp_object_as_sinteger(const cmp_object_t *obj, int64_t *d) {
bool cmp_object_as_uchar(const cmp_object_t *obj, uint8_t *c) {
switch (obj->type) {
case CMP_TYPE_POSITIVE_FIXNUM:
- case CMP_TYPE_UINT8:
+ case CMP_TYPE_UINT8: {
*c = obj->as.u8;
return true;
+ }
default:
- return false;
+ return false;
}
}
bool cmp_object_as_ushort(const cmp_object_t *obj, uint16_t *s) {
switch (obj->type) {
case CMP_TYPE_POSITIVE_FIXNUM:
- case CMP_TYPE_UINT8:
+ case CMP_TYPE_UINT8: {
*s = obj->as.u8;
return true;
- case CMP_TYPE_UINT16:
+ }
+ case CMP_TYPE_UINT16: {
*s = obj->as.u16;
return true;
+ }
default:
- return false;
+ return false;
}
}
bool cmp_object_as_uint(const cmp_object_t *obj, uint32_t *i) {
switch (obj->type) {
case CMP_TYPE_POSITIVE_FIXNUM:
- case CMP_TYPE_UINT8:
+ case CMP_TYPE_UINT8: {
*i = obj->as.u8;
return true;
- case CMP_TYPE_UINT16:
+ }
+ case CMP_TYPE_UINT16: {
*i = obj->as.u16;
return true;
- case CMP_TYPE_UINT32:
+ }
+ case CMP_TYPE_UINT32: {
*i = obj->as.u32;
return true;
+ }
default:
- return false;
+ return false;
}
}
bool cmp_object_as_ulong(const cmp_object_t *obj, uint64_t *u) {
switch (obj->type) {
case CMP_TYPE_POSITIVE_FIXNUM:
- case CMP_TYPE_UINT8:
+ case CMP_TYPE_UINT8: {
*u = obj->as.u8;
return true;
- case CMP_TYPE_UINT16:
+ }
+ case CMP_TYPE_UINT16: {
*u = obj->as.u16;
return true;
- case CMP_TYPE_UINT32:
+ }
+ case CMP_TYPE_UINT32: {
*u = obj->as.u32;
return true;
- case CMP_TYPE_UINT64:
+ }
+ case CMP_TYPE_UINT64: {
*u = obj->as.u64;
return true;
+ }
default:
- return false;
+ return false;
}
}
@@ -3428,10 +3487,11 @@ bool cmp_object_as_double(const cmp_object_t *obj, double *d) {
bool cmp_object_as_bool(const cmp_object_t *obj, bool *b) {
if (obj->type == CMP_TYPE_BOOLEAN) {
- if (obj->as.boolean)
+ if (obj->as.boolean) {
*b = true;
- else
+ } else {
*b = false;
+ }
return true;
}
@@ -3444,11 +3504,12 @@ bool cmp_object_as_str(const cmp_object_t *obj, uint32_t *size) {
case CMP_TYPE_FIXSTR:
case CMP_TYPE_STR8:
case CMP_TYPE_STR16:
- case CMP_TYPE_STR32:
+ case CMP_TYPE_STR32: {
*size = obj->as.str_size;
return true;
+ }
default:
- return false;
+ return false;
}
}
@@ -3456,11 +3517,12 @@ bool cmp_object_as_bin(const cmp_object_t *obj, uint32_t *size) {
switch (obj->type) {
case CMP_TYPE_BIN8:
case CMP_TYPE_BIN16:
- case CMP_TYPE_BIN32:
+ case CMP_TYPE_BIN32: {
*size = obj->as.bin_size;
return true;
+ }
default:
- return false;
+ return false;
}
}
@@ -3468,11 +3530,12 @@ bool cmp_object_as_array(const cmp_object_t *obj, uint32_t *size) {
switch (obj->type) {
case CMP_TYPE_FIXARRAY:
case CMP_TYPE_ARRAY16:
- case CMP_TYPE_ARRAY32:
+ case CMP_TYPE_ARRAY32: {
*size = obj->as.array_size;
return true;
+ }
default:
- return false;
+ return false;
}
}
@@ -3480,11 +3543,12 @@ bool cmp_object_as_map(const cmp_object_t *obj, uint32_t *size) {
switch (obj->type) {
case CMP_TYPE_FIXMAP:
case CMP_TYPE_MAP16:
- case CMP_TYPE_MAP32:
+ case CMP_TYPE_MAP32: {
*size = obj->as.map_size;
return true;
+ }
default:
- return false;
+ return false;
}
}
@@ -3497,37 +3561,37 @@ bool cmp_object_as_ext(const cmp_object_t *obj, int8_t *type, uint32_t *size) {
case CMP_TYPE_FIXEXT16:
case CMP_TYPE_EXT8:
case CMP_TYPE_EXT16:
- case CMP_TYPE_EXT32:
+ case CMP_TYPE_EXT32: {
*type = obj->as.ext.type;
*size = obj->as.ext.size;
return true;
+ }
default:
- return false;
+ return false;
}
}
bool cmp_object_to_str(cmp_ctx_t *ctx, const cmp_object_t *obj, char *data,
uint32_t buf_size) {
- uint32_t str_size = 0;
-
switch (obj->type) {
case CMP_TYPE_FIXSTR:
case CMP_TYPE_STR8:
case CMP_TYPE_STR16:
- case CMP_TYPE_STR32:
- str_size = obj->as.str_size;
+ case CMP_TYPE_STR32: {
+ const uint32_t str_size = obj->as.str_size;
if (str_size >= buf_size) {
- ctx->error = STR_DATA_LENGTH_TOO_LONG_ERROR;
+ ctx->error = CMP_ERROR_STR_DATA_LENGTH_TOO_LONG;
return false;
}
if (!ctx->read(ctx, data, str_size)) {
- ctx->error = DATA_READING_ERROR;
+ ctx->error = CMP_ERROR_DATA_READING;
return false;
}
data[str_size] = 0;
return true;
+ }
default:
return false;
}
@@ -3535,27 +3599,25 @@ bool cmp_object_to_str(cmp_ctx_t *ctx, const cmp_object_t *obj, char *data,
bool cmp_object_to_bin(cmp_ctx_t *ctx, const cmp_object_t *obj, void *data,
uint32_t buf_size) {
- uint32_t bin_size = 0;
-
switch (obj->type) {
case CMP_TYPE_BIN8:
case CMP_TYPE_BIN16:
- case CMP_TYPE_BIN32:
- bin_size = obj->as.bin_size;
+ case CMP_TYPE_BIN32: {
+ const uint32_t bin_size = obj->as.bin_size;
if (bin_size > buf_size) {
- ctx->error = BIN_DATA_LENGTH_TOO_LONG_ERROR;
+ ctx->error = CMP_ERROR_BIN_DATA_LENGTH_TOO_LONG;
return false;
}
if (!ctx->read(ctx, data, bin_size)) {
- ctx->error = DATA_READING_ERROR;
+ ctx->error = CMP_ERROR_DATA_READING;
return false;
}
return true;
+ }
default:
return false;
}
}
/* vi: set et ts=2 sw=2: */
-
diff --git a/protocols/Tox/libtox/src/third_party/cmp/cmp.h b/protocols/Tox/libtox/src/third_party/cmp/cmp.h
index 3fde68dbf0..56cf9990b2 100644
--- a/protocols/Tox/libtox/src/third_party/cmp/cmp.h
+++ b/protocols/Tox/libtox/src/third_party/cmp/cmp.h
@@ -1,27 +1,6 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2020 Charles Gunyon
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-*/
-
+/* SPDX-License-Identifier: MIT
+ * Copyright © 2020-2024 Charles Gunyon.
+ */
#ifndef CMP_H_INCLUDED
#define CMP_H_INCLUDED
@@ -29,12 +8,11 @@ THE SOFTWARE.
#include <stddef.h>
#include <stdint.h>
-struct cmp_ctx_s;
+typedef struct cmp_ctx_s cmp_ctx_t;
-typedef bool (*cmp_reader)(struct cmp_ctx_s *ctx, void *data, size_t limit);
-typedef bool (*cmp_skipper)(struct cmp_ctx_s *ctx, size_t count);
-typedef size_t (*cmp_writer)(struct cmp_ctx_s *ctx, const void *data,
- size_t count);
+typedef bool cmp_reader(cmp_ctx_t *ctx, void *data, size_t limit);
+typedef bool cmp_skipper(cmp_ctx_t *ctx, size_t count);
+typedef size_t cmp_writer(cmp_ctx_t *ctx, const void *data, size_t count);
enum {
CMP_TYPE_POSITIVE_FIXNUM, /* 0 */
@@ -79,7 +57,7 @@ typedef struct cmp_ext_s {
uint32_t size;
} cmp_ext_t;
-union cmp_object_data_u {
+typedef union cmp_object_data_u {
bool boolean;
uint8_t u8;
uint16_t u16;
@@ -98,19 +76,19 @@ union cmp_object_data_u {
uint32_t str_size;
uint32_t bin_size;
cmp_ext_t ext;
-};
+} cmp_object_data_t;
-typedef struct cmp_ctx_s {
+struct cmp_ctx_s {
uint8_t error;
void *buf;
- cmp_reader read;
- cmp_skipper skip;
- cmp_writer write;
-} cmp_ctx_t;
+ cmp_reader *read;
+ cmp_skipper *skip;
+ cmp_writer *write;
+};
typedef struct cmp_object_s {
uint8_t type;
- union cmp_object_data_u as;
+ cmp_object_data_t as;
} cmp_object_t;
#ifdef __cplusplus
@@ -134,9 +112,9 @@ extern "C" {
* If you don't intend to write, `write` may be NULL, but calling `*write*`
* functions will crash; there is no check.
*/
-void cmp_init(cmp_ctx_t *ctx, void *buf, cmp_reader read,
- cmp_skipper skip,
- cmp_writer write);
+void cmp_init(cmp_ctx_t *ctx, void *buf, cmp_reader *read,
+ cmp_skipper *skip,
+ cmp_writer *write);
/* Returns CMP's version */
uint32_t cmp_version(void);
@@ -145,7 +123,7 @@ uint32_t cmp_version(void);
uint32_t cmp_mp_version(void);
/* Returns a string description of a CMP context's error */
-const char* cmp_strerror(cmp_ctx_t *ctx);
+const char* cmp_strerror(const cmp_ctx_t *ctx);
/* Writes a signed integer to the backend */
bool cmp_write_integer(cmp_ctx_t *ctx, int64_t d);
@@ -298,7 +276,7 @@ bool cmp_read_str_size(cmp_ctx_t *ctx, uint32_t *size);
/*
* Reads a string from the backend; according to the spec, the string's data
- * ought to be encoded using UTF-8,
+ * ought to be encoded using UTF-8, but CMP leaves that job up to the programmer.
*/
bool cmp_read_str(cmp_ctx_t *ctx, char *data, uint32_t *size);
@@ -363,37 +341,6 @@ bool cmp_skip_object_flat(cmp_ctx_t *ctx, cmp_object_t *obj);
bool cmp_skip_object_no_limit(cmp_ctx_t *ctx);
/*
- * WARNING: THIS FUNCTION IS DEPRECATED AND WILL BE REMOVED IN A FUTURE RELEASE
- *
- * There is no way to track depths across elements without allocation. For
- * example, an array constructed as: `[ [] [] [] [] [] [] [] [] [] [] ]`
- * should be able to be skipped with `cmp_skip_object_limit(&cmp, &obj, 2)`.
- * However, because we cannot track depth across the elements, there's no way
- * to reset it after descending down into each element.
- *
- * This is similar to `cmp_skip_object`, except it tolerates up to `limit`
- * levels of nesting. For example, in order to skip an array that contains a
- * map, call `cmp_skip_object_limit(ctx, &obj, 2)`. Or in other words,
- * `cmp_skip_object(ctx, &obj)` acts similarly to `cmp_skip_object_limit(ctx,
- * &obj, 0)`
- *
- * Specifically, `limit` refers to depth, not breadth. So in order to skip an
- * array that contains two arrays that each contain 3 strings, you would call
- * `cmp_skip_object_limit(ctx, &obj, 2). In order to skip an array that
- * contains 4 arrays that each contain 1 string, you would still call
- * `cmp_skip_object_limit(ctx, &obj, 2).
- */
-bool cmp_skip_object_limit(cmp_ctx_t *ctx, cmp_object_t *obj, uint32_t limit)
-#ifdef __GNUC__
- __attribute__((deprecated))
-#endif
-;
-
-#ifdef _MSC_VER
-#pragma deprecated(cmp_skip_object_limit)
-#endif
-
-/*
* ============================================================================
* === Specific API
* ============================================================================
@@ -538,8 +485,10 @@ bool cmp_object_as_ushort(const cmp_object_t *obj, uint16_t *s);
bool cmp_object_as_uint(const cmp_object_t *obj, uint32_t *i);
bool cmp_object_as_ulong(const cmp_object_t *obj, uint64_t *u);
bool cmp_object_as_uinteger(const cmp_object_t *obj, uint64_t *u);
+#ifndef CMP_NO_FLOAT
bool cmp_object_as_float(const cmp_object_t *obj, float *f);
bool cmp_object_as_double(const cmp_object_t *obj, double *d);
+#endif /* CMP_NO_FLOAT */
bool cmp_object_as_bool(const cmp_object_t *obj, bool *b);
bool cmp_object_as_str(const cmp_object_t *obj, uint32_t *size);
bool cmp_object_as_bin(const cmp_object_t *obj, uint32_t *size);
@@ -554,19 +503,6 @@ bool cmp_object_to_bin(cmp_ctx_t *ctx, const cmp_object_t *obj, void *data, uint
} /* extern "C" */
#endif
-/*
- * ============================================================================
- * === Backwards compatibility defines
- * ============================================================================
- */
-
-#define cmp_write_int cmp_write_integer
-#define cmp_write_sint cmp_write_integer
-#define cmp_write_sinteger cmp_write_integer
-#define cmp_write_uint cmp_write_uinteger
-#define cmp_read_sinteger cmp_read_integer
-
#endif /* CMP_H_INCLUDED */
/* vi: set et ts=2 sw=2: */
-
diff --git a/protocols/Tox/libtox/src/toxcore/DHT.c b/protocols/Tox/libtox/src/toxcore/DHT.c
index 91f0e0ae47..2567d1b5a8 100644
--- a/protocols/Tox/libtox/src/toxcore/DHT.c
+++ b/protocols/Tox/libtox/src/toxcore/DHT.c
@@ -13,14 +13,18 @@
#include <string.h>
#include "LAN_discovery.h"
+#include "attributes.h"
+#include "bin_pack.h"
#include "ccompat.h"
+#include "crypto_core.h"
#include "logger.h"
+#include "mem.h"
#include "mono_time.h"
#include "network.h"
#include "ping.h"
+#include "ping_array.h"
#include "shared_key_cache.h"
#include "state.h"
-#include "util.h"
/** The timeout after which a node is discarded completely. */
#define KILL_NODE_TIMEOUT (BAD_NODE_TIMEOUT + PING_INTERVAL)
@@ -80,7 +84,7 @@ struct DHT_Friend {
static const DHT_Friend empty_dht_friend = {{0}};
const Node_format empty_node_format = {{0}};
-static_assert(sizeof (empty_dht_friend.lock_flags) * 8 == DHT_FRIEND_MAX_LOCKS, "Bitfield size and number of locks don't match");
+static_assert(sizeof(empty_dht_friend.lock_flags) * 8 == DHT_FRIEND_MAX_LOCKS, "Bitfield size and number of locks don't match");
typedef struct Cryptopacket_Handler {
cryptopacket_handler_cb *function;
@@ -91,6 +95,7 @@ struct DHT {
const Logger *log;
const Network *ns;
Mono_Time *mono_time;
+ const Memory *mem;
const Random *rng;
Networking_Core *net;
@@ -358,69 +363,14 @@ int packed_node_size(Family ip_family)
return -1;
}
-
-int pack_ip_port(const Logger *logger, uint8_t *data, uint16_t length, const IP_Port *ip_port)
-{
- if (data == nullptr) {
- return -1;
- }
-
- bool is_ipv4;
- uint8_t family;
-
- if (net_family_is_ipv4(ip_port->ip.family)) {
- // TODO(irungentoo): use functions to convert endianness
- is_ipv4 = true;
- family = TOX_AF_INET;
- } else if (net_family_is_tcp_ipv4(ip_port->ip.family)) {
- is_ipv4 = true;
- family = TOX_TCP_INET;
- } else if (net_family_is_ipv6(ip_port->ip.family)) {
- is_ipv4 = false;
- family = TOX_AF_INET6;
- } else if (net_family_is_tcp_ipv6(ip_port->ip.family)) {
- is_ipv4 = false;
- family = TOX_TCP_INET6;
- } else {
- Ip_Ntoa ip_str;
- // TODO(iphydf): Find out why we're trying to pack invalid IPs, stop
- // doing that, and turn this into an error.
- LOGGER_TRACE(logger, "cannot pack invalid IP: %s", net_ip_ntoa(&ip_port->ip, &ip_str));
- return -1;
- }
-
- if (is_ipv4) {
- const uint32_t size = 1 + SIZE_IP4 + sizeof(uint16_t);
-
- if (size > length) {
- return -1;
- }
-
- data[0] = family;
- memcpy(data + 1, &ip_port->ip.ip.v4, SIZE_IP4);
- memcpy(data + 1 + SIZE_IP4, &ip_port->port, sizeof(uint16_t));
- return size;
- } else {
- const uint32_t size = 1 + SIZE_IP6 + sizeof(uint16_t);
-
- if (size > length) {
- return -1;
- }
-
- data[0] = family;
- memcpy(data + 1, &ip_port->ip.ip.v6, SIZE_IP6);
- memcpy(data + 1 + SIZE_IP6, &ip_port->port, sizeof(uint16_t));
- return size;
- }
-}
-
-int dht_create_packet(const Random *rng, const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE],
+int dht_create_packet(const Memory *mem, const Random *rng,
+ const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE],
const uint8_t *shared_key, const uint8_t type,
const uint8_t *plain, size_t plain_length,
uint8_t *packet, size_t length)
{
- uint8_t *encrypted = (uint8_t *)malloc(plain_length + CRYPTO_MAC_SIZE);
uint8_t nonce[CRYPTO_NONCE_SIZE];
+ uint8_t *encrypted = (uint8_t *)mem_balloc(mem, plain_length + CRYPTO_MAC_SIZE);
if (encrypted == nullptr) {
return -1;
@@ -431,12 +381,12 @@ int dht_create_packet(const Random *rng, const uint8_t public_key[CRYPTO_PUBLIC_
const int encrypted_length = encrypt_data_symmetric(shared_key, nonce, plain, plain_length, encrypted);
if (encrypted_length == -1) {
- free(encrypted);
+ mem_delete(mem, encrypted);
return -1;
}
if (length < 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + encrypted_length) {
- free(encrypted);
+ mem_delete(mem, encrypted);
return -1;
}
@@ -445,97 +395,29 @@ int dht_create_packet(const Random *rng, const uint8_t public_key[CRYPTO_PUBLIC_
memcpy(packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, nonce, CRYPTO_NONCE_SIZE);
memcpy(packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, encrypted, encrypted_length);
- free(encrypted);
+ mem_delete(mem, encrypted);
return 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + encrypted_length;
}
-int unpack_ip_port(IP_Port *ip_port, const uint8_t *data, uint16_t length, bool tcp_enabled)
+/** @brief Pack a single node from a node array.
+ *
+ * @retval true on success.
+ */
+non_null()
+static bool bin_pack_node_handler(const void *arr, uint32_t index, const Logger *logger, Bin_Pack *bp)
{
- if (data == nullptr) {
- return -1;
- }
-
- bool is_ipv4;
- Family host_family;
-
- if (data[0] == TOX_AF_INET) {
- is_ipv4 = true;
- host_family = net_family_ipv4();
- } else if (data[0] == TOX_TCP_INET) {
- if (!tcp_enabled) {
- return -1;
- }
-
- is_ipv4 = true;
- host_family = net_family_tcp_ipv4();
- } else if (data[0] == TOX_AF_INET6) {
- is_ipv4 = false;
- host_family = net_family_ipv6();
- } else if (data[0] == TOX_TCP_INET6) {
- if (!tcp_enabled) {
- return -1;
- }
-
- is_ipv4 = false;
- host_family = net_family_tcp_ipv6();
- } else {
- return -1;
- }
-
- *ip_port = empty_ip_port;
-
- if (is_ipv4) {
- const uint32_t size = 1 + SIZE_IP4 + sizeof(uint16_t);
-
- if (size > length) {
- return -1;
- }
-
- ip_port->ip.family = host_family;
- memcpy(&ip_port->ip.ip.v4, data + 1, SIZE_IP4);
- memcpy(&ip_port->port, data + 1 + SIZE_IP4, sizeof(uint16_t));
- return size;
- } else {
- const uint32_t size = 1 + SIZE_IP6 + sizeof(uint16_t);
-
- if (size > length) {
- return -1;
- }
-
- ip_port->ip.family = host_family;
- memcpy(&ip_port->ip.ip.v6, data + 1, SIZE_IP6);
- memcpy(&ip_port->port, data + 1 + SIZE_IP6, sizeof(uint16_t));
- return size;
- }
+ const Node_format *nodes = (const Node_format *)arr;
+ return bin_pack_ip_port(bp, logger, &nodes[index].ip_port)
+ && bin_pack_bin_b(bp, nodes[index].public_key, CRYPTO_PUBLIC_KEY_SIZE);
}
int pack_nodes(const Logger *logger, uint8_t *data, uint16_t length, const Node_format *nodes, uint16_t number)
{
- uint32_t packed_length = 0;
-
- for (uint32_t i = 0; i < number && packed_length < length; ++i) {
- const int ipp_size = pack_ip_port(logger, data + packed_length, length - packed_length, &nodes[i].ip_port);
-
- if (ipp_size == -1) {
- return -1;
- }
-
- packed_length += ipp_size;
-
- if (packed_length + CRYPTO_PUBLIC_KEY_SIZE > length) {
- return -1;
- }
-
- memcpy(data + packed_length, nodes[i].public_key, CRYPTO_PUBLIC_KEY_SIZE);
- packed_length += CRYPTO_PUBLIC_KEY_SIZE;
-
-#ifndef NDEBUG
- const uint32_t increment = ipp_size + CRYPTO_PUBLIC_KEY_SIZE;
-#endif
- assert(increment == PACKED_NODE_SIZE_IP4 || increment == PACKED_NODE_SIZE_IP6);
+ const uint32_t size = bin_pack_obj_array_b_size(bin_pack_node_handler, nodes, number, logger);
+ if (!bin_pack_obj_array_b(bin_pack_node_handler, nodes, number, logger, data, length)) {
+ return -1;
}
-
- return packed_length;
+ return size;
}
int unpack_nodes(Node_format *nodes, uint16_t max_num_nodes, uint16_t *processed_data_len, const uint8_t *data,
@@ -563,8 +445,8 @@ int unpack_nodes(Node_format *nodes, uint16_t max_num_nodes, uint16_t *processed
#ifndef NDEBUG
const uint32_t increment = ipp_size + CRYPTO_PUBLIC_KEY_SIZE;
-#endif
assert(increment == PACKED_NODE_SIZE_IP4 || increment == PACKED_NODE_SIZE_IP6);
+#endif /* NDEBUG */
}
if (processed_data_len != nullptr) {
@@ -729,16 +611,21 @@ static bool client_or_ip_port_in_list(const Logger *log, const Mono_Time *mono_t
return true;
}
-bool add_to_list(Node_format *nodes_list, uint32_t length, const uint8_t *pk, const IP_Port *ip_port,
- const uint8_t *cmp_pk)
+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])
{
for (uint32_t i = 0; i < length; ++i) {
- if (id_closest(cmp_pk, nodes_list[i].public_key, pk) == 2) {
+ Node_format *node = &nodes_list[i];
+
+ if (id_closest(cmp_pk, node->public_key, pk) == 2) {
uint8_t pk_bak[CRYPTO_PUBLIC_KEY_SIZE];
- memcpy(pk_bak, nodes_list[i].public_key, CRYPTO_PUBLIC_KEY_SIZE);
- const IP_Port ip_port_bak = nodes_list[i].ip_port;
- memcpy(nodes_list[i].public_key, pk, CRYPTO_PUBLIC_KEY_SIZE);
- nodes_list[i].ip_port = *ip_port;
+ 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;
if (i != length - 1) {
add_to_list(nodes_list, length, pk_bak, &ip_port_bak, cmp_pk);
@@ -755,10 +642,11 @@ bool add_to_list(Node_format *nodes_list, uint32_t length, const uint8_t *pk, co
* helper for `get_close_nodes()`. argument list is a monster :D
*/
non_null()
-static void get_close_nodes_inner(uint64_t cur_time, const uint8_t *public_key, Node_format *nodes_list,
- Family sa_family, const Client_data *client_list, uint32_t client_list_length,
- uint32_t *num_nodes_ptr, bool is_LAN,
- bool want_announce)
+static void get_close_nodes_inner(
+ uint64_t cur_time, const uint8_t *public_key,
+ Node_format *nodes_list, uint32_t *num_nodes_ptr,
+ Family sa_family, const Client_data *client_list, uint32_t client_list_length,
+ bool is_lan, bool want_announce)
{
if (!net_family_is_ipv4(sa_family) && !net_family_is_ipv6(sa_family) && !net_family_is_unspec(sa_family)) {
return;
@@ -792,7 +680,7 @@ static void get_close_nodes_inner(uint64_t cur_time, const uint8_t *public_key,
}
/* don't send LAN ips to non LAN peers */
- if (ip_is_lan(&ipptp->ip_port.ip) && !is_LAN) {
+ if (ip_is_lan(&ipptp->ip_port.ip) && !is_lan) {
continue;
}
@@ -802,7 +690,7 @@ static void get_close_nodes_inner(uint64_t cur_time, const uint8_t *public_key,
continue;
}
-#endif
+#endif /* CHECK_ANNOUNCE_NODE */
if (num_nodes < MAX_SENT_NODES) {
memcpy(nodes_list[num_nodes].public_key, client->public_key, CRYPTO_PUBLIC_KEY_SIZE);
@@ -825,28 +713,46 @@ static void get_close_nodes_inner(uint64_t cur_time, const uint8_t *public_key,
* want_announce: return only nodes which implement the dht announcements protocol.
*/
non_null()
-static int get_somewhat_close_nodes(const DHT *dht, const uint8_t *public_key, Node_format *nodes_list,
- Family sa_family, bool is_LAN, bool want_announce)
+static int get_somewhat_close_nodes(
+ uint64_t cur_time, const uint8_t *public_key, Node_format nodes_list[MAX_SENT_NODES],
+ Family sa_family, const Client_data *close_clientlist,
+ const DHT_Friend *friends_list, uint16_t friends_list_size,
+ bool is_lan, bool want_announce)
{
+ for (uint16_t i = 0; i < MAX_SENT_NODES; ++i) {
+ nodes_list[i] = empty_node_format;
+ }
+
uint32_t num_nodes = 0;
- get_close_nodes_inner(dht->cur_time, public_key, nodes_list, sa_family,
- dht->close_clientlist, LCLIENT_LIST, &num_nodes, is_LAN, want_announce);
+ get_close_nodes_inner(
+ cur_time, public_key,
+ nodes_list, &num_nodes,
+ sa_family, close_clientlist, LCLIENT_LIST,
+ is_lan, want_announce);
- for (uint32_t i = 0; i < dht->num_friends; ++i) {
- get_close_nodes_inner(dht->cur_time, public_key, nodes_list, sa_family,
- dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS,
- &num_nodes, is_LAN, want_announce);
+ for (uint16_t i = 0; i < friends_list_size; ++i) {
+ const DHT_Friend *dht_friend = &friends_list[i];
+
+ get_close_nodes_inner(
+ cur_time, public_key,
+ nodes_list, &num_nodes,
+ sa_family, dht_friend->client_list, MAX_FRIEND_CLIENTS,
+ is_lan, want_announce);
}
return num_nodes;
}
-int get_close_nodes(const DHT *dht, const uint8_t *public_key, Node_format *nodes_list, Family sa_family,
- bool is_LAN, bool want_announce)
+int get_close_nodes(
+ const DHT *dht, const uint8_t *public_key,
+ Node_format nodes_list[MAX_SENT_NODES], Family sa_family,
+ bool is_lan, bool want_announce)
{
- memset(nodes_list, 0, MAX_SENT_NODES * sizeof(Node_format));
- return get_somewhat_close_nodes(dht, public_key, nodes_list, sa_family,
- is_LAN, want_announce);
+ return get_somewhat_close_nodes(
+ dht->cur_time, public_key, nodes_list,
+ sa_family, dht->close_clientlist,
+ dht->friends_list, dht->num_friends,
+ is_lan, want_announce);
}
typedef struct DHT_Cmp_Data {
@@ -937,7 +843,8 @@ static bool send_announce_ping(DHT *dht, const uint8_t *public_key, const IP_Por
uint8_t request[1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + sizeof(plain) + CRYPTO_MAC_SIZE];
- if (dht_create_packet(dht->rng, dht->self_public_key, shared_key, NET_PACKET_DATA_SEARCH_REQUEST,
+ if (dht_create_packet(dht->mem, dht->rng,
+ dht->self_public_key, shared_key, NET_PACKET_DATA_SEARCH_REQUEST,
plain, sizeof(plain), request, sizeof(request)) != sizeof(request)) {
return false;
}
@@ -991,7 +898,7 @@ static int handle_data_search_response(void *object, const IP_Port *source,
return 0;
}
-#endif
+#endif /* CHECK_ANNOUNCE_NODE */
/** @brief Is it ok to store node with public_key in client.
*
@@ -1008,12 +915,12 @@ static bool store_node_ok(const Client_data *client, uint64_t cur_time, const ui
}
non_null()
-static void sort_client_list(Client_data *list, uint64_t cur_time, unsigned int length,
+static void sort_client_list(const Memory *mem, Client_data *list, uint64_t cur_time, unsigned int length,
const uint8_t *comp_public_key)
{
// Pass comp_public_key to qsort with each Client_data entry, so the
// comparison function can use it as the base of comparison.
- DHT_Cmp_Data *cmp_list = (DHT_Cmp_Data *)calloc(length, sizeof(DHT_Cmp_Data));
+ DHT_Cmp_Data *cmp_list = (DHT_Cmp_Data *)mem_valloc(mem, length, sizeof(DHT_Cmp_Data));
if (cmp_list == nullptr) {
return;
@@ -1031,7 +938,7 @@ static void sort_client_list(Client_data *list, uint64_t cur_time, unsigned int
list[i] = cmp_list[i].entry;
}
- free(cmp_list);
+ mem_delete(mem, cmp_list);
}
non_null()
@@ -1057,7 +964,8 @@ static void update_client_with_reset(const Mono_Time *mono_time, Client_data *cl
ipptp_write->ret_ip_self = false;
/* zero out other address */
- memset(ipptp_clear, 0, sizeof(*ipptp_clear));
+ const IPPTsPng empty_ipptp = {{{{0}}}};
+ *ipptp_clear = empty_ipptp;
}
/**
@@ -1092,7 +1000,7 @@ static bool replace_all(const DHT *dht,
return false;
}
- sort_client_list(list, dht->cur_time, length, comp_public_key);
+ sort_client_list(dht->mem, list, dht->cur_time, length, comp_public_key);
Client_data *const client = &list[0];
pk_copy(client->public_key, public_key);
@@ -1136,7 +1044,7 @@ static bool add_to_close(DHT *dht, const uint8_t *public_key, const IP_Port *ip_
#ifdef CHECK_ANNOUNCE_NODE
client->announce_node = false;
send_announce_ping(dht, public_key, ip_port);
-#endif
+#endif /* CHECK_ANNOUNCE_NODE */
return true;
}
@@ -1254,7 +1162,7 @@ static bool ping_node_from_getnodes_ok(DHT *dht, const uint8_t *public_key, cons
*/
uint32_t addto_lists(DHT *dht, const IP_Port *ip_port, const uint8_t *public_key)
{
- IP_Port ipp_copy = ip_port_normalize(ip_port);
+ const IP_Port ipp_copy = ip_port_normalize(ip_port);
uint32_t used = 0;
@@ -1340,7 +1248,7 @@ static bool update_client_data(const Mono_Time *mono_time, Client_data *array, s
non_null()
static void returnedip_ports(DHT *dht, const IP_Port *ip_port, const uint8_t *public_key, const uint8_t *nodepublic_key)
{
- IP_Port ipp_copy = ip_port_normalize(ip_port);
+ const IP_Port ipp_copy = ip_port_normalize(ip_port);
if (pk_equal(public_key, dht->self_public_key)) {
update_client_data(dht->mono_time, dht->close_clientlist, LCLIENT_LIST, &ipp_copy, nodepublic_key, true);
@@ -1392,7 +1300,7 @@ bool dht_getnodes(DHT *dht, const IP_Port *ip_port, const uint8_t *public_key, c
const uint8_t *shared_key = dht_get_shared_key_sent(dht, public_key);
- const int len = dht_create_packet(dht->rng,
+ const int len = dht_create_packet(dht->mem, dht->rng,
dht->self_public_key, shared_key, NET_PACKET_GET_NODES,
plain, sizeof(plain), data, sizeof(data));
@@ -1440,13 +1348,14 @@ static int sendnodes_ipv6(const DHT *dht, const IP_Port *ip_port, const uint8_t
memcpy(plain + 1 + nodes_length, sendback_data, length);
const uint32_t crypto_size = 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_MAC_SIZE;
- VLA(uint8_t, data, 1 + nodes_length + length + crypto_size);
+ const uint32_t data_size = 1 + nodes_length + length + crypto_size;
+ VLA(uint8_t, data, data_size);
- const int len = dht_create_packet(dht->rng,
+ const int len = dht_create_packet(dht->mem, dht->rng,
dht->self_public_key, shared_encryption_key, NET_PACKET_SEND_NODES_IPV6,
- plain, 1 + nodes_length + length, data, SIZEOF_VLA(data));
+ plain, 1 + nodes_length + length, data, data_size);
- if (len != SIZEOF_VLA(data)) {
+ if (len != data_size) {
return -1;
}
@@ -1458,12 +1367,12 @@ static int sendnodes_ipv6(const DHT *dht, const IP_Port *ip_port, const uint8_t
non_null()
static int handle_getnodes(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, void *userdata)
{
+ DHT *const dht = (DHT *)object;
+
if (length != (CRYPTO_SIZE + CRYPTO_MAC_SIZE + sizeof(uint64_t))) {
return 1;
}
- DHT *const dht = (DHT *)object;
-
/* Check if packet is from ourself. */
if (pk_equal(packet + 1, dht->self_public_key)) {
return 1;
@@ -1529,7 +1438,8 @@ static bool handle_sendnodes_core(void *object, const IP_Port *source, const uin
return false;
}
- VLA(uint8_t, plain, 1 + data_size + sizeof(uint64_t));
+ const uint32_t plain_size = 1 + data_size + sizeof(uint64_t);
+ VLA(uint8_t, plain, plain_size);
const uint8_t *shared_key = dht_get_shared_key_sent(dht, packet + 1);
const int len = decrypt_data_symmetric(
shared_key,
@@ -1538,7 +1448,7 @@ static bool handle_sendnodes_core(void *object, const IP_Port *source, const uin
1 + data_size + sizeof(uint64_t) + CRYPTO_MAC_SIZE,
plain);
- if ((unsigned int)len != SIZEOF_VLA(plain)) {
+ if ((uint32_t)len != plain_size) {
return false;
}
@@ -1611,7 +1521,7 @@ static int handle_sendnodes_ipv6(void *object, const IP_Port *source, const uint
non_null(1) nullable(2, 3)
static uint32_t dht_friend_lock(DHT_Friend *const dht_friend, dht_ip_cb *ip_callback,
- void *data, int32_t number)
+ void *data, int32_t number)
{
// find first free slot
uint8_t lock_num;
@@ -1681,7 +1591,7 @@ int dht_addfriend(DHT *dht, const uint8_t *public_key, dht_ip_cb *ip_callback,
return 0;
}
- DHT_Friend *const temp = (DHT_Friend *)realloc(dht->friends_list, sizeof(DHT_Friend) * (dht->num_friends + 1));
+ DHT_Friend *const temp = (DHT_Friend *)mem_vrealloc(dht->mem, dht->friends_list, dht->num_friends + 1, sizeof(DHT_Friend));
if (temp == nullptr) {
return -1;
@@ -1726,12 +1636,12 @@ int dht_delfriend(DHT *dht, const uint8_t *public_key, uint32_t lock_token)
}
if (dht->num_friends == 0) {
- free(dht->friends_list);
+ mem_delete(dht->mem, dht->friends_list);
dht->friends_list = nullptr;
return 0;
}
- DHT_Friend *const temp = (DHT_Friend *)realloc(dht->friends_list, sizeof(DHT_Friend) * dht->num_friends);
+ DHT_Friend *const temp = (DHT_Friend *)mem_vrealloc(dht->mem, dht->friends_list, dht->num_friends, sizeof(DHT_Friend));
if (temp == nullptr) {
return -1;
@@ -1784,14 +1694,14 @@ static uint8_t do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, co
const uint64_t temp_time = mono_time_get(dht->mono_time);
uint32_t num_nodes = 0;
- Client_data **client_list = (Client_data **)calloc(list_count * 2, sizeof(Client_data *));
- IPPTsPng **assoc_list = (IPPTsPng **)calloc(list_count * 2, sizeof(IPPTsPng *));
+ Client_data **client_list = (Client_data **)mem_valloc(dht->mem, list_count * 2, sizeof(Client_data *));
+ IPPTsPng **assoc_list = (IPPTsPng **)mem_valloc(dht->mem, list_count * 2, sizeof(IPPTsPng *));
unsigned int sort = 0;
bool sort_ok = false;
if (client_list == nullptr || assoc_list == nullptr) {
- free(assoc_list);
- free(client_list);
+ mem_delete(dht->mem, assoc_list);
+ mem_delete(dht->mem, client_list);
return 0;
}
@@ -1809,7 +1719,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;
}
@@ -1831,7 +1743,7 @@ static uint8_t do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, co
}
if (sortable && sort_ok) {
- sort_client_list(list, dht->cur_time, list_count, public_key);
+ sort_client_list(dht->mem, list, dht->cur_time, list_count, public_key);
}
if (num_nodes > 0 && (mono_time_is_timeout(dht->mono_time, *lastgetnode, GET_NODE_INTERVAL)
@@ -1842,14 +1754,16 @@ 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;
}
- free(assoc_list);
- free(client_list);
+ mem_delete(dht->mem, assoc_list);
+ mem_delete(dht->mem, client_list);
return not_kill;
}
@@ -1871,8 +1785,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);
}
}
@@ -1881,7 +1794,7 @@ static void do_dht_friends(DHT *dht)
* Send a get nodes request every GET_NODE_INTERVAL seconds to a random good node in the list.
*/
non_null()
-static void do_Close(DHT *dht)
+static void do_close(DHT *dht)
{
for (size_t i = 0; i < dht->num_to_bootstrap; ++i) {
dht_getnodes(dht, &dht->to_bootstrap[i].ip_port, dht->to_bootstrap[i].public_key, dht->self_public_key);
@@ -1908,14 +1821,11 @@ static void do_Close(DHT *dht)
for (size_t i = 0; i < LCLIENT_LIST; ++i) {
Client_data *const client = &dht->close_clientlist[i];
- IPPTsPng *const assocs[] = { &client->assoc6, &client->assoc4, nullptr };
-
- for (IPPTsPng * const *it = assocs; *it != nullptr; ++it) {
- IPPTsPng *const assoc = *it;
-
- if (assoc->timestamp != 0) {
- assoc->timestamp = badonly;
- }
+ if (client->assoc4.timestamp != 0) {
+ client->assoc4.timestamp = badonly;
+ }
+ if (client->assoc6.timestamp != 0) {
+ client->assoc6.timestamp = badonly;
}
}
}
@@ -1930,8 +1840,8 @@ bool dht_bootstrap(DHT *dht, const IP_Port *ip_port, const uint8_t *public_key)
return dht_getnodes(dht, ip_port, public_key, dht->self_public_key);
}
-int dht_bootstrap_from_address(DHT *dht, const char *address, bool ipv6enabled,
- uint16_t port, const uint8_t *public_key)
+bool dht_bootstrap_from_address(DHT *dht, const char *address, bool ipv6enabled,
+ uint16_t port, const uint8_t *public_key)
{
IP_Port ip_port_v64;
IP *ip_extra = nullptr;
@@ -1954,10 +1864,10 @@ int dht_bootstrap_from_address(DHT *dht, const char *address, bool ipv6enabled,
dht_bootstrap(dht, &ip_port_v4, public_key);
}
- return 1;
+ return true;
}
- return 0;
+ return false;
}
int route_packet(const DHT *dht, const uint8_t *public_key, const uint8_t *packet, uint16_t length)
@@ -2059,7 +1969,6 @@ static int friend_iplist(const DHT *dht, IP_Port *ip_portlist, uint16_t friend_n
#endif /* !FRIEND_IPLIST_PAD */
}
-
/**
* Callback invoked for each IP/port of each client of a friend.
*
@@ -2146,7 +2055,6 @@ uint32_t route_to_friend(const DHT *dht, const uint8_t *friend_id, const Packet
return 0;
}
-
IP_Port ip_list[MAX_FRIEND_CLIENTS];
const int ip_num = friend_iplist(dht, ip_list, num);
@@ -2206,7 +2114,7 @@ static uint32_t routeone_to_friend(const DHT *dht, const uint8_t *friend_id, con
/*---------------------BEGINNING OF NAT PUNCHING FUNCTIONS--------------------------*/
non_null()
-static int send_NATping(const DHT *dht, const uint8_t *public_key, uint64_t ping_id, uint8_t type)
+static int send_nat_ping(const DHT *dht, const uint8_t *public_key, uint64_t ping_id, uint8_t type)
{
uint8_t data[sizeof(uint64_t) + 1];
uint8_t packet_data[MAX_CRYPTO_REQUEST_SIZE];
@@ -2241,14 +2149,15 @@ static int send_NATping(const DHT *dht, const uint8_t *public_key, uint64_t ping
/** Handle a received ping request for. */
non_null()
-static int handle_NATping(void *object, const IP_Port *source, const uint8_t *source_pubkey, const uint8_t *packet,
- uint16_t length, void *userdata)
+static int handle_nat_ping(void *object, const IP_Port *source, const uint8_t *source_pubkey, const uint8_t *packet,
+ uint16_t length, void *userdata)
{
+ DHT *const dht = (DHT *)object;
+
if (length != sizeof(uint64_t) + 1) {
return 1;
}
- DHT *const dht = (DHT *)object;
uint64_t ping_id;
memcpy(&ping_id, packet + 1, sizeof(uint64_t));
@@ -2262,7 +2171,7 @@ static int handle_NATping(void *object, const IP_Port *source, const uint8_t *so
if (packet[0] == NAT_PING_REQUEST) {
/* 1 is reply */
- send_NATping(dht, source_pubkey, ping_id, NAT_PING_RESPONSE);
+ send_nat_ping(dht, source_pubkey, ping_id, NAT_PING_RESPONSE);
dht_friend->nat.recv_nat_ping_timestamp = mono_time_get(dht->mono_time);
return 0;
}
@@ -2381,7 +2290,7 @@ static void punch_holes(DHT *dht, const IP *ip, const uint16_t *port_list, uint1
uint16_t i;
for (i = 0; i < MAX_PUNCHING_PORTS; ++i) {
- uint32_t it = i + dht->friends_list[friend_num].nat.punching_index2;
+ const uint32_t it = i + dht->friends_list[friend_num].nat.punching_index2;
const uint16_t port = 1024;
pinging.port = net_htons(port + it);
ping_send_request(dht->ping, &pinging, dht->friends_list[friend_num].public_key);
@@ -2394,7 +2303,7 @@ static void punch_holes(DHT *dht, const IP *ip, const uint16_t *port_list, uint1
}
non_null()
-static void do_NAT(DHT *dht)
+static void do_nat(DHT *dht)
{
const uint64_t temp_time = mono_time_get(dht->mono_time);
@@ -2408,7 +2317,7 @@ static void do_NAT(DHT *dht)
}
if (dht->friends_list[i].nat.nat_ping_timestamp + PUNCH_INTERVAL < temp_time) {
- send_NATping(dht, dht->friends_list[i].public_key, dht->friends_list[i].nat.nat_ping_id, NAT_PING_REQUEST);
+ send_nat_ping(dht, dht->friends_list[i].public_key, dht->friends_list[i].nat.nat_ping_id, NAT_PING_REQUEST);
dht->friends_list[i].nat.nat_ping_timestamp = temp_time;
}
@@ -2463,9 +2372,7 @@ static uint16_t list_nodes(const Random *rng, const Client_data *list, size_t le
}
if (!assoc_timeout(cur_time, &list[i - 1].assoc6)) {
- if (assoc == nullptr) {
- assoc = &list[i - 1].assoc6;
- } else if ((random_u08(rng) % 2) != 0) {
+ if (assoc == nullptr || (random_u08(rng) % 2) != 0) {
assoc = &list[i - 1].assoc6;
}
}
@@ -2583,8 +2490,8 @@ void dht_callback_get_nodes_response(DHT *dht, dht_get_nodes_response_cb *functi
}
non_null(1, 2, 3) nullable(5)
-static int handle_LANdiscovery(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length,
- void *userdata)
+static int handle_lan_discovery(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length,
+ void *userdata)
{
DHT *dht = (DHT *)object;
@@ -2606,16 +2513,18 @@ static int handle_LANdiscovery(void *object, const IP_Port *source, const uint8_
/*----------------------------------------------------------------------------------*/
-DHT *new_dht(const Logger *log, const Random *rng, const Network *ns, Mono_Time *mono_time, Networking_Core *net,
+DHT *new_dht(const Logger *log, const Memory *mem, const Random *rng, const Network *ns,
+ Mono_Time *mono_time, Networking_Core *net,
bool hole_punching_enabled, bool lan_discovery_enabled)
{
if (net == nullptr) {
return nullptr;
}
- DHT *const dht = (DHT *)calloc(1, sizeof(DHT));
+ 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;
}
@@ -2625,13 +2534,15 @@ DHT *new_dht(const Logger *log, const Random *rng, const Network *ns, Mono_Time
dht->log = log;
dht->net = net;
dht->rng = rng;
+ dht->mem = mem;
dht->hole_punching_enabled = hole_punching_enabled;
dht->lan_discovery_enabled = lan_discovery_enabled;
- dht->ping = ping_new(mono_time, rng, dht);
+ 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;
}
@@ -2639,27 +2550,28 @@ DHT *new_dht(const Logger *log, const Random *rng, const Network *ns, Mono_Time
networking_registerhandler(dht->net, NET_PACKET_GET_NODES, &handle_getnodes, dht);
networking_registerhandler(dht->net, NET_PACKET_SEND_NODES_IPV6, &handle_sendnodes_ipv6, dht);
networking_registerhandler(dht->net, NET_PACKET_CRYPTO, &cryptopacket_handle, dht);
- networking_registerhandler(dht->net, NET_PACKET_LAN_DISCOVERY, &handle_LANdiscovery, dht);
- cryptopacket_registerhandler(dht, CRYPTO_PACKET_NAT_PING, &handle_NATping, dht);
+ networking_registerhandler(dht->net, NET_PACKET_LAN_DISCOVERY, &handle_lan_discovery, dht);
+ cryptopacket_registerhandler(dht, CRYPTO_PACKET_NAT_PING, &handle_nat_ping, dht);
#ifdef CHECK_ANNOUNCE_NODE
networking_registerhandler(dht->net, NET_PACKET_DATA_SEARCH_RESPONSE, &handle_data_search_response, dht);
-#endif
+#endif /* CHECK_ANNOUNCE_NODE */
crypto_new_keypair(rng, dht->self_public_key, dht->self_secret_key);
- dht->shared_keys_recv = shared_key_cache_new(mono_time, dht->self_secret_key, KEYS_TIMEOUT, MAX_KEYS_PER_SLOT);
- dht->shared_keys_sent = shared_key_cache_new(mono_time, 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;
}
-
- dht->dht_ping_array = ping_array_new(DHT_PING_ARRAY_SIZE, PING_TIMEOUT);
+ 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;
}
@@ -2672,6 +2584,7 @@ DHT *new_dht(const Logger *log, const Random *rng, const Network *ns, Mono_Time
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;
}
@@ -2701,9 +2614,9 @@ void do_dht(DHT *dht)
dht_connect_after_load(dht);
}
- do_Close(dht);
+ do_close(dht);
do_dht_friends(dht);
- do_NAT(dht);
+ do_nat(dht);
ping_iterate(dht->ping);
}
@@ -2722,11 +2635,11 @@ void kill_dht(DHT *dht)
shared_key_cache_free(dht->shared_keys_recv);
shared_key_cache_free(dht->shared_keys_sent);
ping_array_kill(dht->dht_ping_array);
- ping_kill(dht->ping);
- free(dht->friends_list);
- free(dht->loaded_nodes_list);
+ ping_kill(dht->mem, dht->ping);
+ mem_delete(dht->mem, dht->friends_list);
+ mem_delete(dht->mem, dht->loaded_nodes_list);
crypto_memzero(dht->self_secret_key, sizeof(dht->self_secret_key));
- free(dht);
+ mem_delete(dht->mem, dht);
}
/* new DHT format for load/save, more robust and forward compatible */
@@ -2745,21 +2658,21 @@ uint32_t dht_size(const DHT *dht)
uint32_t numv6 = 0;
for (uint32_t i = 0; i < dht->loaded_num_nodes; ++i) {
- numv4 += net_family_is_ipv4(dht->loaded_nodes_list[i].ip_port.ip.family);
- numv6 += net_family_is_ipv6(dht->loaded_nodes_list[i].ip_port.ip.family);
+ numv4 += net_family_is_ipv4(dht->loaded_nodes_list[i].ip_port.ip.family) ? 1 : 0;
+ numv6 += net_family_is_ipv6(dht->loaded_nodes_list[i].ip_port.ip.family) ? 1 : 0;
}
for (uint32_t i = 0; i < LCLIENT_LIST; ++i) {
- numv4 += dht->close_clientlist[i].assoc4.timestamp != 0;
- numv6 += dht->close_clientlist[i].assoc6.timestamp != 0;
+ numv4 += dht->close_clientlist[i].assoc4.timestamp != 0 ? 1 : 0;
+ numv6 += dht->close_clientlist[i].assoc6.timestamp != 0 ? 1 : 0;
}
for (uint32_t i = 0; i < DHT_FAKE_FRIEND_NUMBER && i < dht->num_friends; ++i) {
const DHT_Friend *const fr = &dht->friends_list[i];
for (uint32_t j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
- numv4 += fr->client_list[j].assoc4.timestamp != 0;
- numv6 += fr->client_list[j].assoc6.timestamp != 0;
+ numv4 += fr->client_list[j].assoc4.timestamp != 0 ? 1 : 0;
+ numv6 += fr->client_list[j].assoc6.timestamp != 0 ? 1 : 0;
}
}
@@ -2780,7 +2693,7 @@ void dht_save(const DHT *dht, uint8_t *data)
/* get right offset. we write the actual header later. */
data = state_write_section_header(data, DHT_STATE_COOKIE_TYPE, 0, 0);
- Node_format *clients = (Node_format *)calloc(MAX_SAVED_DHT_NODES, sizeof(Node_format));
+ Node_format *clients = (Node_format *)mem_valloc(dht->mem, MAX_SAVED_DHT_NODES, sizeof(Node_format));
if (clients == nullptr) {
LOGGER_ERROR(dht->log, "could not allocate %u nodes", MAX_SAVED_DHT_NODES);
@@ -2826,10 +2739,11 @@ void dht_save(const DHT *dht, uint8_t *data)
}
}
- state_write_section_header(old_data, DHT_STATE_COOKIE_TYPE, pack_nodes(dht->log, data, sizeof(Node_format) * num,
- clients, num), DHT_STATE_TYPE_NODES);
+ state_write_section_header(
+ old_data, DHT_STATE_COOKIE_TYPE, pack_nodes(dht->log, data, sizeof(Node_format) * num, clients, num),
+ DHT_STATE_TYPE_NODES);
- free(clients);
+ mem_delete(dht->mem, clients);
}
/** Bootstrap from this number of nodes every time `dht_connect_after_load()` is called */
@@ -2847,7 +2761,7 @@ int dht_connect_after_load(DHT *dht)
/* DHT is connected, stop. */
if (dht_non_lan_connected(dht)) {
- free(dht->loaded_nodes_list);
+ mem_delete(dht->mem, dht->loaded_nodes_list);
dht->loaded_nodes_list = nullptr;
dht->loaded_num_nodes = 0;
return 0;
@@ -2873,24 +2787,28 @@ static State_Load_Status dht_load_state_callback(void *outer, const uint8_t *dat
break;
}
- free(dht->loaded_nodes_list);
+ mem_delete(dht->mem, dht->loaded_nodes_list);
+
// Copy to loaded_clients_list
- dht->loaded_nodes_list = (Node_format *)calloc(MAX_SAVED_DHT_NODES, sizeof(Node_format));
+ Node_format *nodes = (Node_format *)mem_valloc(dht->mem, MAX_SAVED_DHT_NODES, sizeof(Node_format));
- if (dht->loaded_nodes_list == nullptr) {
+ if (nodes == nullptr) {
LOGGER_ERROR(dht->log, "could not allocate %u nodes", MAX_SAVED_DHT_NODES);
dht->loaded_num_nodes = 0;
break;
}
- const int num = unpack_nodes(dht->loaded_nodes_list, MAX_SAVED_DHT_NODES, nullptr, data, length, false);
+ const int num = unpack_nodes(nodes, MAX_SAVED_DHT_NODES, nullptr, data, length, false);
- if (num > 0) {
- dht->loaded_num_nodes = num;
- } else {
+ if (num < 0) {
+ // Unpack error happened, we ignore it.
dht->loaded_num_nodes = 0;
+ } else {
+ dht->loaded_num_nodes = num;
}
+ dht->loaded_nodes_list = nodes;
+
break;
}
@@ -2962,6 +2880,36 @@ bool dht_non_lan_connected(const DHT *dht)
return false;
}
+uint16_t dht_get_num_closelist(const DHT *dht)
+{
+ uint16_t num_valid_close_clients = 0;
+ for (uint32_t i = 0; i < LCLIENT_LIST; ++i) {
+ const Client_data *const client = dht_get_close_client(dht, i);
+
+ // check if client is valid
+ if (!(assoc_timeout(dht->cur_time, &client->assoc4) && assoc_timeout(dht->cur_time, &client->assoc6))) {
+ ++num_valid_close_clients;
+ }
+ }
+
+ return num_valid_close_clients;
+}
+
+uint16_t dht_get_num_closelist_announce_capable(const DHT *dht)
+{
+ uint16_t num_valid_close_clients_with_cap = 0;
+ for (uint32_t i = 0; i < LCLIENT_LIST; ++i) {
+ const Client_data *const client = dht_get_close_client(dht, i);
+
+ // check if client is valid
+ if (!(assoc_timeout(dht->cur_time, &client->assoc4) && assoc_timeout(dht->cur_time, &client->assoc6)) && client->announce_node) {
+ ++num_valid_close_clients_with_cap;
+ }
+ }
+
+ return num_valid_close_clients_with_cap;
+}
+
unsigned int ipport_self_copy(const DHT *dht, IP_Port *dest)
{
ipport_reset(dest);
diff --git a/protocols/Tox/libtox/src/toxcore/DHT.h b/protocols/Tox/libtox/src/toxcore/DHT.h
index 86ac4f9d40..19a9e1d937 100644
--- a/protocols/Tox/libtox/src/toxcore/DHT.h
+++ b/protocols/Tox/libtox/src/toxcore/DHT.h
@@ -14,6 +14,7 @@
#include "attributes.h"
#include "crypto_core.h"
#include "logger.h"
+#include "mem.h"
#include "mono_time.h"
#include "network.h"
#include "ping_array.h"
@@ -22,20 +23,6 @@
extern "C" {
#endif
-/* Encryption and signature keys definition */
-#define ENC_PUBLIC_KEY_SIZE CRYPTO_PUBLIC_KEY_SIZE
-#define ENC_SECRET_KEY_SIZE CRYPTO_SECRET_KEY_SIZE
-#define SIG_PUBLIC_KEY_SIZE CRYPTO_SIGN_PUBLIC_KEY_SIZE
-#define SIG_SECRET_KEY_SIZE CRYPTO_SIGN_SECRET_KEY_SIZE
-
-/* Size of the group chat_id */
-#define CHAT_ID_SIZE SIG_PUBLIC_KEY_SIZE
-
-/* Extended keys for group chats */
-#define EXT_SECRET_KEY_SIZE (ENC_SECRET_KEY_SIZE + SIG_SECRET_KEY_SIZE)
-#define EXT_PUBLIC_KEY_SIZE (ENC_PUBLIC_KEY_SIZE + SIG_PUBLIC_KEY_SIZE)
-
-
/* Maximum size of a signature (may be smaller) */
#define SIGNATURE_SIZE CRYPTO_SIGNATURE_SIZE
/** Maximum number of clients stored per friend. */
@@ -168,7 +155,7 @@ typedef struct Client_data {
#ifdef CHECK_ANNOUNCE_NODE
/* Responded to data search? */
bool announce_node;
-#endif
+#endif /* CHECK_ANNOUNCE_NODE */
} Client_data;
/*----------------------------------------------------------------------------------*/
@@ -203,38 +190,18 @@ non_null() const Client_data *dht_friend_client(const DHT_Friend *dht_friend, si
*/
int packed_node_size(Family ip_family);
-/** @brief Pack an IP_Port structure into data of max size length.
- *
- * Packed_length is the offset of data currently packed.
- *
- * @return size of packed IP_Port data on success.
- * @retval -1 on failure.
- */
-non_null()
-int pack_ip_port(const Logger *logger, uint8_t *data, uint16_t length, const IP_Port *ip_port);
-
/** @brief Encrypt plain and write resulting DHT packet into packet with max size length.
*
* @return size of packet on success.
* @retval -1 on failure.
*/
non_null()
-int dht_create_packet(const Random *rng,
+int dht_create_packet(const Memory *mem, const Random *rng,
const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE],
- const uint8_t *shared_key, const uint8_t type,
+ const uint8_t *shared_key, uint8_t type,
const uint8_t *plain, size_t plain_length,
uint8_t *packet, size_t length);
-/** @brief Unpack IP_Port structure from data of max size length into ip_port.
- *
- * len_processed is the offset of data currently unpacked.
- *
- * @return size of unpacked ip_port on success.
- * @retval -1 on failure.
- */
-non_null()
-int unpack_ip_port(IP_Port *ip_port, const uint8_t *data, uint16_t length, bool tcp_enabled);
-
/** @brief Pack number of nodes into data of maxlength length.
*
* @return length of packed nodes on success.
@@ -256,8 +223,8 @@ int unpack_nodes(Node_format *nodes, uint16_t max_num_nodes, uint16_t *processed
/*----------------------------------------------------------------------------------*/
-typedef int cryptopacket_handler_cb(void *object, const IP_Port *ip_port, const uint8_t *source_pubkey,
- const uint8_t *data, uint16_t len, void *userdata);
+typedef int cryptopacket_handler_cb(void *object, const IP_Port *source, const uint8_t *source_pubkey,
+ const uint8_t *packet, uint16_t length, void *userdata);
typedef struct DHT DHT;
@@ -369,7 +336,8 @@ unsigned int bit_by_bit_cmp(const uint8_t *pk1, const uint8_t *pk2);
*/
non_null()
bool add_to_list(
- Node_format *nodes_list, uint32_t length, const uint8_t *pk, const IP_Port *ip_port, const uint8_t *cmp_pk);
+ 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]);
/** Return 1 if node can be added to close list, 0 if it can't. */
non_null()
@@ -379,22 +347,23 @@ bool node_addable_to_close_list(DHT *dht, const uint8_t *public_key, const IP_Po
/** Set node as announce node. */
non_null()
void set_announce_node(DHT *dht, const uint8_t *public_key);
-#endif
+#endif /* CHECK_ANNOUNCE_NODE */
/**
- * Get the (maximum MAX_SENT_NODES) closest nodes to public_key we know
+ * @brief Get the (maximum MAX_SENT_NODES) closest nodes to public_key we know
* and put them in nodes_list (must be MAX_SENT_NODES big).
*
- * sa_family = family (IPv4 or IPv6) (0 if we don't care)?
- * is_LAN = return some LAN ips (true or false)
- * want_announce: return only nodes which implement the dht announcements protocol.
+ * @param sa_family family (IPv4 or IPv6) (0 if we don't care)?
+ * @param is_lan return some LAN ips (true or false).
+ * @param want_announce return only nodes which implement the dht announcements protocol.
*
* @return the number of nodes returned.
*/
non_null()
-int get_close_nodes(const DHT *dht, const uint8_t *public_key, Node_format *nodes_list, Family sa_family,
- bool is_LAN, bool want_announce);
-
+int get_close_nodes(
+ const DHT *dht, const uint8_t *public_key,
+ Node_format nodes_list[MAX_SENT_NODES], Family sa_family,
+ bool is_lan, bool want_announce);
/** @brief Put up to max_num nodes in nodes from the random friends.
*
@@ -436,12 +405,12 @@ bool dht_bootstrap(DHT *dht, const IP_Port *ip_port, const uint8_t *public_key);
* @param ipv6enabled if false, the resolving sticks STRICTLY to IPv4 addresses.
* Otherwise, the resolving looks for IPv6 addresses first, then IPv4 addresses.
*
- * @retval 1 if the address could be converted into an IP address
- * @retval 0 otherwise
+ * @retval true if the address could be converted into an IP address
+ * @retval false otherwise
*/
non_null()
-int dht_bootstrap_from_address(DHT *dht, const char *address, bool ipv6enabled,
- uint16_t port, const uint8_t *public_key);
+bool dht_bootstrap_from_address(DHT *dht, const char *address, bool ipv6enabled,
+ uint16_t port, const uint8_t *public_key);
/** @brief Start sending packets after DHT loaded_friends_list and loaded_clients_list are set.
*
@@ -494,8 +463,8 @@ int dht_load(DHT *dht, const uint8_t *data, uint32_t length);
/** Initialize DHT. */
non_null()
-DHT *new_dht(const Logger *log, const Random *rng, const Network *ns, Mono_Time *mono_time, Networking_Core *net,
- bool hole_punching_enabled, bool lan_discovery_enabled);
+DHT *new_dht(const Logger *log, const Memory *mem, const Random *rng, const Network *ns,
+ Mono_Time *mono_time, Networking_Core *net, bool hole_punching_enabled, bool lan_discovery_enabled);
nullable(1)
void kill_dht(DHT *dht);
@@ -514,6 +483,24 @@ bool dht_isconnected(const DHT *dht);
non_null()
bool dht_non_lan_connected(const DHT *dht);
+/**
+ * This function returns the ratio of close dht nodes that are known to support announce/store.
+ * This function returns the number of DHT nodes in the closelist.
+ *
+ * @return number
+ */
+non_null()
+uint16_t dht_get_num_closelist(const DHT *dht);
+
+/**
+ * This function returns the number of DHT nodes in the closelist,
+ * that are capable to store annouce data (introduced in version 0.2.18).
+ *
+ * @return number
+ */
+non_null()
+uint16_t dht_get_num_closelist_announce_capable(const DHT *dht);
+
/** @brief Attempt to add client with ip_port and public_key to the friends client list
* and close_clientlist.
*
@@ -536,7 +523,7 @@ non_null()
unsigned int ipport_self_copy(const DHT *dht, IP_Port *dest);
#ifdef __cplusplus
-} // extern "C"
+} /* extern "C" */
#endif
-#endif
+#endif /* C_TOXCORE_TOXCORE_DHT_H */
diff --git a/protocols/Tox/libtox/src/toxcore/LAN_discovery.c b/protocols/Tox/libtox/src/toxcore/LAN_discovery.c
index ef44d3b552..aead975911 100644
--- a/protocols/Tox/libtox/src/toxcore/LAN_discovery.c
+++ b/protocols/Tox/libtox/src/toxcore/LAN_discovery.c
@@ -9,7 +9,6 @@
#include "LAN_discovery.h"
#include <stdlib.h>
-#include <string.h>
#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
// The mingw32/64 Windows library warns about including winsock2.h after
@@ -21,7 +20,7 @@
#include <ws2tcpip.h>
#include <iphlpapi.h>
-#endif
+#endif /* WIN32 */
#if defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__)
#include <netinet/in.h>
@@ -29,23 +28,23 @@
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
-#endif
+#endif /* Linux/BSD */
#ifdef __linux__
-#include <linux/netdevice.h>
-#endif
+#include <linux/if.h>
+#endif /* Linux */
#if defined(__FreeBSD__) || defined(__DragonFly__)
#include <net/if.h>
-#endif
+#endif /* BSD */
+#include "attributes.h"
#include "ccompat.h"
#include "crypto_core.h"
-#include "util.h"
+#include "network.h"
#define MAX_INTERFACES 16
-
struct Broadcast_Info {
uint32_t count;
IP ips[MAX_INTERFACES];
@@ -62,35 +61,38 @@ static Broadcast_Info *fetch_broadcast_info(const Network *ns)
return nullptr;
}
- IP_ADAPTER_INFO *pAdapterInfo = (IP_ADAPTER_INFO *)malloc(sizeof(IP_ADAPTER_INFO));
- unsigned long ulOutBufLen = sizeof(IP_ADAPTER_INFO);
+ IP_ADAPTER_INFO *adapter_info = (IP_ADAPTER_INFO *)malloc(sizeof(IP_ADAPTER_INFO));
- if (pAdapterInfo == nullptr) {
+ if (adapter_info == nullptr) {
free(broadcast);
return nullptr;
}
- if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) {
- free(pAdapterInfo);
- pAdapterInfo = (IP_ADAPTER_INFO *)malloc(ulOutBufLen);
+ unsigned long out_buf_len = sizeof(IP_ADAPTER_INFO);
+
+ if (GetAdaptersInfo(adapter_info, &out_buf_len) == ERROR_BUFFER_OVERFLOW) {
+ free(adapter_info);
+ IP_ADAPTER_INFO *new_adapter_info = (IP_ADAPTER_INFO *)malloc(out_buf_len);
- if (pAdapterInfo == nullptr) {
+ if (new_adapter_info == nullptr) {
free(broadcast);
return nullptr;
}
+
+ adapter_info = new_adapter_info;
}
- const int ret = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen);
+ const int ret = GetAdaptersInfo(adapter_info, &out_buf_len);
if (ret == NO_ERROR) {
- IP_ADAPTER_INFO *pAdapter = pAdapterInfo;
+ IP_ADAPTER_INFO *adapter = adapter_info;
- while (pAdapter != nullptr) {
+ while (adapter != nullptr) {
IP gateway = {0};
IP subnet_mask = {0};
- if (addr_parse_ip(pAdapter->IpAddressList.IpMask.String, &subnet_mask)
- && addr_parse_ip(pAdapter->GatewayList.IpAddress.String, &gateway)) {
+ if (addr_parse_ip(adapter->IpAddressList.IpMask.String, &subnet_mask)
+ && addr_parse_ip(adapter->GatewayList.IpAddress.String, &gateway)) {
if (net_family_is_ipv4(gateway.family) && net_family_is_ipv4(subnet_mask.family)) {
IP *ip = &broadcast->ips[broadcast->count];
ip->family = net_family_ipv4();
@@ -106,12 +108,12 @@ static Broadcast_Info *fetch_broadcast_info(const Network *ns)
}
}
- pAdapter = pAdapter->Next;
+ adapter = adapter->Next;
}
}
- if (pAdapterInfo != nullptr) {
- free(pAdapterInfo);
+ if (adapter_info != nullptr) {
+ free(adapter_info);
}
return broadcast;
@@ -140,14 +142,13 @@ static Broadcast_Info *fetch_broadcast_info(const Network *ns)
}
/* Configure ifconf for the ioctl call. */
- struct ifreq i_faces[MAX_INTERFACES];
- memset(i_faces, 0, sizeof(struct ifreq) * MAX_INTERFACES);
+ struct ifreq i_faces[MAX_INTERFACES] = {{{0}}};
struct ifconf ifc;
ifc.ifc_buf = (char *)i_faces;
ifc.ifc_len = sizeof(i_faces);
- if (ioctl(sock.sock, SIOCGIFCONF, &ifc) < 0) {
+ if (ioctl(net_socket_to_native(sock), SIOCGIFCONF, &ifc) < 0) {
kill_sock(ns, sock);
free(broadcast);
return nullptr;
@@ -162,7 +163,7 @@ static Broadcast_Info *fetch_broadcast_info(const Network *ns)
for (int i = 0; i < n; ++i) {
/* there are interfaces with are incapable of broadcast */
- if (ioctl(sock.sock, SIOCGIFBRDADDR, &i_faces[i]) < 0) {
+ if (ioctl(net_socket_to_native(sock), SIOCGIFBRDADDR, &i_faces[i]) < 0) {
continue;
}
@@ -201,7 +202,7 @@ static Broadcast_Info *fetch_broadcast_info(const Network *ns)
return (Broadcast_Info *)calloc(1, sizeof(Broadcast_Info));
}
-#endif
+#endif /* platforms */
/** @brief Send packet to all IPv4 broadcast addresses
*
@@ -238,16 +239,16 @@ static IP broadcast_ip(Family family_socket, Family family_broadcast)
/* `FF02::1` is - according to RFC 4291 - multicast all-nodes link-local */
/* `FE80::*:` MUST be exact, for that we would need to look over all
* interfaces and check in which status they are */
- ip.ip.v6.uint8[ 0] = 0xFF;
- ip.ip.v6.uint8[ 1] = 0x02;
+ ip.ip.v6.uint8[0] = 0xFF;
+ ip.ip.v6.uint8[1] = 0x02;
ip.ip.v6.uint8[15] = 0x01;
} else if (net_family_is_ipv4(family_broadcast)) {
ip.family = net_family_ipv6();
- ip.ip.v6 = ip6_broadcast;
+ ip.ip.v6 = get_ip6_broadcast();
}
} else if (net_family_is_ipv4(family_socket) && net_family_is_ipv4(family_broadcast)) {
ip.family = net_family_ipv4();
- ip.ip.v4 = ip4_broadcast;
+ ip.ip.v4 = get_ip4_broadcast();
}
return ip;
@@ -338,7 +339,6 @@ bool ip_is_lan(const IP *ip)
return false;
}
-
bool lan_discovery_send(const Networking_Core *net, const Broadcast_Info *broadcast, const uint8_t *dht_pk,
uint16_t port)
{
@@ -375,7 +375,6 @@ bool lan_discovery_send(const Networking_Core *net, const Broadcast_Info *broadc
return res;
}
-
Broadcast_Info *lan_discovery_init(const Network *ns)
{
return fetch_broadcast_info(ns);
diff --git a/protocols/Tox/libtox/src/toxcore/LAN_discovery.h b/protocols/Tox/libtox/src/toxcore/LAN_discovery.h
index 5d9c83335b..94e5d3581c 100644
--- a/protocols/Tox/libtox/src/toxcore/LAN_discovery.h
+++ b/protocols/Tox/libtox/src/toxcore/LAN_discovery.h
@@ -9,6 +9,7 @@
#ifndef C_TOXCORE_TOXCORE_LAN_DISCOVERY_H
#define C_TOXCORE_TOXCORE_LAN_DISCOVERY_H
+#include "attributes.h"
#include "network.h"
/**
@@ -53,4 +54,4 @@ bool ip_is_local(const IP *ip);
non_null()
bool ip_is_lan(const IP *ip);
-#endif // C_TOXCORE_TOXCORE_LAN_DISCOVERY_H
+#endif /* C_TOXCORE_TOXCORE_LAN_DISCOVERY_H */
diff --git a/protocols/Tox/libtox/src/toxcore/Messenger.c b/protocols/Tox/libtox/src/toxcore/Messenger.c
index 118c7d946c..947edef7e1 100644
--- a/protocols/Tox/libtox/src/toxcore/Messenger.c
+++ b/protocols/Tox/libtox/src/toxcore/Messenger.c
@@ -10,17 +10,34 @@
#include <assert.h>
#include <stdio.h>
-#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "DHT.h"
+#include "TCP_client.h"
+#include "TCP_connection.h"
+#include "TCP_server.h"
+#include "announce.h"
+#include "attributes.h"
+#include "bin_pack.h"
+#include "bin_unpack.h"
#include "ccompat.h"
+#include "crypto_core.h"
+#include "forwarding.h"
+#include "friend_connection.h"
+#include "friend_requests.h"
+#include "group_announce.h"
#include "group_chats.h"
+#include "group_common.h"
#include "group_onion_announce.h"
#include "logger.h"
+#include "mem.h"
#include "mono_time.h"
+#include "net_crypto.h"
#include "network.h"
+#include "onion.h"
+#include "onion_announce.h"
+#include "onion_client.h"
#include "state.h"
#include "util.h"
@@ -41,18 +58,18 @@ bool friend_is_valid(const Messenger *m, int32_t friendnumber)
/** @brief Set the size of the friend list to numfriends.
*
- * @retval -1 if realloc fails.
+ * @retval -1 if mem_vrealloc fails.
*/
non_null()
static int realloc_friendlist(Messenger *m, uint32_t num)
{
if (num == 0) {
- free(m->friendlist);
+ mem_delete(m->mem, m->friendlist);
m->friendlist = nullptr;
return 0;
}
- Friend *newfriendlist = (Friend *)realloc(m->friendlist, num * sizeof(Friend));
+ Friend *newfriendlist = (Friend *)mem_vrealloc(m->mem, m->friendlist, num, sizeof(Friend));
if (newfriendlist == nullptr) {
return -1;
@@ -122,25 +139,25 @@ void getaddress(const Messenger *m, uint8_t *address)
non_null()
static bool send_online_packet(Messenger *m, int friendcon_id)
{
- uint8_t packet = PACKET_ID_ONLINE;
- return write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, friendcon_id), &packet,
+ const uint8_t packet[1] = {PACKET_ID_ONLINE};
+ return write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, friendcon_id), packet,
sizeof(packet), false) != -1;
}
non_null()
static bool send_offline_packet(Messenger *m, int friendcon_id)
{
- uint8_t packet = PACKET_ID_OFFLINE;
- return write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, friendcon_id), &packet,
+ const uint8_t packet[1] = {PACKET_ID_OFFLINE};
+ return write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, friendcon_id), packet,
sizeof(packet), false) != -1;
}
non_null(1) nullable(4)
-static int m_handle_status(void *object, int i, bool status, void *userdata);
+static int m_handle_status(void *object, int friendcon_id, bool status, void *userdata);
non_null(1, 3) nullable(5)
-static int m_handle_packet(void *object, int i, const uint8_t *temp, uint16_t len, void *userdata);
+static int m_handle_packet(void *object, int friendcon_id, const uint8_t *data, uint16_t length, void *userdata);
non_null(1, 3) nullable(5)
-static int m_handle_lossy_packet(void *object, int friend_num, const uint8_t *packet, uint16_t length,
+static int m_handle_lossy_packet(void *object, int friendcon_id, const uint8_t *data, uint16_t length,
void *userdata);
non_null()
@@ -313,7 +330,7 @@ static int clear_receipts(Messenger *m, int32_t friendnumber)
while (receipts != nullptr) {
struct Receipts *temp_r = receipts->next;
- free(receipts);
+ mem_delete(m->mem, receipts);
receipts = temp_r;
}
@@ -329,7 +346,7 @@ static int add_receipt(Messenger *m, int32_t friendnumber, uint32_t packet_num,
return -1;
}
- struct Receipts *new_receipts = (struct Receipts *)calloc(1, sizeof(struct Receipts));
+ struct Receipts *new_receipts = (struct Receipts *)mem_alloc(m->mem, sizeof(struct Receipts));
if (new_receipts == nullptr) {
return -1;
@@ -387,7 +404,7 @@ bool m_create_group_connection(Messenger *m, GC_Chat *chat)
const int onion_friend_number = friend_conn_get_onion_friendnum(connection);
Onion_Friend *onion_friend = onion_get_friend(m->onion_c, (uint16_t)onion_friend_number);
- onion_friend_set_gc_public_key(onion_friend, get_chat_id(chat->chat_public_key));
+ onion_friend_set_gc_public_key(onion_friend, get_chat_id(&chat->chat_public_key));
onion_friend_set_gc_data(onion_friend, nullptr, 0);
return true;
@@ -430,7 +447,7 @@ static int do_receipts(Messenger *m, int32_t friendnumber, void *userdata)
struct Receipts *r_next = receipts->next;
- free(receipts);
+ mem_delete(m->mem, receipts);
m->friendlist[friendnumber].receipts_start = r_next;
@@ -456,7 +473,7 @@ int m_delfriend(Messenger *m, int32_t friendnumber)
}
if (m->friend_connectionstatuschange_internal != nullptr) {
- m->friend_connectionstatuschange_internal(m, friendnumber, 0, m->friend_connectionstatuschange_internal_userdata);
+ m->friend_connectionstatuschange_internal(m, friendnumber, false, m->friend_connectionstatuschange_internal_userdata);
}
clear_receipts(m, friendnumber);
@@ -575,7 +592,7 @@ int m_send_message_generic(Messenger *m, int32_t friendnumber, uint8_t type, con
memcpy(packet + 1, message, length);
const int64_t packet_num = write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c,
- m->friendlist[friendnumber].friendcon_id), packet, length + 1, false);
+ m->friendlist[friendnumber].friendcon_id), packet, length + 1, false);
if (packet_num == -1) {
return -4;
@@ -757,6 +774,37 @@ int m_set_statusmessage(Messenger *m, const uint8_t *status, uint16_t length)
return 0;
}
+non_null()
+static bool userstatus_from_int(uint8_t status, Userstatus *out)
+{
+ switch (status) {
+ case USERSTATUS_NONE: {
+ *out = USERSTATUS_NONE;
+ return true;
+ }
+
+ case USERSTATUS_AWAY: {
+ *out = USERSTATUS_AWAY;
+ return true;
+ }
+
+ case USERSTATUS_BUSY: {
+ *out = USERSTATUS_BUSY;
+ return true;
+ }
+
+ case USERSTATUS_INVALID: {
+ *out = USERSTATUS_INVALID;
+ return true;
+ }
+
+ default: {
+ *out = USERSTATUS_INVALID;
+ return false;
+ }
+ }
+}
+
int m_set_userstatus(Messenger *m, uint8_t status)
{
if (status >= USERSTATUS_INVALID) {
@@ -767,7 +815,7 @@ int m_set_userstatus(Messenger *m, uint8_t status)
return 0;
}
- m->userstatus = (Userstatus)status;
+ userstatus_from_int(status, &m->userstatus);
for (uint32_t i = 0; i < m->numfriends; ++i) {
m->friendlist[i].userstatus_sent = false;
@@ -810,7 +858,7 @@ int m_copy_statusmessage(const Messenger *m, int32_t friendnumber, uint8_t *buf,
const uint32_t msglen = min_u32(maxlen, m->friendlist[friendnumber].statusmessage_length);
memcpy(buf, m->friendlist[friendnumber].statusmessage, msglen);
- memset(buf + msglen, 0, maxlen - msglen);
+ memzero(buf + msglen, maxlen - msglen);
return msglen;
}
@@ -923,7 +971,7 @@ static int set_friend_statusmessage(const Messenger *m, int32_t friendnumber, co
non_null()
static void set_friend_userstatus(const Messenger *m, int32_t friendnumber, uint8_t status)
{
- m->friendlist[friendnumber].userstatus = (Userstatus)status;
+ userstatus_from_int(status, &m->friendlist[friendnumber].userstatus);
}
non_null()
@@ -1050,7 +1098,6 @@ static void set_friend_status(Messenger *m, int32_t friendnumber, uint8_t status
/*** CONFERENCES */
-
/** @brief Set the callback for conference invites. */
void m_callback_conference_invite(Messenger *m, m_conference_invite_cb *function)
{
@@ -1073,20 +1120,17 @@ bool send_conference_invite_packet(const Messenger *m, int32_t friendnumber, con
return write_cryptpacket_id(m, friendnumber, PACKET_ID_INVITE_CONFERENCE, data, length, false);
}
-
/** @brief Send a group invite packet.
*
* @retval true if success
*/
-bool send_group_invite_packet(const Messenger *m, uint32_t friendnumber, const uint8_t *data, uint16_t length)
+bool send_group_invite_packet(const Messenger *m, uint32_t friendnumber, const uint8_t *packet, uint16_t length)
{
- return write_cryptpacket_id(m, friendnumber, PACKET_ID_INVITE_GROUPCHAT, data, length, false);
+ return write_cryptpacket_id(m, friendnumber, PACKET_ID_INVITE_GROUPCHAT, packet, length, false);
}
-
/*** FILE SENDING */
-
/** @brief Set the callback for file send requests. */
void callback_file_sendrequest(Messenger *m, m_file_recv_cb *function)
{
@@ -1148,8 +1192,8 @@ int file_get_id(const Messenger *m, int32_t friendnumber, uint32_t filenumber, u
file_number = temp_filenum;
const struct File_Transfers *const ft = inbound
- ? &m->friendlist[friendnumber].file_receiving[file_number]
- : &m->friendlist[friendnumber].file_sending[file_number];
+ ? &m->friendlist[friendnumber].file_receiving[file_number]
+ : &m->friendlist[friendnumber].file_sending[file_number];
if (ft->status == FILESTATUS_NONE) {
return -2;
@@ -1176,7 +1220,8 @@ static bool file_sendrequest(const Messenger *m, int32_t friendnumber, uint8_t f
return false;
}
- VLA(uint8_t, packet, 1 + sizeof(file_type) + sizeof(filesize) + FILE_ID_LENGTH + filename_length);
+ const uint16_t packet_size = 1 + sizeof(file_type) + sizeof(filesize) + FILE_ID_LENGTH + filename_length;
+ VLA(uint8_t, packet, packet_size);
packet[0] = filenumber;
file_type = net_htonl(file_type);
memcpy(packet + 1, &file_type, sizeof(file_type));
@@ -1187,7 +1232,7 @@ static bool file_sendrequest(const Messenger *m, int32_t friendnumber, uint8_t f
memcpy(packet + 1 + sizeof(file_type) + sizeof(filesize) + FILE_ID_LENGTH, filename, filename_length);
}
- return write_cryptpacket_id(m, friendnumber, PACKET_ID_FILE_SENDREQUEST, packet, SIZEOF_VLA(packet), false);
+ return write_cryptpacket_id(m, friendnumber, PACKET_ID_FILE_SENDREQUEST, packet, packet_size, false);
}
/** @brief Send a file send request.
@@ -1254,7 +1299,8 @@ static bool send_file_control_packet(const Messenger *m, int32_t friendnumber, b
return false;
}
- VLA(uint8_t, packet, 3 + data_length);
+ const uint16_t packet_size = 3 + data_length;
+ VLA(uint8_t, packet, packet_size);
packet[0] = inbound ? 1 : 0;
packet[1] = filenumber;
@@ -1264,7 +1310,7 @@ static bool send_file_control_packet(const Messenger *m, int32_t friendnumber, b
memcpy(packet + 3, data, data_length);
}
- return write_cryptpacket_id(m, friendnumber, PACKET_ID_FILE_CONTROL, packet, SIZEOF_VLA(packet), false);
+ return write_cryptpacket_id(m, friendnumber, PACKET_ID_FILE_CONTROL, packet, packet_size, false);
}
/** @brief Send a file control request.
@@ -1454,7 +1500,8 @@ static int64_t send_file_data_packet(const Messenger *m, int32_t friendnumber, u
return -1;
}
- VLA(uint8_t, packet, 2 + length);
+ const uint16_t packet_size = 2 + length;
+ VLA(uint8_t, packet, packet_size);
packet[0] = PACKET_ID_FILE_DATA;
packet[1] = filenumber;
@@ -1463,7 +1510,7 @@ static int64_t send_file_data_packet(const Messenger *m, int32_t friendnumber, u
}
return write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c,
- m->friendlist[friendnumber].friendcon_id), packet, SIZEOF_VLA(packet), true);
+ m->friendlist[friendnumber].friendcon_id), packet, packet_size, true);
}
#define MAX_FILE_DATA_SIZE (MAX_CRYPTO_DATA_SIZE - 2)
@@ -1665,7 +1712,6 @@ static void do_reqchunk_filecb(Messenger *m, int32_t friendnumber, void *userdat
}
}
-
/** @brief Run this when the friend disconnects.
* Kill all current file transfers.
*/
@@ -1826,28 +1872,28 @@ bool m_msi_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data,
return write_cryptpacket_id(m, friendnumber, PACKET_ID_MSI, data, length, false);
}
-static int m_handle_lossy_packet(void *object, int friend_num, const uint8_t *packet, uint16_t length,
+static int m_handle_lossy_packet(void *object, int friendcon_id, const uint8_t *data, uint16_t length,
void *userdata)
{
Messenger *m = (Messenger *)object;
- if (!m_friend_exists(m, friend_num)) {
+ if (!m_friend_exists(m, friendcon_id)) {
return 1;
}
- if (packet[0] <= PACKET_ID_RANGE_LOSSY_AV_END) {
+ if (data[0] <= PACKET_ID_RANGE_LOSSY_AV_END) {
const RTP_Packet_Handler *const ph =
- &m->friendlist[friend_num].lossy_rtp_packethandlers[packet[0] % PACKET_ID_RANGE_LOSSY_AV_SIZE];
+ &m->friendlist[friendcon_id].lossy_rtp_packethandlers[data[0] % PACKET_ID_RANGE_LOSSY_AV_SIZE];
if (ph->function != nullptr) {
- return ph->function(m, friend_num, packet, length, ph->object);
+ return ph->function(m, friendcon_id, data, length, ph->object);
}
return 1;
}
if (m->lossy_packethandler != nullptr) {
- m->lossy_packethandler(m, friend_num, packet[0], packet, length, userdata);
+ m->lossy_packethandler(m, friendcon_id, data[0], data, length, userdata);
}
return 1;
@@ -1874,7 +1920,6 @@ int m_callback_rtp_packet(Messenger *m, int32_t friendnumber, uint8_t byte, m_lo
return 0;
}
-
/** @brief High level function to send custom lossy packets.
*
* TODO(oxij): this name is confusing, because this function sends both av and custom lossy packets.
@@ -1973,11 +2018,11 @@ int send_custom_lossless_packet(const Messenger *m, int32_t friendnumber, const
/** Function to filter out some friend requests*/
non_null()
-static int friend_already_added(const uint8_t *real_pk, void *data)
+static int friend_already_added(void *object, const uint8_t *public_key)
{
- const Messenger *m = (const Messenger *)data;
+ const Messenger *m = (const Messenger *)object;
- if (getfriend_id(m, real_pk) == -1) {
+ if (getfriend_id(m, public_key) == -1) {
return 0;
}
@@ -1987,16 +2032,16 @@ static int friend_already_added(const uint8_t *real_pk, void *data)
/** @brief Check for and handle a timed-out friend request.
*
* If the request has timed-out then the friend status is set back to FRIEND_ADDED.
- * @param i friendlist index of the timed-out friend
+ * @param friendcon_id friendlist index of the timed-out friend
* @param t time
*/
non_null(1) nullable(4)
-static void check_friend_request_timed_out(Messenger *m, uint32_t i, uint64_t t, void *userdata)
+static void check_friend_request_timed_out(Messenger *m, uint32_t friendcon_id, uint64_t t, void *userdata)
{
- Friend *f = &m->friendlist[i];
+ Friend *f = &m->friendlist[friendcon_id];
if (f->friendrequest_lastsent + f->friendrequest_timeout < t) {
- set_friend_status(m, i, FRIEND_ADDED, userdata);
+ set_friend_status(m, friendcon_id, FRIEND_ADDED, userdata);
/* Double the default timeout every time if friendrequest is assumed
* to have been sent unsuccessfully.
*/
@@ -2005,15 +2050,15 @@ static void check_friend_request_timed_out(Messenger *m, uint32_t i, uint64_t t,
}
non_null(1) nullable(4)
-static int m_handle_status(void *object, int i, bool status, void *userdata)
+static int m_handle_status(void *object, int friendcon_id, bool status, void *userdata)
{
Messenger *m = (Messenger *)object;
if (status) { /* Went online. */
- send_online_packet(m, m->friendlist[i].friendcon_id);
+ send_online_packet(m, m->friendlist[friendcon_id].friendcon_id);
} else { /* Went offline. */
- if (m->friendlist[i].status == FRIEND_ONLINE) {
- set_friend_status(m, i, FRIEND_CONFIRMED, userdata);
+ if (m->friendlist[friendcon_id].status == FRIEND_ONLINE) {
+ set_friend_status(m, friendcon_id, FRIEND_CONFIRMED, userdata);
}
}
@@ -2021,17 +2066,17 @@ static int m_handle_status(void *object, int i, bool status, void *userdata)
}
non_null(1, 3) nullable(5)
-static int m_handle_packet_offline(Messenger *m, const int i, const uint8_t *data, const uint16_t data_length, void *userdata)
+static int m_handle_packet_offline(Messenger *m, const int friendcon_id, const uint8_t *data, const uint16_t data_length, void *userdata)
{
if (data_length == 0) {
- set_friend_status(m, i, FRIEND_CONFIRMED, userdata);
+ set_friend_status(m, friendcon_id, FRIEND_CONFIRMED, userdata);
}
return 0;
}
non_null(1, 3) nullable(5)
-static int m_handle_packet_nickname(Messenger *m, const int i, const uint8_t *data, const uint16_t data_length, void *userdata)
+static int m_handle_packet_nickname(Messenger *m, const int friendcon_id, const uint8_t *data, const uint16_t data_length, void *userdata)
{
if (data_length > MAX_NAME_LENGTH) {
return 0;
@@ -2044,17 +2089,17 @@ static int m_handle_packet_nickname(Messenger *m, const int i, const uint8_t *da
/* inform of namechange before we overwrite the old name */
if (m->friend_namechange != nullptr) {
- m->friend_namechange(m, i, data_terminated, data_length, userdata);
+ m->friend_namechange(m, friendcon_id, data_terminated, data_length, userdata);
}
- memcpy(m->friendlist[i].name, data_terminated, data_length);
- m->friendlist[i].name_length = data_length;
+ memcpy(m->friendlist[friendcon_id].name, data_terminated, data_length);
+ m->friendlist[friendcon_id].name_length = data_length;
return 0;
}
non_null(1, 3) nullable(5)
-static int m_handle_packet_statusmessage(Messenger *m, const int i, const uint8_t *data, const uint16_t data_length, void *userdata)
+static int m_handle_packet_statusmessage(Messenger *m, const int friendcon_id, const uint8_t *data, const uint16_t data_length, void *userdata)
{
if (data_length > MAX_STATUSMESSAGE_LENGTH) {
return 0;
@@ -2066,38 +2111,37 @@ static int m_handle_packet_statusmessage(Messenger *m, const int i, const uint8_
data_terminated[data_length] = 0;
if (m->friend_statusmessagechange != nullptr) {
- m->friend_statusmessagechange(m, i, data_terminated, data_length, userdata);
+ m->friend_statusmessagechange(m, friendcon_id, data_terminated, data_length, userdata);
}
- set_friend_statusmessage(m, i, data_terminated, data_length);
+ set_friend_statusmessage(m, friendcon_id, data_terminated, data_length);
return 0;
}
non_null(1, 3) nullable(5)
-static int m_handle_packet_userstatus(Messenger *m, const int i, const uint8_t *data, const uint16_t data_length, void *userdata)
+static int m_handle_packet_userstatus(Messenger *m, const int friendcon_id, const uint8_t *data, const uint16_t data_length, void *userdata)
{
if (data_length != 1) {
return 0;
}
- const Userstatus status = (Userstatus)data[0];
-
- if (status >= USERSTATUS_INVALID) {
+ Userstatus status;
+ if (!userstatus_from_int(data[0], &status)) {
return 0;
}
if (m->friend_userstatuschange != nullptr) {
- m->friend_userstatuschange(m, i, status, userdata);
+ m->friend_userstatuschange(m, friendcon_id, status, userdata);
}
- set_friend_userstatus(m, i, status);
+ set_friend_userstatus(m, friendcon_id, status);
return 0;
}
non_null(1, 3) nullable(5)
-static int m_handle_packet_typing(Messenger *m, const int i, const uint8_t *data, const uint16_t data_length, void *userdata)
+static int m_handle_packet_typing(Messenger *m, const int friendcon_id, const uint8_t *data, const uint16_t data_length, void *userdata)
{
if (data_length != 1) {
return 0;
@@ -2105,17 +2149,17 @@ static int m_handle_packet_typing(Messenger *m, const int i, const uint8_t *data
const bool typing = data[0] != 0;
- set_friend_typing(m, i, typing);
+ set_friend_typing(m, friendcon_id, typing);
if (m->friend_typingchange != nullptr) {
- m->friend_typingchange(m, i, typing, userdata);
+ m->friend_typingchange(m, friendcon_id, typing, userdata);
}
return 0;
}
non_null(1, 3) nullable(6)
-static int m_handle_packet_message(Messenger *m, const int i, const uint8_t *data, const uint16_t data_length, const Message_Type message_type, void *userdata)
+static int m_handle_packet_message(Messenger *m, const int friendcon_id, const uint8_t *data, const uint16_t data_length, const Message_Type message_type, void *userdata)
{
if (data_length == 0) {
return 0;
@@ -2130,28 +2174,28 @@ static int m_handle_packet_message(Messenger *m, const int i, const uint8_t *dat
message_terminated[message_length] = 0;
if (m->friend_message != nullptr) {
- m->friend_message(m, i, message_type, message_terminated, message_length, userdata);
+ m->friend_message(m, friendcon_id, message_type, message_terminated, message_length, userdata);
}
return 0;
}
non_null(1, 3) nullable(5)
-static int m_handle_packet_invite_conference(Messenger *m, const int i, const uint8_t *data, const uint16_t data_length, void *userdata)
+static int m_handle_packet_invite_conference(Messenger *m, const int friendcon_id, const uint8_t *data, const uint16_t data_length, void *userdata)
{
if (data_length == 0) {
return 0;
}
if (m->conference_invite != nullptr) {
- m->conference_invite(m, i, data, data_length, userdata);
+ m->conference_invite(m, friendcon_id, data, data_length, userdata);
}
return 0;
}
non_null(1, 3) nullable(5)
-static int m_handle_packet_file_sendrequest(Messenger *m, const int i, const uint8_t *data, const uint16_t data_length, void *userdata)
+static int m_handle_packet_file_sendrequest(Messenger *m, const int friendcon_id, const uint8_t *data, const uint16_t data_length, void *userdata)
{
const unsigned int head_length = 1 + sizeof(uint32_t) + sizeof(uint64_t) + FILE_ID_LENGTH;
@@ -2167,7 +2211,7 @@ static int m_handle_packet_file_sendrequest(Messenger *m, const int i, const uin
return 0;
}
-#endif
+#endif /* UINT8_MAX >= MAX_CONCURRENT_FILE_PIPES */
uint64_t filesize;
uint32_t file_type;
@@ -2181,7 +2225,7 @@ static int m_handle_packet_file_sendrequest(Messenger *m, const int i, const uin
file_type = net_ntohl(file_type);
net_unpack_u64(data + 1 + sizeof(uint32_t), &filesize);
- struct File_Transfers *ft = &m->friendlist[i].file_receiving[filenumber];
+ struct File_Transfers *ft = &m->friendlist[friendcon_id].file_receiving[filenumber];
if (ft->status != FILESTATUS_NONE) {
return 0;
@@ -2208,7 +2252,7 @@ static int m_handle_packet_file_sendrequest(Messenger *m, const int i, const uin
real_filenumber <<= 16;
if (m->file_sendrequest != nullptr) {
- m->file_sendrequest(m, i, real_filenumber, file_type, filesize, filename, filename_length,
+ m->file_sendrequest(m, friendcon_id, real_filenumber, file_type, filesize, filename, filename_length,
userdata);
}
@@ -2216,7 +2260,7 @@ static int m_handle_packet_file_sendrequest(Messenger *m, const int i, const uin
}
non_null(1, 3) nullable(5)
-static int m_handle_packet_file_control(Messenger *m, const int i, const uint8_t *data, const uint16_t data_length, void *userdata)
+static int m_handle_packet_file_control(Messenger *m, const int friendcon_id, const uint8_t *data, const uint16_t data_length, void *userdata)
{
if (data_length < 3) {
return 0;
@@ -2235,9 +2279,9 @@ static int m_handle_packet_file_control(Messenger *m, const int i, const uint8_t
return 0;
}
-#endif
+#endif /* UINT8_MAX >= MAX_CONCURRENT_FILE_PIPES */
- if (handle_filecontrol(m, i, outbound, filenumber, control_type, data + 3, data_length - 3, userdata) == -1) {
+ if (handle_filecontrol(m, friendcon_id, outbound, filenumber, control_type, data + 3, data_length - 3, userdata) == -1) {
// TODO(iphydf): Do something different here? Right now, this
// check is pointless.
return 0;
@@ -2247,7 +2291,7 @@ static int m_handle_packet_file_control(Messenger *m, const int i, const uint8_t
}
non_null(1, 3) nullable(5)
-static int m_handle_packet_file_data(Messenger *m, const int i, const uint8_t *data, const uint16_t data_length, void *userdata)
+static int m_handle_packet_file_data(Messenger *m, const int friendcon_id, const uint8_t *data, const uint16_t data_length, void *userdata)
{
if (data_length < 1) {
return 0;
@@ -2261,9 +2305,9 @@ static int m_handle_packet_file_data(Messenger *m, const int i, const uint8_t *d
return 0;
}
-#endif
+#endif /* UINT8_MAX >= MAX_CONCURRENT_FILE_PIPES */
- struct File_Transfers *ft = &m->friendlist[i].file_receiving[filenumber];
+ struct File_Transfers *ft = &m->friendlist[friendcon_id].file_receiving[filenumber];
if (ft->status != FILESTATUS_TRANSFERRING) {
return 0;
@@ -2288,7 +2332,7 @@ static int m_handle_packet_file_data(Messenger *m, const int i, const uint8_t *d
}
if (m->file_filedata != nullptr) {
- m->file_filedata(m, i, real_filenumber, position, file_data, file_data_length, userdata);
+ m->file_filedata(m, friendcon_id, real_filenumber, position, file_data, file_data_length, userdata);
}
ft->transferred += file_data_length;
@@ -2300,7 +2344,7 @@ static int m_handle_packet_file_data(Messenger *m, const int i, const uint8_t *d
/* Full file received. */
if (m->file_filedata != nullptr) {
- m->file_filedata(m, i, real_filenumber, position, file_data, file_data_length, userdata);
+ m->file_filedata(m, friendcon_id, real_filenumber, position, file_data, file_data_length, userdata);
}
}
@@ -2313,24 +2357,22 @@ static int m_handle_packet_file_data(Messenger *m, const int i, const uint8_t *d
}
non_null(1, 3) nullable(5)
-static int m_handle_packet_msi(Messenger *m, const int i, const uint8_t *data, const uint16_t data_length, void *userdata)
+static int m_handle_packet_msi(Messenger *m, const int friendcon_id, const uint8_t *data, const uint16_t data_length, void *userdata)
{
if (data_length == 0) {
return 0;
}
if (m->msi_packet != nullptr) {
- m->msi_packet(m, i, data, data_length, m->msi_packet_userdata);
+ m->msi_packet(m, friendcon_id, data, data_length, m->msi_packet_userdata);
}
return 0;
}
non_null(1, 3) nullable(5)
-static int m_handle_packet_invite_groupchat(Messenger *m, const int i, const uint8_t *data, const uint16_t data_length, void *userdata)
+static int m_handle_packet_invite_groupchat(Messenger *m, const int friendcon_id, const uint8_t *data, const uint16_t data_length, void *userdata)
{
-#ifndef VANILLA_NACL
-
// first two bytes are messenger packet type and group invite type
if (data_length < 2 + GC_JOIN_DATA_LENGTH) {
return 0;
@@ -2342,36 +2384,35 @@ static int m_handle_packet_invite_groupchat(Messenger *m, const int i, const uin
if (m->group_invite != nullptr && data[1] == GROUP_INVITE && data_length != 2 + GC_JOIN_DATA_LENGTH) {
if (group_not_added(m->group_handler, join_data, join_data_len)) {
- m->group_invite(m, i, join_data, GC_JOIN_DATA_LENGTH,
+ m->group_invite(m, friendcon_id, join_data, GC_JOIN_DATA_LENGTH,
join_data + GC_JOIN_DATA_LENGTH, join_data_len - GC_JOIN_DATA_LENGTH, userdata);
}
} else if (invite_type == GROUP_INVITE_ACCEPTED) {
- handle_gc_invite_accepted_packet(m->group_handler, i, join_data, join_data_len);
+ handle_gc_invite_accepted_packet(m->group_handler, friendcon_id, join_data, join_data_len);
} else if (invite_type == GROUP_INVITE_CONFIRMATION) {
- handle_gc_invite_confirmed_packet(m->group_handler, i, join_data, join_data_len);
+ handle_gc_invite_confirmed_packet(m->group_handler, friendcon_id, join_data, join_data_len);
}
-#endif // VANILLA_NACL
-
return 0;
}
non_null(1, 3) nullable(5)
-static int m_handle_packet(void *object, int i, const uint8_t *temp, uint16_t len, void *userdata)
+static int m_handle_packet(void *object, int friendcon_id, const uint8_t *data, uint16_t length, void *userdata)
{
- if (len == 0) {
+ Messenger *m = (Messenger *)object;
+
+ if (length == 0) {
return -1;
}
- Messenger *m = (Messenger *)object;
- const uint8_t packet_id = temp[0];
- const uint8_t *data = temp + 1;
- const uint16_t data_length = len - 1;
-
- if (m->friendlist[i].status != FRIEND_ONLINE) {
- if (packet_id == PACKET_ID_ONLINE && len == 1) {
- set_friend_status(m, i, FRIEND_ONLINE, userdata);
- send_online_packet(m, m->friendlist[i].friendcon_id);
+ const uint8_t packet_id = data[0];
+ const uint8_t *payload = data + 1;
+ const uint16_t payload_length = length - 1;
+
+ if (m->friendlist[friendcon_id].status != FRIEND_ONLINE) {
+ if (packet_id == PACKET_ID_ONLINE && length == 1) {
+ set_friend_status(m, friendcon_id, FRIEND_ONLINE, userdata);
+ send_online_packet(m, m->friendlist[friendcon_id].friendcon_id);
} else {
return -1;
}
@@ -2380,34 +2421,34 @@ static int m_handle_packet(void *object, int i, const uint8_t *temp, uint16_t le
switch (packet_id) {
// TODO(Green-Sky): now all return 0 on error AND success, make errors errors?
case PACKET_ID_OFFLINE:
- return m_handle_packet_offline(m, i, data, data_length, userdata);
+ return m_handle_packet_offline(m, friendcon_id, payload, payload_length, userdata);
case PACKET_ID_NICKNAME:
- return m_handle_packet_nickname(m, i, data, data_length, userdata);
+ return m_handle_packet_nickname(m, friendcon_id, payload, payload_length, userdata);
case PACKET_ID_STATUSMESSAGE:
- return m_handle_packet_statusmessage(m, i, data, data_length, userdata);
+ return m_handle_packet_statusmessage(m, friendcon_id, payload, payload_length, userdata);
case PACKET_ID_USERSTATUS:
- return m_handle_packet_userstatus(m, i, data, data_length, userdata);
+ return m_handle_packet_userstatus(m, friendcon_id, payload, payload_length, userdata);
case PACKET_ID_TYPING:
- return m_handle_packet_typing(m, i, data, data_length, userdata);
+ return m_handle_packet_typing(m, friendcon_id, payload, payload_length, userdata);
case PACKET_ID_MESSAGE:
- return m_handle_packet_message(m, i, data, data_length, MESSAGE_NORMAL, userdata);
+ return m_handle_packet_message(m, friendcon_id, payload, payload_length, MESSAGE_NORMAL, userdata);
case PACKET_ID_ACTION:
- return m_handle_packet_message(m, i, data, data_length, MESSAGE_ACTION, userdata);
+ return m_handle_packet_message(m, friendcon_id, payload, payload_length, MESSAGE_ACTION, userdata);
case PACKET_ID_INVITE_CONFERENCE:
- return m_handle_packet_invite_conference(m, i, data, data_length, userdata);
+ return m_handle_packet_invite_conference(m, friendcon_id, payload, payload_length, userdata);
case PACKET_ID_FILE_SENDREQUEST:
- return m_handle_packet_file_sendrequest(m, i, data, data_length, userdata);
+ return m_handle_packet_file_sendrequest(m, friendcon_id, payload, payload_length, userdata);
case PACKET_ID_FILE_CONTROL:
- return m_handle_packet_file_control(m, i, data, data_length, userdata);
+ return m_handle_packet_file_control(m, friendcon_id, payload, payload_length, userdata);
case PACKET_ID_FILE_DATA:
- return m_handle_packet_file_data(m, i, data, data_length, userdata);
+ return m_handle_packet_file_data(m, friendcon_id, payload, payload_length, userdata);
case PACKET_ID_MSI:
- return m_handle_packet_msi(m, i, data, data_length, userdata);
- case PACKET_ID_INVITE_GROUPCHAT:
- return m_handle_packet_invite_groupchat(m, i, data, data_length, userdata);
+ return m_handle_packet_msi(m, friendcon_id, payload, payload_length, userdata);
+ case PACKET_ID_INVITE_GROUPCHAT:
+ return m_handle_packet_invite_groupchat(m, friendcon_id, payload, payload_length, userdata);
}
- return handle_custom_lossless_packet(object, i, temp, len, userdata);
+ return handle_custom_lossless_packet(object, friendcon_id, data, length, userdata);
}
non_null(1) nullable(2)
@@ -2418,8 +2459,8 @@ static void do_friends(Messenger *m, void *userdata)
for (uint32_t i = 0; i < m->numfriends; ++i) {
if (m->friendlist[i].status == FRIEND_ADDED) {
const int fr = send_friend_request_packet(m->fr_c, m->friendlist[i].friendcon_id, m->friendlist[i].friendrequest_nospam,
- m->friendlist[i].info,
- m->friendlist[i].info_size);
+ m->friendlist[i].info,
+ m->friendlist[i].info_size);
if (fr >= 0) {
set_friend_status(m, i, FRIEND_REQUESTED, userdata);
@@ -2485,7 +2526,6 @@ static void m_connection_status_callback(Messenger *m, void *userdata)
}
}
-
#define DUMPING_CLIENTS_FRIENDS_EVERY_N_SECONDS 60UL
#define IDSTRING_LEN (CRYPTO_PUBLIC_KEY_SIZE * 2 + 1)
@@ -2533,7 +2573,6 @@ uint32_t messenger_run_interval(const Messenger *m)
*
* @retval true if success.
*/
-#ifndef VANILLA_NACL
non_null()
static bool self_announce_group(const Messenger *m, GC_Chat *chat, Onion_Friend *onion_friend)
{
@@ -2549,14 +2588,14 @@ static bool self_announce_group(const Messenger *m, GC_Chat *chat, Onion_Friend
}
announce.base_announce.tcp_relays_count = (uint8_t)tcp_num;
- announce.base_announce.ip_port_is_set = (uint8_t)(ip_port_is_set ? 1 : 0);
+ announce.base_announce.ip_port_is_set = ip_port_is_set;
if (ip_port_is_set) {
memcpy(&announce.base_announce.ip_port, &chat->self_ip_port, sizeof(IP_Port));
}
- memcpy(announce.base_announce.peer_public_key, chat->self_public_key, ENC_PUBLIC_KEY_SIZE);
- memcpy(announce.chat_public_key, get_chat_id(chat->chat_public_key), ENC_PUBLIC_KEY_SIZE);
+ memcpy(announce.base_announce.peer_public_key, chat->self_public_key.enc, ENC_PUBLIC_KEY_SIZE);
+ memcpy(announce.chat_public_key, get_chat_id(&chat->chat_public_key), ENC_PUBLIC_KEY_SIZE);
uint8_t gc_data[GCA_MAX_DATA_LENGTH];
const int length = gca_pack_public_announce(m->log, gc_data, GCA_MAX_DATA_LENGTH, &announce);
@@ -2578,7 +2617,7 @@ static bool self_announce_group(const Messenger *m, GC_Chat *chat, Onion_Friend
if (tcp_num > 0) {
pk_copy(chat->announced_tcp_relay_pk, announce.base_announce.tcp_relays[0].public_key);
} else {
- memset(chat->announced_tcp_relay_pk, 0, sizeof(chat->announced_tcp_relay_pk));
+ memzero(chat->announced_tcp_relay_pk, sizeof(chat->announced_tcp_relay_pk));
}
LOGGER_DEBUG(chat->log, "Published group announce. TCP relays: %d, UDP status: %d", tcp_num,
@@ -2609,7 +2648,6 @@ static void do_gc_onion_friends(const Messenger *m)
}
}
}
-#endif // VANILLA_NACL
/** @brief The main loop that needs to be run at least 20 times per second. */
void do_messenger(Messenger *m, void *userdata)
@@ -2627,7 +2665,7 @@ void do_messenger(Messenger *m, void *userdata)
if (m->tcp_server != nullptr) {
/* Add self tcp server. */
IP_Port local_ip_port;
- local_ip_port.port = m->options.tcp_server_port;
+ local_ip_port.port = net_htons(m->options.tcp_server_port);
local_ip_port.ip.family = net_family_ipv4();
local_ip_port.ip.ip.v4 = get_ip4_loopback();
add_tcp_relay(m->net_crypto, &local_ip_port, tcp_server_public_key(m->tcp_server));
@@ -2640,18 +2678,16 @@ void do_messenger(Messenger *m, void *userdata)
}
if (m->tcp_server != nullptr) {
- do_TCP_server(m->tcp_server, m->mono_time);
+ do_tcp_server(m->tcp_server, m->mono_time);
}
do_net_crypto(m->net_crypto, userdata);
do_onion_client(m->onion_c);
do_friend_connections(m->fr_c, userdata);
do_friends(m, userdata);
-#ifndef VANILLA_NACL
do_gc(m->group_handler, userdata);
do_gca(m->mono_time, m->group_announce);
do_gc_onion_friends(m);
-#endif
m_connection_status_callback(m, userdata);
if (mono_time_get(m->mono_time) > m->lastdump + DUMPING_CLIENTS_FRIENDS_EVERY_N_SECONDS) {
@@ -2682,7 +2718,6 @@ void do_messenger(Messenger *m, void *userdata)
}
}
-
/* dht contains additional "friends" (requests) */
const uint32_t num_dhtfriends = dht_get_num_friends(m->dht);
VLA(int32_t, m2dht, num_dhtfriends);
@@ -2850,7 +2885,6 @@ static uint8_t *friend_save(const struct Saved_Friend *temp, uint8_t *data)
return data;
}
-
non_null()
static const uint8_t *friend_load(struct Saved_Friend *temp, const uint8_t *data)
{
@@ -2888,7 +2922,6 @@ static const uint8_t *friend_load(struct Saved_Friend *temp, const uint8_t *data
return data;
}
-
non_null()
static uint32_t m_state_plugins_size(const Messenger *m)
{
@@ -2915,15 +2948,16 @@ bool m_register_state_plugin(Messenger *m, State_Type type, m_state_size_cb *siz
m_state_load_cb *load_callback,
m_state_save_cb *save_callback)
{
- Messenger_State_Plugin *temp = (Messenger_State_Plugin *)realloc(m->options.state_plugins,
- sizeof(Messenger_State_Plugin) * (m->options.state_plugins_length + 1));
+ const uint32_t new_length = m->options.state_plugins_length + 1;
+ Messenger_State_Plugin *temp = (Messenger_State_Plugin *)mem_vrealloc(
+ m->mem, m->options.state_plugins, new_length, sizeof(Messenger_State_Plugin));
if (temp == nullptr) {
return false;
}
m->options.state_plugins = temp;
- ++m->options.state_plugins_length;
+ m->options.state_plugins_length = new_length;
const uint8_t index = m->options.state_plugins_length - 1;
m->options.state_plugins[index].type = type;
@@ -2987,6 +3021,7 @@ static State_Load_Status load_nospam_keys(Messenger *m, const uint8_t *data, uin
load_secret_key(m->net_crypto, data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE);
if (!pk_equal(data + sizeof(uint32_t), nc_get_self_public_key(m->net_crypto))) {
+ LOGGER_ERROR(m->log, "public key stored in savedata does not match its secret key");
return STATE_LOAD_STATUS_ERROR;
}
@@ -3076,7 +3111,7 @@ static uint8_t *friends_list_save(const Messenger *m, uint8_t *data)
assert(next_data - cur_data == friend_size());
#ifdef __LP64__
assert(memcmp(cur_data, &temp, friend_size()) == 0);
-#endif
+#endif /* __LP64__ */
cur_data = next_data;
++num;
}
@@ -3132,7 +3167,6 @@ static State_Load_Status friends_list_load(Messenger *m, const uint8_t *data, ui
return STATE_LOAD_STATUS_CONTINUE;
}
-#ifndef VANILLA_NACL
non_null()
static void pack_groupchats(const GC_Session *c, Bin_Pack *bp)
{
@@ -3151,17 +3185,18 @@ static void pack_groupchats(const GC_Session *c, Bin_Pack *bp)
}
non_null()
-static bool pack_groupchats_handler(Bin_Pack *bp, const void *obj)
+static bool pack_groupchats_handler(const void *obj, const Logger *logger, Bin_Pack *bp)
{
- pack_groupchats((const GC_Session *)obj, bp);
+ const GC_Session *session = (const GC_Session *)obj;
+ pack_groupchats(session, bp);
return true; // TODO(iphydf): Return bool from pack functions.
}
non_null()
static uint32_t saved_groups_size(const Messenger *m)
{
- GC_Session *c = m->group_handler;
- return bin_pack_obj_size(pack_groupchats_handler, c);
+ const GC_Session *session = m->group_handler;
+ return bin_pack_obj_size(pack_groupchats_handler, session, m->log);
}
non_null()
@@ -3183,7 +3218,7 @@ static uint8_t *groups_save(const Messenger *m, uint8_t *data)
data = state_write_section_header(data, STATE_COOKIE_TYPE, len, STATE_TYPE_GROUPS);
- if (!bin_pack_obj(pack_groupchats_handler, c, data, len)) {
+ if (!bin_pack_obj(pack_groupchats_handler, c, m->log, data, len)) {
LOGGER_FATAL(m->log, "failed to pack group chats into buffer of length %u", len);
return data;
}
@@ -3196,36 +3231,43 @@ static uint8_t *groups_save(const Messenger *m, uint8_t *data)
}
non_null()
-static State_Load_Status groups_load(Messenger *m, const uint8_t *data, uint32_t length)
+static bool handle_groups_load(void *obj, Bin_Unpack *bu)
{
- Bin_Unpack *bu = bin_unpack_new(data, length);
- if (bu == nullptr) {
- LOGGER_ERROR(m->log, "failed to allocate binary unpacker");
- return STATE_LOAD_STATUS_ERROR;
- }
+ Messenger *m = (Messenger *)obj;
uint32_t num_groups;
if (!bin_unpack_array(bu, &num_groups)) {
LOGGER_ERROR(m->log, "msgpack failed to unpack groupchats array: expected array");
- bin_unpack_free(bu);
- return STATE_LOAD_STATUS_ERROR;
+ return false;
}
- LOGGER_DEBUG(m->log, "Loading %u groups (length %u)", num_groups, length);
+ LOGGER_DEBUG(m->log, "Loading %u groups", num_groups);
for (uint32_t i = 0; i < num_groups; ++i) {
const int group_number = gc_group_load(m->group_handler, bu);
if (group_number < 0) {
LOGGER_WARNING(m->log, "Failed to load group %u", i);
+ // Can't recover trivially. We may need to skip over some data here.
+ break;
}
}
- bin_unpack_free(bu);
+ LOGGER_DEBUG(m->log, "Successfully loaded %u groups", gc_count_groups(m->group_handler));
+
+ return true;
+}
+
+non_null()
+static State_Load_Status groups_load(Messenger *m, const uint8_t *data, uint32_t length)
+{
+ if (!bin_unpack_obj(handle_groups_load, m, data, length)) {
+ LOGGER_ERROR(m->log, "msgpack failed to unpack groupchats array");
+ return STATE_LOAD_STATUS_ERROR;
+ }
return STATE_LOAD_STATUS_CONTINUE;
}
-#endif /* VANILLA_NACL */
// name state plugin
non_null()
@@ -3368,10 +3410,9 @@ static uint32_t path_node_size(const Messenger *m)
non_null()
static uint8_t *save_path_nodes(const Messenger *m, uint8_t *data)
{
- Node_format nodes[NUM_SAVED_PATH_NODES];
+ Node_format nodes[NUM_SAVED_PATH_NODES] = {{{0}}};
uint8_t *temp_data = data;
data = state_write_section_header(data, STATE_COOKIE_TYPE, 0, STATE_TYPE_PATH_NODE);
- memset(nodes, 0, sizeof(nodes));
const unsigned int num = onion_backup_nodes(m->onion_c, nodes, NUM_SAVED_PATH_NODES);
const int l = pack_nodes(m->log, data, NUM_SAVED_PATH_NODES * packed_node_size(net_family_tcp_ipv6()), nodes, num);
@@ -3413,9 +3454,9 @@ static void m_register_default_plugins(Messenger *m)
m_register_state_plugin(m, STATE_TYPE_STATUSMESSAGE, status_message_size, load_status_message,
save_status_message);
m_register_state_plugin(m, STATE_TYPE_STATUS, status_size, load_status, save_status);
-#ifndef VANILLA_NACL
- m_register_state_plugin(m, STATE_TYPE_GROUPS, saved_groups_size, groups_load, groups_save);
-#endif
+ if (m->options.groups_persistence_enabled) {
+ m_register_state_plugin(m, STATE_TYPE_GROUPS, saved_groups_size, groups_load, groups_save);
+ }
m_register_state_plugin(m, STATE_TYPE_TCP_RELAY, tcp_relay_size, load_tcp_relays, save_tcp_relays);
m_register_state_plugin(m, STATE_TYPE_PATH_NODE, path_node_size, load_path_nodes, save_path_nodes);
}
@@ -3502,7 +3543,8 @@ static void m_handle_friend_request(
*
* if error is not NULL it will be set to one of the values in the enum above.
*/
-Messenger *new_messenger(Mono_Time *mono_time, const Random *rng, const Network *ns, Messenger_Options *options, Messenger_Error *error)
+Messenger *new_messenger(Mono_Time *mono_time, const Memory *mem, const Random *rng, const Network *ns,
+ Messenger_Options *options, Messenger_Error *error)
{
if (options == nullptr) {
return nullptr;
@@ -3512,20 +3554,21 @@ Messenger *new_messenger(Mono_Time *mono_time, const Random *rng, const Network
*error = MESSENGER_ERROR_OTHER;
}
- Messenger *m = (Messenger *)calloc(1, sizeof(Messenger));
+ Messenger *m = (Messenger *)mem_alloc(mem, sizeof(Messenger));
if (m == nullptr) {
return nullptr;
}
m->mono_time = mono_time;
+ m->mem = mem;
m->rng = rng;
m->ns = ns;
m->fr = friendreq_new();
if (m->fr == nullptr) {
- free(m);
+ mem_delete(mem, m);
return nullptr;
}
@@ -3533,7 +3576,7 @@ Messenger *new_messenger(Mono_Time *mono_time, const Random *rng, const Network
if (m->log == nullptr) {
friendreq_kill(m->fr);
- free(m);
+ mem_delete(mem, m);
return nullptr;
}
@@ -3548,82 +3591,90 @@ Messenger *new_messenger(Mono_Time *mono_time, const Random *rng, const Network
}
if (options->udp_disabled) {
- m->net = new_networking_no_udp(m->log, m->ns);
+ m->net = new_networking_no_udp(m->log, m->mem, m->ns);
} else {
IP ip;
ip_init(&ip, options->ipv6enabled);
- m->net = new_networking_ex(m->log, m->ns, &ip, options->port_range[0], options->port_range[1], &net_err);
+ m->net = new_networking_ex(m->log, m->mem, m->ns, &ip, options->port_range[0], options->port_range[1], &net_err);
}
if (m->net == nullptr) {
friendreq_kill(m->fr);
- logger_kill(m->log);
- free(m);
if (error != nullptr && net_err == 1) {
+ LOGGER_WARNING(m->log, "network initialisation failed (no ports available)");
*error = MESSENGER_ERROR_PORT;
}
+ logger_kill(m->log);
+ mem_delete(mem, m);
return nullptr;
}
- m->dht = new_dht(m->log, m->rng, m->ns, m->mono_time, m->net, options->hole_punching_enabled, options->local_discovery_enabled);
+ m->dht = new_dht(m->log, m->mem, m->rng, m->ns, m->mono_time, m->net, options->hole_punching_enabled, options->local_discovery_enabled);
if (m->dht == nullptr) {
kill_networking(m->net);
friendreq_kill(m->fr);
logger_kill(m->log);
- free(m);
+ mem_delete(mem, m);
return nullptr;
}
- m->net_crypto = new_net_crypto(m->log, m->rng, m->ns, m->mono_time, m->dht, &options->proxy_info);
+ 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);
logger_kill(m->log);
- free(m);
+ mem_delete(mem, m);
return nullptr;
}
-#ifndef VANILLA_NACL
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);
friendreq_kill(m->fr);
logger_kill(m->log);
- free(m);
+ mem_delete(mem, m);
return nullptr;
}
-#endif /* VANILLA_NACL */
-
if (options->dht_announcements_enabled) {
m->forwarding = new_forwarding(m->log, m->rng, m->mono_time, m->dht);
- m->announce = new_announcements(m->log, m->rng, m->mono_time, m->forwarding);
+ if (m->forwarding != nullptr) {
+ m->announce = new_announcements(m->log, m->mem, m->rng, m->mono_time, m->forwarding);
+ } else {
+ m->announce = nullptr;
+ }
} else {
m->forwarding = nullptr;
m->announce = nullptr;
}
- m->onion = new_onion(m->log, m->mono_time, m->rng, m->dht);
- m->onion_a = new_onion_announce(m->log, m->rng, m->mono_time, m->dht);
- m->onion_c = new_onion_client(m->log, m->rng, m->mono_time, m->net_crypto);
- m->fr_c = new_friend_connections(m->log, m->mono_time, m->ns, m->onion_c, options->local_discovery_enabled);
+ m->onion = new_onion(m->log, m->mem, m->mono_time, m->rng, m->dht);
+ m->onion_a = new_onion_announce(m->log, m->mem, m->rng, m->mono_time, m->dht);
+ m->onion_c = new_onion_client(m->log, m->mem, m->rng, m->mono_time, m->net_crypto);
+ if (m->onion_c != nullptr) {
+ m->fr_c = new_friend_connections(m->log, m->mono_time, m->ns, m->onion_c, options->local_discovery_enabled);
+ }
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);
-#ifndef VANILLA_NACL
kill_gca(m->group_announce);
-#endif /* VANILLA_NACL */
kill_friend_connections(m->fr_c);
kill_announcements(m->announce);
kill_forwarding(m->forwarding);
@@ -3632,16 +3683,17 @@ Messenger *new_messenger(Mono_Time *mono_time, const Random *rng, const Network
kill_networking(m->net);
friendreq_kill(m->fr);
logger_kill(m->log);
- free(m);
+ mem_delete(mem, m);
return nullptr;
}
-#ifndef VANILLA_NACL
gca_onion_init(m->group_announce, m->onion_a);
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);
@@ -3654,27 +3706,24 @@ Messenger *new_messenger(Mono_Time *mono_time, const Random *rng, const Network
kill_networking(m->net);
friendreq_kill(m->fr);
logger_kill(m->log);
- free(m);
+ mem_delete(mem, m);
return nullptr;
}
-#endif /* VANILLA_NACL */
-
if (options->tcp_server_port != 0) {
- m->tcp_server = new_TCP_server(m->log, m->rng, m->ns, options->ipv6enabled, 1, &options->tcp_server_port,
- dht_get_self_secret_key(m->dht), m->onion, m->forwarding);
+ m->tcp_server = new_tcp_server(m->log, m->mem, m->rng, m->ns, options->ipv6enabled, 1,
+ &options->tcp_server_port, dht_get_self_secret_key(m->dht),
+ 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
kill_dht_groupchats(m->group_handler);
-#endif
kill_friend_connections(m->fr_c);
kill_onion_client(m->onion_c);
-#ifndef VANILLA_NACL
kill_gca(m->group_announce);
-#endif
kill_announcements(m->announce);
kill_forwarding(m->forwarding);
kill_net_crypto(m->net_crypto);
@@ -3682,7 +3731,7 @@ Messenger *new_messenger(Mono_Time *mono_time, const Random *rng, const Network
kill_networking(m->net);
friendreq_kill(m->fr);
logger_kill(m->log);
- free(m);
+ mem_delete(mem, m);
if (error != nullptr) {
*error = MESSENGER_ERROR_TCP_SERVER;
@@ -3721,19 +3770,15 @@ void kill_messenger(Messenger *m)
}
if (m->tcp_server != nullptr) {
- kill_TCP_server(m->tcp_server);
+ kill_tcp_server(m->tcp_server);
}
kill_onion(m->onion);
kill_onion_announce(m->onion_a);
-#ifndef VANILLA_NACL
kill_dht_groupchats(m->group_handler);
-#endif
kill_friend_connections(m->fr_c);
kill_onion_client(m->onion_c);
-#ifndef VANILLA_NACL
kill_gca(m->group_announce);
-#endif
kill_announcements(m->announce);
kill_forwarding(m->forwarding);
kill_net_crypto(m->net_crypto);
@@ -3744,12 +3789,12 @@ void kill_messenger(Messenger *m)
clear_receipts(m, i);
}
- logger_kill(m->log);
- free(m->friendlist);
+ mem_delete(m->mem, m->friendlist);
friendreq_kill(m->fr);
- free(m->options.state_plugins);
- free(m);
+ mem_delete(m->mem, m->options.state_plugins);
+ logger_kill(m->log);
+ mem_delete(m->mem, m);
}
bool m_is_receiving_file(Messenger *m)
diff --git a/protocols/Tox/libtox/src/toxcore/Messenger.h b/protocols/Tox/libtox/src/toxcore/Messenger.h
index 8279815277..cace3340b2 100644
--- a/protocols/Tox/libtox/src/toxcore/Messenger.h
+++ b/protocols/Tox/libtox/src/toxcore/Messenger.h
@@ -10,15 +10,25 @@
#ifndef C_TOXCORE_TOXCORE_MESSENGER_H
#define C_TOXCORE_TOXCORE_MESSENGER_H
+#include "DHT.h"
+#include "TCP_client.h"
#include "TCP_server.h"
#include "announce.h"
+#include "attributes.h"
+#include "crypto_core.h"
#include "forwarding.h"
#include "friend_connection.h"
#include "friend_requests.h"
#include "group_announce.h"
#include "group_common.h"
#include "logger.h"
+#include "mem.h"
+#include "mono_time.h"
#include "net_crypto.h"
+#include "network.h"
+#include "onion.h"
+#include "onion_announce.h"
+#include "onion_client.h"
#include "state.h"
#define MAX_NAME_LENGTH 128
@@ -29,7 +39,6 @@
/* This cannot be bigger than 256 */
#define MAX_CONCURRENT_FILE_PIPES 256
-
#define FRIEND_ADDRESS_SIZE (CRYPTO_PUBLIC_KEY_SIZE + sizeof(uint32_t) + sizeof(uint16_t))
typedef enum Message_Type {
@@ -41,7 +50,7 @@ typedef enum Message_Type {
#ifndef MESSENGER_DEFINED
#define MESSENGER_DEFINED
typedef struct Messenger Messenger;
-#endif // MESSENGER_DEFINED
+#endif /* MESSENGER_DEFINED */
// Returns the size of the data
typedef uint32_t m_state_size_cb(const Messenger *m);
@@ -69,6 +78,7 @@ typedef struct Messenger_Options {
bool hole_punching_enabled;
bool local_discovery_enabled;
bool dht_announcements_enabled;
+ bool groups_persistence_enabled;
logger_cb *log_callback;
void *log_context;
@@ -78,7 +88,6 @@ typedef struct Messenger_Options {
uint8_t state_plugins_length;
} Messenger_Options;
-
struct Receipts {
uint32_t packet_num;
uint32_t msg_id;
@@ -108,7 +117,6 @@ typedef enum Friend_Add_Error {
FAERR_NOMEM = -8,
} Friend_Add_Error;
-
/** Default start timeout in seconds between friend requests. */
#define FRIENDREQUEST_TIMEOUT 5
@@ -166,7 +174,6 @@ typedef enum Filekind {
FILEKIND_AVATAR,
} Filekind;
-
typedef void m_self_connection_status_cb(Messenger *m, Onion_Connection_Status connection_status, void *user_data);
typedef void m_friend_status_cb(Messenger *m, uint32_t friend_number, unsigned int status, void *user_data);
typedef void m_friend_connection_status_cb(Messenger *m, uint32_t friend_number, unsigned int connection_status,
@@ -194,14 +201,14 @@ typedef void m_friend_lossy_packet_cb(Messenger *m, uint32_t friend_number, uint
typedef void m_friend_lossless_packet_cb(Messenger *m, uint32_t friend_number, uint8_t packet_id, const uint8_t *data,
size_t length, void *user_data);
typedef void m_friend_connectionstatuschange_internal_cb(Messenger *m, uint32_t friend_number,
- uint8_t connection_status, void *user_data);
+ bool is_online, void *user_data);
typedef void m_conference_invite_cb(Messenger *m, uint32_t friend_number, const uint8_t *cookie, uint16_t length,
void *user_data);
-typedef void m_group_invite_cb(const Messenger *m, uint32_t friendnumber, const uint8_t *data, size_t length,
- const uint8_t *group_name, size_t group_name_length, void *userdata);
+typedef void m_group_invite_cb(const Messenger *m, uint32_t friend_number, const uint8_t *invite_data, size_t length,
+ const uint8_t *group_name, size_t group_name_length, void *user_data);
typedef void m_msi_packet_cb(Messenger *m, uint32_t friend_number, const uint8_t *data, uint16_t length,
void *user_data);
-typedef int m_lossy_rtp_packet_cb(Messenger *m, uint32_t friendnumber, const uint8_t *data, uint16_t len, void *object);
+typedef int m_lossy_rtp_packet_cb(Messenger *m, uint32_t friend_number, const uint8_t *data, uint16_t length, void *object);
typedef struct RTP_Packet_Handler {
m_lossy_rtp_packet_cb *function;
@@ -245,6 +252,7 @@ typedef struct Friend {
struct Messenger {
Logger *log;
Mono_Time *mono_time;
+ const Memory *mem;
const Random *rng;
const Network *ns;
@@ -296,7 +304,7 @@ struct Messenger {
m_friend_connectionstatuschange_internal_cb *friend_connectionstatuschange_internal;
void *friend_connectionstatuschange_internal_userdata;
- struct Group_Chats *conferences_object; /* Set by new_groupchats()*/
+ struct Group_Chats *conferences_object;
m_conference_invite_cb *conference_invite;
m_group_invite_cb *group_invite;
@@ -358,7 +366,6 @@ void getaddress(const Messenger *m, uint8_t *address);
non_null()
int32_t m_addfriend(Messenger *m, const uint8_t *address, const uint8_t *data, uint16_t length);
-
/** @brief Add a friend without sending a friendrequest.
* @return the friend number if success.
* @retval -3 if user's own key.
@@ -448,7 +455,6 @@ non_null(1, 4) nullable(6)
int m_send_message_generic(Messenger *m, int32_t friendnumber, uint8_t type, const uint8_t *message, uint32_t length,
uint32_t *message_id);
-
/** @brief Set the name and name_length of a friend.
*
* name must be a string of maximum MAX_NAME_LENGTH length.
@@ -539,7 +545,6 @@ non_null() int m_copy_self_statusmessage(const Messenger *m, uint8_t *buf);
non_null() uint8_t m_get_userstatus(const Messenger *m, int32_t friendnumber);
non_null() uint8_t m_get_self_userstatus(const Messenger *m);
-
/** @brief returns timestamp of last time friendnumber was seen online or 0 if never seen.
* if friendnumber is invalid this function will return UINT64_MAX.
*/
@@ -613,7 +618,6 @@ non_null() void m_callback_connectionstatus(Messenger *m, m_friend_connection_st
non_null() void m_callback_connectionstatus_internal_av(
Messenger *m, m_friend_connectionstatuschange_internal_cb *function, void *userdata);
-
/** @brief Set the callback for typing changes. */
non_null() void m_callback_core_connection(Messenger *m, m_self_connection_status_cb *function);
@@ -628,7 +632,6 @@ void m_callback_conference_invite(Messenger *m, m_conference_invite_cb *function
non_null(1) nullable(2)
void m_callback_group_invite(Messenger *m, m_group_invite_cb *function);
-
/** @brief Send a conference invite packet.
*
* return true on success
@@ -645,16 +648,13 @@ bool send_conference_invite_packet(const Messenger *m, int32_t friendnumber, con
* return true on success
*/
non_null()
-bool send_group_invite_packet(const Messenger *m, uint32_t friendnumber, const uint8_t *data, uint16_t length);
-
+bool send_group_invite_packet(const Messenger *m, uint32_t friendnumber, const uint8_t *packet, uint16_t length);
/*** FILE SENDING */
-
/** @brief Set the callback for file send requests. */
non_null() void callback_file_sendrequest(Messenger *m, m_file_recv_cb *function);
-
/** @brief Set the callback for file control requests. */
non_null() void callback_file_control(Messenger *m, m_file_recv_control_cb *function);
@@ -664,7 +664,6 @@ non_null() void callback_file_data(Messenger *m, m_file_recv_chunk_cb *function)
/** @brief Set the callback for file request chunk. */
non_null() void callback_file_reqchunk(Messenger *m, m_file_chunk_request_cb *function);
-
/** @brief Copy the file transfer file id to file_id
*
* @retval 0 on success.
@@ -779,7 +778,6 @@ non_null() void custom_lossy_packet_registerhandler(Messenger *m, m_friend_lossy
non_null()
int m_send_custom_lossy_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint32_t length);
-
/** @brief Set handlers for custom lossless packets. */
non_null()
void custom_lossless_packet_registerhandler(Messenger *m, m_friend_lossless_packet_cb *lossless_packethandler);
@@ -813,7 +811,8 @@ typedef enum Messenger_Error {
* if error is not NULL it will be set to one of the values in the enum above.
*/
non_null()
-Messenger *new_messenger(Mono_Time *mono_time, const Random *rng, const Network *ns, Messenger_Options *options, Messenger_Error *error);
+Messenger *new_messenger(Mono_Time *mono_time, const Memory *mem, const Random *rng, const Network *ns,
+ Messenger_Options *options, Messenger_Error *error);
/** @brief Run this before closing shop.
*
@@ -888,4 +887,4 @@ uint32_t copy_friendlist(const Messenger *m, uint32_t *out_list, uint32_t list_s
non_null()
bool m_is_receiving_file(Messenger *m);
-#endif
+#endif /* C_TOXCORE_TOXCORE_MESSENGER_H */
diff --git a/protocols/Tox/libtox/src/toxcore/TCP_client.c b/protocols/Tox/libtox/src/toxcore/TCP_client.c
index 1bc0964004..2b8c6e448f 100644
--- a/protocols/Tox/libtox/src/toxcore/TCP_client.c
+++ b/protocols/Tox/libtox/src/toxcore/TCP_client.c
@@ -8,13 +8,19 @@
*/
#include "TCP_client.h"
+#include <assert.h>
#include <stdio.h>
-#include <stdlib.h>
#include <string.h>
#include "TCP_common.h"
+#include "attributes.h"
#include "ccompat.h"
+#include "crypto_core.h"
+#include "forwarding.h"
+#include "logger.h"
+#include "mem.h"
#include "mono_time.h"
+#include "network.h"
#include "util.h"
typedef struct TCP_Client_Conn {
@@ -101,12 +107,12 @@ void tcp_con_set_custom_uint(TCP_Client_Connection *con, uint32_t value)
* @retval false on failure
*/
non_null()
-static bool connect_sock_to(const Logger *logger, Socket sock, const IP_Port *ip_port, const TCP_Proxy_Info *proxy_info)
+static bool connect_sock_to(const Logger *logger, const Memory *mem, Socket sock, const IP_Port *ip_port, const TCP_Proxy_Info *proxy_info)
{
if (proxy_info->proxy_type != TCP_PROXY_NONE) {
- return net_connect(logger, sock, &proxy_info->ip_port);
+ return net_connect(mem, logger, sock, &proxy_info->ip_port);
} else {
- return net_connect(logger, sock, ip_port);
+ return net_connect(mem, logger, sock, ip_port);
}
}
@@ -117,9 +123,9 @@ static bool connect_sock_to(const Logger *logger, Socket sock, const IP_Port *ip
non_null()
static int proxy_http_generate_connection_request(TCP_Client_Connection *tcp_conn)
{
- char one[] = "CONNECT ";
- char two[] = " HTTP/1.1\nHost: ";
- char three[] = "\r\n\r\n";
+ const char one[] = "CONNECT ";
+ const char two[] = " HTTP/1.1\nHost: ";
+ const char three[] = "\r\n\r\n";
char ip[TOX_INET6_ADDRSTRLEN];
@@ -148,11 +154,11 @@ static int proxy_http_generate_connection_request(TCP_Client_Connection *tcp_con
non_null()
static int proxy_http_read_connection_response(const Logger *logger, const TCP_Client_Connection *tcp_conn)
{
- char success[] = "200";
+ const char success[] = "200";
uint8_t data[16]; // draining works the best if the length is a power of 2
- const int ret = read_TCP_packet(logger, tcp_conn->con.ns, tcp_conn->con.sock, data, sizeof(data) - 1,
- &tcp_conn->con.ip_port);
+ const TCP_Connection *con0 = &tcp_conn->con;
+ const int ret = read_tcp_packet(logger, con0->mem, con0->ns, con0->sock, data, sizeof(data) - 1, &con0->ip_port);
if (ret == -1) {
return 0;
@@ -167,9 +173,10 @@ static int proxy_http_read_connection_response(const Logger *logger, const TCP_C
while (data_left > 0) {
uint8_t temp_data[16];
const uint16_t temp_data_size = min_u16(data_left, sizeof(temp_data));
+ const TCP_Connection *con = &tcp_conn->con;
- if (read_TCP_packet(logger, tcp_conn->con.ns, tcp_conn->con.sock, temp_data, temp_data_size,
- &tcp_conn->con.ip_port) == -1) {
+ if (read_tcp_packet(logger, con->mem, con->ns, con->sock, temp_data, temp_data_size,
+ &con->ip_port) == -1) {
LOGGER_ERROR(logger, "failed to drain TCP data (but ignoring failure)");
return 1;
}
@@ -183,14 +190,16 @@ static int proxy_http_read_connection_response(const Logger *logger, const TCP_C
return -1;
}
-#define TCP_SOCKS5_PROXY_HS_VERSION_SOCKS5 0x05
-#define TCP_SOCKS5_PROXY_HS_COMM_ESTABLISH_REQUEST 0x01
-#define TCP_SOCKS5_PROXY_HS_COMM_REQUEST_GRANTED 0x00
-#define TCP_SOCKS5_PROXY_HS_AUTH_METHODS_SUPPORTED 0x01
-#define TCP_SOCKS5_PROXY_HS_NO_AUTH 0x00
-#define TCP_SOCKS5_PROXY_HS_RESERVED 0x00
-#define TCP_SOCKS5_PROXY_HS_ADDR_TYPE_IPV4 0x01
-#define TCP_SOCKS5_PROXY_HS_ADDR_TYPE_IPV6 0x04
+enum Tcp_Socks5_Proxy_Hs {
+ TCP_SOCKS5_PROXY_HS_VERSION_SOCKS5 = 0x05,
+ TCP_SOCKS5_PROXY_HS_COMM_ESTABLISH_REQUEST = 0x01,
+ TCP_SOCKS5_PROXY_HS_COMM_REQUEST_GRANTED = 0x00,
+ TCP_SOCKS5_PROXY_HS_AUTH_METHODS_SUPPORTED = 0x01,
+ TCP_SOCKS5_PROXY_HS_NO_AUTH = 0x00,
+ TCP_SOCKS5_PROXY_HS_RESERVED = 0x00,
+ TCP_SOCKS5_PROXY_HS_ADDR_TYPE_IPV4 = 0x01,
+ TCP_SOCKS5_PROXY_HS_ADDR_TYPE_IPV6 = 0x04,
+};
non_null()
static void proxy_socks5_generate_greetings(TCP_Client_Connection *tcp_conn)
@@ -212,7 +221,8 @@ non_null()
static int socks5_read_handshake_response(const Logger *logger, const TCP_Client_Connection *tcp_conn)
{
uint8_t data[2];
- const int ret = read_TCP_packet(logger, tcp_conn->con.ns, tcp_conn->con.sock, data, sizeof(data), &tcp_conn->con.ip_port);
+ const TCP_Connection *con = &tcp_conn->con;
+ const int ret = read_tcp_packet(logger, con->mem, con->ns, con->sock, data, sizeof(data), &con->ip_port);
if (ret == -1) {
return 0;
@@ -262,7 +272,8 @@ static int proxy_socks5_read_connection_response(const Logger *logger, const TCP
{
if (net_family_is_ipv4(tcp_conn->ip_port.ip.family)) {
uint8_t data[4 + sizeof(IP4) + sizeof(uint16_t)];
- const int ret = read_TCP_packet(logger, tcp_conn->con.ns, tcp_conn->con.sock, data, sizeof(data), &tcp_conn->con.ip_port);
+ const TCP_Connection *con = &tcp_conn->con;
+ const int ret = read_tcp_packet(logger, con->mem, con->ns, con->sock, data, sizeof(data), &con->ip_port);
if (ret == -1) {
return 0;
@@ -273,7 +284,8 @@ static int proxy_socks5_read_connection_response(const Logger *logger, const TCP
}
} else {
uint8_t data[4 + sizeof(IP6) + sizeof(uint16_t)];
- int ret = read_TCP_packet(logger, tcp_conn->con.ns, tcp_conn->con.sock, data, sizeof(data), &tcp_conn->con.ip_port);
+ const TCP_Connection *con = &tcp_conn->con;
+ const int ret = read_tcp_packet(logger, con->mem, con->ns, con->sock, data, sizeof(data), &con->ip_port);
if (ret == -1) {
return 0;
@@ -301,7 +313,7 @@ static int generate_handshake(TCP_Client_Connection *tcp_conn)
memcpy(tcp_conn->con.last_packet, tcp_conn->self_public_key, CRYPTO_PUBLIC_KEY_SIZE);
random_nonce(tcp_conn->con.rng, tcp_conn->con.last_packet + CRYPTO_PUBLIC_KEY_SIZE);
const int len = encrypt_data_symmetric(tcp_conn->con.shared_key, tcp_conn->con.last_packet + CRYPTO_PUBLIC_KEY_SIZE, plain,
- sizeof(plain), tcp_conn->con.last_packet + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE);
+ sizeof(plain), tcp_conn->con.last_packet + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE);
if (len != sizeof(plain) + CRYPTO_MAC_SIZE) {
return -1;
@@ -323,7 +335,7 @@ static int handle_handshake(TCP_Client_Connection *tcp_conn, const uint8_t *data
{
uint8_t plain[CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE];
const int len = decrypt_data_symmetric(tcp_conn->con.shared_key, data, data + CRYPTO_NONCE_SIZE,
- TCP_SERVER_HANDSHAKE_SIZE - CRYPTO_NONCE_SIZE, plain);
+ TCP_SERVER_HANDSHAKE_SIZE - CRYPTO_NONCE_SIZE, plain);
if (len != sizeof(plain)) {
return -1;
@@ -345,7 +357,7 @@ int send_routing_request(const Logger *logger, TCP_Client_Connection *con, const
uint8_t packet[1 + CRYPTO_PUBLIC_KEY_SIZE];
packet[0] = TCP_PACKET_ROUTING_REQUEST;
memcpy(packet + 1, public_key, CRYPTO_PUBLIC_KEY_SIZE);
- return write_packet_TCP_secure_connection(logger, &con->con, packet, sizeof(packet), true);
+ return write_packet_tcp_secure_connection(logger, &con->con, packet, sizeof(packet), true);
}
void routing_response_handler(TCP_Client_Connection *con, tcp_routing_response_cb *response_callback, void *object)
@@ -382,10 +394,11 @@ int send_data(const Logger *logger, TCP_Client_Connection *con, uint8_t con_id,
return 0;
}
- VLA(uint8_t, packet, 1 + length);
+ const uint16_t packet_size = 1 + length;
+ VLA(uint8_t, packet, packet_size);
packet[0] = con_id + NUM_RESERVED_PORTS;
memcpy(packet + 1, data, length);
- return write_packet_TCP_secure_connection(logger, &con->con, packet, SIZEOF_VLA(packet), false);
+ return write_packet_tcp_secure_connection(logger, &con->con, packet, packet_size, false);
}
/**
@@ -400,14 +413,14 @@ int send_oob_packet(const Logger *logger, TCP_Client_Connection *con, const uint
return -1;
}
- VLA(uint8_t, packet, 1 + CRYPTO_PUBLIC_KEY_SIZE + length);
+ const uint16_t packet_size = 1 + CRYPTO_PUBLIC_KEY_SIZE + length;
+ VLA(uint8_t, packet, packet_size);
packet[0] = TCP_PACKET_OOB_SEND;
memcpy(packet + 1, public_key, CRYPTO_PUBLIC_KEY_SIZE);
memcpy(packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, data, length);
- return write_packet_TCP_secure_connection(logger, &con->con, packet, SIZEOF_VLA(packet), false);
+ return write_packet_tcp_secure_connection(logger, &con->con, packet, packet_size, false);
}
-
/** @brief Set the number that will be used as an argument in the callbacks related to con_id.
*
* When not set by this function, the number is -1.
@@ -452,7 +465,7 @@ static int client_send_disconnect_notification(const Logger *logger, TCP_Client_
uint8_t packet[1 + 1];
packet[0] = TCP_PACKET_DISCONNECT_NOTIFICATION;
packet[1] = id;
- return write_packet_TCP_secure_connection(logger, &con->con, packet, sizeof(packet), true);
+ return write_packet_tcp_secure_connection(logger, &con->con, packet, sizeof(packet), true);
}
/**
@@ -469,7 +482,7 @@ static int tcp_send_ping_request(const Logger *logger, TCP_Client_Connection *co
uint8_t packet[1 + sizeof(uint64_t)];
packet[0] = TCP_PACKET_PING;
memcpy(packet + 1, &con->ping_request_id, sizeof(uint64_t));
- const int ret = write_packet_TCP_secure_connection(logger, &con->con, packet, sizeof(packet), true);
+ const int ret = write_packet_tcp_secure_connection(logger, &con->con, packet, sizeof(packet), true);
if (ret == 1) {
con->ping_request_id = 0;
@@ -492,7 +505,7 @@ static int tcp_send_ping_response(const Logger *logger, TCP_Client_Connection *c
uint8_t packet[1 + sizeof(uint64_t)];
packet[0] = TCP_PACKET_PONG;
memcpy(packet + 1, &con->ping_response_id, sizeof(uint64_t));
- const int ret = write_packet_TCP_secure_connection(logger, &con->con, packet, sizeof(packet), true);
+ const int ret = write_packet_tcp_secure_connection(logger, &con->con, packet, sizeof(packet), true);
if (ret == 1) {
con->ping_response_id = 0;
@@ -524,10 +537,11 @@ int send_disconnect_request(const Logger *logger, TCP_Client_Connection *con, ui
*/
int send_onion_request(const Logger *logger, TCP_Client_Connection *con, const uint8_t *data, uint16_t length)
{
- VLA(uint8_t, packet, 1 + length);
+ const uint16_t packet_size = 1 + length;
+ VLA(uint8_t, packet, packet_size);
packet[0] = TCP_PACKET_ONION_REQUEST;
memcpy(packet + 1, data, length);
- return write_packet_TCP_secure_connection(logger, &con->con, packet, SIZEOF_VLA(packet), false);
+ return write_packet_tcp_secure_connection(logger, &con->con, packet, packet_size, false);
}
void onion_response_handler(TCP_Client_Connection *con, tcp_onion_response_cb *onion_callback, void *object)
@@ -555,7 +569,7 @@ int send_forward_request_tcp(const Logger *logger, TCP_Client_Connection *con, c
}
memcpy(packet + 1 + ipport_length, data, length);
- return write_packet_TCP_secure_connection(logger, &con->con, packet, 1 + ipport_length + length, false);
+ return write_packet_tcp_secure_connection(logger, &con->con, packet, 1 + ipport_length + length, false);
}
void forwarding_handler(TCP_Client_Connection *con, forwarded_response_cb *forwarded_response_callback, void *object)
@@ -565,11 +579,17 @@ void forwarding_handler(TCP_Client_Connection *con, forwarded_response_cb *forwa
}
/** Create new TCP connection to ip_port/public_key */
-TCP_Client_Connection *new_TCP_connection(
- const Logger *logger, const Mono_Time *mono_time, const Random *rng, const Network *ns, const IP_Port *ip_port,
- const uint8_t *public_key, const uint8_t *self_public_key, const uint8_t *self_secret_key,
- const TCP_Proxy_Info *proxy_info)
+TCP_Client_Connection *new_tcp_connection(
+ const Logger *logger, const Memory *mem, const Mono_Time *mono_time, const Random *rng, const Network *ns,
+ const IP_Port *ip_port, const uint8_t *public_key, const uint8_t *self_public_key, const uint8_t *self_secret_key,
+ const TCP_Proxy_Info *proxy_info)
{
+ assert(logger != nullptr);
+ assert(mem != nullptr);
+ assert(mono_time != nullptr);
+ assert(rng != nullptr);
+ assert(ns != nullptr);
+
if (!net_family_is_ipv4(ip_port->ip.family) && !net_family_is_ipv6(ip_port->ip.family)) {
return nullptr;
}
@@ -597,12 +617,12 @@ TCP_Client_Connection *new_TCP_connection(
return nullptr;
}
- if (!(set_socket_nonblock(ns, sock) && connect_sock_to(logger, sock, ip_port, proxy_info))) {
+ if (!(set_socket_nonblock(ns, sock) && connect_sock_to(logger, mem, sock, ip_port, proxy_info))) {
kill_sock(ns, sock);
return nullptr;
}
- TCP_Client_Connection *temp = (TCP_Client_Connection *)calloc(1, sizeof(TCP_Client_Connection));
+ TCP_Client_Connection *temp = (TCP_Client_Connection *)mem_alloc(mem, sizeof(TCP_Client_Connection));
if (temp == nullptr) {
kill_sock(ns, sock);
@@ -610,6 +630,7 @@ TCP_Client_Connection *new_TCP_connection(
}
temp->con.ns = ns;
+ temp->con.mem = mem;
temp->con.rng = rng;
temp->con.sock = sock;
temp->con.ip_port = *ip_port;
@@ -637,7 +658,7 @@ TCP_Client_Connection *new_TCP_connection(
if (generate_handshake(temp) == -1) {
kill_sock(ns, sock);
- free(temp);
+ mem_delete(mem, temp);
return nullptr;
}
@@ -651,7 +672,7 @@ TCP_Client_Connection *new_TCP_connection(
}
non_null()
-static int handle_TCP_client_routing_response(TCP_Client_Connection *conn, const uint8_t *data, uint16_t length)
+static int handle_tcp_client_routing_response(TCP_Client_Connection *conn, const uint8_t *data, uint16_t length)
{
if (length != 1 + 1 + CRYPTO_PUBLIC_KEY_SIZE) {
return -1;
@@ -679,7 +700,7 @@ static int handle_TCP_client_routing_response(TCP_Client_Connection *conn, const
}
non_null()
-static int handle_TCP_client_connection_notification(TCP_Client_Connection *conn, const uint8_t *data, uint16_t length)
+static int handle_tcp_client_connection_notification(TCP_Client_Connection *conn, const uint8_t *data, uint16_t length)
{
if (length != 1 + 1) {
return -1;
@@ -706,7 +727,7 @@ static int handle_TCP_client_connection_notification(TCP_Client_Connection *conn
}
non_null()
-static int handle_TCP_client_disconnect_notification(TCP_Client_Connection *conn, const uint8_t *data, uint16_t length)
+static int handle_tcp_client_disconnect_notification(TCP_Client_Connection *conn, const uint8_t *data, uint16_t length)
{
if (length != 1 + 1) {
return -1;
@@ -737,7 +758,7 @@ static int handle_TCP_client_disconnect_notification(TCP_Client_Connection *conn
}
non_null()
-static int handle_TCP_client_ping(const Logger *logger, TCP_Client_Connection *conn, const uint8_t *data, uint16_t length)
+static int handle_tcp_client_ping(const Logger *logger, TCP_Client_Connection *conn, const uint8_t *data, uint16_t length)
{
if (length != 1 + sizeof(uint64_t)) {
return -1;
@@ -751,7 +772,7 @@ static int handle_TCP_client_ping(const Logger *logger, TCP_Client_Connection *c
}
non_null()
-static int handle_TCP_client_pong(TCP_Client_Connection *conn, const uint8_t *data, uint16_t length)
+static int handle_tcp_client_pong(TCP_Client_Connection *conn, const uint8_t *data, uint16_t length)
{
if (length != 1 + sizeof(uint64_t)) {
return -1;
@@ -772,7 +793,7 @@ static int handle_TCP_client_pong(TCP_Client_Connection *conn, const uint8_t *da
}
non_null(1, 2) nullable(4)
-static int handle_TCP_client_oob_recv(TCP_Client_Connection *conn, const uint8_t *data, uint16_t length, void *userdata)
+static int handle_tcp_client_oob_recv(TCP_Client_Connection *conn, const uint8_t *data, uint16_t length, void *userdata)
{
if (length <= 1 + CRYPTO_PUBLIC_KEY_SIZE) {
return -1;
@@ -791,7 +812,7 @@ static int handle_TCP_client_oob_recv(TCP_Client_Connection *conn, const uint8_t
* @retval -1 on failure
*/
non_null(1, 2, 3) nullable(5)
-static int handle_TCP_client_packet(const Logger *logger, TCP_Client_Connection *conn, const uint8_t *data,
+static int handle_tcp_client_packet(const Logger *logger, TCP_Client_Connection *conn, const uint8_t *data,
uint16_t length, void *userdata)
{
if (length <= 1) {
@@ -800,22 +821,22 @@ static int handle_TCP_client_packet(const Logger *logger, TCP_Client_Connection
switch (data[0]) {
case TCP_PACKET_ROUTING_RESPONSE:
- return handle_TCP_client_routing_response(conn, data, length);
+ return handle_tcp_client_routing_response(conn, data, length);
case TCP_PACKET_CONNECTION_NOTIFICATION:
- return handle_TCP_client_connection_notification(conn, data, length);
+ return handle_tcp_client_connection_notification(conn, data, length);
case TCP_PACKET_DISCONNECT_NOTIFICATION:
- return handle_TCP_client_disconnect_notification(conn, data, length);
+ return handle_tcp_client_disconnect_notification(conn, data, length);
case TCP_PACKET_PING:
- return handle_TCP_client_ping(logger, conn, data, length);
+ return handle_tcp_client_ping(logger, conn, data, length);
case TCP_PACKET_PONG:
- return handle_TCP_client_pong(conn, data, length);
+ return handle_tcp_client_pong(conn, data, length);
case TCP_PACKET_OOB_RECV:
- return handle_TCP_client_oob_recv(conn, data, length, userdata);
+ return handle_tcp_client_oob_recv(conn, data, length, userdata);
case TCP_PACKET_ONION_RESPONSE: {
if (conn->onion_callback != nullptr) {
@@ -852,7 +873,8 @@ non_null(1, 2) nullable(3)
static bool tcp_process_packet(const Logger *logger, TCP_Client_Connection *conn, void *userdata)
{
uint8_t packet[MAX_PACKET_SIZE];
- const int len = read_packet_TCP_secure_connection(logger, conn->con.ns, conn->con.sock, &conn->next_packet_length, conn->con.shared_key, conn->recv_nonce, packet, sizeof(packet), &conn->ip_port);
+ const int len = read_packet_tcp_secure_connection(logger, conn->con.mem, conn->con.ns, conn->con.sock, &conn->next_packet_length, conn->con.shared_key, conn->recv_nonce, packet, sizeof(packet),
+ &conn->ip_port);
if (len == 0) {
return false;
@@ -863,7 +885,7 @@ static bool tcp_process_packet(const Logger *logger, TCP_Client_Connection *conn
return false;
}
- if (handle_TCP_client_packet(logger, conn, packet, len, userdata) == -1) {
+ if (handle_tcp_client_packet(logger, conn, packet, len, userdata) == -1) {
conn->status = TCP_CLIENT_DISCONNECTED;
return false;
}
@@ -872,7 +894,7 @@ static bool tcp_process_packet(const Logger *logger, TCP_Client_Connection *conn
}
non_null(1, 2, 3) nullable(4)
-static int do_confirmed_TCP(const Logger *logger, TCP_Client_Connection *conn, const Mono_Time *mono_time,
+static int do_confirmed_tcp(const Logger *logger, TCP_Client_Connection *conn, const Mono_Time *mono_time,
void *userdata)
{
send_pending_data(logger, &conn->con);
@@ -898,15 +920,14 @@ static int do_confirmed_TCP(const Logger *logger, TCP_Client_Connection *conn, c
}
while (tcp_process_packet(logger, conn, userdata)) {
- // Keep reading until error or out of data.
- continue;
+ /* Keep reading until error or out of data. */
}
return 0;
}
/** Run the TCP connection */
-void do_TCP_connection(const Logger *logger, const Mono_Time *mono_time,
+void do_tcp_connection(const Logger *logger, const Mono_Time *mono_time,
TCP_Client_Connection *tcp_connection, void *userdata)
{
if (tcp_connection->status == TCP_CLIENT_DISCONNECTED) {
@@ -931,7 +952,7 @@ void do_TCP_connection(const Logger *logger, const Mono_Time *mono_time,
if (tcp_connection->status == TCP_CLIENT_PROXY_SOCKS5_CONNECTING) {
if (send_pending_data(logger, &tcp_connection->con) == 0) {
- int ret = socks5_read_handshake_response(logger, tcp_connection);
+ const int ret = socks5_read_handshake_response(logger, tcp_connection);
if (ret == -1) {
tcp_connection->kill_at = 0;
@@ -947,7 +968,7 @@ void do_TCP_connection(const Logger *logger, const Mono_Time *mono_time,
if (tcp_connection->status == TCP_CLIENT_PROXY_SOCKS5_UNCONFIRMED) {
if (send_pending_data(logger, &tcp_connection->con) == 0) {
- int ret = proxy_socks5_read_connection_response(logger, tcp_connection);
+ const int ret = proxy_socks5_read_connection_response(logger, tcp_connection);
if (ret == -1) {
tcp_connection->kill_at = 0;
@@ -969,7 +990,8 @@ void do_TCP_connection(const Logger *logger, const Mono_Time *mono_time,
if (tcp_connection->status == TCP_CLIENT_UNCONFIRMED) {
uint8_t data[TCP_SERVER_HANDSHAKE_SIZE];
- const int len = read_TCP_packet(logger, tcp_connection->con.ns, tcp_connection->con.sock, data, sizeof(data), &tcp_connection->con.ip_port);
+ const TCP_Connection *con = &tcp_connection->con;
+ const int len = read_tcp_packet(logger, con->mem, con->ns, con->sock, data, sizeof(data), &con->ip_port);
if (sizeof(data) == len) {
if (handle_handshake(tcp_connection, data) == 0) {
@@ -983,7 +1005,7 @@ void do_TCP_connection(const Logger *logger, const Mono_Time *mono_time,
}
if (tcp_connection->status == TCP_CLIENT_CONFIRMED) {
- do_confirmed_TCP(logger, tcp_connection, mono_time, userdata);
+ do_confirmed_tcp(logger, tcp_connection, mono_time, userdata);
}
if (tcp_connection->kill_at <= mono_time_get(mono_time)) {
@@ -992,14 +1014,16 @@ void do_TCP_connection(const Logger *logger, const Mono_Time *mono_time,
}
/** Kill the TCP connection */
-void kill_TCP_connection(TCP_Client_Connection *tcp_connection)
+void kill_tcp_connection(TCP_Client_Connection *tcp_connection)
{
if (tcp_connection == nullptr) {
return;
}
- wipe_priority_list(tcp_connection->con.priority_queue_start);
+ const Memory *mem = tcp_connection->con.mem;
+
+ wipe_priority_list(tcp_connection->con.mem, tcp_connection->con.priority_queue_start);
kill_sock(tcp_connection->con.ns, tcp_connection->con.sock);
crypto_memzero(tcp_connection, sizeof(TCP_Client_Connection));
- free(tcp_connection);
+ mem_delete(mem, tcp_connection);
}
diff --git a/protocols/Tox/libtox/src/toxcore/TCP_client.h b/protocols/Tox/libtox/src/toxcore/TCP_client.h
index fdc91de70d..ea2654b953 100644
--- a/protocols/Tox/libtox/src/toxcore/TCP_client.h
+++ b/protocols/Tox/libtox/src/toxcore/TCP_client.h
@@ -9,8 +9,11 @@
#ifndef C_TOXCORE_TOXCORE_TCP_CLIENT_H
#define C_TOXCORE_TOXCORE_TCP_CLIENT_H
+#include "attributes.h"
#include "crypto_core.h"
#include "forwarding.h"
+#include "logger.h"
+#include "mem.h"
#include "mono_time.h"
#include "network.h"
@@ -57,20 +60,20 @@ non_null()
void tcp_con_set_custom_uint(TCP_Client_Connection *con, uint32_t value);
/** Create new TCP connection to ip_port/public_key */
-non_null(1, 2, 3, 4, 5, 6, 7, 8) nullable(9)
-TCP_Client_Connection *new_TCP_connection(
- const Logger *logger, const Mono_Time *mono_time, const Random *rng, const Network *ns, const IP_Port *ip_port,
- const uint8_t *public_key, const uint8_t *self_public_key, const uint8_t *self_secret_key,
- const TCP_Proxy_Info *proxy_info);
+non_null(1, 2, 3, 4, 5, 6, 7, 8, 9) nullable(10)
+TCP_Client_Connection *new_tcp_connection(
+ const Logger *logger, const Memory *mem, const Mono_Time *mono_time, const Random *rng, const Network *ns,
+ const IP_Port *ip_port, const uint8_t *public_key, const uint8_t *self_public_key, const uint8_t *self_secret_key,
+ const TCP_Proxy_Info *proxy_info);
/** Run the TCP connection */
non_null(1, 2, 3) nullable(4)
-void do_TCP_connection(const Logger *logger, const Mono_Time *mono_time,
+void do_tcp_connection(const Logger *logger, const Mono_Time *mono_time,
TCP_Client_Connection *tcp_connection, void *userdata);
/** Kill the TCP connection */
nullable(1)
-void kill_TCP_connection(TCP_Client_Connection *tcp_connection);
+void kill_tcp_connection(TCP_Client_Connection *tcp_connection);
typedef int tcp_onion_response_cb(void *object, const uint8_t *data, uint16_t length, void *userdata);
@@ -150,5 +153,4 @@ int send_oob_packet(const Logger *logger, TCP_Client_Connection *con, const uint
non_null()
void oob_data_handler(TCP_Client_Connection *con, tcp_oob_data_cb *oob_data_callback, void *object);
-
-#endif
+#endif /* C_TOXCORE_TOXCORE_TCP_CLIENT_H */
diff --git a/protocols/Tox/libtox/src/toxcore/TCP_common.c b/protocols/Tox/libtox/src/toxcore/TCP_common.c
index a42faced1a..bd3b7ca4c7 100644
--- a/protocols/Tox/libtox/src/toxcore/TCP_common.c
+++ b/protocols/Tox/libtox/src/toxcore/TCP_common.c
@@ -5,18 +5,22 @@
#include "TCP_common.h"
-#include <stdlib.h>
#include <string.h>
+#include "attributes.h"
#include "ccompat.h"
+#include "crypto_core.h"
+#include "logger.h"
+#include "mem.h"
+#include "network.h"
-void wipe_priority_list(TCP_Priority_List *p)
+void wipe_priority_list(const Memory *mem, TCP_Priority_List *p)
{
while (p != nullptr) {
TCP_Priority_List *pp = p;
p = p->next;
- free(pp->data);
- free(pp);
+ mem_delete(mem, pp->data);
+ mem_delete(mem, pp);
}
}
@@ -74,8 +78,8 @@ int send_pending_data(const Logger *logger, TCP_Connection *con)
TCP_Priority_List *pp = p;
p = p->next;
- free(pp->data);
- free(pp);
+ mem_delete(con->mem, pp->data);
+ mem_delete(con->mem, pp);
}
con->priority_queue_start = p;
@@ -89,30 +93,32 @@ int send_pending_data(const Logger *logger, TCP_Connection *con)
}
/**
- * @retval false on failure (only if calloc fails)
+ * @retval false on failure (only if mem_alloc fails)
* @retval true on success
*/
non_null()
static bool add_priority(TCP_Connection *con, const uint8_t *packet, uint16_t size, uint16_t sent)
{
TCP_Priority_List *p = con->priority_queue_end;
- TCP_Priority_List *new_list = (TCP_Priority_List *)calloc(1, sizeof(TCP_Priority_List));
+ TCP_Priority_List *new_list = (TCP_Priority_List *)mem_alloc(con->mem, sizeof(TCP_Priority_List));
if (new_list == nullptr) {
return false;
}
- new_list->next = nullptr;
- new_list->size = size;
- new_list->sent = sent;
- new_list->data = (uint8_t *)malloc(size);
+ uint8_t *data = (uint8_t *)mem_balloc(con->mem, size);
- if (new_list->data == nullptr) {
- free(new_list);
+ if (data == nullptr) {
+ mem_delete(con->mem, new_list);
return false;
}
- memcpy(new_list->data, packet, size);
+ memcpy(data, packet, size);
+ new_list->data = data;
+ new_list->size = size;
+
+ new_list->next = nullptr;
+ new_list->sent = sent;
if (p != nullptr) {
p->next = new_list;
@@ -129,7 +135,7 @@ static bool add_priority(TCP_Connection *con, const uint8_t *packet, uint16_t si
* @retval 0 if could not send packet.
* @retval -1 on failure (connection must be killed).
*/
-int write_packet_TCP_secure_connection(const Logger *logger, TCP_Connection *con, const uint8_t *data, uint16_t length,
+int write_packet_tcp_secure_connection(const Logger *logger, TCP_Connection *con, const uint8_t *data, uint16_t length,
bool priority)
{
if (length + CRYPTO_MAC_SIZE > MAX_PACKET_SIZE) {
@@ -146,18 +152,19 @@ int write_packet_TCP_secure_connection(const Logger *logger, TCP_Connection *con
}
}
- VLA(uint8_t, packet, sizeof(uint16_t) + length + CRYPTO_MAC_SIZE);
+ const uint16_t packet_size = sizeof(uint16_t) + length + CRYPTO_MAC_SIZE;
+ VLA(uint8_t, packet, packet_size);
uint16_t c_length = net_htons(length + CRYPTO_MAC_SIZE);
memcpy(packet, &c_length, sizeof(uint16_t));
int len = encrypt_data_symmetric(con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t));
- if ((unsigned int)len != (SIZEOF_VLA(packet) - sizeof(uint16_t))) {
+ if ((unsigned int)len != (packet_size - sizeof(uint16_t))) {
return -1;
}
if (priority) {
- len = sendpriority ? net_send(con->ns, logger, con->sock, packet, SIZEOF_VLA(packet), &con->ip_port) : 0;
+ len = sendpriority ? net_send(con->ns, logger, con->sock, packet, packet_size, &con->ip_port) : 0;
if (len <= 0) {
len = 0;
@@ -165,14 +172,14 @@ int write_packet_TCP_secure_connection(const Logger *logger, TCP_Connection *con
increment_nonce(con->sent_nonce);
- if ((unsigned int)len == SIZEOF_VLA(packet)) {
+ if ((unsigned int)len == packet_size) {
return 1;
}
- return add_priority(con, packet, SIZEOF_VLA(packet), len) ? 1 : 0;
+ return add_priority(con, packet, packet_size, len) ? 1 : 0;
}
- len = net_send(con->ns, logger, con->sock, packet, SIZEOF_VLA(packet), &con->ip_port);
+ len = net_send(con->ns, logger, con->sock, packet, packet_size, &con->ip_port);
if (len <= 0) {
return 0;
@@ -180,12 +187,12 @@ int write_packet_TCP_secure_connection(const Logger *logger, TCP_Connection *con
increment_nonce(con->sent_nonce);
- if ((unsigned int)len == SIZEOF_VLA(packet)) {
+ if ((unsigned int)len == packet_size) {
return 1;
}
- memcpy(con->last_packet, packet, SIZEOF_VLA(packet));
- con->last_packet_length = SIZEOF_VLA(packet);
+ memcpy(con->last_packet, packet, packet_size);
+ con->last_packet_length = packet_size;
con->last_packet_sent = len;
return 1;
}
@@ -195,12 +202,17 @@ int write_packet_TCP_secure_connection(const Logger *logger, TCP_Connection *con
* return length on success
* return -1 on failure/no data in buffer.
*/
-int read_TCP_packet(const Logger *logger, const Network *ns, Socket sock, uint8_t *data, uint16_t length, const IP_Port *ip_port)
+int read_tcp_packet(
+ const Logger *logger, const Memory *mem, const Network *ns, Socket sock, uint8_t *data, uint16_t length, const IP_Port *ip_port)
{
const uint16_t count = net_socket_data_recv_buffer(ns, sock);
if (count < length) {
- LOGGER_TRACE(logger, "recv buffer has %d bytes, but requested %d bytes", 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;
}
@@ -222,7 +234,7 @@ int read_TCP_packet(const Logger *logger, const Network *ns, Socket sock, uint8_
* return -1 on failure.
*/
non_null()
-static uint16_t read_TCP_length(const Logger *logger, const Network *ns, Socket sock, const IP_Port *ip_port)
+static uint16_t read_tcp_length(const Logger *logger, const Memory *mem, const Network *ns, Socket sock, const IP_Port *ip_port)
{
const uint16_t count = net_socket_data_recv_buffer(ns, sock);
@@ -254,13 +266,14 @@ static uint16_t read_TCP_length(const Logger *logger, const Network *ns, Socket
* @retval 0 if could not read any packet.
* @retval -1 on failure (connection must be killed).
*/
-int read_packet_TCP_secure_connection(
- const Logger *logger, const Network *ns, Socket sock, uint16_t *next_packet_length,
- const uint8_t *shared_key, uint8_t *recv_nonce, uint8_t *data,
- uint16_t max_len, const IP_Port *ip_port)
+int read_packet_tcp_secure_connection(
+ const Logger *logger, const Memory *mem, const Network *ns,
+ Socket sock, uint16_t *next_packet_length,
+ const uint8_t *shared_key, uint8_t *recv_nonce, uint8_t *data,
+ uint16_t max_len, const IP_Port *ip_port)
{
if (*next_packet_length == 0) {
- const uint16_t len = read_TCP_length(logger, ns, sock, ip_port);
+ const uint16_t len = read_tcp_length(logger, mem, ns, sock, ip_port);
if (len == (uint16_t) -1) {
return -1;
@@ -279,7 +292,7 @@ int read_packet_TCP_secure_connection(
}
VLA(uint8_t, data_encrypted, (int) *next_packet_length);
- const int len_packet = read_TCP_packet(logger, ns, sock, data_encrypted, *next_packet_length, ip_port);
+ const int len_packet = read_tcp_packet(logger, mem, ns, sock, data_encrypted, *next_packet_length, ip_port);
if (len_packet == -1) {
return 0;
diff --git a/protocols/Tox/libtox/src/toxcore/TCP_common.h b/protocols/Tox/libtox/src/toxcore/TCP_common.h
index 78d1623d8a..9fa136609c 100644
--- a/protocols/Tox/libtox/src/toxcore/TCP_common.h
+++ b/protocols/Tox/libtox/src/toxcore/TCP_common.h
@@ -6,7 +6,10 @@
#ifndef C_TOXCORE_TOXCORE_TCP_COMMON_H
#define C_TOXCORE_TOXCORE_TCP_COMMON_H
+#include "attributes.h"
#include "crypto_core.h"
+#include "logger.h"
+#include "mem.h"
#include "network.h"
typedef struct TCP_Priority_List TCP_Priority_List;
@@ -17,39 +20,26 @@ struct TCP_Priority_List {
uint8_t *data;
};
-nullable(1)
-void wipe_priority_list(TCP_Priority_List *p);
+non_null(1) nullable(2)
+void wipe_priority_list(const Memory *mem, TCP_Priority_List *p);
#define NUM_RESERVED_PORTS 16
#define NUM_CLIENT_CONNECTIONS (256 - NUM_RESERVED_PORTS)
-#ifdef USE_TEST_NETWORK
-#define TCP_PACKET_FORWARD_REQUEST 11
-#define TCP_PACKET_FORWARDING 10
-#define TCP_PACKET_ROUTING_REQUEST 9
-#define TCP_PACKET_ROUTING_RESPONSE 8
-#define TCP_PACKET_CONNECTION_NOTIFICATION 7
-#define TCP_PACKET_DISCONNECT_NOTIFICATION 6
-#define TCP_PACKET_PING 5
-#define TCP_PACKET_PONG 4
-#define TCP_PACKET_OOB_SEND 3
-#define TCP_PACKET_OOB_RECV 2
-#define TCP_PACKET_ONION_REQUEST 1
-#define TCP_PACKET_ONION_RESPONSE 0
-#else
-#define TCP_PACKET_ROUTING_REQUEST 0
-#define TCP_PACKET_ROUTING_RESPONSE 1
-#define TCP_PACKET_CONNECTION_NOTIFICATION 2
-#define TCP_PACKET_DISCONNECT_NOTIFICATION 3
-#define TCP_PACKET_PING 4
-#define TCP_PACKET_PONG 5
-#define TCP_PACKET_OOB_SEND 6
-#define TCP_PACKET_OOB_RECV 7
-#define TCP_PACKET_ONION_REQUEST 8
-#define TCP_PACKET_ONION_RESPONSE 9
-#define TCP_PACKET_FORWARD_REQUEST 10
-#define TCP_PACKET_FORWARDING 11
-#endif // test network
+typedef enum Tcp_Packet {
+ TCP_PACKET_ROUTING_REQUEST = 0,
+ TCP_PACKET_ROUTING_RESPONSE = 1,
+ TCP_PACKET_CONNECTION_NOTIFICATION = 2,
+ TCP_PACKET_DISCONNECT_NOTIFICATION = 3,
+ TCP_PACKET_PING = 4,
+ TCP_PACKET_PONG = 5,
+ TCP_PACKET_OOB_SEND = 6,
+ TCP_PACKET_OOB_RECV = 7,
+ TCP_PACKET_ONION_REQUEST = 8,
+ TCP_PACKET_ONION_RESPONSE = 9,
+ TCP_PACKET_FORWARD_REQUEST = 10,
+ TCP_PACKET_FORWARDING = 11,
+} Tcp_Packet;
#define TCP_HANDSHAKE_PLAIN_SIZE (CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE)
#define TCP_SERVER_HANDSHAKE_SIZE (CRYPTO_NONCE_SIZE + TCP_HANDSHAKE_PLAIN_SIZE + CRYPTO_MAC_SIZE)
@@ -63,6 +53,7 @@ void wipe_priority_list(TCP_Priority_List *p);
#define MAX_PACKET_SIZE 2048
typedef struct TCP_Connection {
+ const Memory *mem;
const Random *rng;
const Network *ns;
Socket sock;
@@ -97,9 +88,9 @@ int send_pending_data(const Logger *logger, TCP_Connection *con);
* @retval -1 on failure (connection must be killed).
*/
non_null()
-int write_packet_TCP_secure_connection(
- const Logger *logger, TCP_Connection *con, const uint8_t *data, uint16_t length,
- bool priority);
+int write_packet_tcp_secure_connection(
+ const Logger *logger, TCP_Connection *con, const uint8_t *data, uint16_t length,
+ bool priority);
/** @brief Read length bytes from socket.
*
@@ -107,8 +98,8 @@ int write_packet_TCP_secure_connection(
* return -1 on failure/no data in buffer.
*/
non_null()
-int read_TCP_packet(
- const Logger *logger, const Network *ns, Socket sock, uint8_t *data, uint16_t length, const IP_Port *ip_port);
+int read_tcp_packet(
+ const Logger *logger, const Memory *mem, const Network *ns, Socket sock, uint8_t *data, uint16_t length, const IP_Port *ip_port);
/**
* @return length of received packet on success.
@@ -116,9 +107,10 @@ int read_TCP_packet(
* @retval -1 on failure (connection must be killed).
*/
non_null()
-int read_packet_TCP_secure_connection(
- const Logger *logger, const Network *ns, Socket sock, uint16_t *next_packet_length,
- const uint8_t *shared_key, uint8_t *recv_nonce, uint8_t *data,
- uint16_t max_len, const IP_Port *ip_port);
+int read_packet_tcp_secure_connection(
+ const Logger *logger, const Memory *mem, const Network *ns,
+ Socket sock, uint16_t *next_packet_length,
+ const uint8_t *shared_key, uint8_t *recv_nonce, uint8_t *data,
+ uint16_t max_len, const IP_Port *ip_port);
-#endif
+#endif /* C_TOXCORE_TOXCORE_TCP_COMMON_H */
diff --git a/protocols/Tox/libtox/src/toxcore/TCP_connection.c b/protocols/Tox/libtox/src/toxcore/TCP_connection.c
index 4c71f366b3..c7161a9289 100644
--- a/protocols/Tox/libtox/src/toxcore/TCP_connection.c
+++ b/protocols/Tox/libtox/src/toxcore/TCP_connection.c
@@ -9,16 +9,23 @@
#include "TCP_connection.h"
#include <assert.h>
-#include <stdlib.h>
#include <string.h>
+#include "DHT.h"
#include "TCP_client.h"
+#include "attributes.h"
#include "ccompat.h"
+#include "crypto_core.h"
+#include "forwarding.h"
+#include "logger.h"
+#include "mem.h"
#include "mono_time.h"
+#include "network.h"
#include "util.h"
struct TCP_Connections {
const Logger *logger;
+ const Memory *mem;
const Random *rng;
Mono_Time *mono_time;
const Network *ns;
@@ -51,17 +58,14 @@ struct TCP_Connections {
uint16_t onion_num_conns;
};
-
static const TCP_Connection_to empty_tcp_connection_to = {0};
static const TCP_con empty_tcp_con = {0};
-
const uint8_t *tcp_connections_public_key(const TCP_Connections *tcp_c)
{
return tcp_c->self_public_key;
}
-
uint32_t tcp_connections_count(const TCP_Connections *tcp_c)
{
return tcp_c->tcp_connections_length;
@@ -69,20 +73,20 @@ uint32_t tcp_connections_count(const TCP_Connections *tcp_c)
/** @brief Set the size of the array to num.
*
- * @retval -1 if realloc fails.
+ * @retval -1 if mem_vrealloc fails.
* @retval 0 if it succeeds.
*/
non_null()
-static int realloc_TCP_Connection_to(TCP_Connection_to **array, size_t num)
+static int realloc_tcp_connection_to(const Memory *mem, TCP_Connection_to **array, size_t num)
{
if (num == 0) {
- free(*array);
+ mem_delete(mem, *array);
*array = nullptr;
return 0;
}
TCP_Connection_to *temp_pointer =
- (TCP_Connection_to *)realloc(*array, num * sizeof(TCP_Connection_to));
+ (TCP_Connection_to *)mem_vrealloc(mem, *array, num, sizeof(TCP_Connection_to));
if (temp_pointer == nullptr) {
return -1;
@@ -94,15 +98,15 @@ static int realloc_TCP_Connection_to(TCP_Connection_to **array, size_t num)
}
non_null()
-static int realloc_TCP_con(TCP_con **array, size_t num)
+static int realloc_tcp_con(const Memory *mem, TCP_con **array, size_t num)
{
if (num == 0) {
- free(*array);
+ mem_delete(mem, *array);
*array = nullptr;
return 0;
}
- TCP_con *temp_pointer = (TCP_con *)realloc(*array, num * sizeof(TCP_con));
+ TCP_con *temp_pointer = (TCP_con *)mem_vrealloc(mem, *array, num, sizeof(TCP_con));
if (temp_pointer == nullptr) {
return -1;
@@ -113,7 +117,6 @@ static int realloc_TCP_con(TCP_con **array, size_t num)
return 0;
}
-
/**
* Return true if the connections_number is valid.
*/
@@ -164,7 +167,7 @@ static int create_connection(TCP_Connections *tcp_c)
int id = -1;
- if (realloc_TCP_Connection_to(&tcp_c->connections, tcp_c->connections_length + 1) == 0) {
+ if (realloc_tcp_connection_to(tcp_c->mem, &tcp_c->connections, tcp_c->connections_length + 1) == 0) {
id = tcp_c->connections_length;
++tcp_c->connections_length;
tcp_c->connections[id] = empty_tcp_connection_to;
@@ -189,7 +192,7 @@ static int create_tcp_connection(TCP_Connections *tcp_c)
int id = -1;
- if (realloc_TCP_con(&tcp_c->tcp_connections, tcp_c->tcp_connections_length + 1) == 0) {
+ if (realloc_tcp_con(tcp_c->mem, &tcp_c->tcp_connections, tcp_c->tcp_connections_length + 1) == 0) {
id = tcp_c->tcp_connections_length;
++tcp_c->tcp_connections_length;
tcp_c->tcp_connections[id] = empty_tcp_con;
@@ -221,7 +224,9 @@ static int wipe_connection(TCP_Connections *tcp_c, int connections_number)
if (tcp_c->connections_length != i) {
tcp_c->connections_length = i;
- realloc_TCP_Connection_to(&tcp_c->connections, tcp_c->connections_length);
+ if (realloc_tcp_connection_to(tcp_c->mem, &tcp_c->connections, tcp_c->connections_length) != 0) {
+ return -1;
+ }
}
return 0;
@@ -251,7 +256,9 @@ static int wipe_tcp_connection(TCP_Connections *tcp_c, int tcp_connections_numbe
if (tcp_c->tcp_connections_length != i) {
tcp_c->tcp_connections_length = i;
- realloc_TCP_con(&tcp_c->tcp_connections, tcp_c->tcp_connections_length);
+ if (realloc_tcp_con(tcp_c->mem, &tcp_c->tcp_connections, tcp_c->tcp_connections_length) != 0) {
+ return -1;
+ }
}
return 0;
@@ -280,8 +287,9 @@ static TCP_con *get_tcp_connection(const TCP_Connections *tcp_c, int tcp_connect
uint32_t tcp_connected_relays_count(const TCP_Connections *tcp_c)
{
uint32_t count = 0;
+ const uint32_t size = tcp_connections_count(tcp_c);
- for (uint32_t i = 0; i < tcp_connections_count(tcp_c); ++i) {
+ for (uint32_t i = 0; i < size; ++i) {
const TCP_con *tcp_con = get_tcp_connection(tcp_c, i);
if (tcp_con == nullptr) {
@@ -402,7 +410,7 @@ int get_random_tcp_onion_conn_number(const TCP_Connections *tcp_c)
* return -1 on failure.
*/
non_null()
-static int get_conn_number_by_ip_port(TCP_Connections *tcp_c, const IP_Port *ip_port)
+static int get_conn_number_by_ip_port(const TCP_Connections *tcp_c, const IP_Port *ip_port)
{
for (uint32_t i = 0; i < tcp_c->tcp_connections_length; ++i) {
const IP_Port conn_ip_port = tcp_con_ip_port(tcp_c->tcp_connections[i].connection);
@@ -741,7 +749,7 @@ int set_tcp_connection_to_status(const TCP_Connections *tcp_c, int connections_n
}
if (tcp_con->status == TCP_CONN_SLEEPING) {
- tcp_con->unsleep = 1;
+ tcp_con->unsleep = true;
}
}
}
@@ -757,7 +765,7 @@ int set_tcp_connection_to_status(const TCP_Connections *tcp_c, int connections_n
for (uint32_t i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
if (con_to->connections[i].tcp_connection > 0) {
- unsigned int tcp_connections_number = con_to->connections[i].tcp_connection - 1;
+ const unsigned int tcp_connections_number = con_to->connections[i].tcp_connection - 1;
TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
if (tcp_con == nullptr) {
@@ -898,7 +906,7 @@ int kill_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connections_number
--tcp_c->onion_num_conns;
}
- kill_TCP_connection(tcp_con->connection);
+ kill_tcp_connection(tcp_con->connection);
return wipe_tcp_connection(tcp_c, tcp_connections_number);
}
@@ -916,11 +924,11 @@ static int reconnect_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connec
return -1;
}
- IP_Port ip_port = tcp_con_ip_port(tcp_con->connection);
+ const IP_Port ip_port = tcp_con_ip_port(tcp_con->connection);
uint8_t relay_pk[CRYPTO_PUBLIC_KEY_SIZE];
memcpy(relay_pk, tcp_con_public_key(tcp_con->connection), CRYPTO_PUBLIC_KEY_SIZE);
- kill_TCP_connection(tcp_con->connection);
- tcp_con->connection = new_TCP_connection(tcp_c->logger, tcp_c->mono_time, tcp_c->rng, tcp_c->ns, &ip_port, relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key, &tcp_c->proxy_info);
+ kill_tcp_connection(tcp_con->connection);
+ tcp_con->connection = new_tcp_connection(tcp_c->logger, tcp_c->mem, tcp_c->mono_time, tcp_c->rng, tcp_c->ns, &ip_port, relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key, &tcp_c->proxy_info);
if (tcp_con->connection == nullptr) {
kill_tcp_relay_connection(tcp_c, tcp_connections_number);
@@ -937,14 +945,14 @@ static int reconnect_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connec
if (tcp_con->onion) {
--tcp_c->onion_num_conns;
- tcp_con->onion = 0;
+ tcp_con->onion = false;
}
tcp_con->lock_count = 0;
tcp_con->sleep_count = 0;
tcp_con->connected_time = 0;
tcp_con->status = TCP_CONN_VALID;
- tcp_con->unsleep = 0;
+ tcp_con->unsleep = false;
return 0;
}
@@ -969,7 +977,7 @@ static int sleep_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connection
tcp_con->ip_port = tcp_con_ip_port(tcp_con->connection);
memcpy(tcp_con->relay_pk, tcp_con_public_key(tcp_con->connection), CRYPTO_PUBLIC_KEY_SIZE);
- kill_TCP_connection(tcp_con->connection);
+ kill_tcp_connection(tcp_con->connection);
tcp_con->connection = nullptr;
for (uint32_t i = 0; i < tcp_c->connections_length; ++i) {
@@ -982,14 +990,14 @@ static int sleep_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connection
if (tcp_con->onion) {
--tcp_c->onion_num_conns;
- tcp_con->onion = 0;
+ tcp_con->onion = false;
}
tcp_con->lock_count = 0;
tcp_con->sleep_count = 0;
tcp_con->connected_time = 0;
tcp_con->status = TCP_CONN_SLEEPING;
- tcp_con->unsleep = 0;
+ tcp_con->unsleep = false;
return 0;
}
@@ -1007,9 +1015,9 @@ static int unsleep_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connecti
return -1;
}
- tcp_con->connection = new_TCP_connection(
- tcp_c->logger, tcp_c->mono_time, tcp_c->rng, tcp_c->ns, &tcp_con->ip_port,
- tcp_con->relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key, &tcp_c->proxy_info);
+ tcp_con->connection = new_tcp_connection(
+ tcp_c->logger, tcp_c->mem, tcp_c->mono_time, tcp_c->rng, tcp_c->ns, &tcp_con->ip_port,
+ tcp_con->relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key, &tcp_c->proxy_info);
if (tcp_con->connection == nullptr) {
kill_tcp_relay_connection(tcp_c, tcp_connections_number);
@@ -1020,7 +1028,7 @@ static int unsleep_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connecti
tcp_con->sleep_count = 0;
tcp_con->connected_time = 0;
tcp_con->status = TCP_CONN_VALID;
- tcp_con->unsleep = 0;
+ tcp_con->unsleep = false;
return 0;
}
@@ -1054,7 +1062,7 @@ static int send_tcp_relay_routing_request(const TCP_Connections *tcp_c, int tcp_
non_null()
static int tcp_response_callback(void *object, uint8_t connection_id, const uint8_t *public_key)
{
- TCP_Client_Connection *tcp_client_con = (TCP_Client_Connection *)object;
+ const TCP_Client_Connection *tcp_client_con = (const TCP_Client_Connection *)object;
const TCP_Connections *tcp_c = (const TCP_Connections *)tcp_con_custom_object(tcp_client_con);
const unsigned int tcp_connections_number = tcp_con_custom_uint(tcp_client_con);
@@ -1128,11 +1136,12 @@ non_null(1, 4) nullable(6)
static int tcp_conn_data_callback(void *object, uint32_t number, uint8_t connection_id, const uint8_t *data,
uint16_t length, void *userdata)
{
+ const TCP_Client_Connection *tcp_client_con = (TCP_Client_Connection *)object;
+
if (length == 0) {
return -1;
}
- const TCP_Client_Connection *tcp_client_con = (TCP_Client_Connection *)object;
TCP_Connections *tcp_c = (TCP_Connections *)tcp_con_custom_object(tcp_client_con);
const unsigned int tcp_connections_number = tcp_con_custom_uint(tcp_client_con);
@@ -1159,11 +1168,12 @@ non_null()
static int tcp_conn_oob_callback(void *object, const uint8_t *public_key, const uint8_t *data, uint16_t length,
void *userdata)
{
+ const TCP_Client_Connection *tcp_client_con = (const TCP_Client_Connection *)object;
+
if (length == 0) {
return -1;
}
- const TCP_Client_Connection *tcp_client_con = (const TCP_Client_Connection *)object;
TCP_Connections *tcp_c = (TCP_Connections *)tcp_con_custom_object(tcp_client_con);
const unsigned int tcp_connections_number = tcp_con_custom_uint(tcp_client_con);
@@ -1251,7 +1261,7 @@ static int tcp_relay_on_online(TCP_Connections *tcp_c, int tcp_connections_numbe
bool sent_any = false;
for (uint32_t i = 0; i < tcp_c->connections_length; ++i) {
- TCP_Connection_to *con_to = get_connection(tcp_c, i);
+ const TCP_Connection_to *con_to = get_connection(tcp_c, i);
if (con_to != nullptr) {
if (tcp_connection_in_conn(con_to, tcp_connections_number)) {
@@ -1273,7 +1283,7 @@ static int tcp_relay_on_online(TCP_Connections *tcp_c, int tcp_connections_numbe
}
if (tcp_c->onion_status && tcp_c->onion_num_conns < NUM_ONION_TCP_CONNECTIONS) {
- tcp_con->onion = 1;
+ tcp_con->onion = true;
++tcp_c->onion_num_conns;
}
@@ -1303,9 +1313,9 @@ static int add_tcp_relay_instance(TCP_Connections *tcp_c, const IP_Port *ip_port
TCP_con *tcp_con = &tcp_c->tcp_connections[tcp_connections_number];
- tcp_con->connection = new_TCP_connection(
- tcp_c->logger, tcp_c->mono_time, tcp_c->rng, tcp_c->ns, &ipp_copy,
- relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key, &tcp_c->proxy_info);
+ tcp_con->connection = new_tcp_connection(
+ tcp_c->logger, tcp_c->mem, tcp_c->mono_time, tcp_c->rng, tcp_c->ns, &ipp_copy,
+ relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key, &tcp_c->proxy_info);
if (tcp_con->connection == nullptr) {
return -1;
@@ -1359,7 +1369,7 @@ int add_tcp_number_relay_connection(const TCP_Connections *tcp_c, int connection
}
if (con_to->status != TCP_CONN_SLEEPING && tcp_con->status == TCP_CONN_SLEEPING) {
- tcp_con->unsleep = 1;
+ tcp_con->unsleep = true;
}
if (add_tcp_connection_to_conn(con_to, tcp_connections_number) == -1) {
@@ -1527,7 +1537,7 @@ int set_tcp_onion_status(TCP_Connections *tcp_c, bool status)
if (tcp_con != nullptr) {
if (tcp_con->status == TCP_CONN_CONNECTED && !tcp_con->onion) {
++tcp_c->onion_num_conns;
- tcp_con->onion = 1;
+ tcp_con->onion = true;
}
}
@@ -1544,7 +1554,7 @@ int set_tcp_onion_status(TCP_Connections *tcp_c, bool status)
if (tcp_con != nullptr) {
if (tcp_con->status == TCP_CONN_SLEEPING) {
- tcp_con->unsleep = 1;
+ tcp_con->unsleep = true;
}
}
@@ -1554,7 +1564,7 @@ int set_tcp_onion_status(TCP_Connections *tcp_c, bool status)
}
}
- tcp_c->onion_status = 1;
+ tcp_c->onion_status = true;
} else {
for (uint32_t i = 0; i < tcp_c->tcp_connections_length; ++i) {
TCP_con *tcp_con = get_tcp_connection(tcp_c, i);
@@ -1562,12 +1572,12 @@ int set_tcp_onion_status(TCP_Connections *tcp_c, bool status)
if (tcp_con != nullptr) {
if (tcp_con->onion) {
--tcp_c->onion_num_conns;
- tcp_con->onion = 0;
+ tcp_con->onion = false;
}
}
}
- tcp_c->onion_status = 0;
+ tcp_c->onion_status = false;
}
return 0;
@@ -1580,21 +1590,27 @@ int set_tcp_onion_status(TCP_Connections *tcp_c, bool status)
*
* Returns NULL on failure.
*/
-TCP_Connections *new_tcp_connections(
- const Logger *logger, const Random *rng, const Network *ns, Mono_Time *mono_time, const uint8_t *secret_key,
- const TCP_Proxy_Info *proxy_info)
+TCP_Connections *new_tcp_connections(const Logger *logger, const Memory *mem, const Random *rng, const Network *ns,
+ Mono_Time *mono_time, const uint8_t *secret_key, const TCP_Proxy_Info *proxy_info)
{
+ assert(logger != nullptr);
+ assert(mem != nullptr);
+ assert(rng != nullptr);
+ assert(ns != nullptr);
+ assert(mono_time != nullptr);
+
if (secret_key == nullptr) {
return nullptr;
}
- TCP_Connections *temp = (TCP_Connections *)calloc(1, sizeof(TCP_Connections));
+ TCP_Connections *temp = (TCP_Connections *)mem_alloc(mem, sizeof(TCP_Connections));
if (temp == nullptr) {
return nullptr;
}
temp->logger = logger;
+ temp->mem = mem;
temp->rng = rng;
temp->mono_time = mono_time;
temp->ns = ns;
@@ -1617,7 +1633,7 @@ static void do_tcp_conns(const Logger *logger, TCP_Connections *tcp_c, void *use
}
if (tcp_con->status != TCP_CONN_SLEEPING) {
- do_TCP_connection(logger, tcp_c->mono_time, tcp_con->connection, userdata);
+ do_tcp_connection(logger, tcp_c->mono_time, tcp_con->connection, userdata);
/* callbacks can change TCP connection address. */
tcp_con = get_tcp_connection(tcp_c, i);
@@ -1702,12 +1718,12 @@ void kill_tcp_connections(TCP_Connections *tcp_c)
}
for (uint32_t i = 0; i < tcp_c->tcp_connections_length; ++i) {
- kill_TCP_connection(tcp_c->tcp_connections[i].connection);
+ kill_tcp_connection(tcp_c->tcp_connections[i].connection);
}
crypto_memzero(tcp_c->self_secret_key, sizeof(tcp_c->self_secret_key));
- free(tcp_c->tcp_connections);
- free(tcp_c->connections);
- free(tcp_c);
+ mem_delete(tcp_c->mem, tcp_c->tcp_connections);
+ mem_delete(tcp_c->mem, tcp_c->connections);
+ mem_delete(tcp_c->mem, tcp_c);
}
diff --git a/protocols/Tox/libtox/src/toxcore/TCP_connection.h b/protocols/Tox/libtox/src/toxcore/TCP_connection.h
index 0434a73eb0..2d35919f10 100644
--- a/protocols/Tox/libtox/src/toxcore/TCP_connection.h
+++ b/protocols/Tox/libtox/src/toxcore/TCP_connection.h
@@ -10,10 +10,18 @@
#define C_TOXCORE_TOXCORE_TCP_CONNECTION_H
#include <stdbool.h>
+#include <stdint.h>
#include "DHT.h" // for Node_format
#include "TCP_client.h"
#include "TCP_common.h"
+#include "attributes.h"
+#include "crypto_core.h"
+#include "forwarding.h"
+#include "logger.h"
+#include "mem.h"
+#include "mono_time.h"
+#include "network.h"
#define TCP_CONN_NONE 0
#define TCP_CONN_VALID 1
@@ -120,7 +128,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.
@@ -156,7 +164,7 @@ non_null()
int tcp_send_oob_packet(const TCP_Connections *tcp_c, unsigned int tcp_connections_number, const uint8_t *public_key,
const uint8_t *packet, uint16_t length);
-typedef int tcp_data_cb(void *object, int id, const uint8_t *data, uint16_t length, void *userdata);
+typedef int tcp_data_cb(void *object, int crypt_connection_id, const uint8_t *packet, uint16_t length, void *userdata);
non_null()
int tcp_send_oob_packet_using_relay(const TCP_Connections *tcp_c, const uint8_t *relay_pk, const uint8_t *public_key,
@@ -178,9 +186,8 @@ void set_forwarding_packet_tcp_connection_callback(TCP_Connections *tcp_c,
forwarded_response_cb *tcp_forwarded_response_callback,
void *object);
-
typedef int tcp_oob_cb(void *object, const uint8_t *public_key, unsigned int tcp_connections_number,
- const uint8_t *data, uint16_t length, void *userdata);
+ const uint8_t *packet, uint16_t length, void *userdata);
/** @brief Set the callback for TCP oob data packets. */
non_null()
@@ -298,9 +305,8 @@ uint32_t tcp_copy_connected_relays_index(const TCP_Connections *tcp_c, Node_form
* Returns NULL on failure.
*/
non_null()
-TCP_Connections *new_tcp_connections(
- const Logger *logger, const Random *rng, const Network *ns, Mono_Time *mono_time,
- const uint8_t *secret_key, const TCP_Proxy_Info *proxy_info);
+TCP_Connections *new_tcp_connections(const Logger *logger, const Memory *mem, const Random *rng, const Network *ns,
+ Mono_Time *mono_time, const uint8_t *secret_key, const TCP_Proxy_Info *proxy_info);
non_null()
int kill_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connections_number);
@@ -311,4 +317,4 @@ void do_tcp_connections(const Logger *logger, TCP_Connections *tcp_c, void *user
nullable(1)
void kill_tcp_connections(TCP_Connections *tcp_c);
-#endif
+#endif /* C_TOXCORE_TOXCORE_TCP_CONNECTION_H */
diff --git a/protocols/Tox/libtox/src/toxcore/TCP_server.c b/protocols/Tox/libtox/src/toxcore/TCP_server.c
index ecd557d1b2..1363d90220 100644
--- a/protocols/Tox/libtox/src/toxcore/TCP_server.c
+++ b/protocols/Tox/libtox/src/toxcore/TCP_server.c
@@ -8,29 +8,34 @@
*/
#include "TCP_server.h"
-#include <stdlib.h>
#include <string.h>
#if !defined(_WIN32) && !defined(__WIN32__) && !defined (WIN32)
#include <sys/ioctl.h>
-#endif
+#endif /* !WIN32 */
#ifdef TCP_SERVER_USE_EPOLL
#include <sys/epoll.h>
#include <unistd.h>
-#endif
+#endif /* TCP_SERVER_USE_EPOLL */
#include "TCP_common.h"
+#include "attributes.h"
#include "ccompat.h"
+#include "crypto_core.h"
+#include "forwarding.h"
#include "list.h"
+#include "logger.h"
+#include "mem.h"
#include "mono_time.h"
-#include "util.h"
+#include "network.h"
+#include "onion.h"
#ifdef TCP_SERVER_USE_EPOLL
#define TCP_SOCKET_LISTENING 0
#define TCP_SOCKET_INCOMING 1
#define TCP_SOCKET_UNCONFIRMED 2
#define TCP_SOCKET_CONFIRMED 3
-#endif
+#endif /* TCP_SERVER_USE_EPOLL */
typedef struct TCP_Secure_Conn {
uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
@@ -55,9 +60,11 @@ typedef struct TCP_Secure_Connection {
uint64_t ping_id;
} TCP_Secure_Connection;
+static const TCP_Secure_Connection empty_tcp_secure_connection = {{nullptr}};
struct TCP_Server {
const Logger *logger;
+ const Memory *mem;
const Random *rng;
const Network *ns;
Onion *onion;
@@ -66,7 +73,7 @@ struct TCP_Server {
#ifdef TCP_SERVER_USE_EPOLL
int efd;
uint64_t last_run_pinged;
-#endif
+#endif /* TCP_SERVER_USE_EPOLL */
Socket *socks_listening;
unsigned int num_listening_socks;
@@ -86,6 +93,9 @@ struct TCP_Server {
BS_List accepted_key_list;
};
+static_assert(sizeof(TCP_Server) < 7 * 1024 * 1024,
+ "TCP_Server struct should not grow more; it's already 6MB");
+
const uint8_t *tcp_server_public_key(const TCP_Server *tcp_server)
{
return tcp_server->public_key;
@@ -100,8 +110,8 @@ size_t tcp_server_listen_count(const TCP_Server *tcp_server)
#ifdef TCP_SERVER_USE_EPOLL
#ifndef EPOLLRDHUP
#define EPOLLRDHUP 0x2000
-#endif
-#endif
+#endif /* EPOLLRDHUP */
+#endif /* TCP_SERVER_USE_EPOLL */
/** @brief Increase the size of the connection list
*
@@ -117,17 +127,18 @@ static int alloc_new_connections(TCP_Server *tcp_server, uint32_t num)
return -1;
}
- TCP_Secure_Connection *new_connections = (TCP_Secure_Connection *)realloc(
- tcp_server->accepted_connection_array,
- new_size * sizeof(TCP_Secure_Connection));
+ TCP_Secure_Connection *new_connections = (TCP_Secure_Connection *)mem_vrealloc(
+ tcp_server->mem, tcp_server->accepted_connection_array,
+ new_size, sizeof(TCP_Secure_Connection));
if (new_connections == nullptr) {
return -1;
}
const uint32_t old_size = tcp_server->size_accepted_connections;
- const uint32_t size_new_entries = num * sizeof(TCP_Secure_Connection);
- memset(new_connections + old_size, 0, size_new_entries);
+ for (uint32_t i = 0; i < num; ++i) {
+ new_connections[old_size + i] = empty_tcp_secure_connection;
+ }
tcp_server->accepted_connection_array = new_connections;
tcp_server->size_accepted_connections = new_size;
@@ -138,7 +149,7 @@ non_null()
static void wipe_secure_connection(TCP_Secure_Connection *con)
{
if (con->status != 0) {
- wipe_priority_list(con->con.priority_queue_start);
+ wipe_priority_list(con->con.mem, con->con.priority_queue_start);
crypto_memzero(con, sizeof(TCP_Secure_Connection));
}
}
@@ -161,7 +172,7 @@ static void free_accepted_connection_array(TCP_Server *tcp_server)
wipe_secure_connection(&tcp_server->accepted_connection_array[i]);
}
- free(tcp_server->accepted_connection_array);
+ mem_delete(tcp_server->mem, tcp_server->accepted_connection_array);
tcp_server->accepted_connection_array = nullptr;
tcp_server->size_accepted_connections = 0;
}
@@ -171,12 +182,11 @@ static void free_accepted_connection_array(TCP_Server *tcp_server)
* @retval -1 on failure.
*/
non_null()
-static int get_TCP_connection_index(const TCP_Server *tcp_server, const uint8_t *public_key)
+static int get_tcp_connection_index(const TCP_Server *tcp_server, const uint8_t *public_key)
{
return bs_list_find(&tcp_server->accepted_key_list, public_key);
}
-
non_null()
static int kill_accepted(TCP_Server *tcp_server, int index);
@@ -188,7 +198,7 @@ static int kill_accepted(TCP_Server *tcp_server, int index);
non_null()
static int add_accepted(TCP_Server *tcp_server, const Mono_Time *mono_time, TCP_Secure_Connection *con)
{
- int index = get_TCP_connection_index(tcp_server, con->public_key);
+ int index = get_tcp_connection_index(tcp_server, con->public_key);
if (index != -1) { /* If an old connection to the same public key exists, kill it. */
kill_accepted(tcp_server, index);
@@ -262,7 +272,7 @@ static int del_accepted(TCP_Server *tcp_server, int index)
/** Kill a TCP_Secure_Connection */
non_null()
-static void kill_TCP_secure_connection(TCP_Secure_Connection *con)
+static void kill_tcp_secure_connection(TCP_Secure_Connection *con)
{
kill_sock(con->con.ns, con->con.sock);
wipe_secure_connection(con);
@@ -301,7 +311,7 @@ static int kill_accepted(TCP_Server *tcp_server, int index)
* @retval -1 if the connection must be killed.
*/
non_null()
-static int handle_TCP_handshake(const Logger *logger, TCP_Secure_Connection *con, const uint8_t *data, uint16_t length,
+static int handle_tcp_handshake(const Logger *logger, TCP_Secure_Connection *con, const uint8_t *data, uint16_t length,
const uint8_t *self_secret_key)
{
if (length != TCP_CLIENT_HANDSHAKE_SIZE) {
@@ -345,7 +355,7 @@ static int handle_TCP_handshake(const Logger *logger, TCP_Secure_Connection *con
return -1;
}
- IP_Port ipp = {{{0}}};
+ const IP_Port ipp = {{{0}}};
if (TCP_SERVER_HANDSHAKE_SIZE != net_send(con->con.ns, logger, con->con.sock, response, TCP_SERVER_HANDSHAKE_SIZE, &ipp)) {
crypto_memzero(shared_key, sizeof(shared_key));
@@ -369,14 +379,14 @@ non_null()
static int read_connection_handshake(const Logger *logger, TCP_Secure_Connection *con, const uint8_t *self_secret_key)
{
uint8_t data[TCP_CLIENT_HANDSHAKE_SIZE];
- const int len = read_TCP_packet(logger, con->con.ns, con->con.sock, data, TCP_CLIENT_HANDSHAKE_SIZE, &con->con.ip_port);
+ const int len = read_tcp_packet(logger, con->con.mem, con->con.ns, con->con.sock, data, TCP_CLIENT_HANDSHAKE_SIZE, &con->con.ip_port);
if (len == -1) {
LOGGER_TRACE(logger, "connection handshake is not ready yet");
return 0;
}
- return handle_TCP_handshake(logger, con, data, len, self_secret_key);
+ return handle_tcp_handshake(logger, con, data, len, self_secret_key);
}
/**
@@ -393,7 +403,7 @@ static int send_routing_response(const Logger *logger, TCP_Secure_Connection *co
data[1] = rpid;
memcpy(data + 2, public_key, CRYPTO_PUBLIC_KEY_SIZE);
- return write_packet_TCP_secure_connection(logger, &con->con, data, sizeof(data), true);
+ return write_packet_tcp_secure_connection(logger, &con->con, data, sizeof(data), true);
}
/**
@@ -405,7 +415,7 @@ non_null()
static int send_connect_notification(const Logger *logger, TCP_Secure_Connection *con, uint8_t id)
{
uint8_t data[2] = {TCP_PACKET_CONNECTION_NOTIFICATION, (uint8_t)(id + NUM_RESERVED_PORTS)};
- return write_packet_TCP_secure_connection(logger, &con->con, data, sizeof(data), true);
+ return write_packet_tcp_secure_connection(logger, &con->con, data, sizeof(data), true);
}
/**
@@ -417,7 +427,7 @@ non_null()
static int send_disconnect_notification(const Logger *logger, TCP_Secure_Connection *con, uint8_t id)
{
uint8_t data[2] = {TCP_PACKET_DISCONNECT_NOTIFICATION, (uint8_t)(id + NUM_RESERVED_PORTS)};
- return write_packet_TCP_secure_connection(logger, &con->con, data, sizeof(data), true);
+ return write_packet_tcp_secure_connection(logger, &con->con, data, sizeof(data), true);
}
/**
@@ -425,7 +435,7 @@ static int send_disconnect_notification(const Logger *logger, TCP_Secure_Connect
* @retval -1 on failure (connection must be killed).
*/
non_null()
-static int handle_TCP_routing_req(TCP_Server *tcp_server, uint32_t con_id, const uint8_t *public_key)
+static int handle_tcp_routing_req(TCP_Server *tcp_server, uint32_t con_id, const uint8_t *public_key)
{
uint32_t index = -1;
TCP_Secure_Connection *con = &tcp_server->accepted_connection_array[con_id];
@@ -473,7 +483,7 @@ static int handle_TCP_routing_req(TCP_Server *tcp_server, uint32_t con_id, const
con->connections[index].status = 1;
memcpy(con->connections[index].public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
- const int other_index = get_TCP_connection_index(tcp_server, public_key);
+ const int other_index = get_tcp_connection_index(tcp_server, public_key);
if (other_index != -1) {
uint32_t other_id = -1;
@@ -508,7 +518,7 @@ static int handle_TCP_routing_req(TCP_Server *tcp_server, uint32_t con_id, const
* @retval -1 on failure (connection must be killed).
*/
non_null()
-static int handle_TCP_oob_send(TCP_Server *tcp_server, uint32_t con_id, const uint8_t *public_key, const uint8_t *data,
+static int handle_tcp_oob_send(TCP_Server *tcp_server, uint32_t con_id, const uint8_t *public_key, const uint8_t *data,
uint16_t length)
{
if (length == 0 || length > TCP_MAX_OOB_DATA_LENGTH) {
@@ -517,15 +527,16 @@ static int handle_TCP_oob_send(TCP_Server *tcp_server, uint32_t con_id, const ui
const TCP_Secure_Connection *con = &tcp_server->accepted_connection_array[con_id];
- const int other_index = get_TCP_connection_index(tcp_server, public_key);
+ const int other_index = get_tcp_connection_index(tcp_server, public_key);
if (other_index != -1) {
- VLA(uint8_t, resp_packet, 1 + CRYPTO_PUBLIC_KEY_SIZE + length);
+ const uint16_t resp_packet_size = 1 + CRYPTO_PUBLIC_KEY_SIZE + length;
+ VLA(uint8_t, resp_packet, resp_packet_size);
resp_packet[0] = TCP_PACKET_OOB_RECV;
memcpy(resp_packet + 1, con->public_key, CRYPTO_PUBLIC_KEY_SIZE);
memcpy(resp_packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, data, length);
- write_packet_TCP_secure_connection(tcp_server->logger, &tcp_server->accepted_connection_array[other_index].con,
- resp_packet, SIZEOF_VLA(resp_packet), false);
+ write_packet_tcp_secure_connection(tcp_server->logger, &tcp_server->accepted_connection_array[other_index].con,
+ resp_packet, resp_packet_size, false);
}
return 0;
@@ -608,11 +619,12 @@ static int handle_onion_recv_1(void *object, const IP_Port *dest, const uint8_t
TCP_Secure_Connection *con = &tcp_server->accepted_connection_array[index];
- VLA(uint8_t, packet, 1 + length);
+ const uint16_t packet_size = 1 + length;
+ VLA(uint8_t, packet, packet_size);
memcpy(packet + 1, data, length);
packet[0] = TCP_PACKET_ONION_RESPONSE;
- if (write_packet_TCP_secure_connection(tcp_server->logger, &con->con, packet, SIZEOF_VLA(packet), false) != 1) {
+ if (write_packet_tcp_secure_connection(tcp_server->logger, &con->con, packet, packet_size, false) != 1) {
return 1;
}
@@ -648,11 +660,12 @@ static bool handle_forward_reply_tcp(void *object, const uint8_t *sendback_data,
return false;
}
- VLA(uint8_t, packet, 1 + length);
+ const uint16_t packet_size = 1 + length;
+ VLA(uint8_t, packet, packet_size);
memcpy(packet + 1, data, length);
packet[0] = TCP_PACKET_FORWARDING;
- return write_packet_TCP_secure_connection(tcp_server->logger, &con->con, packet, SIZEOF_VLA(packet), false) == 1;
+ return write_packet_tcp_secure_connection(tcp_server->logger, &con->con, packet, packet_size, false) == 1;
}
/**
@@ -660,7 +673,7 @@ static bool handle_forward_reply_tcp(void *object, const uint8_t *sendback_data,
* @retval -1 on failure
*/
non_null()
-static int handle_TCP_packet(TCP_Server *tcp_server, uint32_t con_id, const uint8_t *data, uint16_t length)
+static int handle_tcp_packet(TCP_Server *tcp_server, uint32_t con_id, const uint8_t *data, uint16_t length)
{
if (length == 0) {
return -1;
@@ -675,7 +688,7 @@ static int handle_TCP_packet(TCP_Server *tcp_server, uint32_t con_id, const uint
}
LOGGER_TRACE(tcp_server->logger, "handling routing request for %d", con_id);
- return handle_TCP_routing_req(tcp_server, con_id, data + 1);
+ return handle_tcp_routing_req(tcp_server, con_id, data + 1);
}
case TCP_PACKET_CONNECTION_NOTIFICATION: {
@@ -706,7 +719,7 @@ static int handle_TCP_packet(TCP_Server *tcp_server, uint32_t con_id, const uint
uint8_t response[1 + sizeof(uint64_t)];
response[0] = TCP_PACKET_PONG;
memcpy(response + 1, data + 1, sizeof(uint64_t));
- write_packet_TCP_secure_connection(tcp_server->logger, &con->con, response, sizeof(response), true);
+ write_packet_tcp_secure_connection(tcp_server->logger, &con->con, response, sizeof(response), true);
return 0;
}
@@ -738,7 +751,7 @@ static int handle_TCP_packet(TCP_Server *tcp_server, uint32_t con_id, const uint
LOGGER_TRACE(tcp_server->logger, "handling oob send for %d", con_id);
- return handle_TCP_oob_send(tcp_server, con_id, data + 1, data + 1 + CRYPTO_PUBLIC_KEY_SIZE,
+ return handle_tcp_oob_send(tcp_server, con_id, data + 1, data + 1 + CRYPTO_PUBLIC_KEY_SIZE,
length - (1 + CRYPTO_PUBLIC_KEY_SIZE));
}
@@ -750,7 +763,7 @@ static int handle_TCP_packet(TCP_Server *tcp_server, uint32_t con_id, const uint
return -1;
}
- IP_Port source = con_id_to_ip_port(con_id, con->identifier);
+ const IP_Port source = con_id_to_ip_port(con_id, con->identifier);
onion_send_1(tcp_server->onion, data + 1 + CRYPTO_NONCE_SIZE, length - (1 + CRYPTO_NONCE_SIZE), &source,
data + 1);
}
@@ -821,7 +834,7 @@ static int handle_TCP_packet(TCP_Server *tcp_server, uint32_t con_id, const uint
VLA(uint8_t, new_data, length);
memcpy(new_data, data, length);
new_data[0] = other_c_id;
- const int ret = write_packet_TCP_secure_connection(tcp_server->logger,
+ const int ret = write_packet_tcp_secure_connection(tcp_server->logger,
&tcp_server->accepted_connection_array[index].con, new_data, length, false);
if (ret == -1) {
@@ -835,22 +848,21 @@ static int handle_TCP_packet(TCP_Server *tcp_server, uint32_t con_id, const uint
return 0;
}
-
non_null()
-static int confirm_TCP_connection(TCP_Server *tcp_server, const Mono_Time *mono_time, TCP_Secure_Connection *con,
+static int confirm_tcp_connection(TCP_Server *tcp_server, const Mono_Time *mono_time, TCP_Secure_Connection *con,
const uint8_t *data, uint16_t length)
{
const int index = add_accepted(tcp_server, mono_time, con);
if (index == -1) {
LOGGER_DEBUG(tcp_server->logger, "dropping connection %u: not accepted", (unsigned int)con->identifier);
- kill_TCP_secure_connection(con);
+ kill_tcp_secure_connection(con);
return -1;
}
wipe_secure_connection(con);
- if (handle_TCP_packet(tcp_server, index, data, length) == -1) {
+ if (handle_tcp_packet(tcp_server, index, data, length) == -1) {
LOGGER_DEBUG(tcp_server->logger, "dropping connection %u: data packet (len=%d) not handled",
(unsigned int)con->identifier, length);
kill_accepted(tcp_server, index);
@@ -887,11 +899,12 @@ static int accept_connection(TCP_Server *tcp_server, Socket sock)
if (conn->status != TCP_STATUS_NO_STATUS) {
LOGGER_DEBUG(tcp_server->logger, "connection %d dropped before accepting", index);
- kill_TCP_secure_connection(conn);
+ kill_tcp_secure_connection(conn);
}
conn->status = TCP_STATUS_CONNECTED;
conn->con.ns = tcp_server->ns;
+ conn->con.mem = tcp_server->mem;
conn->con.rng = tcp_server->rng;
conn->con.sock = sock;
conn->next_packet_length = 0;
@@ -901,13 +914,13 @@ static int accept_connection(TCP_Server *tcp_server, Socket sock)
}
non_null()
-static Socket new_listening_TCP_socket(const Logger *logger, const Network *ns, Family family, uint16_t port)
+static Socket new_listening_tcp_socket(const Logger *logger, const Network *ns, Family family, uint16_t port)
{
const Socket sock = net_socket(ns, family, TOX_SOCK_STREAM, TOX_PROTO_TCP);
if (!sock_valid(sock)) {
LOGGER_ERROR(logger, "TCP socket creation failed (family = %d)", family.value);
- return net_invalid_socket;
+ return net_invalid_socket();
}
bool ok = set_socket_nonblock(ns, sock);
@@ -928,14 +941,14 @@ static Socket new_listening_TCP_socket(const Logger *logger, const Network *ns,
port, family.value, error != nullptr ? error : "(null)");
net_kill_strerror(error);
kill_sock(ns, sock);
- return net_invalid_socket;
+ return net_invalid_socket();
}
LOGGER_DEBUG(logger, "successfully bound to TCP port %d", port);
return sock;
}
-TCP_Server *new_TCP_server(const Logger *logger, const Random *rng, const Network *ns,
+TCP_Server *new_tcp_server(const Logger *logger, const Memory *mem, const Random *rng, const Network *ns,
bool ipv6_enabled, uint16_t num_sockets,
const uint16_t *ports, const uint8_t *secret_key, Onion *onion, Forwarding *forwarding)
{
@@ -949,7 +962,7 @@ TCP_Server *new_TCP_server(const Logger *logger, const Random *rng, const Networ
return nullptr;
}
- TCP_Server *temp = (TCP_Server *)calloc(1, sizeof(TCP_Server));
+ TCP_Server *temp = (TCP_Server *)mem_alloc(mem, sizeof(TCP_Server));
if (temp == nullptr) {
LOGGER_ERROR(logger, "TCP server allocation failed");
@@ -957,33 +970,36 @@ TCP_Server *new_TCP_server(const Logger *logger, const Random *rng, const Networ
}
temp->logger = logger;
+ temp->mem = mem;
temp->ns = ns;
temp->rng = rng;
- temp->socks_listening = (Socket *)calloc(num_sockets, sizeof(Socket));
+ Socket *socks_listening = (Socket *)mem_valloc(mem, num_sockets, sizeof(Socket));
- if (temp->socks_listening == nullptr) {
+ if (socks_listening == nullptr) {
LOGGER_ERROR(logger, "socket allocation failed");
- free(temp);
+ mem_delete(mem, temp);
return nullptr;
}
+ temp->socks_listening = socks_listening;
+
#ifdef TCP_SERVER_USE_EPOLL
temp->efd = epoll_create(8);
if (temp->efd == -1) {
LOGGER_ERROR(logger, "epoll initialisation failed");
- free(temp->socks_listening);
- free(temp);
+ mem_delete(mem, socks_listening);
+ mem_delete(mem, temp);
return nullptr;
}
-#endif
+#endif /* TCP_SERVER_USE_EPOLL */
const Family family = ipv6_enabled ? net_family_ipv6() : net_family_ipv4();
for (uint32_t i = 0; i < num_sockets; ++i) {
- const Socket sock = new_listening_TCP_socket(logger, ns, family, ports[i]);
+ const Socket sock = new_listening_tcp_socket(logger, ns, family, ports[i]);
if (!sock_valid(sock)) {
continue;
@@ -993,21 +1009,21 @@ TCP_Server *new_TCP_server(const Logger *logger, const Random *rng, const Networ
struct epoll_event ev;
ev.events = EPOLLIN | EPOLLET;
- ev.data.u64 = sock.sock | ((uint64_t)TCP_SOCKET_LISTENING << 32);
+ ev.data.u64 = net_socket_to_native(sock) | ((uint64_t)TCP_SOCKET_LISTENING << 32);
- if (epoll_ctl(temp->efd, EPOLL_CTL_ADD, sock.sock, &ev) == -1) {
+ if (epoll_ctl(temp->efd, EPOLL_CTL_ADD, net_socket_to_native(sock), &ev) == -1) {
continue;
}
-#endif
+#endif /* TCP_SERVER_USE_EPOLL */
temp->socks_listening[temp->num_listening_socks] = sock;
++temp->num_listening_socks;
}
if (temp->num_listening_socks == 0) {
- free(temp->socks_listening);
- free(temp);
+ mem_delete(mem, temp->socks_listening);
+ mem_delete(mem, temp);
return nullptr;
}
@@ -1024,14 +1040,14 @@ TCP_Server *new_TCP_server(const Logger *logger, const Random *rng, const Networ
memcpy(temp->secret_key, secret_key, CRYPTO_SECRET_KEY_SIZE);
crypto_derive_public_key(temp->public_key, temp->secret_key);
- bs_list_init(&temp->accepted_key_list, CRYPTO_PUBLIC_KEY_SIZE, 8);
+ bs_list_init(&temp->accepted_key_list, CRYPTO_PUBLIC_KEY_SIZE, 8, memcmp);
return temp;
}
#ifndef TCP_SERVER_USE_EPOLL
non_null()
-static void do_TCP_accept_new(TCP_Server *tcp_server)
+static void do_tcp_accept_new(TCP_Server *tcp_server)
{
for (uint32_t sock_idx = 0; sock_idx < tcp_server->num_listening_socks; ++sock_idx) {
@@ -1044,7 +1060,7 @@ static void do_TCP_accept_new(TCP_Server *tcp_server)
}
}
}
-#endif
+#endif /* TCP_SERVER_USE_EPOLL */
non_null()
static int do_incoming(TCP_Server *tcp_server, uint32_t i)
@@ -1061,7 +1077,7 @@ static int do_incoming(TCP_Server *tcp_server, uint32_t i)
if (ret == -1) {
LOGGER_TRACE(tcp_server->logger, "incoming connection %d dropped due to failed handshake", i);
- kill_TCP_secure_connection(conn);
+ kill_tcp_secure_connection(conn);
return -1;
}
@@ -1075,7 +1091,7 @@ static int do_incoming(TCP_Server *tcp_server, uint32_t i)
if (conn_new->status != TCP_STATUS_NO_STATUS) {
LOGGER_ERROR(tcp_server->logger, "incoming connection %d would overwrite existing", i);
- kill_TCP_secure_connection(conn_new);
+ kill_tcp_secure_connection(conn_new);
}
move_secure_connection(conn_new, conn_old);
@@ -1096,18 +1112,19 @@ static int do_unconfirmed(TCP_Server *tcp_server, const Mono_Time *mono_time, ui
LOGGER_TRACE(tcp_server->logger, "handling unconfirmed TCP connection %d", i);
uint8_t packet[MAX_PACKET_SIZE];
- const int len = read_packet_TCP_secure_connection(tcp_server->logger, conn->con.ns, conn->con.sock, &conn->next_packet_length, conn->con.shared_key, conn->recv_nonce, packet, sizeof(packet), &conn->con.ip_port);
+ const int len = read_packet_tcp_secure_connection(tcp_server->logger, conn->con.mem, conn->con.ns, conn->con.sock, &conn->next_packet_length, conn->con.shared_key, conn->recv_nonce, packet,
+ sizeof(packet), &conn->con.ip_port);
if (len == 0) {
return -1;
}
if (len == -1) {
- kill_TCP_secure_connection(conn);
+ kill_tcp_secure_connection(conn);
return -1;
}
- return confirm_TCP_connection(tcp_server, mono_time, conn, packet, len);
+ return confirm_tcp_connection(tcp_server, mono_time, conn, packet, len);
}
non_null()
@@ -1116,7 +1133,8 @@ static bool tcp_process_secure_packet(TCP_Server *tcp_server, uint32_t i)
TCP_Secure_Connection *const conn = &tcp_server->accepted_connection_array[i];
uint8_t packet[MAX_PACKET_SIZE];
- const int len = read_packet_TCP_secure_connection(tcp_server->logger, conn->con.ns, conn->con.sock, &conn->next_packet_length, conn->con.shared_key, conn->recv_nonce, packet, sizeof(packet), &conn->con.ip_port);
+ const int len = read_packet_tcp_secure_connection(tcp_server->logger, conn->con.mem, conn->con.ns, conn->con.sock, &conn->next_packet_length, conn->con.shared_key, conn->recv_nonce, packet,
+ sizeof(packet), &conn->con.ip_port);
LOGGER_TRACE(tcp_server->logger, "processing packet for %d: %d", i, len);
if (len == 0) {
@@ -1128,7 +1146,7 @@ static bool tcp_process_secure_packet(TCP_Server *tcp_server, uint32_t i)
return false;
}
- if (handle_TCP_packet(tcp_server, i, packet, len) == -1) {
+ if (handle_tcp_packet(tcp_server, i, packet, len) == -1) {
LOGGER_TRACE(tcp_server->logger, "dropping connection %d: data packet (len=%d) not handled", i, len);
kill_accepted(tcp_server, i);
return false;
@@ -1141,14 +1159,13 @@ non_null()
static void do_confirmed_recv(TCP_Server *tcp_server, uint32_t i)
{
while (tcp_process_secure_packet(tcp_server, i)) {
- // Keep reading until an error occurs or there is no more data to read.
- continue;
+ /* Keep reading until an error occurs or there is no more data to read. */
}
}
#ifndef TCP_SERVER_USE_EPOLL
non_null()
-static void do_TCP_incoming(TCP_Server *tcp_server)
+static void do_tcp_incoming(TCP_Server *tcp_server)
{
for (uint32_t i = 0; i < MAX_INCOMING_CONNECTIONS; ++i) {
do_incoming(tcp_server, i);
@@ -1156,16 +1173,16 @@ static void do_TCP_incoming(TCP_Server *tcp_server)
}
non_null()
-static void do_TCP_unconfirmed(TCP_Server *tcp_server, const Mono_Time *mono_time)
+static void do_tcp_unconfirmed(TCP_Server *tcp_server, const Mono_Time *mono_time)
{
for (uint32_t i = 0; i < MAX_INCOMING_CONNECTIONS; ++i) {
do_unconfirmed(tcp_server, mono_time, i);
}
}
-#endif
+#endif /* TCP_SERVER_USE_EPOLL */
non_null()
-static void do_TCP_confirmed(TCP_Server *tcp_server, const Mono_Time *mono_time)
+static void do_tcp_confirmed(TCP_Server *tcp_server, const Mono_Time *mono_time)
{
#ifdef TCP_SERVER_USE_EPOLL
@@ -1174,7 +1191,7 @@ static void do_TCP_confirmed(TCP_Server *tcp_server, const Mono_Time *mono_time)
}
tcp_server->last_run_pinged = mono_time_get(mono_time);
-#endif
+#endif /* TCP_SERVER_USE_EPOLL */
for (uint32_t i = 0; i < tcp_server->size_accepted_connections; ++i) {
TCP_Secure_Connection *conn = &tcp_server->accepted_connection_array[i];
@@ -1193,7 +1210,7 @@ static void do_TCP_confirmed(TCP_Server *tcp_server, const Mono_Time *mono_time)
}
memcpy(ping + 1, &ping_id, sizeof(uint64_t));
- const int ret = write_packet_TCP_secure_connection(tcp_server->logger, &conn->con, ping, sizeof(ping), true);
+ const int ret = write_packet_tcp_secure_connection(tcp_server->logger, &conn->con, ping, sizeof(ping), true);
if (ret == 1) {
conn->last_pinged = mono_time_get(mono_time);
@@ -1217,7 +1234,7 @@ static void do_TCP_confirmed(TCP_Server *tcp_server, const Mono_Time *mono_time)
do_confirmed_recv(tcp_server, i);
-#endif
+#endif /* TCP_SERVER_USE_EPOLL */
}
}
@@ -1231,7 +1248,7 @@ static bool tcp_epoll_process(TCP_Server *tcp_server, const Mono_Time *mono_time
#undef MAX_EVENTS
for (int n = 0; n < nfds; ++n) {
- const Socket sock = {(int)(events[n].data.u64 & 0xFFFFFFFF)};
+ const Socket sock = net_socket_from_native((int)(events[n].data.u64 & 0xFFFFFFFF));
const int status = (events[n].data.u64 >> 32) & 0xFF;
const int index = events[n].data.u64 >> 40;
@@ -1245,13 +1262,13 @@ static bool tcp_epoll_process(TCP_Server *tcp_server, const Mono_Time *mono_time
case TCP_SOCKET_INCOMING: {
LOGGER_TRACE(tcp_server->logger, "incoming connection %d dropped", index);
- kill_TCP_secure_connection(&tcp_server->incoming_connection_queue[index]);
+ kill_tcp_secure_connection(&tcp_server->incoming_connection_queue[index]);
break;
}
case TCP_SOCKET_UNCONFIRMED: {
LOGGER_TRACE(tcp_server->logger, "unconfirmed connection %d dropped", index);
- kill_TCP_secure_connection(&tcp_server->unconfirmed_connection_queue[index]);
+ kill_tcp_secure_connection(&tcp_server->unconfirmed_connection_queue[index]);
break;
}
@@ -1265,7 +1282,6 @@ static bool tcp_epoll_process(TCP_Server *tcp_server, const Mono_Time *mono_time
continue;
}
-
if ((events[n].events & EPOLLIN) == 0) {
continue;
}
@@ -1290,11 +1306,11 @@ static bool tcp_epoll_process(TCP_Server *tcp_server, const Mono_Time *mono_time
ev.events = EPOLLIN | EPOLLET | EPOLLRDHUP;
- ev.data.u64 = sock_new.sock | ((uint64_t)TCP_SOCKET_INCOMING << 32) | ((uint64_t)index_new << 40);
+ ev.data.u64 = net_socket_to_native(sock_new) | ((uint64_t)TCP_SOCKET_INCOMING << 32) | ((uint64_t)index_new << 40);
- if (epoll_ctl(tcp_server->efd, EPOLL_CTL_ADD, sock_new.sock, &ev) == -1) {
+ if (epoll_ctl(tcp_server->efd, EPOLL_CTL_ADD, net_socket_to_native(sock_new), &ev) == -1) {
LOGGER_DEBUG(tcp_server->logger, "new connection %d was dropped due to epoll error %d", index, net_error());
- kill_TCP_secure_connection(&tcp_server->incoming_connection_queue[index_new]);
+ kill_tcp_secure_connection(&tcp_server->incoming_connection_queue[index_new]);
continue;
}
}
@@ -1308,11 +1324,11 @@ static bool tcp_epoll_process(TCP_Server *tcp_server, const Mono_Time *mono_time
if (index_new != -1) {
LOGGER_TRACE(tcp_server->logger, "incoming connection %d was accepted as %d", index, index_new);
events[n].events = EPOLLIN | EPOLLET | EPOLLRDHUP;
- events[n].data.u64 = sock.sock | ((uint64_t)TCP_SOCKET_UNCONFIRMED << 32) | ((uint64_t)index_new << 40);
+ events[n].data.u64 = net_socket_to_native(sock) | ((uint64_t)TCP_SOCKET_UNCONFIRMED << 32) | ((uint64_t)index_new << 40);
- if (epoll_ctl(tcp_server->efd, EPOLL_CTL_MOD, sock.sock, &events[n]) == -1) {
+ if (epoll_ctl(tcp_server->efd, EPOLL_CTL_MOD, net_socket_to_native(sock), &events[n]) == -1) {
LOGGER_DEBUG(tcp_server->logger, "incoming connection %d was dropped due to epoll error %d", index, net_error());
- kill_TCP_secure_connection(&tcp_server->unconfirmed_connection_queue[index_new]);
+ kill_tcp_secure_connection(&tcp_server->unconfirmed_connection_queue[index_new]);
break;
}
}
@@ -1326,9 +1342,9 @@ static bool tcp_epoll_process(TCP_Server *tcp_server, const Mono_Time *mono_time
if (index_new != -1) {
LOGGER_TRACE(tcp_server->logger, "unconfirmed connection %d was confirmed as %d", index, index_new);
events[n].events = EPOLLIN | EPOLLET | EPOLLRDHUP;
- events[n].data.u64 = sock.sock | ((uint64_t)TCP_SOCKET_CONFIRMED << 32) | ((uint64_t)index_new << 40);
+ events[n].data.u64 = net_socket_to_native(sock) | ((uint64_t)TCP_SOCKET_CONFIRMED << 32) | ((uint64_t)index_new << 40);
- if (epoll_ctl(tcp_server->efd, EPOLL_CTL_MOD, sock.sock, &events[n]) == -1) {
+ if (epoll_ctl(tcp_server->efd, EPOLL_CTL_MOD, net_socket_to_native(sock), &events[n]) == -1) {
// remove from confirmed connections
LOGGER_DEBUG(tcp_server->logger, "unconfirmed connection %d was dropped due to epoll error %d", index, net_error());
kill_accepted(tcp_server, index_new);
@@ -1350,30 +1366,30 @@ static bool tcp_epoll_process(TCP_Server *tcp_server, const Mono_Time *mono_time
}
non_null()
-static void do_TCP_epoll(TCP_Server *tcp_server, const Mono_Time *mono_time)
+static void do_tcp_epoll(TCP_Server *tcp_server, const Mono_Time *mono_time)
{
while (tcp_epoll_process(tcp_server, mono_time)) {
// Keep processing packets until there are no more FDs ready for reading.
continue;
}
}
-#endif
+#endif /* TCP_SERVER_USE_EPOLL */
-void do_TCP_server(TCP_Server *tcp_server, const Mono_Time *mono_time)
+void do_tcp_server(TCP_Server *tcp_server, const Mono_Time *mono_time)
{
#ifdef TCP_SERVER_USE_EPOLL
- do_TCP_epoll(tcp_server, mono_time);
+ do_tcp_epoll(tcp_server, mono_time);
#else
- do_TCP_accept_new(tcp_server);
- do_TCP_incoming(tcp_server);
- do_TCP_unconfirmed(tcp_server, mono_time);
-#endif
+ do_tcp_accept_new(tcp_server);
+ do_tcp_incoming(tcp_server);
+ do_tcp_unconfirmed(tcp_server, mono_time);
+#endif /* TCP_SERVER_USE_EPOLL */
- do_TCP_confirmed(tcp_server, mono_time);
+ do_tcp_confirmed(tcp_server, mono_time);
}
-void kill_TCP_server(TCP_Server *tcp_server)
+void kill_tcp_server(TCP_Server *tcp_server)
{
if (tcp_server == nullptr) {
return;
@@ -1395,7 +1411,7 @@ void kill_TCP_server(TCP_Server *tcp_server)
#ifdef TCP_SERVER_USE_EPOLL
close(tcp_server->efd);
-#endif
+#endif /* TCP_SERVER_USE_EPOLL */
for (uint32_t i = 0; i < MAX_INCOMING_CONNECTIONS; ++i) {
wipe_secure_connection(&tcp_server->incoming_connection_queue[i]);
@@ -1406,6 +1422,6 @@ void kill_TCP_server(TCP_Server *tcp_server)
crypto_memzero(tcp_server->secret_key, sizeof(tcp_server->secret_key));
- free(tcp_server->socks_listening);
- free(tcp_server);
+ mem_delete(tcp_server->mem, tcp_server->socks_listening);
+ mem_delete(tcp_server->mem, tcp_server);
}
diff --git a/protocols/Tox/libtox/src/toxcore/TCP_server.h b/protocols/Tox/libtox/src/toxcore/TCP_server.h
index 2224938a09..1d3933a415 100644
--- a/protocols/Tox/libtox/src/toxcore/TCP_server.h
+++ b/protocols/Tox/libtox/src/toxcore/TCP_server.h
@@ -9,8 +9,13 @@
#ifndef C_TOXCORE_TOXCORE_TCP_SERVER_H
#define C_TOXCORE_TOXCORE_TCP_SERVER_H
+#include "attributes.h"
#include "crypto_core.h"
#include "forwarding.h"
+#include "logger.h"
+#include "mem.h"
+#include "mono_time.h"
+#include "network.h"
#include "onion.h"
#define MAX_INCOMING_CONNECTIONS 256
@@ -34,18 +39,17 @@ non_null()
size_t tcp_server_listen_count(const TCP_Server *tcp_server);
/** Create new TCP server instance. */
-non_null(1, 2, 3, 6, 7) nullable(8, 9)
-TCP_Server *new_TCP_server(const Logger *logger, const Random *rng, const Network *ns,
+non_null(1, 2, 3, 4, 7, 8) nullable(9, 10)
+TCP_Server *new_tcp_server(const Logger *logger, const Memory *mem, const Random *rng, const Network *ns,
bool ipv6_enabled, uint16_t num_sockets, const uint16_t *ports,
const uint8_t *secret_key, Onion *onion, Forwarding *forwarding);
/** Run the TCP_server */
non_null()
-void do_TCP_server(TCP_Server *tcp_server, const Mono_Time *mono_time);
+void do_tcp_server(TCP_Server *tcp_server, const Mono_Time *mono_time);
/** Kill the TCP server */
nullable(1)
-void kill_TCP_server(TCP_Server *tcp_server);
+void kill_tcp_server(TCP_Server *tcp_server);
-
-#endif
+#endif /* C_TOXCORE_TOXCORE_TCP_SERVER_H */
diff --git a/protocols/Tox/libtox/src/toxcore/announce.c b/protocols/Tox/libtox/src/toxcore/announce.c
index 647bd21ea3..b983cb0574 100644
--- a/protocols/Tox/libtox/src/toxcore/announce.c
+++ b/protocols/Tox/libtox/src/toxcore/announce.c
@@ -12,8 +12,16 @@
#include <stdlib.h>
#include <string.h>
+#include "DHT.h"
#include "LAN_discovery.h"
+#include "attributes.h"
#include "ccompat.h"
+#include "crypto_core.h"
+#include "forwarding.h"
+#include "logger.h"
+#include "mem.h"
+#include "mono_time.h"
+#include "network.h"
#include "shared_key_cache.h"
#include "timed_auth.h"
#include "util.h"
@@ -50,6 +58,7 @@ typedef struct Announce_Entry {
struct Announcements {
const Logger *log;
+ const Memory *mem;
const Random *rng;
Forwarding *forwarding;
const Mono_Time *mono_time;
@@ -156,7 +165,6 @@ static const Announce_Entry *get_stored_const(const Announcements *announce, con
return nullptr;
}
-
bool announce_on_stored(const Announcements *announce, const uint8_t *data_public_key,
announce_on_retrieve_cb *on_retrieve_callback, void *object)
{
@@ -231,17 +239,17 @@ bool announce_store_data(Announcements *announce, const uint8_t *data_public_key
if (length > 0) {
assert(data != nullptr);
- if (entry->data != nullptr) {
- free(entry->data);
- }
+ free(entry->data);
- entry->data = (uint8_t *)malloc(length);
+ uint8_t *entry_data = (uint8_t *)malloc(length);
- if (entry->data == nullptr) {
+ if (entry_data == nullptr) {
+ entry->data = nullptr; // TODO(iphydf): Is this necessary?
return false;
}
- memcpy(entry->data, data, length);
+ memcpy(entry_data, data, length);
+ entry->data = entry_data;
}
entry->length = length;
@@ -301,7 +309,7 @@ static int create_reply_plain_data_search_request(Announcements *announce,
const IP_Port *source,
const uint8_t *data, uint16_t length,
uint8_t *reply, uint16_t reply_max_length,
- uint8_t *to_auth, uint16_t to_auth_length)
+ const uint8_t *to_auth, uint16_t to_auth_length)
{
if (length != CRYPTO_PUBLIC_KEY_SIZE &&
length != CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA256_SIZE) {
@@ -344,7 +352,7 @@ static int create_reply_plain_data_search_request(Announcements *announce,
to_auth, to_auth_length, p);
p += TIMED_AUTH_SIZE;
- *p = would_accept_store_request(announce, data_public_key);
+ *p = would_accept_store_request(announce, data_public_key) ? 1 : 0;
++p;
Node_format nodes_list[MAX_SENT_NODES];
@@ -376,11 +384,12 @@ static int create_reply_plain_data_search_request(Announcements *announce,
}
non_null()
-static int create_reply_plain_data_retrieve_request(Announcements *announce,
- const IP_Port *source,
- const uint8_t *data, uint16_t length,
- uint8_t *reply, uint16_t reply_max_length,
- uint8_t *to_auth, uint16_t to_auth_length)
+static int create_reply_plain_data_retrieve_request(
+ const Announcements *announce,
+ const IP_Port *source,
+ const uint8_t *data, uint16_t length,
+ uint8_t *reply, uint16_t reply_max_length,
+ const uint8_t *to_auth, uint16_t to_auth_length)
{
if (length != CRYPTO_PUBLIC_KEY_SIZE + 1 + TIMED_AUTH_SIZE) {
return -1;
@@ -422,10 +431,10 @@ static int create_reply_plain_store_announce_request(Announcements *announce,
const IP_Port *source,
const uint8_t *data, uint16_t length,
uint8_t *reply, uint16_t reply_max_length,
- uint8_t *to_auth, uint16_t to_auth_length)
+ const uint8_t *to_auth, uint16_t to_auth_length)
{
const int plain_len = (int)length - (CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_MAC_SIZE);
- const int announcement_len = (int)plain_len - (TIMED_AUTH_SIZE + sizeof(uint32_t) + 1);
+ const int announcement_len = plain_len - (TIMED_AUTH_SIZE + sizeof(uint32_t) + 1);
const uint8_t *const data_public_key = data;
@@ -435,7 +444,7 @@ static int create_reply_plain_store_announce_request(Announcements *announce,
VLA(uint8_t, plain, plain_len);
- const uint8_t* shared_key = shared_key_cache_lookup(announce->shared_keys, data_public_key);
+ const uint8_t *shared_key = shared_key_cache_lookup(announce->shared_keys, data_public_key);
if (shared_key == nullptr) {
/* Error looking up/deriving the shared key */
@@ -593,8 +602,8 @@ static int create_reply(Announcements *announce, const IP_Port *source,
const uint8_t response_type = announce_response_of_request_type(data[0]);
- return dht_create_packet(announce->rng, announce->public_key, shared_key, response_type,
- plain_reply, plain_reply_len, reply, reply_max_length);
+ return dht_create_packet(announce->mem, announce->rng, announce->public_key, shared_key,
+ response_type, plain_reply, plain_reply_len, reply, reply_max_length);
}
non_null(1, 2, 3, 5) nullable(7)
@@ -618,16 +627,15 @@ static void forwarded_request_callback(void *object, const IP_Port *forwarder,
}
non_null(1, 2, 3) nullable(5)
-static int handle_dht_announce_request(void *object, const IP_Port *source,
- const uint8_t *data, uint16_t length, void *userdata)
+static int handle_dht_announce_request(
+ void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, void *userdata)
{
- Announcements *announce = (Announcements *) object;
+ Announcements *announce = (Announcements *)object;
uint8_t reply[MAX_FORWARD_DATA_SIZE];
- const int len = create_reply(announce, source,
- nullptr, 0,
- data, length, reply, sizeof(reply));
+ const int len
+ = create_reply(announce, source, nullptr, 0, packet, length, reply, sizeof(reply));
if (len == -1) {
return -1;
@@ -636,7 +644,7 @@ static int handle_dht_announce_request(void *object, const IP_Port *source,
return sendpacket(announce->net, source, reply, len) == len ? 0 : -1;
}
-Announcements *new_announcements(const Logger *log, const Random *rng, const Mono_Time *mono_time,
+Announcements *new_announcements(const Logger *log, const Memory *mem, const Random *rng, const Mono_Time *mono_time,
Forwarding *forwarding)
{
if (log == nullptr || mono_time == nullptr || forwarding == nullptr) {
@@ -650,6 +658,7 @@ Announcements *new_announcements(const Logger *log, const Random *rng, const Mon
}
announce->log = log;
+ announce->mem = mem;
announce->rng = rng;
announce->forwarding = forwarding;
announce->mono_time = mono_time;
@@ -658,7 +667,7 @@ Announcements *new_announcements(const Logger *log, const Random *rng, const Mon
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, 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;
@@ -691,9 +700,7 @@ void kill_announcements(Announcements *announce)
shared_key_cache_free(announce->shared_keys);
for (uint32_t i = 0; i < ANNOUNCE_BUCKETS * ANNOUNCE_BUCKET_SIZE; ++i) {
- if (announce->entries[i].data != nullptr) {
- free(announce->entries[i].data);
- }
+ free(announce->entries[i].data);
}
free(announce);
diff --git a/protocols/Tox/libtox/src/toxcore/announce.h b/protocols/Tox/libtox/src/toxcore/announce.h
index e680da68b6..bd05088d06 100644
--- a/protocols/Tox/libtox/src/toxcore/announce.h
+++ b/protocols/Tox/libtox/src/toxcore/announce.h
@@ -5,7 +5,14 @@
#ifndef C_TOXCORE_TOXCORE_ANNOUNCE_H
#define C_TOXCORE_TOXCORE_ANNOUNCE_H
+#include <stdint.h>
+
+#include "attributes.h"
+#include "crypto_core.h"
#include "forwarding.h"
+#include "logger.h"
+#include "mem.h"
+#include "mono_time.h"
#define MAX_ANNOUNCEMENT_SIZE 512
@@ -16,7 +23,8 @@ uint8_t announce_response_of_request_type(uint8_t request_type);
typedef struct Announcements Announcements;
non_null()
-Announcements *new_announcements(const Logger *log, const Random *rng, const Mono_Time *mono_time, Forwarding *forwarding);
+Announcements *new_announcements(const Logger *log, const Memory *mem, const Random *rng, const Mono_Time *mono_time,
+ Forwarding *forwarding);
/**
* @brief If data is stored, run `on_retrieve_callback` on it.
@@ -33,7 +41,6 @@ void announce_set_synch_offset(Announcements *announce, int32_t synch_offset);
nullable(1)
void kill_announcements(Announcements *announce);
-
/* The declarations below are not public, they are exposed only for tests. */
/** @private
@@ -64,4 +71,4 @@ bool announce_store_data(Announcements *announce, const uint8_t *data_public_key
#define ANNOUNCE_BUCKET_PREFIX_LENGTH 5
#define ANNOUNCE_BUCKETS 32 // ANNOUNCE_BUCKETS = 2 ** ANNOUNCE_BUCKET_PREFIX_LENGTH
-#endif
+#endif /* C_TOXCORE_TOXCORE_ANNOUNCE_H */
diff --git a/protocols/Tox/libtox/src/toxcore/attributes.h b/protocols/Tox/libtox/src/toxcore/attributes.h
index 3da768f2a3..087efe20dc 100644
--- a/protocols/Tox/libtox/src/toxcore/attributes.h
+++ b/protocols/Tox/libtox/src/toxcore/attributes.h
@@ -18,7 +18,7 @@
#define GNU_PRINTF(f, a)
#endif
-#if defined(__GNUC__) && defined(_DEBUG) && !defined(__OPTIMIZE__)
+#if defined(__GNUC__) && defined(_DEBUG)
#define non_null(...) __attribute__((__nonnull__(__VA_ARGS__)))
#else
#define non_null(...)
@@ -26,6 +26,14 @@
#define nullable(...)
+#ifdef SPARSE
+#define bitwise __attribute__((bitwise))
+#define force __attribute__((force))
+#else
+#define bitwise
+#define force
+#endif
+
//!TOKSTYLE+
-#endif // C_TOXCORE_TOXCORE_ATTRIBUTES_H
+#endif /* C_TOXCORE_TOXCORE_ATTRIBUTES_H */
diff --git a/protocols/Tox/libtox/src/toxcore/bin_pack.c b/protocols/Tox/libtox/src/toxcore/bin_pack.c
index 3575803aed..56bdc9ec75 100644
--- a/protocols/Tox/libtox/src/toxcore/bin_pack.c
+++ b/protocols/Tox/libtox/src/toxcore/bin_pack.c
@@ -5,11 +5,12 @@
#include "bin_pack.h"
#include <assert.h>
-#include <stdlib.h>
#include <string.h>
#include "../third_party/cmp/cmp.h"
+#include "attributes.h"
#include "ccompat.h"
+#include "logger.h"
struct Bin_Pack {
uint8_t *bytes;
@@ -26,15 +27,16 @@ static bool null_reader(cmp_ctx_t *ctx, void *data, size_t limit)
}
non_null()
-static bool null_skipper(cmp_ctx_t *ctx, size_t limit)
+static bool null_skipper(cmp_ctx_t *ctx, size_t count)
{
- assert(limit == 0);
+ assert(count == 0);
return false;
}
non_null()
static size_t buf_writer(cmp_ctx_t *ctx, const void *data, size_t count)
{
+ const uint8_t *bytes = (const uint8_t *)data;
Bin_Pack *bp = (Bin_Pack *)ctx->buf;
assert(bp != nullptr);
const uint32_t new_pos = bp->bytes_pos + count;
@@ -47,7 +49,7 @@ static size_t buf_writer(cmp_ctx_t *ctx, const void *data, size_t count)
// Buffer too small.
return 0;
}
- memcpy(bp->bytes + bp->bytes_pos, data, count);
+ memcpy(&bp->bytes[bp->bytes_pos], bytes, count);
}
bp->bytes_pos += count;
return count;
@@ -62,34 +64,71 @@ static void bin_pack_init(Bin_Pack *bp, uint8_t *buf, uint32_t buf_size)
cmp_init(&bp->ctx, bp, null_reader, null_skipper, buf_writer);
}
-bool bin_pack_obj(bin_pack_cb *callback, const void *obj, uint8_t *buf, uint32_t buf_size)
+uint32_t bin_pack_obj_size(bin_pack_cb *callback, const void *obj, const Logger *logger)
+{
+ Bin_Pack bp;
+ bin_pack_init(&bp, nullptr, 0);
+ if (!callback(obj, logger, &bp)) {
+ return UINT32_MAX;
+ }
+ return bp.bytes_pos;
+}
+
+bool bin_pack_obj(bin_pack_cb *callback, const void *obj, const Logger *logger, uint8_t *buf, uint32_t buf_size)
{
Bin_Pack bp;
bin_pack_init(&bp, buf, buf_size);
- return callback(&bp, obj);
+ return callback(obj, logger, &bp);
}
-uint32_t bin_pack_obj_size(bin_pack_cb *callback, const void *obj)
+uint32_t bin_pack_obj_array_b_size(bin_pack_array_cb *callback, const void *arr, uint32_t arr_size, const Logger *logger)
{
Bin_Pack bp;
bin_pack_init(&bp, nullptr, 0);
- callback(&bp, obj);
+ if (arr == nullptr) {
+ assert(arr_size == 0);
+ }
+ for (uint32_t i = 0; i < arr_size; ++i) {
+ if (!callback(arr, i, logger, &bp)) {
+ return UINT32_MAX;
+ }
+ }
return bp.bytes_pos;
}
-Bin_Pack *bin_pack_new(uint8_t *buf, uint32_t buf_size)
+bool bin_pack_obj_array_b(bin_pack_array_cb *callback, const void *arr, uint32_t arr_size, const Logger *logger, uint8_t *buf, uint32_t buf_size)
{
- Bin_Pack *bp = (Bin_Pack *)calloc(1, sizeof(Bin_Pack));
- if (bp == nullptr) {
- return nullptr;
+ Bin_Pack bp;
+ bin_pack_init(&bp, buf, buf_size);
+ if (arr == nullptr) {
+ assert(arr_size == 0);
+ }
+ for (uint32_t i = 0; i < arr_size; ++i) {
+ if (!callback(arr, i, logger, &bp)) {
+ return false;
+ }
}
- bin_pack_init(bp, buf, buf_size);
- return bp;
+ return true;
}
-void bin_pack_free(Bin_Pack *bp)
+bool bin_pack_obj_array(Bin_Pack *bp, bin_pack_array_cb *callback, const void *arr, uint32_t arr_size, const Logger *logger)
{
- free(bp);
+ if (arr == nullptr) {
+ assert(arr_size == 0);
+ return bin_pack_array(bp, 0);
+ }
+
+ if (!bin_pack_array(bp, arr_size)) {
+ return false;
+ }
+
+ for (uint32_t i = 0; i < arr_size; ++i) {
+ if (!callback(arr, i, logger, bp)) {
+ return false;
+ }
+ }
+
+ return true;
}
bool bin_pack_array(Bin_Pack *bp, uint32_t size)
@@ -164,4 +203,3 @@ bool bin_pack_bin_b(Bin_Pack *bp, const uint8_t *data, uint32_t length)
{
return bp->ctx.write(&bp->ctx, data, length) == length;
}
-
diff --git a/protocols/Tox/libtox/src/toxcore/bin_pack.h b/protocols/Tox/libtox/src/toxcore/bin_pack.h
index 51646c088a..ce6926a448 100644
--- a/protocols/Tox/libtox/src/toxcore/bin_pack.h
+++ b/protocols/Tox/libtox/src/toxcore/bin_pack.h
@@ -8,6 +8,7 @@
#include <stdint.h>
#include "attributes.h"
+#include "logger.h"
#ifdef __cplusplus
extern "C" {
@@ -15,6 +16,26 @@ extern "C" {
/**
* @brief Binary serialisation object.
+ *
+ * Naming convention:
+ * - Functions ending in `_b` (or `_b_size`) are NOT MessagePack, i.e. write
+ * data in plain big endian binary format.
+ * - All other functions encode their input in MessagePack format.
+ *
+ * Some notes on parameter order:
+ *
+ * - We pass the `obj` pointer as `this`-like pointer first to the callbacks.
+ * - Any extra arguments passed to the callback follow the `obj` (and in case of
+ * array packing, the `arr` and `arr_size` parameters).
+ * - The packer is passed last.
+ *
+ * This roughly matches a curried lambda function:
+ *
+ * @code
+ * bin_pack_obj([](const void *obj, const Logger *logger, Bin_Pack *bp) { ... }, obj, logger, buf, buf_size);
+ * // Translates roughly to:
+ * bin_pack_obj([obj, logger](Bin_Pack *bp) { ... }, buf, buf_size);
+ * @endcode
*/
typedef struct Bin_Pack Bin_Pack;
@@ -23,55 +44,114 @@ typedef struct Bin_Pack Bin_Pack;
* This function would typically cast the `void *` to the actual object pointer type and then call
* more appropriately typed packing functions.
*/
-typedef bool bin_pack_cb(Bin_Pack *bp, const void *obj);
+typedef bool bin_pack_cb(const void *obj, const Logger *logger, Bin_Pack *bp);
+
+/** @brief Function used to pack an array of objects.
+ *
+ * This function would typically cast the `void *` to the actual object pointer type and then call
+ * more appropriately typed packing functions.
+ *
+ * @param arr is the object array as void pointer.
+ * @param index is the index in the object array that is currently being packed.
+ */
+typedef bool bin_pack_array_cb(const void *arr, uint32_t index, const Logger *logger, Bin_Pack *bp);
/** @brief Determine the serialised size of an object.
*
* @param callback The function called on the created packer and packed object.
* @param obj The object to be packed, passed as `obj` to the callback.
+ * @param logger Optional logger object to pass to the callback.
*
- * @return The packed size of the passed object according to the callback. UINT32_MAX in case of
- * errors such as buffer overflow.
+ * @return The packed size of the passed object according to the callback.
+ * @retval UINT32_MAX in case of errors such as buffer overflow.
*/
-non_null(1) nullable(2)
-uint32_t bin_pack_obj_size(bin_pack_cb *callback, const void *obj);
+non_null(1) nullable(2, 3)
+uint32_t bin_pack_obj_size(bin_pack_cb *callback, const void *obj, const Logger *logger);
/** @brief Pack an object into a buffer of a given size.
*
* This function creates and initialises a `Bin_Pack` packer object, calls the callback with the
- * packer object and the to-be-packed object, and then cleans up the packer object.
+ * packer object and the to-be-packed object, and then cleans up the packer object. Note that
+ * there is nothing MessagePack-specific about this function, so it can be used for both custom
+ * binary and MessagePack formats.
*
* You can use `bin_pack_obj_size` to determine the minimum required size of `buf`. If packing
* overflows `uint32_t`, this function returns `false`.
*
+ * Passing NULL for `obj` is supported, but requires that the callback supports nullable inputs.
+ *
* @param callback The function called on the created packer and packed object.
* @param obj The object to be packed, passed as `obj` to the callback.
+ * @param logger Optional logger object to pass to the callback.
* @param buf A byte array large enough to hold the serialised representation of `obj`.
* @param buf_size The size of the byte array. Can be `UINT32_MAX` to disable bounds checking.
*
* @retval false if an error occurred (e.g. buffer overflow).
*/
-non_null(1, 3) nullable(2)
-bool bin_pack_obj(bin_pack_cb *callback, const void *obj, uint8_t *buf, uint32_t buf_size);
+non_null(1, 4) nullable(2, 3)
+bool bin_pack_obj(bin_pack_cb *callback, const void *obj, const Logger *logger, uint8_t *buf, uint32_t buf_size);
-/** @brief Allocate a new packer object.
+/** @brief Determine the serialised size of an object array.
*
- * This is the only function that allocates memory in this module.
+ * Behaves exactly like `bin_pack_obj_b_array` but doesn't write.
*
- * @param buf A byte array large enough to hold the serialised representation of `obj`.
+ * @param callback The function called on the created packer and each object to
+ * be packed.
+ * @param arr The object array to be packed, passed as `arr` to the callback.
+ * @param arr_size The number of elements in the object array.
+ * @param logger Optional logger object to pass to the callback.
+ *
+ * @return The packed size of the passed object array according to the callback.
+ * @retval UINT32_MAX in case of errors such as buffer overflow.
+ */
+non_null(1) nullable(2, 4)
+uint32_t bin_pack_obj_array_b_size(bin_pack_array_cb *callback, const void *arr, uint32_t arr_size, const Logger *logger);
+
+/** @brief Pack an object array into a buffer of a given size.
+ *
+ * Similar to `bin_pack_obj_array` but does not write the array length, so
+ * if you need that, encoding it is on you.
+ *
+ * Passing NULL for `arr` has no effect, but requires that `arr_size` is 0.
+ *
+ * @param callback The function called on the created packer and packed object
+ * array.
+ * @param arr The object array to be packed, passed as `arr` to the callback.
+ * @param arr_size The number of elements in the object array.
+ * @param logger Optional logger object to pass to the callback.
+ * @param buf A byte array large enough to hold the serialised representation of `arr`.
* @param buf_size The size of the byte array. Can be `UINT32_MAX` to disable bounds checking.
*
- * @retval nullptr on allocation failure.
+ * @retval false if an error occurred (e.g. buffer overflow).
*/
-non_null()
-Bin_Pack *bin_pack_new(uint8_t *buf, uint32_t buf_size);
+non_null(1, 5) nullable(2, 4)
+bool bin_pack_obj_array_b(bin_pack_array_cb *callback, const void *arr, uint32_t arr_size, const Logger *logger, uint8_t *buf, uint32_t buf_size);
-/** @brief Deallocates a packer object.
+/** @brief Encode an object array as MessagePack array into a bin packer.
+ *
+ * Calls the callback `arr_size` times with increasing `index` argument from 0 to
+ * `arr_size`. This function is here just so we don't need to write the same
+ * trivial loop many times and so we don't need an extra struct just to contain
+ * an array with size so it can be passed to `bin_pack_obj`.
+ *
+ * Similar to `bin_pack_obj` but for arrays. Note that a `Bin_Pack` object is
+ * required here, so it must be called from within a callback to one of the
+ * functions above.
*
- * Does not deallocate the buffer inside.
+ * Passing NULL for `arr` requires that `arr_size` is 0. This will write a 0-size
+ * MessagePack array to the packer.
+ *
+ * @param bp Bin packer object.
+ * @param callback The function called on the created packer and packed object
+ * array.
+ * @param arr The object array to be packed, passed as `arr` to the callback.
+ * @param arr_size The number of elements in the object array.
+ * @param logger Optional logger object to pass to the callback.
+ *
+ * @retval false if an error occurred (e.g. buffer overflow).
*/
-nullable(1)
-void bin_pack_free(Bin_Pack *bp);
+non_null(1, 2) nullable(3, 5)
+bool bin_pack_obj_array(Bin_Pack *bp, bin_pack_array_cb *callback, const void *arr, uint32_t arr_size, const Logger *logger);
/** @brief Start packing a MessagePack array.
*
@@ -117,7 +197,7 @@ non_null() bool bin_pack_u64_b(Bin_Pack *bp, uint64_t val);
non_null() bool bin_pack_bin_b(Bin_Pack *bp, const uint8_t *data, uint32_t length);
#ifdef __cplusplus
-} // extern "C"
+} /* extern "C" */
#endif
-#endif // C_TOXCORE_TOXCORE_BIN_PACK_H
+#endif /* C_TOXCORE_TOXCORE_BIN_PACK_H */
diff --git a/protocols/Tox/libtox/src/toxcore/bin_unpack.c b/protocols/Tox/libtox/src/toxcore/bin_unpack.c
index ff591ca87a..d6b1c52ea5 100644
--- a/protocols/Tox/libtox/src/toxcore/bin_unpack.c
+++ b/protocols/Tox/libtox/src/toxcore/bin_unpack.c
@@ -9,6 +9,7 @@
#include <string.h>
#include "../third_party/cmp/cmp.h"
+#include "attributes.h"
#include "ccompat.h"
struct Bin_Unpack {
@@ -20,27 +21,28 @@ struct Bin_Unpack {
non_null()
static bool buf_reader(cmp_ctx_t *ctx, void *data, size_t limit)
{
+ uint8_t *bytes = (uint8_t *)data;
Bin_Unpack *reader = (Bin_Unpack *)ctx->buf;
assert(reader != nullptr && reader->bytes != nullptr);
if (limit > reader->bytes_size) {
return false;
}
- memcpy(data, reader->bytes, limit);
+ memcpy(bytes, reader->bytes, limit);
reader->bytes += limit;
reader->bytes_size -= limit;
return true;
}
non_null()
-static bool buf_skipper(cmp_ctx_t *ctx, size_t limit)
+static bool buf_skipper(cmp_ctx_t *ctx, size_t count)
{
Bin_Unpack *reader = (Bin_Unpack *)ctx->buf;
assert(reader != nullptr && reader->bytes != nullptr);
- if (limit > reader->bytes_size) {
+ if (count > reader->bytes_size) {
return false;
}
- reader->bytes += limit;
- reader->bytes_size -= limit;
+ reader->bytes += count;
+ reader->bytes_size -= count;
return true;
}
@@ -51,21 +53,19 @@ static size_t null_writer(cmp_ctx_t *ctx, const void *data, size_t count)
return 0;
}
-Bin_Unpack *bin_unpack_new(const uint8_t *buf, uint32_t buf_size)
+non_null()
+static void bin_unpack_init(Bin_Unpack *bu, const uint8_t *buf, uint32_t buf_size)
{
- Bin_Unpack *bu = (Bin_Unpack *)calloc(1, sizeof(Bin_Unpack));
- if (bu == nullptr) {
- return nullptr;
- }
bu->bytes = buf;
bu->bytes_size = buf_size;
cmp_init(&bu->ctx, bu, buf_reader, buf_skipper, null_writer);
- return bu;
}
-void bin_unpack_free(Bin_Unpack *bu)
+bool bin_unpack_obj(bin_unpack_cb *callback, void *obj, const uint8_t *buf, uint32_t buf_size)
{
- free(bu);
+ Bin_Unpack bu;
+ bin_unpack_init(&bu, buf, buf_size);
+ return callback(obj, &bu);
}
bool bin_unpack_array(Bin_Unpack *bu, uint32_t *size)
@@ -73,10 +73,14 @@ bool bin_unpack_array(Bin_Unpack *bu, uint32_t *size)
return cmp_read_array(&bu->ctx, size) && *size <= bu->bytes_size;
}
-bool bin_unpack_array_fixed(Bin_Unpack *bu, uint32_t required_size)
+bool bin_unpack_array_fixed(Bin_Unpack *bu, uint32_t required_size, uint32_t *actual_size)
{
- uint32_t size;
- return cmp_read_array(&bu->ctx, &size) && size == required_size;
+ uint32_t size = 0;
+ const bool success = cmp_read_array(&bu->ctx, &size) && size == required_size;
+ if (actual_size != nullptr) {
+ *actual_size = size;
+ }
+ return success;
}
bool bin_unpack_bool(Bin_Unpack *bu, bool *val)
@@ -128,6 +132,18 @@ bool bin_unpack_bin(Bin_Unpack *bu, uint8_t **data_ptr, uint32_t *data_length_pt
return true;
}
+bool bin_unpack_bin_max(Bin_Unpack *bu, uint8_t *data, uint16_t *data_length_ptr, uint16_t max_data_length)
+{
+ uint32_t bin_size;
+ if (!bin_unpack_bin_size(bu, &bin_size) || bin_size > max_data_length) {
+ return false;
+ }
+
+ *data_length_ptr = bin_size;
+
+ return bin_unpack_bin_b(bu, data, bin_size);
+}
+
bool bin_unpack_bin_fixed(Bin_Unpack *bu, uint8_t *data, uint32_t data_length)
{
uint32_t bin_size;
@@ -153,7 +169,7 @@ bool bin_unpack_u16_b(Bin_Unpack *bu, uint16_t *val)
uint8_t hi = 0;
uint8_t lo = 0;
if (!(bin_unpack_u08_b(bu, &hi)
- && bin_unpack_u08_b(bu, &lo))) {
+ && bin_unpack_u08_b(bu, &lo))) {
return false;
}
*val = ((uint16_t)hi << 8) | lo;
@@ -165,7 +181,7 @@ bool bin_unpack_u32_b(Bin_Unpack *bu, uint32_t *val)
uint16_t hi = 0;
uint16_t lo = 0;
if (!(bin_unpack_u16_b(bu, &hi)
- && bin_unpack_u16_b(bu, &lo))) {
+ && bin_unpack_u16_b(bu, &lo))) {
return false;
}
*val = ((uint32_t)hi << 16) | lo;
@@ -177,7 +193,7 @@ bool bin_unpack_u64_b(Bin_Unpack *bu, uint64_t *val)
uint32_t hi = 0;
uint32_t lo = 0;
if (!(bin_unpack_u32_b(bu, &hi)
- && bin_unpack_u32_b(bu, &lo))) {
+ && bin_unpack_u32_b(bu, &lo))) {
return false;
}
*val = ((uint64_t)hi << 32) | lo;
diff --git a/protocols/Tox/libtox/src/toxcore/bin_unpack.h b/protocols/Tox/libtox/src/toxcore/bin_unpack.h
index bd4d8785c1..0554bd1a7a 100644
--- a/protocols/Tox/libtox/src/toxcore/bin_unpack.h
+++ b/protocols/Tox/libtox/src/toxcore/bin_unpack.h
@@ -16,25 +16,37 @@ extern "C" {
/**
* @brief Binary deserialisation object.
+ *
+ * User code never creates this object. It is created and destroyed within the below functions,
+ * and passed to the callback. This enforces an alloc/dealloc bracket, so user code can never
+ * forget to clean up an unpacker.
*/
typedef struct Bin_Unpack Bin_Unpack;
-/** @brief Allocate a new unpacker object.
- *
- * @param buf The byte array to unpack values from.
- * @param buf_size The size of the byte array.
+/** @brief Function used to unpack an object.
*
- * @retval nullptr on allocation failure.
+ * This function would typically cast the `void *` to the actual object pointer type and then call
+ * more appropriately typed unpacking functions.
*/
-non_null()
-Bin_Unpack *bin_unpack_new(const uint8_t *buf, uint32_t buf_size);
+typedef bool bin_unpack_cb(void *obj, Bin_Unpack *bu);
-/** @brief Deallocates an unpacker object.
+/** @brief Unpack an object from a buffer of a given size.
+ *
+ * This function creates and initialises a `Bin_Unpack` object, calls the callback with the
+ * unpacker object and the to-be-unpacked object, and then cleans up the unpacker object.
+ *
+ * Unlike `bin_pack_obj`, this function does not support NULL anywhere. The input array
+ * must be non-null, even if it is zero-length.
*
- * Does not deallocate the buffer inside.
+ * @param callback The function called on the created unpacker and unpacked object.
+ * @param obj The object to be packed, passed as `obj` to the callback.
+ * @param buf A byte array containing the serialised representation of `obj`.
+ * @param buf_size The size of the byte array.
+ *
+ * @retval false if an error occurred (e.g. buffer overrun).
*/
-nullable(1)
-void bin_unpack_free(Bin_Unpack *bu);
+non_null()
+bool bin_unpack_obj(bin_unpack_cb *callback, void *obj, const uint8_t *buf, uint32_t buf_size);
/** @brief Start unpacking a MessagePack array.
*
@@ -46,9 +58,13 @@ non_null() bool bin_unpack_array(Bin_Unpack *bu, uint32_t *size);
/** @brief Start unpacking a fixed size MessagePack array.
*
+ * Fails if the array size is not the required size. If `actual_size` is passed a non-null
+ * pointer, the array size is written there.
+ *
* @retval false if the packed array size is not exactly the required size.
*/
-non_null() bool bin_unpack_array_fixed(Bin_Unpack *bu, uint32_t required_size);
+non_null(1) nullable(3)
+bool bin_unpack_array_fixed(Bin_Unpack *bu, uint32_t required_size, uint32_t *actual_size);
/** @brief Unpack a MessagePack bool. */
non_null() bool bin_unpack_bool(Bin_Unpack *bu, bool *val);
@@ -71,10 +87,16 @@ non_null() bool bin_unpack_nil(Bin_Unpack *bu);
* large allocation unless the input array was already that large.
*/
non_null() bool bin_unpack_bin(Bin_Unpack *bu, uint8_t **data_ptr, uint32_t *data_length_ptr);
+/** @brief Unpack a variable size MessagePack bin into a fixed size byte array.
+ *
+ * Stores unpacked data into `data` with its length stored in `data_length_ptr`. This function does
+ * not allocate memory and requires that `max_data_length` is less than or equal to `sizeof(arr)`
+ * when `arr` is passed as `data` pointer.
+ */
+non_null() bool bin_unpack_bin_max(Bin_Unpack *bu, uint8_t *data, uint16_t *data_length_ptr, uint16_t max_data_length);
/** @brief Unpack a MessagePack bin of a fixed length into a pre-allocated byte array.
*
- * Unlike the function above, this function does not allocate any memory, but requires the size to
- * be known up front.
+ * Similar to the function above, but doesn't output the data length.
*/
non_null() bool bin_unpack_bin_fixed(Bin_Unpack *bu, uint8_t *data, uint32_t data_length);
@@ -97,7 +119,7 @@ non_null() bool bin_unpack_u64_b(Bin_Unpack *bu, uint64_t *val);
non_null() bool bin_unpack_bin_b(Bin_Unpack *bu, uint8_t *data, uint32_t length);
#ifdef __cplusplus
-} // extern "C"
+} /* extern "C" */
#endif
-#endif // C_TOXCORE_TOXCORE_BIN_UNPACK_H
+#endif /* C_TOXCORE_TOXCORE_BIN_UNPACK_H */
diff --git a/protocols/Tox/libtox/src/toxcore/ccompat.c b/protocols/Tox/libtox/src/toxcore/ccompat.c
index 30e689d06d..6e4689736a 100644
--- a/protocols/Tox/libtox/src/toxcore/ccompat.c
+++ b/protocols/Tox/libtox/src/toxcore/ccompat.c
@@ -2,3 +2,5 @@
* Copyright © 2022 The TokTok team.
*/
#include "ccompat.h"
+
+static_assert(sizeof(int) >= 4, "toxcore does not support 16-bit platforms");
diff --git a/protocols/Tox/libtox/src/toxcore/ccompat.h b/protocols/Tox/libtox/src/toxcore/ccompat.h
index 9ea6739a7d..47ab9ed2bf 100644
--- a/protocols/Tox/libtox/src/toxcore/ccompat.h
+++ b/protocols/Tox/libtox/src/toxcore/ccompat.h
@@ -26,7 +26,6 @@
#if !defined(DISABLE_VLA) && !defined(_MSC_VER) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
// C99 VLAs.
#define ALLOC_VLA(type, name, size) type name[size]
-#define SIZEOF_VLA sizeof
#else
// Emulation using alloca.
@@ -47,9 +46,7 @@
#endif
#define ALLOC_VLA(type, name, size) \
- const size_t name##_vla_size = (size) * sizeof(type); \
- type *const name = (type *)alloca(name##_vla_size)
-#define SIZEOF_VLA(name) name##_vla_size
+ type *const name = (type *)alloca((size) * sizeof(type))
#endif
@@ -72,16 +69,10 @@
#define STATIC_ASSERT_(cond, msg, line) typedef int static_assert_##line[(cond) ? 1 : -1]
#define STATIC_ASSERT(cond, msg, line) STATIC_ASSERT_(cond, msg, line)
#define static_assert(cond, msg) STATIC_ASSERT(cond, msg, __LINE__)
-#endif // !__GNUC__
-#endif // !static_assert
-#endif // !__cplusplus
-
-#ifdef __GNUC__
-#define GNU_PRINTF(f, a) __attribute__((__format__(__printf__, f, a)))
-#else
-#define GNU_PRINTF(f, a)
-#endif
+#endif /* !__GNUC__ */
+#endif /* !static_assert */
+#endif /* !__cplusplus */
//!TOKSTYLE+
-#endif // C_TOXCORE_TOXCORE_CCOMPAT_H
+#endif /* C_TOXCORE_TOXCORE_CCOMPAT_H */
diff --git a/protocols/Tox/libtox/src/toxcore/crypto_core.c b/protocols/Tox/libtox/src/toxcore/crypto_core.c
index 14025252c4..7bb5bb929f 100644
--- a/protocols/Tox/libtox/src/toxcore/crypto_core.c
+++ b/protocols/Tox/libtox/src/toxcore/crypto_core.c
@@ -1,44 +1,19 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2024 The TokTok team.
* Copyright © 2013 Tox project.
*/
-/**
- * Functions for the core crypto.
- *
- * NOTE: This code has to be perfect. We don't mess around with encryption.
- */
#include "crypto_core.h"
#include <assert.h>
#include <stdlib.h>
#include <string.h>
-#ifndef VANILLA_NACL
-// We use libsodium by default.
#include <sodium.h>
-#else
-#include <crypto_auth.h>
-#include <crypto_box.h>
-#include <crypto_hash_sha256.h>
-#include <crypto_hash_sha512.h>
-#include <crypto_scalarmult_curve25519.h>
-#include <crypto_verify_16.h>
-#include <crypto_verify_32.h>
-#include <randombytes.h>
-#endif
+#include "attributes.h"
#include "ccompat.h"
-
-#ifndef crypto_box_MACBYTES
-#define crypto_box_MACBYTES (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES)
-#endif
-
-#ifndef VANILLA_NACL
-// Need dht because of ENC_SECRET_KEY_SIZE and ENC_PUBLIC_KEY_SIZE
-#define ENC_PUBLIC_KEY_SIZE CRYPTO_PUBLIC_KEY_SIZE
-#define ENC_SECRET_KEY_SIZE CRYPTO_SECRET_KEY_SIZE
-#endif
+#include "util.h"
static_assert(CRYPTO_PUBLIC_KEY_SIZE == crypto_box_PUBLICKEYBYTES,
"CRYPTO_PUBLIC_KEY_SIZE should be equal to crypto_box_PUBLICKEYBYTES");
@@ -63,56 +38,53 @@ static_assert(CRYPTO_SHA512_SIZE == crypto_hash_sha512_BYTES,
static_assert(CRYPTO_PUBLIC_KEY_SIZE == 32,
"CRYPTO_PUBLIC_KEY_SIZE is required to be 32 bytes for pk_equal to work");
-#ifndef VANILLA_NACL
static_assert(CRYPTO_SIGNATURE_SIZE == crypto_sign_BYTES,
"CRYPTO_SIGNATURE_SIZE should be equal to crypto_sign_BYTES");
static_assert(CRYPTO_SIGN_PUBLIC_KEY_SIZE == crypto_sign_PUBLICKEYBYTES,
"CRYPTO_SIGN_PUBLIC_KEY_SIZE should be equal to crypto_sign_PUBLICKEYBYTES");
static_assert(CRYPTO_SIGN_SECRET_KEY_SIZE == crypto_sign_SECRETKEYBYTES,
"CRYPTO_SIGN_SECRET_KEY_SIZE should be equal to crypto_sign_SECRETKEYBYTES");
-#endif /* VANILLA_NACL */
-bool create_extended_keypair(uint8_t *pk, uint8_t *sk)
+bool create_extended_keypair(Extended_Public_Key *pk, Extended_Secret_Key *sk, const Random *rng)
{
-#ifdef VANILLA_NACL
- return false;
-#else
/* create signature key pair */
- crypto_sign_keypair(pk + ENC_PUBLIC_KEY_SIZE, sk + ENC_SECRET_KEY_SIZE);
+ uint8_t seed[crypto_sign_SEEDBYTES];
+ random_bytes(rng, seed, crypto_sign_SEEDBYTES);
+ crypto_sign_seed_keypair(pk->sig, sk->sig, seed);
+ crypto_memzero(seed, crypto_sign_SEEDBYTES);
/* convert public signature key to public encryption key */
- const int res1 = crypto_sign_ed25519_pk_to_curve25519(pk, pk + ENC_PUBLIC_KEY_SIZE);
+ const int res1 = crypto_sign_ed25519_pk_to_curve25519(pk->enc, pk->sig);
/* convert secret signature key to secret encryption key */
- const int res2 = crypto_sign_ed25519_sk_to_curve25519(sk, sk + ENC_SECRET_KEY_SIZE);
+ const int res2 = crypto_sign_ed25519_sk_to_curve25519(sk->enc, sk->sig);
return res1 == 0 && res2 == 0;
-#endif
}
-const uint8_t *get_enc_key(const uint8_t *key)
+const uint8_t *get_enc_key(const Extended_Public_Key *key)
{
- return key;
+ return key->enc;
}
-const uint8_t *get_sig_pk(const uint8_t *key)
+const uint8_t *get_sig_pk(const Extended_Public_Key *key)
{
- return key + ENC_PUBLIC_KEY_SIZE;
+ return key->sig;
}
-void set_sig_pk(uint8_t *key, const uint8_t *sig_pk)
+void set_sig_pk(Extended_Public_Key *key, const uint8_t *sig_pk)
{
- memcpy(key + ENC_PUBLIC_KEY_SIZE, sig_pk, SIG_PUBLIC_KEY_SIZE);
+ memcpy(key->sig, sig_pk, SIG_PUBLIC_KEY_SIZE);
}
-const uint8_t *get_sig_sk(const uint8_t *key)
+const uint8_t *get_sig_sk(const Extended_Secret_Key *key)
{
- return key + ENC_SECRET_KEY_SIZE;
+ return key->sig;
}
-const uint8_t *get_chat_id(const uint8_t *key)
+const uint8_t *get_chat_id(const Extended_Public_Key *key)
{
- return key + ENC_PUBLIC_KEY_SIZE;
+ return key->sig;
}
#if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
@@ -137,43 +109,35 @@ static void crypto_free(uint8_t *ptr, size_t bytes)
free(ptr);
}
-#endif // !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
+#endif /* !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) */
void crypto_memzero(void *data, size_t length)
{
-#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) || defined(VANILLA_NACL)
- memset(data, 0, length);
+#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
+ memzero((uint8_t *)data, length);
#else
sodium_memzero(data, length);
-#endif
+#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
}
bool crypto_memlock(void *data, size_t length)
{
-#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) || defined(VANILLA_NACL)
+#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
return false;
#else
- if (sodium_mlock(data, length) != 0) {
- return false;
- }
-
- return true;
-#endif
+ return sodium_mlock(data, length) == 0;
+#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
}
bool crypto_memunlock(void *data, size_t length)
{
-#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) || defined(VANILLA_NACL)
+#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
return false;
#else
- if (sodium_munlock(data, length) != 0) {
- return false;
- }
-
- return true;
-#endif
+ return sodium_munlock(data, length) == 0;
+#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
}
bool pk_equal(const uint8_t pk1[CRYPTO_PUBLIC_KEY_SIZE], const uint8_t pk2[CRYPTO_PUBLIC_KEY_SIZE])
@@ -183,7 +147,7 @@ bool pk_equal(const uint8_t pk1[CRYPTO_PUBLIC_KEY_SIZE], const uint8_t pk2[CRYPT
return memcmp(pk1, pk2, CRYPTO_PUBLIC_KEY_SIZE) == 0;
#else
return crypto_verify_32(pk1, pk2) == 0;
-#endif
+#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])
@@ -191,28 +155,24 @@ void pk_copy(uint8_t dest[CRYPTO_PUBLIC_KEY_SIZE], const uint8_t src[CRYPTO_PUBL
memcpy(dest, src, CRYPTO_PUBLIC_KEY_SIZE);
}
-bool crypto_sha512_eq(const uint8_t *cksum1, const uint8_t *cksum2)
+bool crypto_sha512_eq(const uint8_t cksum1[CRYPTO_SHA512_SIZE], const uint8_t cksum2[CRYPTO_SHA512_SIZE])
{
#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
// Hope that this is better for the fuzzer
return memcmp(cksum1, cksum2, CRYPTO_SHA512_SIZE) == 0;
-#elif defined(VANILLA_NACL)
- const int lo = crypto_verify_32(cksum1, cksum2) == 0 ? 1 : 0;
- const int hi = crypto_verify_32(cksum1 + 8, cksum2 + 8) == 0 ? 1 : 0;
- return (lo & hi) == 1;
#else
return crypto_verify_64(cksum1, cksum2) == 0;
-#endif
+#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
}
-bool crypto_sha256_eq(const uint8_t *cksum1, const uint8_t *cksum2)
+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
+#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
}
uint8_t random_u08(const Random *rng)
@@ -248,44 +208,40 @@ uint32_t random_range_u32(const Random *rng, uint32_t upper_bound)
return rng->funcs->random_uniform(rng->obj, upper_bound);
}
-bool crypto_signature_create(uint8_t *signature, const uint8_t *message, uint64_t message_length,
- const uint8_t *secret_key)
+bool crypto_signature_create(uint8_t signature[CRYPTO_SIGNATURE_SIZE],
+ const uint8_t *message, uint64_t message_length,
+ const uint8_t secret_key[SIG_SECRET_KEY_SIZE])
{
-#ifdef VANILLA_NACL
- return false;
-#else
return crypto_sign_detached(signature, nullptr, message, message_length, secret_key) == 0;
-#endif // VANILLA_NACL
}
-bool crypto_signature_verify(const uint8_t *signature, const uint8_t *message, uint64_t message_length,
- const uint8_t *public_key)
+bool crypto_signature_verify(const uint8_t signature[CRYPTO_SIGNATURE_SIZE],
+ const uint8_t *message, uint64_t message_length,
+ const uint8_t public_key[SIG_PUBLIC_KEY_SIZE])
{
-#ifdef VANILLA_NACL
- return false;
-#else
return crypto_sign_verify_detached(signature, message, message_length, public_key) == 0;
-#endif
}
-bool public_key_valid(const uint8_t *public_key)
+bool public_key_valid(const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE])
{
/* Last bit of key is always zero. */
return public_key[31] < 128;
}
-int32_t encrypt_precompute(const uint8_t *public_key, const uint8_t *secret_key,
- uint8_t *shared_key)
+int32_t encrypt_precompute(const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE],
+ const uint8_t secret_key[CRYPTO_SECRET_KEY_SIZE],
+ uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE])
{
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
memcpy(shared_key, public_key, CRYPTO_SHARED_KEY_SIZE);
return 0;
#else
return crypto_box_beforenm(shared_key, public_key, secret_key);
-#endif
+#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
}
-int32_t encrypt_data_symmetric(const uint8_t *shared_key, const uint8_t *nonce,
+int32_t encrypt_data_symmetric(const uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE],
+ const uint8_t nonce[CRYPTO_NONCE_SIZE],
const uint8_t *plain, size_t length, uint8_t *encrypted)
{
if (length == 0 || shared_key == nullptr || nonce == nullptr || plain == nullptr || encrypted == nullptr) {
@@ -296,7 +252,7 @@ int32_t encrypt_data_symmetric(const uint8_t *shared_key, const uint8_t *nonce,
// Don't encrypt anything.
memcpy(encrypted, plain, length);
// Zero MAC to avoid uninitialized memory reads.
- memset(encrypted + length, 0, crypto_box_MACBYTES);
+ memzero(encrypted + length, crypto_box_MACBYTES);
#else
const size_t size_temp_plain = length + crypto_box_ZEROBYTES;
@@ -314,9 +270,9 @@ int32_t encrypt_data_symmetric(const uint8_t *shared_key, const uint8_t *nonce,
// crypto_box_afternm requires the entire range of the output array be
// initialised with something. It doesn't matter what it's initialised with,
// so we'll pick 0x00.
- memset(temp_encrypted, 0, size_temp_encrypted);
+ memzero(temp_encrypted, size_temp_encrypted);
- memset(temp_plain, 0, crypto_box_ZEROBYTES);
+ memzero(temp_plain, crypto_box_ZEROBYTES);
// Pad the message with 32 0 bytes.
memcpy(temp_plain + crypto_box_ZEROBYTES, plain, length);
@@ -332,12 +288,13 @@ int32_t encrypt_data_symmetric(const uint8_t *shared_key, const uint8_t *nonce,
crypto_free(temp_plain, size_temp_plain);
crypto_free(temp_encrypted, size_temp_encrypted);
-#endif
+#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
assert(length < INT32_MAX - crypto_box_MACBYTES);
return (int32_t)(length + crypto_box_MACBYTES);
}
-int32_t decrypt_data_symmetric(const uint8_t *shared_key, const uint8_t *nonce,
+int32_t decrypt_data_symmetric(const uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE],
+ const uint8_t nonce[CRYPTO_NONCE_SIZE],
const uint8_t *encrypted, size_t length, uint8_t *plain)
{
if (length <= crypto_box_BOXZEROBYTES || shared_key == nullptr || nonce == nullptr || encrypted == nullptr
@@ -365,9 +322,9 @@ int32_t decrypt_data_symmetric(const uint8_t *shared_key, const uint8_t *nonce,
// crypto_box_open_afternm requires the entire range of the output array be
// initialised with something. It doesn't matter what it's initialised with,
// so we'll pick 0x00.
- memset(temp_plain, 0, size_temp_plain);
+ memzero(temp_plain, size_temp_plain);
- memset(temp_encrypted, 0, crypto_box_BOXZEROBYTES);
+ memzero(temp_encrypted, crypto_box_BOXZEROBYTES);
// Pad the message with 16 0 bytes.
memcpy(temp_encrypted + crypto_box_BOXZEROBYTES, encrypted, length);
@@ -382,13 +339,15 @@ int32_t decrypt_data_symmetric(const uint8_t *shared_key, const uint8_t *nonce,
crypto_free(temp_plain, size_temp_plain);
crypto_free(temp_encrypted, size_temp_encrypted);
-#endif
+#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
assert(length > crypto_box_MACBYTES);
assert(length < INT32_MAX);
return (int32_t)(length - crypto_box_MACBYTES);
}
-int32_t encrypt_data(const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *nonce,
+int32_t encrypt_data(const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE],
+ const uint8_t secret_key[CRYPTO_SECRET_KEY_SIZE],
+ const uint8_t nonce[CRYPTO_NONCE_SIZE],
const uint8_t *plain, size_t length, uint8_t *encrypted)
{
if (public_key == nullptr || secret_key == nullptr) {
@@ -402,7 +361,9 @@ int32_t encrypt_data(const uint8_t *public_key, const uint8_t *secret_key, const
return ret;
}
-int32_t decrypt_data(const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *nonce,
+int32_t decrypt_data(const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE],
+ const uint8_t secret_key[CRYPTO_SECRET_KEY_SIZE],
+ const uint8_t nonce[CRYPTO_NONCE_SIZE],
const uint8_t *encrypted, size_t length, uint8_t *plain)
{
if (public_key == nullptr || secret_key == nullptr) {
@@ -416,7 +377,7 @@ int32_t decrypt_data(const uint8_t *public_key, const uint8_t *secret_key, const
return ret;
}
-void increment_nonce(uint8_t *nonce)
+void increment_nonce(uint8_t nonce[CRYPTO_NONCE_SIZE])
{
/* TODO(irungentoo): use `increment_nonce_number(nonce, 1)` or
* sodium_increment (change to little endian).
@@ -435,7 +396,7 @@ void increment_nonce(uint8_t *nonce)
}
}
-void increment_nonce_number(uint8_t *nonce, uint32_t increment)
+void increment_nonce_number(uint8_t nonce[CRYPTO_NONCE_SIZE], uint32_t increment)
{
/* NOTE don't use breaks inside this loop
* In particular, make sure, as far as possible,
@@ -457,29 +418,28 @@ void increment_nonce_number(uint8_t *nonce, uint32_t increment)
}
}
-void random_nonce(const Random *rng, uint8_t *nonce)
+void random_nonce(const Random *rng, uint8_t nonce[CRYPTO_NONCE_SIZE])
{
random_bytes(rng, nonce, crypto_box_NONCEBYTES);
}
-void new_symmetric_key(const Random *rng, uint8_t *key)
+void new_symmetric_key(const Random *rng, uint8_t key[CRYPTO_SYMMETRIC_KEY_SIZE])
{
random_bytes(rng, key, CRYPTO_SYMMETRIC_KEY_SIZE);
}
-int32_t crypto_new_keypair(const Random *rng, uint8_t *public_key, uint8_t *secret_key)
+int32_t crypto_new_keypair(const Random *rng,
+ uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE],
+ uint8_t secret_key[CRYPTO_SECRET_KEY_SIZE])
{
-#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
random_bytes(rng, secret_key, CRYPTO_SECRET_KEY_SIZE);
- memset(public_key, 0, CRYPTO_PUBLIC_KEY_SIZE); // Make MSAN happy
+ memzero(public_key, CRYPTO_PUBLIC_KEY_SIZE); // Make MSAN happy
crypto_derive_public_key(public_key, secret_key);
return 0;
-#else
- return crypto_box_keypair(public_key, secret_key);
-#endif
}
-void crypto_derive_public_key(uint8_t *public_key, const uint8_t *secret_key)
+void crypto_derive_public_key(uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE],
+ const uint8_t secret_key[CRYPTO_SECRET_KEY_SIZE])
{
crypto_scalarmult_curve25519_base(public_key, secret_key);
}
@@ -489,15 +449,15 @@ void new_hmac_key(const Random *rng, uint8_t key[CRYPTO_HMAC_KEY_SIZE])
random_bytes(rng, key, CRYPTO_HMAC_KEY_SIZE);
}
-void crypto_hmac(uint8_t auth[CRYPTO_HMAC_SIZE], const uint8_t key[CRYPTO_HMAC_KEY_SIZE], const uint8_t *data,
- size_t length)
+void crypto_hmac(uint8_t auth[CRYPTO_HMAC_SIZE], const uint8_t key[CRYPTO_HMAC_KEY_SIZE],
+ const uint8_t *data, size_t length)
{
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
memcpy(auth, key, 16);
memcpy(auth + 16, data, length < 16 ? length : 16);
#else
crypto_auth(auth, data, length, key);
-#endif
+#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
}
bool crypto_hmac_verify(const uint8_t auth[CRYPTO_HMAC_SIZE], const uint8_t key[CRYPTO_HMAC_KEY_SIZE],
@@ -507,27 +467,27 @@ bool crypto_hmac_verify(const uint8_t auth[CRYPTO_HMAC_SIZE], const uint8_t key[
return memcmp(auth, key, 16) == 0 && memcmp(auth + 16, data, length < 16 ? length : 16) == 0;
#else
return crypto_auth_verify(auth, data, length, key) == 0;
-#endif
+#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
}
-void crypto_sha256(uint8_t *hash, const uint8_t *data, size_t length)
+void crypto_sha256(uint8_t hash[CRYPTO_SHA256_SIZE], const uint8_t *data, size_t length)
{
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
- memset(hash, 0, CRYPTO_SHA256_SIZE);
+ memzero(hash, CRYPTO_SHA256_SIZE);
memcpy(hash, data, length < CRYPTO_SHA256_SIZE ? length : CRYPTO_SHA256_SIZE);
#else
crypto_hash_sha256(hash, data, length);
-#endif
+#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
}
-void crypto_sha512(uint8_t *hash, const uint8_t *data, size_t length)
+void crypto_sha512(uint8_t hash[CRYPTO_SHA512_SIZE], const uint8_t *data, size_t length)
{
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
- memset(hash, 0, CRYPTO_SHA512_SIZE);
+ memzero(hash, CRYPTO_SHA512_SIZE);
memcpy(hash, data, length < CRYPTO_SHA512_SIZE ? length : CRYPTO_SHA512_SIZE);
#else
crypto_hash_sha512(hash, data, length);
-#endif
+#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
}
non_null()
@@ -539,41 +499,29 @@ static void sys_random_bytes(void *obj, uint8_t *bytes, size_t length)
non_null()
static uint32_t sys_random_uniform(void *obj, uint32_t upper_bound)
{
-#ifdef VANILLA_NACL
- if (upper_bound == 0) {
- return 0;
- }
-
- uint32_t randnum;
- sys_random_bytes(obj, (uint8_t *)&randnum, sizeof(randnum));
- return randnum % upper_bound;
-#else
return randombytes_uniform(upper_bound);
-#endif
}
-static const Random_Funcs system_random_funcs = {
+static const Random_Funcs os_random_funcs = {
sys_random_bytes,
sys_random_uniform,
};
-static const Random system_random_obj = {&system_random_funcs};
+static const Random os_random_obj = {&os_random_funcs};
-const Random *system_random(void)
+const Random *os_random(void)
{
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
if ((true)) {
return nullptr;
}
-#endif
-#ifndef VANILLA_NACL
+#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
// It is safe to call this function more than once and from different
// threads -- subsequent calls won't have any effects.
if (sodium_init() == -1) {
return nullptr;
}
-#endif
- return &system_random_obj;
+ return &os_random_obj;
}
void random_bytes(const Random *rng, uint8_t *bytes, size_t length)
diff --git a/protocols/Tox/libtox/src/toxcore/crypto_core.h b/protocols/Tox/libtox/src/toxcore/crypto_core.h
index 3b9f27d677..979791bd97 100644
--- a/protocols/Tox/libtox/src/toxcore/crypto_core.h
+++ b/protocols/Tox/libtox/src/toxcore/crypto_core.h
@@ -1,10 +1,12 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2024 The TokTok team.
* Copyright © 2013 Tox project.
*/
/** @file
* @brief Functions for the core crypto.
+ *
+ * @note This code has to be perfect. We don't mess around with encryption.
*/
#ifndef C_TOXCORE_TOXCORE_CRYPTO_CORE_H
#define C_TOXCORE_TOXCORE_CRYPTO_CORE_H
@@ -20,17 +22,17 @@ extern "C" {
#endif
/**
- * The number of bytes in a signature.
+ * @brief The number of bytes in a signature.
*/
#define CRYPTO_SIGNATURE_SIZE 64
/**
- * The number of bytes in a Tox public key used for signatures.
+ * @brief The number of bytes in a Tox public key used for signatures.
*/
#define CRYPTO_SIGN_PUBLIC_KEY_SIZE 32
/**
- * The number of bytes in a Tox secret key used for signatures.
+ * @brief The number of bytes in a Tox secret key used for signatures.
*/
#define CRYPTO_SIGN_SECRET_KEY_SIZE 64
@@ -75,20 +77,43 @@ extern "C" {
*/
#define CRYPTO_SHA512_SIZE 64
+/** @brief Fill a byte array with random bytes.
+ *
+ * This is the key generator callback and as such must be a cryptographically
+ * secure pseudo-random number generator (CSPRNG). The security of Tox heavily
+ * depends on the security of this RNG.
+ */
typedef void crypto_random_bytes_cb(void *obj, uint8_t *bytes, size_t length);
+
+/** @brief Generate a random integer between 0 and @p upper_bound.
+ *
+ * Should produce a uniform random distribution, but Tox security does not
+ * depend on this being correct. In principle, it could even be a non-CSPRNG.
+ */
typedef uint32_t crypto_random_uniform_cb(void *obj, uint32_t upper_bound);
+/** @brief Virtual function table for Random. */
typedef struct Random_Funcs {
crypto_random_bytes_cb *random_bytes;
crypto_random_uniform_cb *random_uniform;
} Random_Funcs;
+/** @brief Random number generator object.
+ *
+ * Can be used by test code and fuzzers to make toxcore behave in specific
+ * well-defined (non-random) ways. Production code ought to use libsodium's
+ * CSPRNG and use `os_random` below.
+ */
typedef struct Random {
const Random_Funcs *funcs;
void *obj;
} Random;
-const Random *system_random(void);
+/** @brief System random number generator.
+ *
+ * Uses libsodium's CSPRNG (on Linux, `/dev/urandom`).
+ */
+const Random *os_random(void);
/**
* @brief The number of bytes in an encryption public key used by DHT group chats.
@@ -147,25 +172,29 @@ void crypto_memzero(void *data, size_t length);
/**
* @brief Compute a SHA256 hash (32 bytes).
+ *
+ * @param[out] hash The SHA256 hash of @p data will be written to this byte array.
*/
non_null()
-void crypto_sha256(uint8_t *hash, const uint8_t *data, size_t length);
+void crypto_sha256(uint8_t hash[CRYPTO_SHA256_SIZE], const uint8_t *data, size_t length);
/**
* @brief Compute a SHA512 hash (64 bytes).
+ *
+ * @param[out] hash The SHA512 hash of @p data will be written to this byte array.
*/
non_null()
-void crypto_sha512(uint8_t *hash, const uint8_t *data, size_t length);
+void crypto_sha512(uint8_t hash[CRYPTO_SHA512_SIZE], const uint8_t *data, size_t length);
/**
* @brief Compute an HMAC authenticator (32 bytes).
*
- * @param auth Resulting authenticator.
+ * @param[out] auth Resulting authenticator.
* @param key Secret key, as generated by `new_hmac_key()`.
*/
non_null()
-void crypto_hmac(uint8_t auth[CRYPTO_HMAC_SIZE], const uint8_t key[CRYPTO_HMAC_KEY_SIZE], const uint8_t *data,
- size_t length);
+void crypto_hmac(uint8_t auth[CRYPTO_HMAC_SIZE], const uint8_t key[CRYPTO_HMAC_KEY_SIZE],
+ const uint8_t *data, size_t length);
/**
* @brief Verify an HMAC authenticator.
@@ -176,7 +205,7 @@ bool crypto_hmac_verify(const uint8_t auth[CRYPTO_HMAC_SIZE], const uint8_t key[
/**
* @brief Compare 2 public keys of length @ref CRYPTO_PUBLIC_KEY_SIZE, not vulnerable to
- * timing attacks.
+ * timing attacks.
*
* @retval true if both mem locations of length are equal
* @retval false if they are not
@@ -192,21 +221,21 @@ void pk_copy(uint8_t dest[CRYPTO_PUBLIC_KEY_SIZE], const uint8_t src[CRYPTO_PUBL
/**
* @brief Compare 2 SHA512 checksums of length CRYPTO_SHA512_SIZE, not vulnerable to
- * timing attacks.
+ * timing attacks.
*
* @return true if both mem locations of length are equal, false if they are not.
*/
non_null()
-bool crypto_sha512_eq(const uint8_t *cksum1, const uint8_t *cksum2);
+bool crypto_sha512_eq(const uint8_t cksum1[CRYPTO_SHA512_SIZE], const uint8_t cksum2[CRYPTO_SHA512_SIZE]);
/**
* @brief Compare 2 SHA256 checksums of length CRYPTO_SHA256_SIZE, not vulnerable to
- * timing attacks.
+ * timing attacks.
*
* @return true if both mem locations of length are equal, false if they are not.
*/
non_null()
-bool crypto_sha256_eq(const uint8_t *cksum1, const uint8_t *cksum2);
+bool crypto_sha256_eq(const uint8_t cksum1[CRYPTO_SHA256_SIZE], const uint8_t cksum2[CRYPTO_SHA256_SIZE]);
/**
* @brief Return a random 8 bit integer.
@@ -235,16 +264,16 @@ uint64_t random_u64(const Random *rng);
/**
* @brief Return a random 32 bit integer between 0 and upper_bound (excluded).
*
- * On libsodium builds this function guarantees a uniform distribution of possible outputs.
- * On vanilla NACL builds this function is equivalent to `random() % upper_bound`.
+ * This function guarantees a uniform distribution of possible outputs.
*/
non_null()
uint32_t random_range_u32(const Random *rng, uint32_t upper_bound);
-/** @brief Cryptographically signs a message using the supplied secret key and puts the resulting signature
- * in the supplied buffer.
+/**
+ * @brief Cryptographically signs a message using the supplied secret key and puts the resulting signature
+ * in the supplied buffer.
*
- * @param signature The buffer for the resulting signature, which must have room for at
+ * @param[out] signature The buffer for the resulting signature, which must have room for at
* least CRYPTO_SIGNATURE_SIZE bytes.
* @param message The message being signed.
* @param message_length The length in bytes of the message being signed.
@@ -254,8 +283,9 @@ uint32_t random_range_u32(const Random *rng, uint32_t upper_bound);
* @retval true on success.
*/
non_null()
-bool crypto_signature_create(uint8_t *signature, const uint8_t *message, uint64_t message_length,
- const uint8_t *secret_key);
+bool crypto_signature_create(uint8_t signature[CRYPTO_SIGNATURE_SIZE],
+ const uint8_t *message, uint64_t message_length,
+ const uint8_t secret_key[SIG_SECRET_KEY_SIZE]);
/** @brief Verifies that the given signature was produced by a given message and public key.
*
@@ -268,14 +298,15 @@ bool crypto_signature_create(uint8_t *signature, const uint8_t *message, uint64_
* @retval true on success.
*/
non_null()
-bool crypto_signature_verify(const uint8_t *signature, const uint8_t *message, uint64_t message_length,
- const uint8_t *public_key);
+bool crypto_signature_verify(const uint8_t signature[CRYPTO_SIGNATURE_SIZE],
+ const uint8_t *message, uint64_t message_length,
+ const uint8_t public_key[SIG_PUBLIC_KEY_SIZE]);
/**
* @brief Fill the given nonce with random bytes.
*/
non_null()
-void random_nonce(const Random *rng, uint8_t *nonce);
+void random_nonce(const Random *rng, uint8_t nonce[CRYPTO_NONCE_SIZE]);
/**
* @brief Fill an array of bytes with random values.
@@ -291,25 +322,40 @@ void random_bytes(const Random *rng, uint8_t *bytes, size_t length);
* @return false if it isn't, true if it is.
*/
non_null()
-bool public_key_valid(const uint8_t *public_key);
+bool public_key_valid(const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE]);
-/** @brief Creates an extended keypair: curve25519 and ed25519 for encryption and signing
+typedef struct Extended_Public_Key {
+ uint8_t enc[CRYPTO_PUBLIC_KEY_SIZE];
+ uint8_t sig[CRYPTO_SIGN_PUBLIC_KEY_SIZE];
+} Extended_Public_Key;
+
+typedef struct Extended_Secret_Key {
+ uint8_t enc[CRYPTO_SECRET_KEY_SIZE];
+ uint8_t sig[CRYPTO_SIGN_SECRET_KEY_SIZE];
+} Extended_Secret_Key;
+
+/**
+ * @brief Creates an extended keypair: curve25519 and ed25519 for encryption and signing
* respectively. The Encryption keys are derived from the signature keys.
*
- * @param pk The buffer where the public key will be stored. Must have room for EXT_PUBLIC_KEY_SIZE bytes.
- * @param sk The buffer where the secret key will be stored. Must have room for EXT_SECRET_KEY_SIZE bytes.
+ * NOTE: This does *not* use Random, so any code using this will not be fuzzable.
+ * TODO: Make it use Random.
+ *
+ * @param[out] pk The buffer where the public key will be stored. Must have room for EXT_PUBLIC_KEY_SIZE bytes.
+ * @param[out] sk The buffer where the secret key will be stored. Must have room for EXT_SECRET_KEY_SIZE bytes.
+ * @param rng The random number generator to use for the key generator seed.
*
* @retval true on success.
*/
non_null()
-bool create_extended_keypair(uint8_t *pk, uint8_t *sk);
+bool create_extended_keypair(Extended_Public_Key *pk, Extended_Secret_Key *sk, const Random *rng);
/** Functions for groupchat extended keys */
-non_null() const uint8_t *get_enc_key(const uint8_t *key);
-non_null() const uint8_t *get_sig_pk(const uint8_t *key);
-non_null() void set_sig_pk(uint8_t *key, const uint8_t *sig_pk);
-non_null() const uint8_t *get_sig_sk(const uint8_t *key);
-non_null() const uint8_t *get_chat_id(const uint8_t *key);
+non_null() const uint8_t *get_enc_key(const Extended_Public_Key *key);
+non_null() const uint8_t *get_sig_pk(const Extended_Public_Key *key);
+non_null() void set_sig_pk(Extended_Public_Key *key, const uint8_t *sig_pk);
+non_null() const uint8_t *get_sig_sk(const Extended_Secret_Key *key);
+non_null() const uint8_t *get_chat_id(const Extended_Public_Key *key);
/**
* @brief Generate a new random keypair.
@@ -317,13 +363,16 @@ non_null() const uint8_t *get_chat_id(const uint8_t *key);
* Every call to this function is likely to generate a different keypair.
*/
non_null()
-int32_t crypto_new_keypair(const Random *rng, uint8_t *public_key, uint8_t *secret_key);
+int32_t crypto_new_keypair(const Random *rng,
+ uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE],
+ uint8_t secret_key[CRYPTO_SECRET_KEY_SIZE]);
/**
* @brief Derive the public key from a given secret key.
*/
non_null()
-void crypto_derive_public_key(uint8_t *public_key, const uint8_t *secret_key);
+void crypto_derive_public_key(uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE],
+ const uint8_t secret_key[CRYPTO_SECRET_KEY_SIZE]);
/**
* @brief Encrypt message to send from secret key to public key.
@@ -337,8 +386,10 @@ void crypto_derive_public_key(uint8_t *public_key, const uint8_t *secret_key);
* @return length of encrypted data if everything was fine.
*/
non_null()
-int32_t encrypt_data(const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *nonce, const uint8_t *plain,
- size_t length, uint8_t *encrypted);
+int32_t encrypt_data(const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE],
+ const uint8_t secret_key[CRYPTO_SECRET_KEY_SIZE],
+ const uint8_t nonce[CRYPTO_NONCE_SIZE],
+ const uint8_t *plain, size_t length, uint8_t *encrypted);
/**
* @brief Decrypt message from public key to secret key.
@@ -352,7 +403,9 @@ int32_t encrypt_data(const uint8_t *public_key, const uint8_t *secret_key, const
* @return length of plain text data if everything was fine.
*/
non_null()
-int32_t decrypt_data(const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *nonce,
+int32_t decrypt_data(const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE],
+ const uint8_t secret_key[CRYPTO_SECRET_KEY_SIZE],
+ const uint8_t nonce[CRYPTO_NONCE_SIZE],
const uint8_t *encrypted, size_t length, uint8_t *plain);
/**
@@ -363,21 +416,24 @@ int32_t decrypt_data(const uint8_t *public_key, const uint8_t *secret_key, const
* encrypt/decrypt.
*/
non_null()
-int32_t encrypt_precompute(const uint8_t *public_key, const uint8_t *secret_key, uint8_t *shared_key);
+int32_t encrypt_precompute(const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE],
+ const uint8_t secret_key[CRYPTO_SECRET_KEY_SIZE],
+ uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE]);
/**
* @brief Encrypt message with precomputed shared key.
*
* Encrypts plain of length length to encrypted of length + @ref CRYPTO_MAC_SIZE
- * using a shared key @ref CRYPTO_SYMMETRIC_KEY_SIZE big and a @ref CRYPTO_NONCE_SIZE
+ * using a shared key @ref CRYPTO_SHARED_KEY_SIZE big and a @ref CRYPTO_NONCE_SIZE
* byte nonce.
*
* @retval -1 if there was a problem.
* @return length of encrypted data if everything was fine.
*/
non_null()
-int32_t encrypt_data_symmetric(const uint8_t *shared_key, const uint8_t *nonce, const uint8_t *plain, size_t length,
- uint8_t *encrypted);
+int32_t encrypt_data_symmetric(const uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE],
+ const uint8_t nonce[CRYPTO_NONCE_SIZE],
+ const uint8_t *plain, size_t length, uint8_t *encrypted);
/**
* @brief Decrypt message with precomputed shared key.
@@ -390,15 +446,15 @@ int32_t encrypt_data_symmetric(const uint8_t *shared_key, const uint8_t *nonce,
* @return length of plain data if everything was fine.
*/
non_null()
-int32_t decrypt_data_symmetric(const uint8_t *shared_key, const uint8_t *nonce, const uint8_t *encrypted, size_t length,
- uint8_t *plain);
+int32_t decrypt_data_symmetric(const uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE],
+ const uint8_t nonce[CRYPTO_NONCE_SIZE],
+ const uint8_t *encrypted, size_t length, uint8_t *plain);
/**
- * @brief Increment the given nonce by 1 in big endian (rightmost byte incremented
- * first).
+ * @brief Increment the given nonce by 1 in big endian (rightmost byte incremented first).
*/
non_null()
-void increment_nonce(uint8_t *nonce);
+void increment_nonce(uint8_t nonce[CRYPTO_NONCE_SIZE]);
/**
* @brief Increment the given nonce by a given number.
@@ -406,13 +462,13 @@ void increment_nonce(uint8_t *nonce);
* The number should be in host byte order.
*/
non_null()
-void increment_nonce_number(uint8_t *nonce, uint32_t increment);
+void increment_nonce_number(uint8_t nonce[CRYPTO_NONCE_SIZE], uint32_t increment);
/**
* @brief Fill a key @ref CRYPTO_SYMMETRIC_KEY_SIZE big with random bytes.
*/
non_null()
-void new_symmetric_key(const Random *rng, uint8_t *key);
+void new_symmetric_key(const Random *rng, uint8_t key[CRYPTO_SYMMETRIC_KEY_SIZE]);
/**
* @brief Locks `length` bytes of memory pointed to by `data`.
@@ -446,7 +502,7 @@ non_null()
void new_hmac_key(const Random *rng, uint8_t key[CRYPTO_HMAC_KEY_SIZE]);
#ifdef __cplusplus
-} // extern "C"
+} /* extern "C" */
#endif
-#endif // C_TOXCORE_TOXCORE_CRYPTO_CORE_H
+#endif /* C_TOXCORE_TOXCORE_CRYPTO_CORE_H */
diff --git a/protocols/Tox/libtox/src/toxcore/crypto_core_pack.c b/protocols/Tox/libtox/src/toxcore/crypto_core_pack.c
new file mode 100644
index 0000000000..a173d39d8d
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/crypto_core_pack.c
@@ -0,0 +1,66 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2016-2024 The TokTok team.
+ * Copyright © 2013 Tox project.
+ */
+
+#include "crypto_core_pack.h"
+
+#include <string.h>
+
+#include "bin_pack.h"
+#include "bin_unpack.h"
+#include "ccompat.h"
+#include "crypto_core.h"
+
+bool pack_extended_public_key(const Extended_Public_Key *key, Bin_Pack *bp)
+{
+ uint8_t ext_key[EXT_PUBLIC_KEY_SIZE];
+ static_assert(sizeof(ext_key) == sizeof(key->enc) + sizeof(key->sig),
+ "extended secret key size is not the sum of the encryption and sign secret key sizes");
+ memcpy(ext_key, key->enc, sizeof(key->enc));
+ memcpy(&ext_key[sizeof(key->enc)], key->sig, sizeof(key->sig));
+
+ return bin_pack_bin(bp, ext_key, sizeof(ext_key));
+}
+
+bool pack_extended_secret_key(const Extended_Secret_Key *key, Bin_Pack *bp)
+{
+ uint8_t ext_key[EXT_SECRET_KEY_SIZE];
+ static_assert(sizeof(ext_key) == sizeof(key->enc) + sizeof(key->sig),
+ "extended secret key size is not the sum of the encryption and sign secret key sizes");
+ memcpy(ext_key, key->enc, sizeof(key->enc));
+ memcpy(&ext_key[sizeof(key->enc)], key->sig, sizeof(key->sig));
+
+ const bool result = bin_pack_bin(bp, ext_key, sizeof(ext_key));
+ crypto_memzero(ext_key, sizeof(ext_key));
+ return result;
+}
+
+bool unpack_extended_public_key(Extended_Public_Key *key, Bin_Unpack *bu)
+{
+ uint8_t ext_key[EXT_PUBLIC_KEY_SIZE];
+
+ if (!bin_unpack_bin_fixed(bu, ext_key, sizeof(ext_key))) {
+ return false;
+ }
+
+ memcpy(key->enc, ext_key, sizeof(key->enc));
+ memcpy(key->sig, &ext_key[sizeof(key->enc)], sizeof(key->sig));
+
+ return true;
+}
+
+bool unpack_extended_secret_key(Extended_Secret_Key *key, Bin_Unpack *bu)
+{
+ uint8_t ext_key[EXT_SECRET_KEY_SIZE];
+
+ if (!bin_unpack_bin_fixed(bu, ext_key, sizeof(ext_key))) {
+ return false;
+ }
+
+ memcpy(key->enc, ext_key, sizeof(key->enc));
+ memcpy(key->sig, &ext_key[sizeof(key->enc)], sizeof(key->sig));
+ crypto_memzero(ext_key, sizeof(ext_key));
+
+ return true;
+}
diff --git a/protocols/Tox/libtox/src/toxcore/crypto_core_pack.h b/protocols/Tox/libtox/src/toxcore/crypto_core_pack.h
new file mode 100644
index 0000000000..1efefff840
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/crypto_core_pack.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2016-2024 The TokTok team.
+ * Copyright © 2013 Tox project.
+ */
+
+#ifndef C_TOXCORE_TOXCORE_CRYPTO_CORE_PACK_H
+#define C_TOXCORE_TOXCORE_CRYPTO_CORE_PACK_H
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include "attributes.h"
+#include "bin_pack.h"
+#include "bin_unpack.h"
+#include "crypto_core.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+non_null() bool pack_extended_public_key(const Extended_Public_Key *key, Bin_Pack *bp);
+non_null() bool pack_extended_secret_key(const Extended_Secret_Key *key, Bin_Pack *bp);
+non_null() bool unpack_extended_public_key(Extended_Public_Key *key, Bin_Unpack *bu);
+non_null() bool unpack_extended_secret_key(Extended_Secret_Key *key, Bin_Unpack *bu);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* C_TOXCORE_TOXCORE_CRYPTO_CORE_PACK_H */
diff --git a/protocols/Tox/libtox/src/toxcore/events/conference_connected.c b/protocols/Tox/libtox/src/toxcore/events/conference_connected.c
index ce278755e1..dbd9e4b51a 100644
--- a/protocols/Tox/libtox/src/toxcore/events/conference_connected.c
+++ b/protocols/Tox/libtox/src/toxcore/events/conference_connected.c
@@ -1,167 +1,151 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2022 The TokTok team.
+ * Copyright © 2023-2024 The TokTok team.
*/
#include "events_alloc.h"
#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
+#include "../attributes.h"
#include "../bin_pack.h"
#include "../bin_unpack.h"
#include "../ccompat.h"
+#include "../mem.h"
#include "../tox.h"
#include "../tox_events.h"
-
/*****************************************************
*
* :: struct and accessors
*
*****************************************************/
-
struct Tox_Event_Conference_Connected {
uint32_t conference_number;
};
non_null()
-static void tox_event_conference_connected_construct(Tox_Event_Conference_Connected *conference_connected)
+static void tox_event_conference_connected_set_conference_number(Tox_Event_Conference_Connected *conference_connected,
+ uint32_t conference_number)
{
- *conference_connected = (Tox_Event_Conference_Connected) {
- 0
- };
+ assert(conference_connected != nullptr);
+ conference_connected->conference_number = conference_number;
}
-non_null()
-static void tox_event_conference_connected_destruct(Tox_Event_Conference_Connected *conference_connected)
+uint32_t tox_event_conference_connected_get_conference_number(const Tox_Event_Conference_Connected *conference_connected)
{
- return;
+ assert(conference_connected != nullptr);
+ return conference_connected->conference_number;
}
non_null()
-static void tox_event_conference_connected_set_conference_number(
- Tox_Event_Conference_Connected *conference_connected, uint32_t conference_number)
+static void tox_event_conference_connected_construct(Tox_Event_Conference_Connected *conference_connected)
{
- assert(conference_connected != nullptr);
- conference_connected->conference_number = conference_number;
+ *conference_connected = (Tox_Event_Conference_Connected) {
+ 0
+ };
}
-uint32_t tox_event_conference_connected_get_conference_number(
- const Tox_Event_Conference_Connected *conference_connected)
+non_null()
+static void tox_event_conference_connected_destruct(Tox_Event_Conference_Connected *conference_connected, const Memory *mem)
{
- assert(conference_connected != nullptr);
- return conference_connected->conference_number;
+ return;
}
-non_null()
-static bool tox_event_conference_connected_pack(
+bool tox_event_conference_connected_pack(
const Tox_Event_Conference_Connected *event, Bin_Pack *bp)
{
- assert(event != nullptr);
- return bin_pack_array(bp, 2)
- && bin_pack_u32(bp, TOX_EVENT_CONFERENCE_CONNECTED)
- && bin_pack_u32(bp, event->conference_number);
+ return bin_pack_u32(bp, event->conference_number);
}
non_null()
-static bool tox_event_conference_connected_unpack(
+static bool tox_event_conference_connected_unpack_into(
Tox_Event_Conference_Connected *event, Bin_Unpack *bu)
{
assert(event != nullptr);
return bin_unpack_u32(bu, &event->conference_number);
}
-
/*****************************************************
*
- * :: add/clear/get
+ * :: new/free/add/get/size/unpack
*
*****************************************************/
-
-non_null()
-static Tox_Event_Conference_Connected *tox_events_add_conference_connected(Tox_Events *events)
+const Tox_Event_Conference_Connected *tox_event_get_conference_connected(const Tox_Event *event)
{
- if (events->conference_connected_size == UINT32_MAX) {
- return nullptr;
- }
-
- if (events->conference_connected_size == events->conference_connected_capacity) {
- const uint32_t new_conference_connected_capacity = events->conference_connected_capacity * 2 + 1;
- Tox_Event_Conference_Connected *new_conference_connected = (Tox_Event_Conference_Connected *)realloc(
- events->conference_connected, new_conference_connected_capacity * sizeof(Tox_Event_Conference_Connected));
+ return event->type == TOX_EVENT_CONFERENCE_CONNECTED ? event->data.conference_connected : nullptr;
+}
- if (new_conference_connected == nullptr) {
- return nullptr;
- }
+Tox_Event_Conference_Connected *tox_event_conference_connected_new(const Memory *mem)
+{
+ Tox_Event_Conference_Connected *const conference_connected =
+ (Tox_Event_Conference_Connected *)mem_alloc(mem, sizeof(Tox_Event_Conference_Connected));
- events->conference_connected = new_conference_connected;
- events->conference_connected_capacity = new_conference_connected_capacity;
+ if (conference_connected == nullptr) {
+ return nullptr;
}
- Tox_Event_Conference_Connected *const conference_connected =
- &events->conference_connected[events->conference_connected_size];
tox_event_conference_connected_construct(conference_connected);
- ++events->conference_connected_size;
return conference_connected;
}
-void tox_events_clear_conference_connected(Tox_Events *events)
+void tox_event_conference_connected_free(Tox_Event_Conference_Connected *conference_connected, const Memory *mem)
{
- if (events == nullptr) {
- return;
- }
-
- for (uint32_t i = 0; i < events->conference_connected_size; ++i) {
- tox_event_conference_connected_destruct(&events->conference_connected[i]);
+ if (conference_connected != nullptr) {
+ tox_event_conference_connected_destruct(conference_connected, mem);
}
-
- free(events->conference_connected);
- events->conference_connected = nullptr;
- events->conference_connected_size = 0;
- events->conference_connected_capacity = 0;
+ mem_delete(mem, conference_connected);
}
-uint32_t tox_events_get_conference_connected_size(const Tox_Events *events)
+non_null()
+static Tox_Event_Conference_Connected *tox_events_add_conference_connected(Tox_Events *events, const Memory *mem)
{
- if (events == nullptr) {
- return 0;
+ Tox_Event_Conference_Connected *const conference_connected = tox_event_conference_connected_new(mem);
+
+ if (conference_connected == nullptr) {
+ return nullptr;
}
- return events->conference_connected_size;
-}
+ Tox_Event event;
+ event.type = TOX_EVENT_CONFERENCE_CONNECTED;
+ event.data.conference_connected = conference_connected;
-const Tox_Event_Conference_Connected *tox_events_get_conference_connected(const Tox_Events *events, uint32_t index)
-{
- assert(index < events->conference_connected_size);
- assert(events->conference_connected != nullptr);
- return &events->conference_connected[index];
+ tox_events_add(events, &event);
+ return conference_connected;
}
-bool tox_events_pack_conference_connected(const Tox_Events *events, Bin_Pack *bp)
+bool tox_event_conference_connected_unpack(
+ Tox_Event_Conference_Connected **event, Bin_Unpack *bu, const Memory *mem)
{
- const uint32_t size = tox_events_get_conference_connected_size(events);
+ assert(event != nullptr);
+ assert(*event == nullptr);
+ *event = tox_event_conference_connected_new(mem);
- for (uint32_t i = 0; i < size; ++i) {
- if (!tox_event_conference_connected_pack(tox_events_get_conference_connected(events, i), bp)) {
- return false;
- }
+ if (*event == nullptr) {
+ return false;
}
- return true;
+
+ return tox_event_conference_connected_unpack_into(*event, bu);
}
-bool tox_events_unpack_conference_connected(Tox_Events *events, Bin_Unpack *bu)
+non_null()
+static Tox_Event_Conference_Connected *tox_event_conference_connected_alloc(void *user_data)
{
- Tox_Event_Conference_Connected *event = tox_events_add_conference_connected(events);
+ Tox_Events_State *state = tox_events_alloc(user_data);
+ assert(state != nullptr);
- if (event == nullptr) {
- return false;
+ if (state->events == nullptr) {
+ return nullptr;
}
- return tox_event_conference_connected_unpack(event, bu);
-}
+ Tox_Event_Conference_Connected *conference_connected = tox_events_add_conference_connected(state->events, state->mem);
+ if (conference_connected == nullptr) {
+ state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
+ return nullptr;
+ }
+ return conference_connected;
+}
/*****************************************************
*
@@ -169,20 +153,13 @@ bool tox_events_unpack_conference_connected(Tox_Events *events, Bin_Unpack *bu)
*
*****************************************************/
-
-void tox_events_handle_conference_connected(Tox *tox, uint32_t conference_number, void *user_data)
+void tox_events_handle_conference_connected(
+ Tox *tox, uint32_t conference_number,
+ void *user_data)
{
- Tox_Events_State *state = tox_events_alloc(user_data);
- assert(state != nullptr);
-
- if (state->events == nullptr) {
- return;
- }
-
- Tox_Event_Conference_Connected *conference_connected = tox_events_add_conference_connected(state->events);
+ Tox_Event_Conference_Connected *conference_connected = tox_event_conference_connected_alloc(user_data);
if (conference_connected == nullptr) {
- state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
return;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/conference_invite.c b/protocols/Tox/libtox/src/toxcore/events/conference_invite.c
index 1d88f41d76..fb1f794bf3 100644
--- a/protocols/Tox/libtox/src/toxcore/events/conference_invite.c
+++ b/protocols/Tox/libtox/src/toxcore/events/conference_invite.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2022 The TokTok team.
+ * Copyright © 2023-2024 The TokTok team.
*/
#include "events_alloc.h"
@@ -8,21 +8,22 @@
#include <stdlib.h>
#include <string.h>
+#include "../attributes.h"
#include "../bin_pack.h"
#include "../bin_unpack.h"
#include "../ccompat.h"
+#include "../mem.h"
#include "../tox.h"
#include "../tox_events.h"
+#include "../tox_pack.h"
#include "../tox_unpack.h"
-
/*****************************************************
*
* :: struct and accessors
*
*****************************************************/
-
struct Tox_Event_Conference_Invite {
uint32_t friend_number;
Tox_Conference_Type type;
@@ -31,19 +32,6 @@ struct Tox_Event_Conference_Invite {
};
non_null()
-static void tox_event_conference_invite_construct(Tox_Event_Conference_Invite *conference_invite)
-{
- *conference_invite = (Tox_Event_Conference_Invite) {
- 0
- };
-}
-non_null()
-static void tox_event_conference_invite_destruct(Tox_Event_Conference_Invite *conference_invite)
-{
- free(conference_invite->cookie);
-}
-
-non_null()
static void tox_event_conference_invite_set_friend_number(Tox_Event_Conference_Invite *conference_invite,
uint32_t friend_number)
{
@@ -69,7 +57,7 @@ Tox_Conference_Type tox_event_conference_invite_get_type(const Tox_Event_Confere
return conference_invite->type;
}
-non_null()
+non_null(1) nullable(2)
static bool tox_event_conference_invite_set_cookie(Tox_Event_Conference_Invite *conference_invite,
const uint8_t *cookie, uint32_t cookie_length)
{
@@ -81,13 +69,19 @@ static bool tox_event_conference_invite_set_cookie(Tox_Event_Conference_Invite *
conference_invite->cookie_length = 0;
}
- conference_invite->cookie = (uint8_t *)malloc(cookie_length);
+ if (cookie == nullptr) {
+ assert(cookie_length == 0);
+ return true;
+ }
+
+ uint8_t *cookie_copy = (uint8_t *)malloc(cookie_length);
- if (conference_invite->cookie == nullptr) {
+ if (cookie_copy == nullptr) {
return false;
}
- memcpy(conference_invite->cookie, cookie, cookie_length);
+ memcpy(cookie_copy, cookie, cookie_length);
+ conference_invite->cookie = cookie_copy;
conference_invite->cookie_length = cookie_length;
return true;
}
@@ -103,121 +97,123 @@ const uint8_t *tox_event_conference_invite_get_cookie(const Tox_Event_Conference
}
non_null()
-static bool tox_event_conference_invite_pack(
+static void tox_event_conference_invite_construct(Tox_Event_Conference_Invite *conference_invite)
+{
+ *conference_invite = (Tox_Event_Conference_Invite) {
+ 0
+ };
+}
+non_null()
+static void tox_event_conference_invite_destruct(Tox_Event_Conference_Invite *conference_invite, const Memory *mem)
+{
+ free(conference_invite->cookie);
+}
+
+bool tox_event_conference_invite_pack(
const Tox_Event_Conference_Invite *event, Bin_Pack *bp)
{
- assert(event != nullptr);
- return bin_pack_array(bp, 2)
- && bin_pack_u32(bp, TOX_EVENT_CONFERENCE_INVITE)
- && bin_pack_array(bp, 3)
+ return bin_pack_array(bp, 3)
&& bin_pack_u32(bp, event->friend_number)
- && bin_pack_u32(bp, event->type)
+ && tox_conference_type_pack(event->type, bp)
&& bin_pack_bin(bp, event->cookie, event->cookie_length);
}
non_null()
-static bool tox_event_conference_invite_unpack(
+static bool tox_event_conference_invite_unpack_into(
Tox_Event_Conference_Invite *event, Bin_Unpack *bu)
{
assert(event != nullptr);
- if (!bin_unpack_array_fixed(bu, 3)) {
+ if (!bin_unpack_array_fixed(bu, 3, nullptr)) {
return false;
}
return bin_unpack_u32(bu, &event->friend_number)
- && tox_unpack_conference_type(bu, &event->type)
+ && tox_conference_type_unpack(&event->type, bu)
&& bin_unpack_bin(bu, &event->cookie, &event->cookie_length);
}
-
/*****************************************************
*
- * :: add/clear/get
+ * :: new/free/add/get/size/unpack
*
*****************************************************/
-
-non_null()
-static Tox_Event_Conference_Invite *tox_events_add_conference_invite(Tox_Events *events)
+const Tox_Event_Conference_Invite *tox_event_get_conference_invite(const Tox_Event *event)
{
- if (events->conference_invite_size == UINT32_MAX) {
- return nullptr;
- }
-
- if (events->conference_invite_size == events->conference_invite_capacity) {
- const uint32_t new_conference_invite_capacity = events->conference_invite_capacity * 2 + 1;
- Tox_Event_Conference_Invite *new_conference_invite = (Tox_Event_Conference_Invite *)realloc(
- events->conference_invite, new_conference_invite_capacity * sizeof(Tox_Event_Conference_Invite));
+ return event->type == TOX_EVENT_CONFERENCE_INVITE ? event->data.conference_invite : nullptr;
+}
- if (new_conference_invite == nullptr) {
- return nullptr;
- }
+Tox_Event_Conference_Invite *tox_event_conference_invite_new(const Memory *mem)
+{
+ Tox_Event_Conference_Invite *const conference_invite =
+ (Tox_Event_Conference_Invite *)mem_alloc(mem, sizeof(Tox_Event_Conference_Invite));
- events->conference_invite = new_conference_invite;
- events->conference_invite_capacity = new_conference_invite_capacity;
+ if (conference_invite == nullptr) {
+ return nullptr;
}
- Tox_Event_Conference_Invite *const conference_invite = &events->conference_invite[events->conference_invite_size];
tox_event_conference_invite_construct(conference_invite);
- ++events->conference_invite_size;
return conference_invite;
}
-void tox_events_clear_conference_invite(Tox_Events *events)
+void tox_event_conference_invite_free(Tox_Event_Conference_Invite *conference_invite, const Memory *mem)
{
- if (events == nullptr) {
- return;
- }
-
- for (uint32_t i = 0; i < events->conference_invite_size; ++i) {
- tox_event_conference_invite_destruct(&events->conference_invite[i]);
+ if (conference_invite != nullptr) {
+ tox_event_conference_invite_destruct(conference_invite, mem);
}
-
- free(events->conference_invite);
- events->conference_invite = nullptr;
- events->conference_invite_size = 0;
- events->conference_invite_capacity = 0;
+ mem_delete(mem, conference_invite);
}
-uint32_t tox_events_get_conference_invite_size(const Tox_Events *events)
+non_null()
+static Tox_Event_Conference_Invite *tox_events_add_conference_invite(Tox_Events *events, const Memory *mem)
{
- if (events == nullptr) {
- return 0;
+ Tox_Event_Conference_Invite *const conference_invite = tox_event_conference_invite_new(mem);
+
+ if (conference_invite == nullptr) {
+ return nullptr;
}
- return events->conference_invite_size;
-}
+ Tox_Event event;
+ event.type = TOX_EVENT_CONFERENCE_INVITE;
+ event.data.conference_invite = conference_invite;
-const Tox_Event_Conference_Invite *tox_events_get_conference_invite(const Tox_Events *events, uint32_t index)
-{
- assert(index < events->conference_invite_size);
- assert(events->conference_invite != nullptr);
- return &events->conference_invite[index];
+ tox_events_add(events, &event);
+ return conference_invite;
}
-bool tox_events_pack_conference_invite(const Tox_Events *events, Bin_Pack *bp)
+bool tox_event_conference_invite_unpack(
+ Tox_Event_Conference_Invite **event, Bin_Unpack *bu, const Memory *mem)
{
- const uint32_t size = tox_events_get_conference_invite_size(events);
+ assert(event != nullptr);
+ assert(*event == nullptr);
+ *event = tox_event_conference_invite_new(mem);
- for (uint32_t i = 0; i < size; ++i) {
- if (!tox_event_conference_invite_pack(tox_events_get_conference_invite(events, i), bp)) {
- return false;
- }
+ if (*event == nullptr) {
+ return false;
}
- return true;
+
+ return tox_event_conference_invite_unpack_into(*event, bu);
}
-bool tox_events_unpack_conference_invite(Tox_Events *events, Bin_Unpack *bu)
+non_null()
+static Tox_Event_Conference_Invite *tox_event_conference_invite_alloc(void *user_data)
{
- Tox_Event_Conference_Invite *event = tox_events_add_conference_invite(events);
+ Tox_Events_State *state = tox_events_alloc(user_data);
+ assert(state != nullptr);
- if (event == nullptr) {
- return false;
+ if (state->events == nullptr) {
+ return nullptr;
}
- return tox_event_conference_invite_unpack(event, bu);
-}
+ Tox_Event_Conference_Invite *conference_invite = tox_events_add_conference_invite(state->events, state->mem);
+
+ if (conference_invite == nullptr) {
+ state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
+ return nullptr;
+ }
+ return conference_invite;
+}
/*****************************************************
*
@@ -225,21 +221,13 @@ bool tox_events_unpack_conference_invite(Tox_Events *events, Bin_Unpack *bu)
*
*****************************************************/
-
-void tox_events_handle_conference_invite(Tox *tox, uint32_t friend_number, Tox_Conference_Type type,
- const uint8_t *cookie, size_t length, void *user_data)
+void tox_events_handle_conference_invite(
+ Tox *tox, uint32_t friend_number, Tox_Conference_Type type, const uint8_t *cookie, size_t length,
+ void *user_data)
{
- Tox_Events_State *state = tox_events_alloc(user_data);
- assert(state != nullptr);
-
- if (state->events == nullptr) {
- return;
- }
-
- Tox_Event_Conference_Invite *conference_invite = tox_events_add_conference_invite(state->events);
+ Tox_Event_Conference_Invite *conference_invite = tox_event_conference_invite_alloc(user_data);
if (conference_invite == nullptr) {
- state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
return;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/conference_message.c b/protocols/Tox/libtox/src/toxcore/events/conference_message.c
index bc9a19b738..74e1123e01 100644
--- a/protocols/Tox/libtox/src/toxcore/events/conference_message.c
+++ b/protocols/Tox/libtox/src/toxcore/events/conference_message.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2022 The TokTok team.
+ * Copyright © 2023-2024 The TokTok team.
*/
#include "events_alloc.h"
@@ -8,21 +8,22 @@
#include <stdlib.h>
#include <string.h>
+#include "../attributes.h"
#include "../bin_pack.h"
#include "../bin_unpack.h"
#include "../ccompat.h"
+#include "../mem.h"
#include "../tox.h"
#include "../tox_events.h"
+#include "../tox_pack.h"
#include "../tox_unpack.h"
-
/*****************************************************
*
* :: struct and accessors
*
*****************************************************/
-
struct Tox_Event_Conference_Message {
uint32_t conference_number;
uint32_t peer_number;
@@ -32,19 +33,6 @@ struct Tox_Event_Conference_Message {
};
non_null()
-static void tox_event_conference_message_construct(Tox_Event_Conference_Message *conference_message)
-{
- *conference_message = (Tox_Event_Conference_Message) {
- 0
- };
-}
-non_null()
-static void tox_event_conference_message_destruct(Tox_Event_Conference_Message *conference_message)
-{
- free(conference_message->message);
-}
-
-non_null()
static void tox_event_conference_message_set_conference_number(Tox_Event_Conference_Message *conference_message,
uint32_t conference_number)
{
@@ -83,7 +71,7 @@ Tox_Message_Type tox_event_conference_message_get_type(const Tox_Event_Conferenc
return conference_message->type;
}
-non_null()
+non_null(1) nullable(2)
static bool tox_event_conference_message_set_message(Tox_Event_Conference_Message *conference_message,
const uint8_t *message, uint32_t message_length)
{
@@ -95,13 +83,19 @@ static bool tox_event_conference_message_set_message(Tox_Event_Conference_Messag
conference_message->message_length = 0;
}
- conference_message->message = (uint8_t *)malloc(message_length);
+ if (message == nullptr) {
+ assert(message_length == 0);
+ return true;
+ }
+
+ uint8_t *message_copy = (uint8_t *)malloc(message_length);
- if (conference_message->message == nullptr) {
+ if (message_copy == nullptr) {
return false;
}
- memcpy(conference_message->message, message, message_length);
+ memcpy(message_copy, message, message_length);
+ conference_message->message = message_copy;
conference_message->message_length = message_length;
return true;
}
@@ -117,123 +111,125 @@ const uint8_t *tox_event_conference_message_get_message(const Tox_Event_Conferen
}
non_null()
-static bool tox_event_conference_message_pack(
+static void tox_event_conference_message_construct(Tox_Event_Conference_Message *conference_message)
+{
+ *conference_message = (Tox_Event_Conference_Message) {
+ 0
+ };
+}
+non_null()
+static void tox_event_conference_message_destruct(Tox_Event_Conference_Message *conference_message, const Memory *mem)
+{
+ free(conference_message->message);
+}
+
+bool tox_event_conference_message_pack(
const Tox_Event_Conference_Message *event, Bin_Pack *bp)
{
- assert(event != nullptr);
- return bin_pack_array(bp, 2)
- && bin_pack_u32(bp, TOX_EVENT_CONFERENCE_MESSAGE)
- && bin_pack_array(bp, 4)
+ return bin_pack_array(bp, 4)
&& bin_pack_u32(bp, event->conference_number)
&& bin_pack_u32(bp, event->peer_number)
- && bin_pack_u32(bp, event->type)
+ && tox_message_type_pack(event->type, bp)
&& bin_pack_bin(bp, event->message, event->message_length);
}
non_null()
-static bool tox_event_conference_message_unpack(
+static bool tox_event_conference_message_unpack_into(
Tox_Event_Conference_Message *event, Bin_Unpack *bu)
{
assert(event != nullptr);
- if (!bin_unpack_array_fixed(bu, 4)) {
+ if (!bin_unpack_array_fixed(bu, 4, nullptr)) {
return false;
}
return bin_unpack_u32(bu, &event->conference_number)
&& bin_unpack_u32(bu, &event->peer_number)
- && tox_unpack_message_type(bu, &event->type)
+ && tox_message_type_unpack(&event->type, bu)
&& bin_unpack_bin(bu, &event->message, &event->message_length);
}
-
/*****************************************************
*
- * :: add/clear/get
+ * :: new/free/add/get/size/unpack
*
*****************************************************/
-
-non_null()
-static Tox_Event_Conference_Message *tox_events_add_conference_message(Tox_Events *events)
+const Tox_Event_Conference_Message *tox_event_get_conference_message(const Tox_Event *event)
{
- if (events->conference_message_size == UINT32_MAX) {
- return nullptr;
- }
-
- if (events->conference_message_size == events->conference_message_capacity) {
- const uint32_t new_conference_message_capacity = events->conference_message_capacity * 2 + 1;
- Tox_Event_Conference_Message *new_conference_message = (Tox_Event_Conference_Message *)realloc(
- events->conference_message, new_conference_message_capacity * sizeof(Tox_Event_Conference_Message));
+ return event->type == TOX_EVENT_CONFERENCE_MESSAGE ? event->data.conference_message : nullptr;
+}
- if (new_conference_message == nullptr) {
- return nullptr;
- }
+Tox_Event_Conference_Message *tox_event_conference_message_new(const Memory *mem)
+{
+ Tox_Event_Conference_Message *const conference_message =
+ (Tox_Event_Conference_Message *)mem_alloc(mem, sizeof(Tox_Event_Conference_Message));
- events->conference_message = new_conference_message;
- events->conference_message_capacity = new_conference_message_capacity;
+ if (conference_message == nullptr) {
+ return nullptr;
}
- Tox_Event_Conference_Message *const conference_message = &events->conference_message[events->conference_message_size];
tox_event_conference_message_construct(conference_message);
- ++events->conference_message_size;
return conference_message;
}
-void tox_events_clear_conference_message(Tox_Events *events)
+void tox_event_conference_message_free(Tox_Event_Conference_Message *conference_message, const Memory *mem)
{
- if (events == nullptr) {
- return;
- }
-
- for (uint32_t i = 0; i < events->conference_message_size; ++i) {
- tox_event_conference_message_destruct(&events->conference_message[i]);
+ if (conference_message != nullptr) {
+ tox_event_conference_message_destruct(conference_message, mem);
}
-
- free(events->conference_message);
- events->conference_message = nullptr;
- events->conference_message_size = 0;
- events->conference_message_capacity = 0;
+ mem_delete(mem, conference_message);
}
-uint32_t tox_events_get_conference_message_size(const Tox_Events *events)
+non_null()
+static Tox_Event_Conference_Message *tox_events_add_conference_message(Tox_Events *events, const Memory *mem)
{
- if (events == nullptr) {
- return 0;
+ Tox_Event_Conference_Message *const conference_message = tox_event_conference_message_new(mem);
+
+ if (conference_message == nullptr) {
+ return nullptr;
}
- return events->conference_message_size;
-}
+ Tox_Event event;
+ event.type = TOX_EVENT_CONFERENCE_MESSAGE;
+ event.data.conference_message = conference_message;
-const Tox_Event_Conference_Message *tox_events_get_conference_message(const Tox_Events *events, uint32_t index)
-{
- assert(index < events->conference_message_size);
- assert(events->conference_message != nullptr);
- return &events->conference_message[index];
+ tox_events_add(events, &event);
+ return conference_message;
}
-bool tox_events_pack_conference_message(const Tox_Events *events, Bin_Pack *bp)
+bool tox_event_conference_message_unpack(
+ Tox_Event_Conference_Message **event, Bin_Unpack *bu, const Memory *mem)
{
- const uint32_t size = tox_events_get_conference_message_size(events);
+ assert(event != nullptr);
+ assert(*event == nullptr);
+ *event = tox_event_conference_message_new(mem);
- for (uint32_t i = 0; i < size; ++i) {
- if (!tox_event_conference_message_pack(tox_events_get_conference_message(events, i), bp)) {
- return false;
- }
+ if (*event == nullptr) {
+ return false;
}
- return true;
+
+ return tox_event_conference_message_unpack_into(*event, bu);
}
-bool tox_events_unpack_conference_message(Tox_Events *events, Bin_Unpack *bu)
+non_null()
+static Tox_Event_Conference_Message *tox_event_conference_message_alloc(void *user_data)
{
- Tox_Event_Conference_Message *event = tox_events_add_conference_message(events);
+ Tox_Events_State *state = tox_events_alloc(user_data);
+ assert(state != nullptr);
- if (event == nullptr) {
- return false;
+ if (state->events == nullptr) {
+ return nullptr;
}
- return tox_event_conference_message_unpack(event, bu);
-}
+ Tox_Event_Conference_Message *conference_message = tox_events_add_conference_message(state->events, state->mem);
+
+ if (conference_message == nullptr) {
+ state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
+ return nullptr;
+ }
+ return conference_message;
+}
/*****************************************************
*
@@ -241,21 +237,13 @@ bool tox_events_unpack_conference_message(Tox_Events *events, Bin_Unpack *bu)
*
*****************************************************/
-
-void tox_events_handle_conference_message(Tox *tox, uint32_t conference_number, uint32_t peer_number,
- Tox_Message_Type type, const uint8_t *message, size_t length, void *user_data)
+void tox_events_handle_conference_message(
+ Tox *tox, uint32_t conference_number, uint32_t peer_number, Tox_Message_Type type, const uint8_t *message, size_t length,
+ void *user_data)
{
- Tox_Events_State *state = tox_events_alloc(user_data);
- assert(state != nullptr);
-
- if (state->events == nullptr) {
- return;
- }
-
- Tox_Event_Conference_Message *conference_message = tox_events_add_conference_message(state->events);
+ Tox_Event_Conference_Message *conference_message = tox_event_conference_message_alloc(user_data);
if (conference_message == nullptr) {
- state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
return;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/conference_peer_list_changed.c b/protocols/Tox/libtox/src/toxcore/events/conference_peer_list_changed.c
index b6aaa3bf7a..050bfb08f8 100644
--- a/protocols/Tox/libtox/src/toxcore/events/conference_peer_list_changed.c
+++ b/protocols/Tox/libtox/src/toxcore/events/conference_peer_list_changed.c
@@ -1,171 +1,151 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2022 The TokTok team.
+ * Copyright © 2023-2024 The TokTok team.
*/
#include "events_alloc.h"
#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
+#include "../attributes.h"
#include "../bin_pack.h"
#include "../bin_unpack.h"
#include "../ccompat.h"
+#include "../mem.h"
#include "../tox.h"
#include "../tox_events.h"
-
/*****************************************************
*
* :: struct and accessors
*
*****************************************************/
-
struct Tox_Event_Conference_Peer_List_Changed {
uint32_t conference_number;
};
non_null()
-static void tox_event_conference_peer_list_changed_construct(Tox_Event_Conference_Peer_List_Changed
- *conference_peer_list_changed)
+static void tox_event_conference_peer_list_changed_set_conference_number(Tox_Event_Conference_Peer_List_Changed *conference_peer_list_changed,
+ uint32_t conference_number)
{
- *conference_peer_list_changed = (Tox_Event_Conference_Peer_List_Changed) {
- 0
- };
+ assert(conference_peer_list_changed != nullptr);
+ conference_peer_list_changed->conference_number = conference_number;
}
-non_null()
-static void tox_event_conference_peer_list_changed_destruct(Tox_Event_Conference_Peer_List_Changed
- *conference_peer_list_changed)
+uint32_t tox_event_conference_peer_list_changed_get_conference_number(const Tox_Event_Conference_Peer_List_Changed *conference_peer_list_changed)
{
- return;
+ assert(conference_peer_list_changed != nullptr);
+ return conference_peer_list_changed->conference_number;
}
non_null()
-static void tox_event_conference_peer_list_changed_set_conference_number(Tox_Event_Conference_Peer_List_Changed
- *conference_peer_list_changed, uint32_t conference_number)
+static void tox_event_conference_peer_list_changed_construct(Tox_Event_Conference_Peer_List_Changed *conference_peer_list_changed)
{
- assert(conference_peer_list_changed != nullptr);
- conference_peer_list_changed->conference_number = conference_number;
+ *conference_peer_list_changed = (Tox_Event_Conference_Peer_List_Changed) {
+ 0
+ };
}
-uint32_t tox_event_conference_peer_list_changed_get_conference_number(const Tox_Event_Conference_Peer_List_Changed
- *conference_peer_list_changed)
+non_null()
+static void tox_event_conference_peer_list_changed_destruct(Tox_Event_Conference_Peer_List_Changed *conference_peer_list_changed, const Memory *mem)
{
- assert(conference_peer_list_changed != nullptr);
- return conference_peer_list_changed->conference_number;
+ return;
}
-non_null()
-static bool tox_event_conference_peer_list_changed_pack(
+bool tox_event_conference_peer_list_changed_pack(
const Tox_Event_Conference_Peer_List_Changed *event, Bin_Pack *bp)
{
- assert(event != nullptr);
- return bin_pack_array(bp, 2)
- && bin_pack_u32(bp, TOX_EVENT_CONFERENCE_PEER_LIST_CHANGED)
- && bin_pack_u32(bp, event->conference_number);
+ return bin_pack_u32(bp, event->conference_number);
}
non_null()
-static bool tox_event_conference_peer_list_changed_unpack(
+static bool tox_event_conference_peer_list_changed_unpack_into(
Tox_Event_Conference_Peer_List_Changed *event, Bin_Unpack *bu)
{
assert(event != nullptr);
return bin_unpack_u32(bu, &event->conference_number);
}
-
/*****************************************************
*
- * :: add/clear/get
+ * :: new/free/add/get/size/unpack
*
*****************************************************/
-
-non_null()
-static Tox_Event_Conference_Peer_List_Changed *tox_events_add_conference_peer_list_changed(Tox_Events *events)
+const Tox_Event_Conference_Peer_List_Changed *tox_event_get_conference_peer_list_changed(const Tox_Event *event)
{
- if (events->conference_peer_list_changed_size == UINT32_MAX) {
- return nullptr;
- }
-
- if (events->conference_peer_list_changed_size == events->conference_peer_list_changed_capacity) {
- const uint32_t new_conference_peer_list_changed_capacity = events->conference_peer_list_changed_capacity * 2 + 1;
- Tox_Event_Conference_Peer_List_Changed *new_conference_peer_list_changed = (Tox_Event_Conference_Peer_List_Changed *)
- realloc(
- events->conference_peer_list_changed,
- new_conference_peer_list_changed_capacity * sizeof(Tox_Event_Conference_Peer_List_Changed));
+ return event->type == TOX_EVENT_CONFERENCE_PEER_LIST_CHANGED ? event->data.conference_peer_list_changed : nullptr;
+}
- if (new_conference_peer_list_changed == nullptr) {
- return nullptr;
- }
+Tox_Event_Conference_Peer_List_Changed *tox_event_conference_peer_list_changed_new(const Memory *mem)
+{
+ Tox_Event_Conference_Peer_List_Changed *const conference_peer_list_changed =
+ (Tox_Event_Conference_Peer_List_Changed *)mem_alloc(mem, sizeof(Tox_Event_Conference_Peer_List_Changed));
- events->conference_peer_list_changed = new_conference_peer_list_changed;
- events->conference_peer_list_changed_capacity = new_conference_peer_list_changed_capacity;
+ if (conference_peer_list_changed == nullptr) {
+ return nullptr;
}
- Tox_Event_Conference_Peer_List_Changed *const conference_peer_list_changed =
- &events->conference_peer_list_changed[events->conference_peer_list_changed_size];
tox_event_conference_peer_list_changed_construct(conference_peer_list_changed);
- ++events->conference_peer_list_changed_size;
return conference_peer_list_changed;
}
-void tox_events_clear_conference_peer_list_changed(Tox_Events *events)
+void tox_event_conference_peer_list_changed_free(Tox_Event_Conference_Peer_List_Changed *conference_peer_list_changed, const Memory *mem)
{
- if (events == nullptr) {
- return;
+ if (conference_peer_list_changed != nullptr) {
+ tox_event_conference_peer_list_changed_destruct(conference_peer_list_changed, mem);
}
-
- for (uint32_t i = 0; i < events->conference_peer_list_changed_size; ++i) {
- tox_event_conference_peer_list_changed_destruct(&events->conference_peer_list_changed[i]);
- }
-
- free(events->conference_peer_list_changed);
- events->conference_peer_list_changed = nullptr;
- events->conference_peer_list_changed_size = 0;
- events->conference_peer_list_changed_capacity = 0;
+ mem_delete(mem, conference_peer_list_changed);
}
-uint32_t tox_events_get_conference_peer_list_changed_size(const Tox_Events *events)
+non_null()
+static Tox_Event_Conference_Peer_List_Changed *tox_events_add_conference_peer_list_changed(Tox_Events *events, const Memory *mem)
{
- if (events == nullptr) {
- return 0;
+ Tox_Event_Conference_Peer_List_Changed *const conference_peer_list_changed = tox_event_conference_peer_list_changed_new(mem);
+
+ if (conference_peer_list_changed == nullptr) {
+ return nullptr;
}
- return events->conference_peer_list_changed_size;
-}
+ Tox_Event event;
+ event.type = TOX_EVENT_CONFERENCE_PEER_LIST_CHANGED;
+ event.data.conference_peer_list_changed = conference_peer_list_changed;
-const Tox_Event_Conference_Peer_List_Changed *tox_events_get_conference_peer_list_changed(const Tox_Events *events,
- uint32_t index)
-{
- assert(index < events->conference_peer_list_changed_size);
- assert(events->conference_peer_list_changed != nullptr);
- return &events->conference_peer_list_changed[index];
+ tox_events_add(events, &event);
+ return conference_peer_list_changed;
}
-bool tox_events_pack_conference_peer_list_changed(const Tox_Events *events, Bin_Pack *bp)
+bool tox_event_conference_peer_list_changed_unpack(
+ Tox_Event_Conference_Peer_List_Changed **event, Bin_Unpack *bu, const Memory *mem)
{
- const uint32_t size = tox_events_get_conference_peer_list_changed_size(events);
+ assert(event != nullptr);
+ assert(*event == nullptr);
+ *event = tox_event_conference_peer_list_changed_new(mem);
- for (uint32_t i = 0; i < size; ++i) {
- if (!tox_event_conference_peer_list_changed_pack(tox_events_get_conference_peer_list_changed(events, i), bp)) {
- return false;
- }
+ if (*event == nullptr) {
+ return false;
}
- return true;
+
+ return tox_event_conference_peer_list_changed_unpack_into(*event, bu);
}
-bool tox_events_unpack_conference_peer_list_changed(Tox_Events *events, Bin_Unpack *bu)
+non_null()
+static Tox_Event_Conference_Peer_List_Changed *tox_event_conference_peer_list_changed_alloc(void *user_data)
{
- Tox_Event_Conference_Peer_List_Changed *event = tox_events_add_conference_peer_list_changed(events);
+ Tox_Events_State *state = tox_events_alloc(user_data);
+ assert(state != nullptr);
- if (event == nullptr) {
- return false;
+ if (state->events == nullptr) {
+ return nullptr;
}
- return tox_event_conference_peer_list_changed_unpack(event, bu);
-}
+ Tox_Event_Conference_Peer_List_Changed *conference_peer_list_changed = tox_events_add_conference_peer_list_changed(state->events, state->mem);
+ if (conference_peer_list_changed == nullptr) {
+ state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
+ return nullptr;
+ }
+
+ return conference_peer_list_changed;
+}
/*****************************************************
*
@@ -173,21 +153,13 @@ bool tox_events_unpack_conference_peer_list_changed(Tox_Events *events, Bin_Unpa
*
*****************************************************/
-
-void tox_events_handle_conference_peer_list_changed(Tox *tox, uint32_t conference_number, void *user_data)
+void tox_events_handle_conference_peer_list_changed(
+ Tox *tox, uint32_t conference_number,
+ void *user_data)
{
- Tox_Events_State *state = tox_events_alloc(user_data);
- assert(state != nullptr);
-
- if (state->events == nullptr) {
- return;
- }
-
- Tox_Event_Conference_Peer_List_Changed *conference_peer_list_changed = tox_events_add_conference_peer_list_changed(
- state->events);
+ Tox_Event_Conference_Peer_List_Changed *conference_peer_list_changed = tox_event_conference_peer_list_changed_alloc(user_data);
if (conference_peer_list_changed == nullptr) {
- state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
return;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/conference_peer_name.c b/protocols/Tox/libtox/src/toxcore/events/conference_peer_name.c
index 4d3f285eee..fc6c255791 100644
--- a/protocols/Tox/libtox/src/toxcore/events/conference_peer_name.c
+++ b/protocols/Tox/libtox/src/toxcore/events/conference_peer_name.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2022 The TokTok team.
+ * Copyright © 2023-2024 The TokTok team.
*/
#include "events_alloc.h"
@@ -8,20 +8,20 @@
#include <stdlib.h>
#include <string.h>
+#include "../attributes.h"
#include "../bin_pack.h"
#include "../bin_unpack.h"
#include "../ccompat.h"
+#include "../mem.h"
#include "../tox.h"
#include "../tox_events.h"
-
/*****************************************************
*
* :: struct and accessors
*
*****************************************************/
-
struct Tox_Event_Conference_Peer_Name {
uint32_t conference_number;
uint32_t peer_number;
@@ -30,27 +30,13 @@ struct Tox_Event_Conference_Peer_Name {
};
non_null()
-static void tox_event_conference_peer_name_construct(Tox_Event_Conference_Peer_Name *conference_peer_name)
-{
- *conference_peer_name = (Tox_Event_Conference_Peer_Name) {
- 0
- };
-}
-non_null()
-static void tox_event_conference_peer_name_destruct(Tox_Event_Conference_Peer_Name *conference_peer_name)
-{
- free(conference_peer_name->name);
-}
-
-non_null()
static void tox_event_conference_peer_name_set_conference_number(Tox_Event_Conference_Peer_Name *conference_peer_name,
uint32_t conference_number)
{
assert(conference_peer_name != nullptr);
conference_peer_name->conference_number = conference_number;
}
-uint32_t tox_event_conference_peer_name_get_conference_number(const Tox_Event_Conference_Peer_Name
- *conference_peer_name)
+uint32_t tox_event_conference_peer_name_get_conference_number(const Tox_Event_Conference_Peer_Name *conference_peer_name)
{
assert(conference_peer_name != nullptr);
return conference_peer_name->conference_number;
@@ -69,7 +55,7 @@ uint32_t tox_event_conference_peer_name_get_peer_number(const Tox_Event_Conferen
return conference_peer_name->peer_number;
}
-non_null()
+non_null(1) nullable(2)
static bool tox_event_conference_peer_name_set_name(Tox_Event_Conference_Peer_Name *conference_peer_name,
const uint8_t *name, uint32_t name_length)
{
@@ -81,13 +67,19 @@ static bool tox_event_conference_peer_name_set_name(Tox_Event_Conference_Peer_Na
conference_peer_name->name_length = 0;
}
- conference_peer_name->name = (uint8_t *)malloc(name_length);
+ if (name == nullptr) {
+ assert(name_length == 0);
+ return true;
+ }
+
+ uint8_t *name_copy = (uint8_t *)malloc(name_length);
- if (conference_peer_name->name == nullptr) {
+ if (name_copy == nullptr) {
return false;
}
- memcpy(conference_peer_name->name, name, name_length);
+ memcpy(name_copy, name, name_length);
+ conference_peer_name->name = name_copy;
conference_peer_name->name_length = name_length;
return true;
}
@@ -103,24 +95,33 @@ const uint8_t *tox_event_conference_peer_name_get_name(const Tox_Event_Conferenc
}
non_null()
-static bool tox_event_conference_peer_name_pack(
+static void tox_event_conference_peer_name_construct(Tox_Event_Conference_Peer_Name *conference_peer_name)
+{
+ *conference_peer_name = (Tox_Event_Conference_Peer_Name) {
+ 0
+ };
+}
+non_null()
+static void tox_event_conference_peer_name_destruct(Tox_Event_Conference_Peer_Name *conference_peer_name, const Memory *mem)
+{
+ free(conference_peer_name->name);
+}
+
+bool tox_event_conference_peer_name_pack(
const Tox_Event_Conference_Peer_Name *event, Bin_Pack *bp)
{
- assert(event != nullptr);
- return bin_pack_array(bp, 2)
- && bin_pack_u32(bp, TOX_EVENT_CONFERENCE_PEER_NAME)
- && bin_pack_array(bp, 3)
+ return bin_pack_array(bp, 3)
&& bin_pack_u32(bp, event->conference_number)
&& bin_pack_u32(bp, event->peer_number)
&& bin_pack_bin(bp, event->name, event->name_length);
}
non_null()
-static bool tox_event_conference_peer_name_unpack(
+static bool tox_event_conference_peer_name_unpack_into(
Tox_Event_Conference_Peer_Name *event, Bin_Unpack *bu)
{
assert(event != nullptr);
- if (!bin_unpack_array_fixed(bu, 3)) {
+ if (!bin_unpack_array_fixed(bu, 3, nullptr)) {
return false;
}
@@ -129,96 +130,88 @@ static bool tox_event_conference_peer_name_unpack(
&& bin_unpack_bin(bu, &event->name, &event->name_length);
}
-
/*****************************************************
*
- * :: add/clear/get
+ * :: new/free/add/get/size/unpack
*
*****************************************************/
-
-non_null()
-static Tox_Event_Conference_Peer_Name *tox_events_add_conference_peer_name(Tox_Events *events)
+const Tox_Event_Conference_Peer_Name *tox_event_get_conference_peer_name(const Tox_Event *event)
{
- if (events->conference_peer_name_size == UINT32_MAX) {
- return nullptr;
- }
-
- if (events->conference_peer_name_size == events->conference_peer_name_capacity) {
- const uint32_t new_conference_peer_name_capacity = events->conference_peer_name_capacity * 2 + 1;
- Tox_Event_Conference_Peer_Name *new_conference_peer_name = (Tox_Event_Conference_Peer_Name *)realloc(
- events->conference_peer_name, new_conference_peer_name_capacity * sizeof(Tox_Event_Conference_Peer_Name));
+ return event->type == TOX_EVENT_CONFERENCE_PEER_NAME ? event->data.conference_peer_name : nullptr;
+}
- if (new_conference_peer_name == nullptr) {
- return nullptr;
- }
+Tox_Event_Conference_Peer_Name *tox_event_conference_peer_name_new(const Memory *mem)
+{
+ Tox_Event_Conference_Peer_Name *const conference_peer_name =
+ (Tox_Event_Conference_Peer_Name *)mem_alloc(mem, sizeof(Tox_Event_Conference_Peer_Name));
- events->conference_peer_name = new_conference_peer_name;
- events->conference_peer_name_capacity = new_conference_peer_name_capacity;
+ if (conference_peer_name == nullptr) {
+ return nullptr;
}
- Tox_Event_Conference_Peer_Name *const conference_peer_name =
- &events->conference_peer_name[events->conference_peer_name_size];
tox_event_conference_peer_name_construct(conference_peer_name);
- ++events->conference_peer_name_size;
return conference_peer_name;
}
-void tox_events_clear_conference_peer_name(Tox_Events *events)
+void tox_event_conference_peer_name_free(Tox_Event_Conference_Peer_Name *conference_peer_name, const Memory *mem)
{
- if (events == nullptr) {
- return;
+ if (conference_peer_name != nullptr) {
+ tox_event_conference_peer_name_destruct(conference_peer_name, mem);
}
-
- for (uint32_t i = 0; i < events->conference_peer_name_size; ++i) {
- tox_event_conference_peer_name_destruct(&events->conference_peer_name[i]);
- }
-
- free(events->conference_peer_name);
- events->conference_peer_name = nullptr;
- events->conference_peer_name_size = 0;
- events->conference_peer_name_capacity = 0;
+ mem_delete(mem, conference_peer_name);
}
-uint32_t tox_events_get_conference_peer_name_size(const Tox_Events *events)
+non_null()
+static Tox_Event_Conference_Peer_Name *tox_events_add_conference_peer_name(Tox_Events *events, const Memory *mem)
{
- if (events == nullptr) {
- return 0;
+ Tox_Event_Conference_Peer_Name *const conference_peer_name = tox_event_conference_peer_name_new(mem);
+
+ if (conference_peer_name == nullptr) {
+ return nullptr;
}
- return events->conference_peer_name_size;
-}
+ Tox_Event event;
+ event.type = TOX_EVENT_CONFERENCE_PEER_NAME;
+ event.data.conference_peer_name = conference_peer_name;
-const Tox_Event_Conference_Peer_Name *tox_events_get_conference_peer_name(const Tox_Events *events, uint32_t index)
-{
- assert(index < events->conference_peer_name_size);
- assert(events->conference_peer_name != nullptr);
- return &events->conference_peer_name[index];
+ tox_events_add(events, &event);
+ return conference_peer_name;
}
-bool tox_events_pack_conference_peer_name(const Tox_Events *events, Bin_Pack *bp)
+bool tox_event_conference_peer_name_unpack(
+ Tox_Event_Conference_Peer_Name **event, Bin_Unpack *bu, const Memory *mem)
{
- const uint32_t size = tox_events_get_conference_peer_name_size(events);
+ assert(event != nullptr);
+ assert(*event == nullptr);
+ *event = tox_event_conference_peer_name_new(mem);
- for (uint32_t i = 0; i < size; ++i) {
- if (!tox_event_conference_peer_name_pack(tox_events_get_conference_peer_name(events, i), bp)) {
- return false;
- }
+ if (*event == nullptr) {
+ return false;
}
- return true;
+
+ return tox_event_conference_peer_name_unpack_into(*event, bu);
}
-bool tox_events_unpack_conference_peer_name(Tox_Events *events, Bin_Unpack *bu)
+non_null()
+static Tox_Event_Conference_Peer_Name *tox_event_conference_peer_name_alloc(void *user_data)
{
- Tox_Event_Conference_Peer_Name *event = tox_events_add_conference_peer_name(events);
+ Tox_Events_State *state = tox_events_alloc(user_data);
+ assert(state != nullptr);
- if (event == nullptr) {
- return false;
+ if (state->events == nullptr) {
+ return nullptr;
}
- return tox_event_conference_peer_name_unpack(event, bu);
-}
+ Tox_Event_Conference_Peer_Name *conference_peer_name = tox_events_add_conference_peer_name(state->events, state->mem);
+
+ if (conference_peer_name == nullptr) {
+ state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
+ return nullptr;
+ }
+ return conference_peer_name;
+}
/*****************************************************
*
@@ -226,21 +219,13 @@ bool tox_events_unpack_conference_peer_name(Tox_Events *events, Bin_Unpack *bu)
*
*****************************************************/
-
-void tox_events_handle_conference_peer_name(Tox *tox, uint32_t conference_number, uint32_t peer_number,
- const uint8_t *name, size_t length, void *user_data)
+void tox_events_handle_conference_peer_name(
+ Tox *tox, uint32_t conference_number, uint32_t peer_number, const uint8_t *name, size_t length,
+ void *user_data)
{
- Tox_Events_State *state = tox_events_alloc(user_data);
- assert(state != nullptr);
-
- if (state->events == nullptr) {
- return;
- }
-
- Tox_Event_Conference_Peer_Name *conference_peer_name = tox_events_add_conference_peer_name(state->events);
+ Tox_Event_Conference_Peer_Name *conference_peer_name = tox_event_conference_peer_name_alloc(user_data);
if (conference_peer_name == nullptr) {
- state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
return;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/conference_title.c b/protocols/Tox/libtox/src/toxcore/events/conference_title.c
index 1866966e9f..d761f51285 100644
--- a/protocols/Tox/libtox/src/toxcore/events/conference_title.c
+++ b/protocols/Tox/libtox/src/toxcore/events/conference_title.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2022 The TokTok team.
+ * Copyright © 2023-2024 The TokTok team.
*/
#include "events_alloc.h"
@@ -8,20 +8,20 @@
#include <stdlib.h>
#include <string.h>
+#include "../attributes.h"
#include "../bin_pack.h"
#include "../bin_unpack.h"
#include "../ccompat.h"
+#include "../mem.h"
#include "../tox.h"
#include "../tox_events.h"
-
/*****************************************************
*
* :: struct and accessors
*
*****************************************************/
-
struct Tox_Event_Conference_Title {
uint32_t conference_number;
uint32_t peer_number;
@@ -30,19 +30,6 @@ struct Tox_Event_Conference_Title {
};
non_null()
-static void tox_event_conference_title_construct(Tox_Event_Conference_Title *conference_title)
-{
- *conference_title = (Tox_Event_Conference_Title) {
- 0
- };
-}
-non_null()
-static void tox_event_conference_title_destruct(Tox_Event_Conference_Title *conference_title)
-{
- free(conference_title->title);
-}
-
-non_null()
static void tox_event_conference_title_set_conference_number(Tox_Event_Conference_Title *conference_title,
uint32_t conference_number)
{
@@ -68,9 +55,9 @@ uint32_t tox_event_conference_title_get_peer_number(const Tox_Event_Conference_T
return conference_title->peer_number;
}
-non_null()
-static bool tox_event_conference_title_set_title(Tox_Event_Conference_Title *conference_title, const uint8_t *title,
- uint32_t title_length)
+non_null(1) nullable(2)
+static bool tox_event_conference_title_set_title(Tox_Event_Conference_Title *conference_title,
+ const uint8_t *title, uint32_t title_length)
{
assert(conference_title != nullptr);
@@ -80,13 +67,19 @@ static bool tox_event_conference_title_set_title(Tox_Event_Conference_Title *con
conference_title->title_length = 0;
}
- conference_title->title = (uint8_t *)malloc(title_length);
+ if (title == nullptr) {
+ assert(title_length == 0);
+ return true;
+ }
+
+ uint8_t *title_copy = (uint8_t *)malloc(title_length);
- if (conference_title->title == nullptr) {
+ if (title_copy == nullptr) {
return false;
}
- memcpy(conference_title->title, title, title_length);
+ memcpy(title_copy, title, title_length);
+ conference_title->title = title_copy;
conference_title->title_length = title_length;
return true;
}
@@ -102,24 +95,33 @@ const uint8_t *tox_event_conference_title_get_title(const Tox_Event_Conference_T
}
non_null()
-static bool tox_event_conference_title_pack(
+static void tox_event_conference_title_construct(Tox_Event_Conference_Title *conference_title)
+{
+ *conference_title = (Tox_Event_Conference_Title) {
+ 0
+ };
+}
+non_null()
+static void tox_event_conference_title_destruct(Tox_Event_Conference_Title *conference_title, const Memory *mem)
+{
+ free(conference_title->title);
+}
+
+bool tox_event_conference_title_pack(
const Tox_Event_Conference_Title *event, Bin_Pack *bp)
{
- assert(event != nullptr);
- return bin_pack_array(bp, 2)
- && bin_pack_u32(bp, TOX_EVENT_CONFERENCE_TITLE)
- && bin_pack_array(bp, 3)
+ return bin_pack_array(bp, 3)
&& bin_pack_u32(bp, event->conference_number)
&& bin_pack_u32(bp, event->peer_number)
&& bin_pack_bin(bp, event->title, event->title_length);
}
non_null()
-static bool tox_event_conference_title_unpack(
+static bool tox_event_conference_title_unpack_into(
Tox_Event_Conference_Title *event, Bin_Unpack *bu)
{
assert(event != nullptr);
- if (!bin_unpack_array_fixed(bu, 3)) {
+ if (!bin_unpack_array_fixed(bu, 3, nullptr)) {
return false;
}
@@ -128,95 +130,88 @@ static bool tox_event_conference_title_unpack(
&& bin_unpack_bin(bu, &event->title, &event->title_length);
}
-
/*****************************************************
*
- * :: add/clear/get
+ * :: new/free/add/get/size/unpack
*
*****************************************************/
-
-non_null()
-static Tox_Event_Conference_Title *tox_events_add_conference_title(Tox_Events *events)
+const Tox_Event_Conference_Title *tox_event_get_conference_title(const Tox_Event *event)
{
- if (events->conference_title_size == UINT32_MAX) {
- return nullptr;
- }
-
- if (events->conference_title_size == events->conference_title_capacity) {
- const uint32_t new_conference_title_capacity = events->conference_title_capacity * 2 + 1;
- Tox_Event_Conference_Title *new_conference_title = (Tox_Event_Conference_Title *)realloc(
- events->conference_title, new_conference_title_capacity * sizeof(Tox_Event_Conference_Title));
+ return event->type == TOX_EVENT_CONFERENCE_TITLE ? event->data.conference_title : nullptr;
+}
- if (new_conference_title == nullptr) {
- return nullptr;
- }
+Tox_Event_Conference_Title *tox_event_conference_title_new(const Memory *mem)
+{
+ Tox_Event_Conference_Title *const conference_title =
+ (Tox_Event_Conference_Title *)mem_alloc(mem, sizeof(Tox_Event_Conference_Title));
- events->conference_title = new_conference_title;
- events->conference_title_capacity = new_conference_title_capacity;
+ if (conference_title == nullptr) {
+ return nullptr;
}
- Tox_Event_Conference_Title *const conference_title = &events->conference_title[events->conference_title_size];
tox_event_conference_title_construct(conference_title);
- ++events->conference_title_size;
return conference_title;
}
-void tox_events_clear_conference_title(Tox_Events *events)
+void tox_event_conference_title_free(Tox_Event_Conference_Title *conference_title, const Memory *mem)
{
- if (events == nullptr) {
- return;
- }
-
- for (uint32_t i = 0; i < events->conference_title_size; ++i) {
- tox_event_conference_title_destruct(&events->conference_title[i]);
+ if (conference_title != nullptr) {
+ tox_event_conference_title_destruct(conference_title, mem);
}
-
- free(events->conference_title);
- events->conference_title = nullptr;
- events->conference_title_size = 0;
- events->conference_title_capacity = 0;
+ mem_delete(mem, conference_title);
}
-uint32_t tox_events_get_conference_title_size(const Tox_Events *events)
+non_null()
+static Tox_Event_Conference_Title *tox_events_add_conference_title(Tox_Events *events, const Memory *mem)
{
- if (events == nullptr) {
- return 0;
+ Tox_Event_Conference_Title *const conference_title = tox_event_conference_title_new(mem);
+
+ if (conference_title == nullptr) {
+ return nullptr;
}
- return events->conference_title_size;
-}
+ Tox_Event event;
+ event.type = TOX_EVENT_CONFERENCE_TITLE;
+ event.data.conference_title = conference_title;
-const Tox_Event_Conference_Title *tox_events_get_conference_title(const Tox_Events *events, uint32_t index)
-{
- assert(index < events->conference_title_size);
- assert(events->conference_title != nullptr);
- return &events->conference_title[index];
+ tox_events_add(events, &event);
+ return conference_title;
}
-bool tox_events_pack_conference_title(const Tox_Events *events, Bin_Pack *bp)
+bool tox_event_conference_title_unpack(
+ Tox_Event_Conference_Title **event, Bin_Unpack *bu, const Memory *mem)
{
- const uint32_t size = tox_events_get_conference_title_size(events);
+ assert(event != nullptr);
+ assert(*event == nullptr);
+ *event = tox_event_conference_title_new(mem);
- for (uint32_t i = 0; i < size; ++i) {
- if (!tox_event_conference_title_pack(tox_events_get_conference_title(events, i), bp)) {
- return false;
- }
+ if (*event == nullptr) {
+ return false;
}
- return true;
+
+ return tox_event_conference_title_unpack_into(*event, bu);
}
-bool tox_events_unpack_conference_title(Tox_Events *events, Bin_Unpack *bu)
+non_null()
+static Tox_Event_Conference_Title *tox_event_conference_title_alloc(void *user_data)
{
- Tox_Event_Conference_Title *event = tox_events_add_conference_title(events);
+ Tox_Events_State *state = tox_events_alloc(user_data);
+ assert(state != nullptr);
- if (event == nullptr) {
- return false;
+ if (state->events == nullptr) {
+ return nullptr;
}
- return tox_event_conference_title_unpack(event, bu);
-}
+ Tox_Event_Conference_Title *conference_title = tox_events_add_conference_title(state->events, state->mem);
+
+ if (conference_title == nullptr) {
+ state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
+ return nullptr;
+ }
+ return conference_title;
+}
/*****************************************************
*
@@ -224,21 +219,13 @@ bool tox_events_unpack_conference_title(Tox_Events *events, Bin_Unpack *bu)
*
*****************************************************/
-
-void tox_events_handle_conference_title(Tox *tox, uint32_t conference_number, uint32_t peer_number,
- const uint8_t *title, size_t length, void *user_data)
+void tox_events_handle_conference_title(
+ Tox *tox, uint32_t conference_number, uint32_t peer_number, const uint8_t *title, size_t length,
+ void *user_data)
{
- Tox_Events_State *state = tox_events_alloc(user_data);
- assert(state != nullptr);
-
- if (state->events == nullptr) {
- return;
- }
-
- Tox_Event_Conference_Title *conference_title = tox_events_add_conference_title(state->events);
+ Tox_Event_Conference_Title *conference_title = tox_event_conference_title_alloc(user_data);
if (conference_title == nullptr) {
- state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
return;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/dht_get_nodes_response.c b/protocols/Tox/libtox/src/toxcore/events/dht_get_nodes_response.c
new file mode 100644
index 0000000000..6e03b73ea4
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/events/dht_get_nodes_response.c
@@ -0,0 +1,223 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2022 The TokTok team.
+ */
+
+#include "events_alloc.h"
+
+#include <assert.h>
+#include <string.h>
+
+#include "../attributes.h"
+#include "../bin_pack.h"
+#include "../bin_unpack.h"
+#include "../ccompat.h"
+#include "../mem.h"
+#include "../tox.h"
+#include "../tox_events.h"
+#include "../tox_private.h"
+
+/*****************************************************
+ *
+ * :: struct and accessors
+ *
+ *****************************************************/
+
+struct Tox_Event_Dht_Get_Nodes_Response {
+ uint8_t public_key[TOX_PUBLIC_KEY_SIZE];
+ uint8_t *ip;
+ uint32_t ip_length;
+ uint16_t port;
+};
+
+non_null()
+static bool tox_event_dht_get_nodes_response_set_public_key(Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response, const uint8_t public_key[TOX_PUBLIC_KEY_SIZE])
+{
+ memcpy(dht_get_nodes_response->public_key, public_key, TOX_PUBLIC_KEY_SIZE);
+ return true;
+}
+const uint8_t *tox_event_dht_get_nodes_response_get_public_key(const Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response)
+{
+ return dht_get_nodes_response->public_key;
+}
+
+non_null()
+static bool tox_event_dht_get_nodes_response_set_ip(Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response,
+ const char *ip, uint32_t ip_length, const Memory *mem)
+{
+ if (dht_get_nodes_response->ip != nullptr) {
+ mem_delete(mem, dht_get_nodes_response->ip);
+ dht_get_nodes_response->ip = nullptr;
+ dht_get_nodes_response->ip_length = 0;
+ }
+
+ uint8_t *ip_tmp = (uint8_t *)mem_balloc(mem, ip_length);
+
+ if (ip_tmp == nullptr) {
+ return false;
+ }
+
+ memcpy(ip_tmp, ip, ip_length);
+ dht_get_nodes_response->ip = ip_tmp;
+ dht_get_nodes_response->ip_length = ip_length;
+ return true;
+}
+uint32_t tox_event_dht_get_nodes_response_get_ip_length(const Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response)
+{
+ return dht_get_nodes_response->ip_length;
+}
+const uint8_t *tox_event_dht_get_nodes_response_get_ip(const Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response)
+{
+ return dht_get_nodes_response->ip;
+}
+
+non_null()
+static bool tox_event_dht_get_nodes_response_set_port(Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response, uint16_t port)
+{
+ dht_get_nodes_response->port = port;
+ return true;
+}
+uint16_t tox_event_dht_get_nodes_response_get_port(const Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response)
+{
+ return dht_get_nodes_response->port;
+}
+
+non_null()
+static void tox_event_dht_get_nodes_response_construct(Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response)
+{
+ *dht_get_nodes_response = (Tox_Event_Dht_Get_Nodes_Response) {
+ {
+ 0
+ }
+ };
+}
+non_null()
+static void tox_event_dht_get_nodes_response_destruct(Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response, const Memory *mem)
+{
+ mem_delete(mem, dht_get_nodes_response->ip);
+}
+
+bool tox_event_dht_get_nodes_response_pack(
+ const Tox_Event_Dht_Get_Nodes_Response *event, Bin_Pack *bp)
+{
+ return bin_pack_array(bp, 3)
+ && bin_pack_bin(bp, event->public_key, TOX_PUBLIC_KEY_SIZE)
+ && bin_pack_bin(bp, event->ip, event->ip_length)
+ && bin_pack_u16(bp, event->port);
+}
+
+non_null()
+static bool tox_event_dht_get_nodes_response_unpack_into(
+ Tox_Event_Dht_Get_Nodes_Response *event, Bin_Unpack *bu)
+{
+ if (!bin_unpack_array_fixed(bu, 3, nullptr)) {
+ return false;
+ }
+
+ return bin_unpack_bin_fixed(bu, event->public_key, TOX_PUBLIC_KEY_SIZE)
+ && bin_unpack_bin(bu, &event->ip, &event->ip_length)
+ && bin_unpack_u16(bu, &event->port);
+}
+
+const Tox_Event_Dht_Get_Nodes_Response *tox_event_get_dht_get_nodes_response(
+ const Tox_Event *event)
+{
+ return event->type == TOX_EVENT_DHT_GET_NODES_RESPONSE ? event->data.dht_get_nodes_response : nullptr;
+}
+
+Tox_Event_Dht_Get_Nodes_Response *tox_event_dht_get_nodes_response_new(const Memory *mem)
+{
+ Tox_Event_Dht_Get_Nodes_Response *const dht_get_nodes_response =
+ (Tox_Event_Dht_Get_Nodes_Response *)mem_alloc(mem, sizeof(Tox_Event_Dht_Get_Nodes_Response));
+
+ if (dht_get_nodes_response == nullptr) {
+ return nullptr;
+ }
+
+ tox_event_dht_get_nodes_response_construct(dht_get_nodes_response);
+ return dht_get_nodes_response;
+}
+
+void tox_event_dht_get_nodes_response_free(Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response, const Memory *mem)
+{
+ if (dht_get_nodes_response != nullptr) {
+ tox_event_dht_get_nodes_response_destruct(dht_get_nodes_response, mem);
+ }
+ mem_delete(mem, dht_get_nodes_response);
+}
+
+non_null()
+static Tox_Event_Dht_Get_Nodes_Response *tox_events_add_dht_get_nodes_response(Tox_Events *events, const Memory *mem)
+{
+ Tox_Event_Dht_Get_Nodes_Response *const dht_get_nodes_response = tox_event_dht_get_nodes_response_new(mem);
+
+ if (dht_get_nodes_response == nullptr) {
+ return nullptr;
+ }
+
+ Tox_Event event;
+ event.type = TOX_EVENT_DHT_GET_NODES_RESPONSE;
+ event.data.dht_get_nodes_response = dht_get_nodes_response;
+
+ tox_events_add(events, &event);
+ return dht_get_nodes_response;
+}
+
+bool tox_event_dht_get_nodes_response_unpack(
+ Tox_Event_Dht_Get_Nodes_Response **event, Bin_Unpack *bu, const Memory *mem)
+{
+ *event = tox_event_dht_get_nodes_response_new(mem);
+
+ if (*event == nullptr) {
+ return false;
+ }
+
+ return tox_event_dht_get_nodes_response_unpack_into(*event, bu);
+}
+
+non_null()
+static Tox_Event_Dht_Get_Nodes_Response *tox_event_dht_get_nodes_response_alloc(void *user_data)
+{
+ Tox_Events_State *state = tox_events_alloc(user_data);
+ assert(state != nullptr);
+
+ if (state->events == nullptr) {
+ return nullptr;
+ }
+
+ Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response = tox_events_add_dht_get_nodes_response(state->events, state->mem);
+
+ if (dht_get_nodes_response == nullptr) {
+ state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
+ return nullptr;
+ }
+
+ return dht_get_nodes_response;
+}
+
+/*****************************************************
+ *
+ * :: event handler
+ *
+ *****************************************************/
+
+void tox_events_handle_dht_get_nodes_response(
+ Tox *tox, const uint8_t public_key[TOX_PUBLIC_KEY_SIZE],
+ const char *ip, uint16_t port, void *user_data)
+{
+ Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response = tox_event_dht_get_nodes_response_alloc(user_data);
+
+ if (dht_get_nodes_response == nullptr) {
+ return;
+ }
+
+ const size_t ip_length = strlen(ip);
+ if (ip_length >= UINT32_MAX) {
+ return;
+ }
+
+ const Tox_System *sys = tox_get_system(tox);
+
+ tox_event_dht_get_nodes_response_set_public_key(dht_get_nodes_response, public_key);
+ tox_event_dht_get_nodes_response_set_ip(dht_get_nodes_response, ip, ip_length + 1, sys->mem);
+ tox_event_dht_get_nodes_response_set_port(dht_get_nodes_response, port);
+}
diff --git a/protocols/Tox/libtox/src/toxcore/events/events_alloc.c b/protocols/Tox/libtox/src/toxcore/events/events_alloc.c
index f661c5c039..24eebb3124 100644
--- a/protocols/Tox/libtox/src/toxcore/events/events_alloc.c
+++ b/protocols/Tox/libtox/src/toxcore/events/events_alloc.c
@@ -5,31 +5,38 @@
#include "events_alloc.h"
#include <assert.h>
-#include <stdlib.h>
#include "../ccompat.h"
+#include "../mem.h"
+#include "../tox_event.h"
+#include "../tox_events.h"
Tox_Events_State *tox_events_alloc(void *user_data)
{
Tox_Events_State *state = (Tox_Events_State *)user_data;
assert(state != nullptr);
+ assert(state->mem != nullptr);
if (state->events != nullptr) {
// Already allocated.
return state;
}
- state->events = (Tox_Events *)calloc(1, sizeof(Tox_Events));
+ Tox_Events *events = (Tox_Events *)mem_alloc(state->mem, sizeof(Tox_Events));
- if (state->events == nullptr) {
+ if (events == nullptr) {
// It's still null => allocation failed.
+ state->events = nullptr;
state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
- } else {
- *state->events = (Tox_Events) {
- nullptr
- };
+ return state;
}
+ *events = (Tox_Events) {
+ nullptr
+ };
+ state->events = events;
+ state->events->mem = state->mem;
+
return state;
}
@@ -39,26 +46,35 @@ void tox_events_free(Tox_Events *events)
return;
}
- tox_events_clear_conference_connected(events);
- tox_events_clear_conference_invite(events);
- tox_events_clear_conference_message(events);
- tox_events_clear_conference_peer_list_changed(events);
- tox_events_clear_conference_peer_name(events);
- tox_events_clear_conference_title(events);
- tox_events_clear_file_chunk_request(events);
- tox_events_clear_file_recv_chunk(events);
- tox_events_clear_file_recv_control(events);
- tox_events_clear_file_recv(events);
- tox_events_clear_friend_connection_status(events);
- tox_events_clear_friend_lossless_packet(events);
- tox_events_clear_friend_lossy_packet(events);
- tox_events_clear_friend_message(events);
- tox_events_clear_friend_name(events);
- tox_events_clear_friend_read_receipt(events);
- tox_events_clear_friend_request(events);
- tox_events_clear_friend_status(events);
- tox_events_clear_friend_status_message(events);
- tox_events_clear_friend_typing(events);
- tox_events_clear_self_connection_status(events);
- free(events);
+ for (uint32_t i = 0; i < events->events_size; ++i) {
+ tox_event_destruct(&events->events[i], events->mem);
+ }
+
+ mem_delete(events->mem, events->events);
+ mem_delete(events->mem, events);
+}
+
+bool tox_events_add(Tox_Events *events, const Tox_Event *event)
+{
+ if (events->events_size == UINT32_MAX) {
+ return false;
+ }
+
+ if (events->events_size == events->events_capacity) {
+ const uint32_t new_events_capacity = events->events_capacity * 2 + 1;
+ Tox_Event *new_events = (Tox_Event *)mem_vrealloc(
+ events->mem, events->events, new_events_capacity, sizeof(Tox_Event));
+
+ if (new_events == nullptr) {
+ return false;
+ }
+
+ events->events = new_events;
+ events->events_capacity = new_events_capacity;
+ }
+
+ events->events[events->events_size] = *event;
+ ++events->events_size;
+
+ return true;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/events_alloc.h b/protocols/Tox/libtox/src/toxcore/events/events_alloc.h
index 6c5a7abd4f..a40db97052 100644
--- a/protocols/Tox/libtox/src/toxcore/events/events_alloc.h
+++ b/protocols/Tox/libtox/src/toxcore/events/events_alloc.h
@@ -2,106 +2,33 @@
* Copyright © 2022 The TokTok team.
*/
-#ifndef C_TOXCORE_TOXCORE_TOX_EVENTS_INTERNAL_H
-#define C_TOXCORE_TOXCORE_TOX_EVENTS_INTERNAL_H
+#ifndef C_TOXCORE_TOXCORE_EVENTS_EVENTS_ALLOC_H
+#define C_TOXCORE_TOXCORE_EVENTS_EVENTS_ALLOC_H
#include "../attributes.h"
#include "../bin_pack.h"
#include "../bin_unpack.h"
+#include "../mem.h"
+#include "../tox.h"
+#include "../tox_event.h"
#include "../tox_events.h"
+#include "../tox_private.h"
#ifdef __cplusplus
extern "C" {
#endif
struct Tox_Events {
- Tox_Event_Conference_Connected *conference_connected;
- uint32_t conference_connected_size;
- uint32_t conference_connected_capacity;
+ Tox_Event *events;
+ uint32_t events_size;
+ uint32_t events_capacity;
- Tox_Event_Conference_Invite *conference_invite;
- uint32_t conference_invite_size;
- uint32_t conference_invite_capacity;
-
- Tox_Event_Conference_Message *conference_message;
- uint32_t conference_message_size;
- uint32_t conference_message_capacity;
-
- Tox_Event_Conference_Peer_List_Changed *conference_peer_list_changed;
- uint32_t conference_peer_list_changed_size;
- uint32_t conference_peer_list_changed_capacity;
-
- Tox_Event_Conference_Peer_Name *conference_peer_name;
- uint32_t conference_peer_name_size;
- uint32_t conference_peer_name_capacity;
-
- Tox_Event_Conference_Title *conference_title;
- uint32_t conference_title_size;
- uint32_t conference_title_capacity;
-
- Tox_Event_File_Chunk_Request *file_chunk_request;
- uint32_t file_chunk_request_size;
- uint32_t file_chunk_request_capacity;
-
- Tox_Event_File_Recv *file_recv;
- uint32_t file_recv_size;
- uint32_t file_recv_capacity;
-
- Tox_Event_File_Recv_Chunk *file_recv_chunk;
- uint32_t file_recv_chunk_size;
- uint32_t file_recv_chunk_capacity;
-
- Tox_Event_File_Recv_Control *file_recv_control;
- uint32_t file_recv_control_size;
- uint32_t file_recv_control_capacity;
-
- Tox_Event_Friend_Connection_Status *friend_connection_status;
- uint32_t friend_connection_status_size;
- uint32_t friend_connection_status_capacity;
-
- Tox_Event_Friend_Lossless_Packet *friend_lossless_packet;
- uint32_t friend_lossless_packet_size;
- uint32_t friend_lossless_packet_capacity;
-
- Tox_Event_Friend_Lossy_Packet *friend_lossy_packet;
- uint32_t friend_lossy_packet_size;
- uint32_t friend_lossy_packet_capacity;
-
- Tox_Event_Friend_Message *friend_message;
- uint32_t friend_message_size;
- uint32_t friend_message_capacity;
-
- Tox_Event_Friend_Name *friend_name;
- uint32_t friend_name_size;
- uint32_t friend_name_capacity;
-
- Tox_Event_Friend_Read_Receipt *friend_read_receipt;
- uint32_t friend_read_receipt_size;
- uint32_t friend_read_receipt_capacity;
-
- Tox_Event_Friend_Request *friend_request;
- uint32_t friend_request_size;
- uint32_t friend_request_capacity;
-
- Tox_Event_Friend_Status *friend_status;
- uint32_t friend_status_size;
- uint32_t friend_status_capacity;
-
- Tox_Event_Friend_Status_Message *friend_status_message;
- uint32_t friend_status_message_size;
- uint32_t friend_status_message_capacity;
-
- Tox_Event_Friend_Typing *friend_typing;
- uint32_t friend_typing_size;
- uint32_t friend_typing_capacity;
-
- Tox_Event_Self_Connection_Status *self_connection_status;
- uint32_t self_connection_status_size;
- uint32_t self_connection_status_capacity;
+ const Memory *mem;
};
typedef struct Tox_Events_State {
Tox_Err_Events_Iterate error;
+ const Memory *mem;
Tox_Events *events;
} Tox_Events_State;
@@ -111,6 +38,7 @@ tox_conference_message_cb tox_events_handle_conference_message;
tox_conference_peer_list_changed_cb tox_events_handle_conference_peer_list_changed;
tox_conference_peer_name_cb tox_events_handle_conference_peer_name;
tox_conference_title_cb tox_events_handle_conference_title;
+tox_dht_get_nodes_response_cb tox_events_handle_dht_get_nodes_response;
tox_file_chunk_request_cb tox_events_handle_file_chunk_request;
tox_file_recv_cb tox_events_handle_file_recv;
tox_file_recv_chunk_cb tox_events_handle_file_recv_chunk;
@@ -126,91 +54,33 @@ tox_friend_status_cb tox_events_handle_friend_status;
tox_friend_status_message_cb tox_events_handle_friend_status_message;
tox_friend_typing_cb tox_events_handle_friend_typing;
tox_self_connection_status_cb tox_events_handle_self_connection_status;
-
-// non_null()
-typedef void tox_events_clear_cb(Tox_Events *events);
-
-tox_events_clear_cb tox_events_clear_conference_connected;
-tox_events_clear_cb tox_events_clear_conference_invite;
-tox_events_clear_cb tox_events_clear_conference_message;
-tox_events_clear_cb tox_events_clear_conference_peer_list_changed;
-tox_events_clear_cb tox_events_clear_conference_peer_name;
-tox_events_clear_cb tox_events_clear_conference_title;
-tox_events_clear_cb tox_events_clear_file_chunk_request;
-tox_events_clear_cb tox_events_clear_file_recv_chunk;
-tox_events_clear_cb tox_events_clear_file_recv_control;
-tox_events_clear_cb tox_events_clear_file_recv;
-tox_events_clear_cb tox_events_clear_friend_connection_status;
-tox_events_clear_cb tox_events_clear_friend_lossless_packet;
-tox_events_clear_cb tox_events_clear_friend_lossy_packet;
-tox_events_clear_cb tox_events_clear_friend_message;
-tox_events_clear_cb tox_events_clear_friend_name;
-tox_events_clear_cb tox_events_clear_friend_read_receipt;
-tox_events_clear_cb tox_events_clear_friend_request;
-tox_events_clear_cb tox_events_clear_friend_status_message;
-tox_events_clear_cb tox_events_clear_friend_status;
-tox_events_clear_cb tox_events_clear_friend_typing;
-tox_events_clear_cb tox_events_clear_self_connection_status;
-
-// non_null()
-typedef bool tox_events_pack_cb(const Tox_Events *events, Bin_Pack *bp);
-
-tox_events_pack_cb tox_events_pack_conference_connected;
-tox_events_pack_cb tox_events_pack_conference_invite;
-tox_events_pack_cb tox_events_pack_conference_message;
-tox_events_pack_cb tox_events_pack_conference_peer_list_changed;
-tox_events_pack_cb tox_events_pack_conference_peer_name;
-tox_events_pack_cb tox_events_pack_conference_title;
-tox_events_pack_cb tox_events_pack_file_chunk_request;
-tox_events_pack_cb tox_events_pack_file_recv_chunk;
-tox_events_pack_cb tox_events_pack_file_recv_control;
-tox_events_pack_cb tox_events_pack_file_recv;
-tox_events_pack_cb tox_events_pack_friend_connection_status;
-tox_events_pack_cb tox_events_pack_friend_lossless_packet;
-tox_events_pack_cb tox_events_pack_friend_lossy_packet;
-tox_events_pack_cb tox_events_pack_friend_message;
-tox_events_pack_cb tox_events_pack_friend_name;
-tox_events_pack_cb tox_events_pack_friend_read_receipt;
-tox_events_pack_cb tox_events_pack_friend_request;
-tox_events_pack_cb tox_events_pack_friend_status_message;
-tox_events_pack_cb tox_events_pack_friend_status;
-tox_events_pack_cb tox_events_pack_friend_typing;
-tox_events_pack_cb tox_events_pack_self_connection_status;
-
-tox_events_pack_cb tox_events_pack;
-
-// non_null()
-typedef bool tox_events_unpack_cb(Tox_Events *events, Bin_Unpack *bu);
-
-tox_events_unpack_cb tox_events_unpack_conference_connected;
-tox_events_unpack_cb tox_events_unpack_conference_invite;
-tox_events_unpack_cb tox_events_unpack_conference_message;
-tox_events_unpack_cb tox_events_unpack_conference_peer_list_changed;
-tox_events_unpack_cb tox_events_unpack_conference_peer_name;
-tox_events_unpack_cb tox_events_unpack_conference_title;
-tox_events_unpack_cb tox_events_unpack_file_chunk_request;
-tox_events_unpack_cb tox_events_unpack_file_recv_chunk;
-tox_events_unpack_cb tox_events_unpack_file_recv_control;
-tox_events_unpack_cb tox_events_unpack_file_recv;
-tox_events_unpack_cb tox_events_unpack_friend_connection_status;
-tox_events_unpack_cb tox_events_unpack_friend_lossless_packet;
-tox_events_unpack_cb tox_events_unpack_friend_lossy_packet;
-tox_events_unpack_cb tox_events_unpack_friend_message;
-tox_events_unpack_cb tox_events_unpack_friend_name;
-tox_events_unpack_cb tox_events_unpack_friend_read_receipt;
-tox_events_unpack_cb tox_events_unpack_friend_request;
-tox_events_unpack_cb tox_events_unpack_friend_status_message;
-tox_events_unpack_cb tox_events_unpack_friend_status;
-tox_events_unpack_cb tox_events_unpack_friend_typing;
-tox_events_unpack_cb tox_events_unpack_self_connection_status;
-
-tox_events_unpack_cb tox_events_unpack;
+tox_group_peer_name_cb tox_events_handle_group_peer_name;
+tox_group_peer_status_cb tox_events_handle_group_peer_status;
+tox_group_topic_cb tox_events_handle_group_topic;
+tox_group_privacy_state_cb tox_events_handle_group_privacy_state;
+tox_group_voice_state_cb tox_events_handle_group_voice_state;
+tox_group_topic_lock_cb tox_events_handle_group_topic_lock;
+tox_group_peer_limit_cb tox_events_handle_group_peer_limit;
+tox_group_password_cb tox_events_handle_group_password;
+tox_group_message_cb tox_events_handle_group_message;
+tox_group_private_message_cb tox_events_handle_group_private_message;
+tox_group_custom_packet_cb tox_events_handle_group_custom_packet;
+tox_group_custom_private_packet_cb tox_events_handle_group_custom_private_packet;
+tox_group_invite_cb tox_events_handle_group_invite;
+tox_group_peer_join_cb tox_events_handle_group_peer_join;
+tox_group_peer_exit_cb tox_events_handle_group_peer_exit;
+tox_group_self_join_cb tox_events_handle_group_self_join;
+tox_group_join_fail_cb tox_events_handle_group_join_fail;
+tox_group_moderation_cb tox_events_handle_group_moderation;
non_null()
Tox_Events_State *tox_events_alloc(void *user_data);
+non_null()
+bool tox_events_add(Tox_Events *events, const Tox_Event *event);
+
#ifdef __cplusplus
-}
+} /* extern "C" */
#endif
-#endif // C_TOXCORE_TOXCORE_TOX_EVENTS_INTERNAL_H
+#endif /* C_TOXCORE_TOXCORE_EVENTS_EVENTS_ALLOC_H */
diff --git a/protocols/Tox/libtox/src/toxcore/events/file_chunk_request.c b/protocols/Tox/libtox/src/toxcore/events/file_chunk_request.c
index f5a9421f58..4117ef3c4b 100644
--- a/protocols/Tox/libtox/src/toxcore/events/file_chunk_request.c
+++ b/protocols/Tox/libtox/src/toxcore/events/file_chunk_request.c
@@ -1,27 +1,25 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2022 The TokTok team.
+ * Copyright © 2023-2024 The TokTok team.
*/
#include "events_alloc.h"
#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
+#include "../attributes.h"
#include "../bin_pack.h"
#include "../bin_unpack.h"
#include "../ccompat.h"
+#include "../mem.h"
#include "../tox.h"
#include "../tox_events.h"
-
/*****************************************************
*
* :: struct and accessors
*
*****************************************************/
-
struct Tox_Event_File_Chunk_Request {
uint32_t friend_number;
uint32_t file_number;
@@ -30,19 +28,6 @@ struct Tox_Event_File_Chunk_Request {
};
non_null()
-static void tox_event_file_chunk_request_construct(Tox_Event_File_Chunk_Request *file_chunk_request)
-{
- *file_chunk_request = (Tox_Event_File_Chunk_Request) {
- 0
- };
-}
-non_null()
-static void tox_event_file_chunk_request_destruct(Tox_Event_File_Chunk_Request *file_chunk_request)
-{
- return;
-}
-
-non_null()
static void tox_event_file_chunk_request_set_friend_number(Tox_Event_File_Chunk_Request *file_chunk_request,
uint32_t friend_number)
{
@@ -82,7 +67,8 @@ uint64_t tox_event_file_chunk_request_get_position(const Tox_Event_File_Chunk_Re
}
non_null()
-static void tox_event_file_chunk_request_set_length(Tox_Event_File_Chunk_Request *file_chunk_request, uint16_t length)
+static void tox_event_file_chunk_request_set_length(Tox_Event_File_Chunk_Request *file_chunk_request,
+ uint16_t length)
{
assert(file_chunk_request != nullptr);
file_chunk_request->length = length;
@@ -94,13 +80,22 @@ uint16_t tox_event_file_chunk_request_get_length(const Tox_Event_File_Chunk_Requ
}
non_null()
-static bool tox_event_file_chunk_request_pack(
+static void tox_event_file_chunk_request_construct(Tox_Event_File_Chunk_Request *file_chunk_request)
+{
+ *file_chunk_request = (Tox_Event_File_Chunk_Request) {
+ 0
+ };
+}
+non_null()
+static void tox_event_file_chunk_request_destruct(Tox_Event_File_Chunk_Request *file_chunk_request, const Memory *mem)
+{
+ return;
+}
+
+bool tox_event_file_chunk_request_pack(
const Tox_Event_File_Chunk_Request *event, Bin_Pack *bp)
{
- assert(event != nullptr);
- return bin_pack_array(bp, 2)
- && bin_pack_u32(bp, TOX_EVENT_FILE_CHUNK_REQUEST)
- && bin_pack_array(bp, 4)
+ return bin_pack_array(bp, 4)
&& bin_pack_u32(bp, event->friend_number)
&& bin_pack_u32(bp, event->file_number)
&& bin_pack_u64(bp, event->position)
@@ -108,11 +103,11 @@ static bool tox_event_file_chunk_request_pack(
}
non_null()
-static bool tox_event_file_chunk_request_unpack(
+static bool tox_event_file_chunk_request_unpack_into(
Tox_Event_File_Chunk_Request *event, Bin_Unpack *bu)
{
assert(event != nullptr);
- if (!bin_unpack_array_fixed(bu, 4)) {
+ if (!bin_unpack_array_fixed(bu, 4, nullptr)) {
return false;
}
@@ -122,95 +117,88 @@ static bool tox_event_file_chunk_request_unpack(
&& bin_unpack_u16(bu, &event->length);
}
-
/*****************************************************
*
- * :: add/clear/get
+ * :: new/free/add/get/size/unpack
*
*****************************************************/
-
-non_null()
-static Tox_Event_File_Chunk_Request *tox_events_add_file_chunk_request(Tox_Events *events)
+const Tox_Event_File_Chunk_Request *tox_event_get_file_chunk_request(const Tox_Event *event)
{
- if (events->file_chunk_request_size == UINT32_MAX) {
- return nullptr;
- }
-
- if (events->file_chunk_request_size == events->file_chunk_request_capacity) {
- const uint32_t new_file_chunk_request_capacity = events->file_chunk_request_capacity * 2 + 1;
- Tox_Event_File_Chunk_Request *new_file_chunk_request = (Tox_Event_File_Chunk_Request *)realloc(
- events->file_chunk_request, new_file_chunk_request_capacity * sizeof(Tox_Event_File_Chunk_Request));
+ return event->type == TOX_EVENT_FILE_CHUNK_REQUEST ? event->data.file_chunk_request : nullptr;
+}
- if (new_file_chunk_request == nullptr) {
- return nullptr;
- }
+Tox_Event_File_Chunk_Request *tox_event_file_chunk_request_new(const Memory *mem)
+{
+ Tox_Event_File_Chunk_Request *const file_chunk_request =
+ (Tox_Event_File_Chunk_Request *)mem_alloc(mem, sizeof(Tox_Event_File_Chunk_Request));
- events->file_chunk_request = new_file_chunk_request;
- events->file_chunk_request_capacity = new_file_chunk_request_capacity;
+ if (file_chunk_request == nullptr) {
+ return nullptr;
}
- Tox_Event_File_Chunk_Request *const file_chunk_request = &events->file_chunk_request[events->file_chunk_request_size];
tox_event_file_chunk_request_construct(file_chunk_request);
- ++events->file_chunk_request_size;
return file_chunk_request;
}
-void tox_events_clear_file_chunk_request(Tox_Events *events)
+void tox_event_file_chunk_request_free(Tox_Event_File_Chunk_Request *file_chunk_request, const Memory *mem)
{
- if (events == nullptr) {
- return;
+ if (file_chunk_request != nullptr) {
+ tox_event_file_chunk_request_destruct(file_chunk_request, mem);
}
-
- for (uint32_t i = 0; i < events->file_chunk_request_size; ++i) {
- tox_event_file_chunk_request_destruct(&events->file_chunk_request[i]);
- }
-
- free(events->file_chunk_request);
- events->file_chunk_request = nullptr;
- events->file_chunk_request_size = 0;
- events->file_chunk_request_capacity = 0;
+ mem_delete(mem, file_chunk_request);
}
-uint32_t tox_events_get_file_chunk_request_size(const Tox_Events *events)
+non_null()
+static Tox_Event_File_Chunk_Request *tox_events_add_file_chunk_request(Tox_Events *events, const Memory *mem)
{
- if (events == nullptr) {
- return 0;
+ Tox_Event_File_Chunk_Request *const file_chunk_request = tox_event_file_chunk_request_new(mem);
+
+ if (file_chunk_request == nullptr) {
+ return nullptr;
}
- return events->file_chunk_request_size;
-}
+ Tox_Event event;
+ event.type = TOX_EVENT_FILE_CHUNK_REQUEST;
+ event.data.file_chunk_request = file_chunk_request;
-const Tox_Event_File_Chunk_Request *tox_events_get_file_chunk_request(const Tox_Events *events, uint32_t index)
-{
- assert(index < events->file_chunk_request_size);
- assert(events->file_chunk_request != nullptr);
- return &events->file_chunk_request[index];
+ tox_events_add(events, &event);
+ return file_chunk_request;
}
-bool tox_events_pack_file_chunk_request(const Tox_Events *events, Bin_Pack *bp)
+bool tox_event_file_chunk_request_unpack(
+ Tox_Event_File_Chunk_Request **event, Bin_Unpack *bu, const Memory *mem)
{
- const uint32_t size = tox_events_get_file_chunk_request_size(events);
+ assert(event != nullptr);
+ assert(*event == nullptr);
+ *event = tox_event_file_chunk_request_new(mem);
- for (uint32_t i = 0; i < size; ++i) {
- if (!tox_event_file_chunk_request_pack(tox_events_get_file_chunk_request(events, i), bp)) {
- return false;
- }
+ if (*event == nullptr) {
+ return false;
}
- return true;
+
+ return tox_event_file_chunk_request_unpack_into(*event, bu);
}
-bool tox_events_unpack_file_chunk_request(Tox_Events *events, Bin_Unpack *bu)
+non_null()
+static Tox_Event_File_Chunk_Request *tox_event_file_chunk_request_alloc(void *user_data)
{
- Tox_Event_File_Chunk_Request *event = tox_events_add_file_chunk_request(events);
+ Tox_Events_State *state = tox_events_alloc(user_data);
+ assert(state != nullptr);
- if (event == nullptr) {
- return false;
+ if (state->events == nullptr) {
+ return nullptr;
}
- return tox_event_file_chunk_request_unpack(event, bu);
-}
+ Tox_Event_File_Chunk_Request *file_chunk_request = tox_events_add_file_chunk_request(state->events, state->mem);
+ if (file_chunk_request == nullptr) {
+ state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
+ return nullptr;
+ }
+
+ return file_chunk_request;
+}
/*****************************************************
*
@@ -218,21 +206,13 @@ bool tox_events_unpack_file_chunk_request(Tox_Events *events, Bin_Unpack *bu)
*
*****************************************************/
-
-void tox_events_handle_file_chunk_request(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position,
- size_t length, void *user_data)
+void tox_events_handle_file_chunk_request(
+ Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position, size_t length,
+ void *user_data)
{
- Tox_Events_State *state = tox_events_alloc(user_data);
- assert(state != nullptr);
-
- if (state->events == nullptr) {
- return;
- }
-
- Tox_Event_File_Chunk_Request *file_chunk_request = tox_events_add_file_chunk_request(state->events);
+ Tox_Event_File_Chunk_Request *file_chunk_request = tox_event_file_chunk_request_alloc(user_data);
if (file_chunk_request == nullptr) {
- state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
return;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/file_recv.c b/protocols/Tox/libtox/src/toxcore/events/file_recv.c
index a907b3fdbe..45cec44b0d 100644
--- a/protocols/Tox/libtox/src/toxcore/events/file_recv.c
+++ b/protocols/Tox/libtox/src/toxcore/events/file_recv.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2022 The TokTok team.
+ * Copyright © 2023-2024 The TokTok team.
*/
#include "events_alloc.h"
@@ -8,20 +8,20 @@
#include <stdlib.h>
#include <string.h>
+#include "../attributes.h"
#include "../bin_pack.h"
#include "../bin_unpack.h"
#include "../ccompat.h"
+#include "../mem.h"
#include "../tox.h"
#include "../tox_events.h"
-
/*****************************************************
*
* :: struct and accessors
*
*****************************************************/
-
struct Tox_Event_File_Recv {
uint32_t friend_number;
uint32_t file_number;
@@ -32,19 +32,6 @@ struct Tox_Event_File_Recv {
};
non_null()
-static void tox_event_file_recv_construct(Tox_Event_File_Recv *file_recv)
-{
- *file_recv = (Tox_Event_File_Recv) {
- 0
- };
-}
-non_null()
-static void tox_event_file_recv_destruct(Tox_Event_File_Recv *file_recv)
-{
- free(file_recv->filename);
-}
-
-non_null()
static void tox_event_file_recv_set_friend_number(Tox_Event_File_Recv *file_recv,
uint32_t friend_number)
{
@@ -96,9 +83,9 @@ uint64_t tox_event_file_recv_get_file_size(const Tox_Event_File_Recv *file_recv)
return file_recv->file_size;
}
-non_null()
-static bool tox_event_file_recv_set_filename(Tox_Event_File_Recv *file_recv, const uint8_t *filename,
- uint32_t filename_length)
+non_null(1) nullable(2)
+static bool tox_event_file_recv_set_filename(Tox_Event_File_Recv *file_recv,
+ const uint8_t *filename, uint32_t filename_length)
{
assert(file_recv != nullptr);
@@ -108,13 +95,19 @@ static bool tox_event_file_recv_set_filename(Tox_Event_File_Recv *file_recv, con
file_recv->filename_length = 0;
}
- file_recv->filename = (uint8_t *)malloc(filename_length);
+ if (filename == nullptr) {
+ assert(filename_length == 0);
+ return true;
+ }
+
+ uint8_t *filename_copy = (uint8_t *)malloc(filename_length);
- if (file_recv->filename == nullptr) {
+ if (filename_copy == nullptr) {
return false;
}
- memcpy(file_recv->filename, filename, filename_length);
+ memcpy(filename_copy, filename, filename_length);
+ file_recv->filename = filename_copy;
file_recv->filename_length = filename_length;
return true;
}
@@ -130,13 +123,22 @@ const uint8_t *tox_event_file_recv_get_filename(const Tox_Event_File_Recv *file_
}
non_null()
-static bool tox_event_file_recv_pack(
+static void tox_event_file_recv_construct(Tox_Event_File_Recv *file_recv)
+{
+ *file_recv = (Tox_Event_File_Recv) {
+ 0
+ };
+}
+non_null()
+static void tox_event_file_recv_destruct(Tox_Event_File_Recv *file_recv, const Memory *mem)
+{
+ free(file_recv->filename);
+}
+
+bool tox_event_file_recv_pack(
const Tox_Event_File_Recv *event, Bin_Pack *bp)
{
- assert(event != nullptr);
- return bin_pack_array(bp, 2)
- && bin_pack_u32(bp, TOX_EVENT_FILE_RECV)
- && bin_pack_array(bp, 5)
+ return bin_pack_array(bp, 5)
&& bin_pack_u32(bp, event->friend_number)
&& bin_pack_u32(bp, event->file_number)
&& bin_pack_u32(bp, event->kind)
@@ -145,11 +147,11 @@ static bool tox_event_file_recv_pack(
}
non_null()
-static bool tox_event_file_recv_unpack(
+static bool tox_event_file_recv_unpack_into(
Tox_Event_File_Recv *event, Bin_Unpack *bu)
{
assert(event != nullptr);
- if (!bin_unpack_array_fixed(bu, 5)) {
+ if (!bin_unpack_array_fixed(bu, 5, nullptr)) {
return false;
}
@@ -160,95 +162,88 @@ static bool tox_event_file_recv_unpack(
&& bin_unpack_bin(bu, &event->filename, &event->filename_length);
}
-
/*****************************************************
*
- * :: add/clear/get
+ * :: new/free/add/get/size/unpack
*
*****************************************************/
-
-non_null()
-static Tox_Event_File_Recv *tox_events_add_file_recv(Tox_Events *events)
+const Tox_Event_File_Recv *tox_event_get_file_recv(const Tox_Event *event)
{
- if (events->file_recv_size == UINT32_MAX) {
- return nullptr;
- }
-
- if (events->file_recv_size == events->file_recv_capacity) {
- const uint32_t new_file_recv_capacity = events->file_recv_capacity * 2 + 1;
- Tox_Event_File_Recv *new_file_recv = (Tox_Event_File_Recv *)realloc(
- events->file_recv, new_file_recv_capacity * sizeof(Tox_Event_File_Recv));
+ return event->type == TOX_EVENT_FILE_RECV ? event->data.file_recv : nullptr;
+}
- if (new_file_recv == nullptr) {
- return nullptr;
- }
+Tox_Event_File_Recv *tox_event_file_recv_new(const Memory *mem)
+{
+ Tox_Event_File_Recv *const file_recv =
+ (Tox_Event_File_Recv *)mem_alloc(mem, sizeof(Tox_Event_File_Recv));
- events->file_recv = new_file_recv;
- events->file_recv_capacity = new_file_recv_capacity;
+ if (file_recv == nullptr) {
+ return nullptr;
}
- Tox_Event_File_Recv *const file_recv = &events->file_recv[events->file_recv_size];
tox_event_file_recv_construct(file_recv);
- ++events->file_recv_size;
return file_recv;
}
-void tox_events_clear_file_recv(Tox_Events *events)
+void tox_event_file_recv_free(Tox_Event_File_Recv *file_recv, const Memory *mem)
{
- if (events == nullptr) {
- return;
- }
-
- for (uint32_t i = 0; i < events->file_recv_size; ++i) {
- tox_event_file_recv_destruct(&events->file_recv[i]);
+ if (file_recv != nullptr) {
+ tox_event_file_recv_destruct(file_recv, mem);
}
-
- free(events->file_recv);
- events->file_recv = nullptr;
- events->file_recv_size = 0;
- events->file_recv_capacity = 0;
+ mem_delete(mem, file_recv);
}
-uint32_t tox_events_get_file_recv_size(const Tox_Events *events)
+non_null()
+static Tox_Event_File_Recv *tox_events_add_file_recv(Tox_Events *events, const Memory *mem)
{
- if (events == nullptr) {
- return 0;
+ Tox_Event_File_Recv *const file_recv = tox_event_file_recv_new(mem);
+
+ if (file_recv == nullptr) {
+ return nullptr;
}
- return events->file_recv_size;
-}
+ Tox_Event event;
+ event.type = TOX_EVENT_FILE_RECV;
+ event.data.file_recv = file_recv;
-const Tox_Event_File_Recv *tox_events_get_file_recv(const Tox_Events *events, uint32_t index)
-{
- assert(index < events->file_recv_size);
- assert(events->file_recv != nullptr);
- return &events->file_recv[index];
+ tox_events_add(events, &event);
+ return file_recv;
}
-bool tox_events_pack_file_recv(const Tox_Events *events, Bin_Pack *bp)
+bool tox_event_file_recv_unpack(
+ Tox_Event_File_Recv **event, Bin_Unpack *bu, const Memory *mem)
{
- const uint32_t size = tox_events_get_file_recv_size(events);
+ assert(event != nullptr);
+ assert(*event == nullptr);
+ *event = tox_event_file_recv_new(mem);
- for (uint32_t i = 0; i < size; ++i) {
- if (!tox_event_file_recv_pack(tox_events_get_file_recv(events, i), bp)) {
- return false;
- }
+ if (*event == nullptr) {
+ return false;
}
- return true;
+
+ return tox_event_file_recv_unpack_into(*event, bu);
}
-bool tox_events_unpack_file_recv(Tox_Events *events, Bin_Unpack *bu)
+non_null()
+static Tox_Event_File_Recv *tox_event_file_recv_alloc(void *user_data)
{
- Tox_Event_File_Recv *event = tox_events_add_file_recv(events);
+ Tox_Events_State *state = tox_events_alloc(user_data);
+ assert(state != nullptr);
- if (event == nullptr) {
- return false;
+ if (state->events == nullptr) {
+ return nullptr;
}
- return tox_event_file_recv_unpack(event, bu);
-}
+ Tox_Event_File_Recv *file_recv = tox_events_add_file_recv(state->events, state->mem);
+
+ if (file_recv == nullptr) {
+ state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
+ return nullptr;
+ }
+ return file_recv;
+}
/*****************************************************
*
@@ -256,21 +251,13 @@ bool tox_events_unpack_file_recv(Tox_Events *events, Bin_Unpack *bu)
*
*****************************************************/
-
-void tox_events_handle_file_recv(Tox *tox, uint32_t friend_number, uint32_t file_number, uint32_t kind,
- uint64_t file_size, const uint8_t *filename, size_t filename_length, void *user_data)
+void tox_events_handle_file_recv(
+ Tox *tox, uint32_t friend_number, uint32_t file_number, uint32_t kind, uint64_t file_size, const uint8_t *filename, size_t filename_length,
+ void *user_data)
{
- Tox_Events_State *state = tox_events_alloc(user_data);
- assert(state != nullptr);
-
- if (state->events == nullptr) {
- return;
- }
-
- Tox_Event_File_Recv *file_recv = tox_events_add_file_recv(state->events);
+ Tox_Event_File_Recv *file_recv = tox_event_file_recv_alloc(user_data);
if (file_recv == nullptr) {
- state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
return;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/file_recv_chunk.c b/protocols/Tox/libtox/src/toxcore/events/file_recv_chunk.c
index 0fe7784465..2edf7c5a7b 100644
--- a/protocols/Tox/libtox/src/toxcore/events/file_recv_chunk.c
+++ b/protocols/Tox/libtox/src/toxcore/events/file_recv_chunk.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2022 The TokTok team.
+ * Copyright © 2023-2024 The TokTok team.
*/
#include "events_alloc.h"
@@ -8,20 +8,20 @@
#include <stdlib.h>
#include <string.h>
+#include "../attributes.h"
#include "../bin_pack.h"
#include "../bin_unpack.h"
#include "../ccompat.h"
+#include "../mem.h"
#include "../tox.h"
#include "../tox_events.h"
-
/*****************************************************
*
* :: struct and accessors
*
*****************************************************/
-
struct Tox_Event_File_Recv_Chunk {
uint32_t friend_number;
uint32_t file_number;
@@ -31,19 +31,6 @@ struct Tox_Event_File_Recv_Chunk {
};
non_null()
-static void tox_event_file_recv_chunk_construct(Tox_Event_File_Recv_Chunk *file_recv_chunk)
-{
- *file_recv_chunk = (Tox_Event_File_Recv_Chunk) {
- 0
- };
-}
-non_null()
-static void tox_event_file_recv_chunk_destruct(Tox_Event_File_Recv_Chunk *file_recv_chunk)
-{
- free(file_recv_chunk->data);
-}
-
-non_null()
static void tox_event_file_recv_chunk_set_friend_number(Tox_Event_File_Recv_Chunk *file_recv_chunk,
uint32_t friend_number)
{
@@ -82,9 +69,9 @@ uint64_t tox_event_file_recv_chunk_get_position(const Tox_Event_File_Recv_Chunk
return file_recv_chunk->position;
}
-non_null()
-static bool tox_event_file_recv_chunk_set_data(Tox_Event_File_Recv_Chunk *file_recv_chunk, const uint8_t *data,
- uint32_t data_length)
+non_null(1) nullable(2)
+static bool tox_event_file_recv_chunk_set_data(Tox_Event_File_Recv_Chunk *file_recv_chunk,
+ const uint8_t *data, uint32_t data_length)
{
assert(file_recv_chunk != nullptr);
@@ -94,17 +81,23 @@ static bool tox_event_file_recv_chunk_set_data(Tox_Event_File_Recv_Chunk *file_r
file_recv_chunk->data_length = 0;
}
- file_recv_chunk->data = (uint8_t *)malloc(data_length);
+ if (data == nullptr) {
+ assert(data_length == 0);
+ return true;
+ }
+
+ uint8_t *data_copy = (uint8_t *)malloc(data_length);
- if (file_recv_chunk->data == nullptr) {
+ if (data_copy == nullptr) {
return false;
}
- memcpy(file_recv_chunk->data, data, data_length);
+ memcpy(data_copy, data, data_length);
+ file_recv_chunk->data = data_copy;
file_recv_chunk->data_length = data_length;
return true;
}
-uint32_t tox_event_file_recv_chunk_get_length(const Tox_Event_File_Recv_Chunk *file_recv_chunk)
+uint32_t tox_event_file_recv_chunk_get_data_length(const Tox_Event_File_Recv_Chunk *file_recv_chunk)
{
assert(file_recv_chunk != nullptr);
return file_recv_chunk->data_length;
@@ -116,13 +109,22 @@ const uint8_t *tox_event_file_recv_chunk_get_data(const Tox_Event_File_Recv_Chun
}
non_null()
-static bool tox_event_file_recv_chunk_pack(
+static void tox_event_file_recv_chunk_construct(Tox_Event_File_Recv_Chunk *file_recv_chunk)
+{
+ *file_recv_chunk = (Tox_Event_File_Recv_Chunk) {
+ 0
+ };
+}
+non_null()
+static void tox_event_file_recv_chunk_destruct(Tox_Event_File_Recv_Chunk *file_recv_chunk, const Memory *mem)
+{
+ free(file_recv_chunk->data);
+}
+
+bool tox_event_file_recv_chunk_pack(
const Tox_Event_File_Recv_Chunk *event, Bin_Pack *bp)
{
- assert(event != nullptr);
- return bin_pack_array(bp, 2)
- && bin_pack_u32(bp, TOX_EVENT_FILE_RECV_CHUNK)
- && bin_pack_array(bp, 4)
+ return bin_pack_array(bp, 4)
&& bin_pack_u32(bp, event->friend_number)
&& bin_pack_u32(bp, event->file_number)
&& bin_pack_u64(bp, event->position)
@@ -130,11 +132,11 @@ static bool tox_event_file_recv_chunk_pack(
}
non_null()
-static bool tox_event_file_recv_chunk_unpack(
+static bool tox_event_file_recv_chunk_unpack_into(
Tox_Event_File_Recv_Chunk *event, Bin_Unpack *bu)
{
assert(event != nullptr);
- if (!bin_unpack_array_fixed(bu, 4)) {
+ if (!bin_unpack_array_fixed(bu, 4, nullptr)) {
return false;
}
@@ -144,95 +146,88 @@ static bool tox_event_file_recv_chunk_unpack(
&& bin_unpack_bin(bu, &event->data, &event->data_length);
}
-
/*****************************************************
*
- * :: add/clear/get
+ * :: new/free/add/get/size/unpack
*
*****************************************************/
-
-non_null()
-static Tox_Event_File_Recv_Chunk *tox_events_add_file_recv_chunk(Tox_Events *events)
+const Tox_Event_File_Recv_Chunk *tox_event_get_file_recv_chunk(const Tox_Event *event)
{
- if (events->file_recv_chunk_size == UINT32_MAX) {
- return nullptr;
- }
-
- if (events->file_recv_chunk_size == events->file_recv_chunk_capacity) {
- const uint32_t new_file_recv_chunk_capacity = events->file_recv_chunk_capacity * 2 + 1;
- Tox_Event_File_Recv_Chunk *new_file_recv_chunk = (Tox_Event_File_Recv_Chunk *)realloc(
- events->file_recv_chunk, new_file_recv_chunk_capacity * sizeof(Tox_Event_File_Recv_Chunk));
+ return event->type == TOX_EVENT_FILE_RECV_CHUNK ? event->data.file_recv_chunk : nullptr;
+}
- if (new_file_recv_chunk == nullptr) {
- return nullptr;
- }
+Tox_Event_File_Recv_Chunk *tox_event_file_recv_chunk_new(const Memory *mem)
+{
+ Tox_Event_File_Recv_Chunk *const file_recv_chunk =
+ (Tox_Event_File_Recv_Chunk *)mem_alloc(mem, sizeof(Tox_Event_File_Recv_Chunk));
- events->file_recv_chunk = new_file_recv_chunk;
- events->file_recv_chunk_capacity = new_file_recv_chunk_capacity;
+ if (file_recv_chunk == nullptr) {
+ return nullptr;
}
- Tox_Event_File_Recv_Chunk *const file_recv_chunk = &events->file_recv_chunk[events->file_recv_chunk_size];
tox_event_file_recv_chunk_construct(file_recv_chunk);
- ++events->file_recv_chunk_size;
return file_recv_chunk;
}
-void tox_events_clear_file_recv_chunk(Tox_Events *events)
+void tox_event_file_recv_chunk_free(Tox_Event_File_Recv_Chunk *file_recv_chunk, const Memory *mem)
{
- if (events == nullptr) {
- return;
- }
-
- for (uint32_t i = 0; i < events->file_recv_chunk_size; ++i) {
- tox_event_file_recv_chunk_destruct(&events->file_recv_chunk[i]);
+ if (file_recv_chunk != nullptr) {
+ tox_event_file_recv_chunk_destruct(file_recv_chunk, mem);
}
-
- free(events->file_recv_chunk);
- events->file_recv_chunk = nullptr;
- events->file_recv_chunk_size = 0;
- events->file_recv_chunk_capacity = 0;
+ mem_delete(mem, file_recv_chunk);
}
-uint32_t tox_events_get_file_recv_chunk_size(const Tox_Events *events)
+non_null()
+static Tox_Event_File_Recv_Chunk *tox_events_add_file_recv_chunk(Tox_Events *events, const Memory *mem)
{
- if (events == nullptr) {
- return 0;
+ Tox_Event_File_Recv_Chunk *const file_recv_chunk = tox_event_file_recv_chunk_new(mem);
+
+ if (file_recv_chunk == nullptr) {
+ return nullptr;
}
- return events->file_recv_chunk_size;
-}
+ Tox_Event event;
+ event.type = TOX_EVENT_FILE_RECV_CHUNK;
+ event.data.file_recv_chunk = file_recv_chunk;
-const Tox_Event_File_Recv_Chunk *tox_events_get_file_recv_chunk(const Tox_Events *events, uint32_t index)
-{
- assert(index < events->file_recv_chunk_size);
- assert(events->file_recv_chunk != nullptr);
- return &events->file_recv_chunk[index];
+ tox_events_add(events, &event);
+ return file_recv_chunk;
}
-bool tox_events_pack_file_recv_chunk(const Tox_Events *events, Bin_Pack *bp)
+bool tox_event_file_recv_chunk_unpack(
+ Tox_Event_File_Recv_Chunk **event, Bin_Unpack *bu, const Memory *mem)
{
- const uint32_t size = tox_events_get_file_recv_chunk_size(events);
+ assert(event != nullptr);
+ assert(*event == nullptr);
+ *event = tox_event_file_recv_chunk_new(mem);
- for (uint32_t i = 0; i < size; ++i) {
- if (!tox_event_file_recv_chunk_pack(tox_events_get_file_recv_chunk(events, i), bp)) {
- return false;
- }
+ if (*event == nullptr) {
+ return false;
}
- return true;
+
+ return tox_event_file_recv_chunk_unpack_into(*event, bu);
}
-bool tox_events_unpack_file_recv_chunk(Tox_Events *events, Bin_Unpack *bu)
+non_null()
+static Tox_Event_File_Recv_Chunk *tox_event_file_recv_chunk_alloc(void *user_data)
{
- Tox_Event_File_Recv_Chunk *event = tox_events_add_file_recv_chunk(events);
+ Tox_Events_State *state = tox_events_alloc(user_data);
+ assert(state != nullptr);
- if (event == nullptr) {
- return false;
+ if (state->events == nullptr) {
+ return nullptr;
}
- return tox_event_file_recv_chunk_unpack(event, bu);
-}
+ Tox_Event_File_Recv_Chunk *file_recv_chunk = tox_events_add_file_recv_chunk(state->events, state->mem);
+
+ if (file_recv_chunk == nullptr) {
+ state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
+ return nullptr;
+ }
+ return file_recv_chunk;
+}
/*****************************************************
*
@@ -240,21 +235,13 @@ bool tox_events_unpack_file_recv_chunk(Tox_Events *events, Bin_Unpack *bu)
*
*****************************************************/
-
-void tox_events_handle_file_recv_chunk(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position,
- const uint8_t *data, size_t length, void *user_data)
+void tox_events_handle_file_recv_chunk(
+ Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position, const uint8_t *data, size_t length,
+ void *user_data)
{
- Tox_Events_State *state = tox_events_alloc(user_data);
- assert(state != nullptr);
-
- if (state->events == nullptr) {
- return;
- }
-
- Tox_Event_File_Recv_Chunk *file_recv_chunk = tox_events_add_file_recv_chunk(state->events);
+ Tox_Event_File_Recv_Chunk *file_recv_chunk = tox_event_file_recv_chunk_alloc(user_data);
if (file_recv_chunk == nullptr) {
- state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
return;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/file_recv_control.c b/protocols/Tox/libtox/src/toxcore/events/file_recv_control.c
index af04b33dce..14a34aaf3b 100644
--- a/protocols/Tox/libtox/src/toxcore/events/file_recv_control.c
+++ b/protocols/Tox/libtox/src/toxcore/events/file_recv_control.c
@@ -1,28 +1,27 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2022 The TokTok team.
+ * Copyright © 2023-2024 The TokTok team.
*/
#include "events_alloc.h"
#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
+#include "../attributes.h"
#include "../bin_pack.h"
#include "../bin_unpack.h"
#include "../ccompat.h"
+#include "../mem.h"
#include "../tox.h"
#include "../tox_events.h"
+#include "../tox_pack.h"
#include "../tox_unpack.h"
-
/*****************************************************
*
* :: struct and accessors
*
*****************************************************/
-
struct Tox_Event_File_Recv_Control {
uint32_t friend_number;
uint32_t file_number;
@@ -30,19 +29,6 @@ struct Tox_Event_File_Recv_Control {
};
non_null()
-static void tox_event_file_recv_control_construct(Tox_Event_File_Recv_Control *file_recv_control)
-{
- *file_recv_control = (Tox_Event_File_Recv_Control) {
- 0
- };
-}
-non_null()
-static void tox_event_file_recv_control_destruct(Tox_Event_File_Recv_Control *file_recv_control)
-{
- return;
-}
-
-non_null()
static void tox_event_file_recv_control_set_friend_number(Tox_Event_File_Recv_Control *file_recv_control,
uint32_t friend_number)
{
@@ -82,121 +68,123 @@ Tox_File_Control tox_event_file_recv_control_get_control(const Tox_Event_File_Re
}
non_null()
-static bool tox_event_file_recv_control_pack(
+static void tox_event_file_recv_control_construct(Tox_Event_File_Recv_Control *file_recv_control)
+{
+ *file_recv_control = (Tox_Event_File_Recv_Control) {
+ 0
+ };
+}
+non_null()
+static void tox_event_file_recv_control_destruct(Tox_Event_File_Recv_Control *file_recv_control, const Memory *mem)
+{
+ return;
+}
+
+bool tox_event_file_recv_control_pack(
const Tox_Event_File_Recv_Control *event, Bin_Pack *bp)
{
- assert(event != nullptr);
- return bin_pack_array(bp, 2)
- && bin_pack_u32(bp, TOX_EVENT_FILE_RECV_CONTROL)
- && bin_pack_array(bp, 3)
+ return bin_pack_array(bp, 3)
&& bin_pack_u32(bp, event->friend_number)
&& bin_pack_u32(bp, event->file_number)
- && bin_pack_u32(bp, event->control);
+ && tox_file_control_pack(event->control, bp);
}
non_null()
-static bool tox_event_file_recv_control_unpack(
+static bool tox_event_file_recv_control_unpack_into(
Tox_Event_File_Recv_Control *event, Bin_Unpack *bu)
{
assert(event != nullptr);
- if (!bin_unpack_array_fixed(bu, 3)) {
+ if (!bin_unpack_array_fixed(bu, 3, nullptr)) {
return false;
}
return bin_unpack_u32(bu, &event->friend_number)
&& bin_unpack_u32(bu, &event->file_number)
- && tox_unpack_file_control(bu, &event->control);
+ && tox_file_control_unpack(&event->control, bu);
}
-
/*****************************************************
*
- * :: add/clear/get
+ * :: new/free/add/get/size/unpack
*
*****************************************************/
-
-non_null()
-static Tox_Event_File_Recv_Control *tox_events_add_file_recv_control(Tox_Events *events)
+const Tox_Event_File_Recv_Control *tox_event_get_file_recv_control(const Tox_Event *event)
{
- if (events->file_recv_control_size == UINT32_MAX) {
- return nullptr;
- }
-
- if (events->file_recv_control_size == events->file_recv_control_capacity) {
- const uint32_t new_file_recv_control_capacity = events->file_recv_control_capacity * 2 + 1;
- Tox_Event_File_Recv_Control *new_file_recv_control = (Tox_Event_File_Recv_Control *)realloc(
- events->file_recv_control, new_file_recv_control_capacity * sizeof(Tox_Event_File_Recv_Control));
+ return event->type == TOX_EVENT_FILE_RECV_CONTROL ? event->data.file_recv_control : nullptr;
+}
- if (new_file_recv_control == nullptr) {
- return nullptr;
- }
+Tox_Event_File_Recv_Control *tox_event_file_recv_control_new(const Memory *mem)
+{
+ Tox_Event_File_Recv_Control *const file_recv_control =
+ (Tox_Event_File_Recv_Control *)mem_alloc(mem, sizeof(Tox_Event_File_Recv_Control));
- events->file_recv_control = new_file_recv_control;
- events->file_recv_control_capacity = new_file_recv_control_capacity;
+ if (file_recv_control == nullptr) {
+ return nullptr;
}
- Tox_Event_File_Recv_Control *const file_recv_control = &events->file_recv_control[events->file_recv_control_size];
tox_event_file_recv_control_construct(file_recv_control);
- ++events->file_recv_control_size;
return file_recv_control;
}
-void tox_events_clear_file_recv_control(Tox_Events *events)
+void tox_event_file_recv_control_free(Tox_Event_File_Recv_Control *file_recv_control, const Memory *mem)
{
- if (events == nullptr) {
- return;
+ if (file_recv_control != nullptr) {
+ tox_event_file_recv_control_destruct(file_recv_control, mem);
}
-
- for (uint32_t i = 0; i < events->file_recv_control_size; ++i) {
- tox_event_file_recv_control_destruct(&events->file_recv_control[i]);
- }
-
- free(events->file_recv_control);
- events->file_recv_control = nullptr;
- events->file_recv_control_size = 0;
- events->file_recv_control_capacity = 0;
+ mem_delete(mem, file_recv_control);
}
-uint32_t tox_events_get_file_recv_control_size(const Tox_Events *events)
+non_null()
+static Tox_Event_File_Recv_Control *tox_events_add_file_recv_control(Tox_Events *events, const Memory *mem)
{
- if (events == nullptr) {
- return 0;
+ Tox_Event_File_Recv_Control *const file_recv_control = tox_event_file_recv_control_new(mem);
+
+ if (file_recv_control == nullptr) {
+ return nullptr;
}
- return events->file_recv_control_size;
-}
+ Tox_Event event;
+ event.type = TOX_EVENT_FILE_RECV_CONTROL;
+ event.data.file_recv_control = file_recv_control;
-const Tox_Event_File_Recv_Control *tox_events_get_file_recv_control(const Tox_Events *events, uint32_t index)
-{
- assert(index < events->file_recv_control_size);
- assert(events->file_recv_control != nullptr);
- return &events->file_recv_control[index];
+ tox_events_add(events, &event);
+ return file_recv_control;
}
-bool tox_events_pack_file_recv_control(const Tox_Events *events, Bin_Pack *bp)
+bool tox_event_file_recv_control_unpack(
+ Tox_Event_File_Recv_Control **event, Bin_Unpack *bu, const Memory *mem)
{
- const uint32_t size = tox_events_get_file_recv_control_size(events);
+ assert(event != nullptr);
+ assert(*event == nullptr);
+ *event = tox_event_file_recv_control_new(mem);
- for (uint32_t i = 0; i < size; ++i) {
- if (!tox_event_file_recv_control_pack(tox_events_get_file_recv_control(events, i), bp)) {
- return false;
- }
+ if (*event == nullptr) {
+ return false;
}
- return true;
+
+ return tox_event_file_recv_control_unpack_into(*event, bu);
}
-bool tox_events_unpack_file_recv_control(Tox_Events *events, Bin_Unpack *bu)
+non_null()
+static Tox_Event_File_Recv_Control *tox_event_file_recv_control_alloc(void *user_data)
{
- Tox_Event_File_Recv_Control *event = tox_events_add_file_recv_control(events);
+ Tox_Events_State *state = tox_events_alloc(user_data);
+ assert(state != nullptr);
- if (event == nullptr) {
- return false;
+ if (state->events == nullptr) {
+ return nullptr;
}
- return tox_event_file_recv_control_unpack(event, bu);
-}
+ Tox_Event_File_Recv_Control *file_recv_control = tox_events_add_file_recv_control(state->events, state->mem);
+ if (file_recv_control == nullptr) {
+ state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
+ return nullptr;
+ }
+
+ return file_recv_control;
+}
/*****************************************************
*
@@ -204,21 +192,13 @@ bool tox_events_unpack_file_recv_control(Tox_Events *events, Bin_Unpack *bu)
*
*****************************************************/
-
-void tox_events_handle_file_recv_control(Tox *tox, uint32_t friend_number, uint32_t file_number,
- Tox_File_Control control, void *user_data)
+void tox_events_handle_file_recv_control(
+ Tox *tox, uint32_t friend_number, uint32_t file_number, Tox_File_Control control,
+ void *user_data)
{
- Tox_Events_State *state = tox_events_alloc(user_data);
- assert(state != nullptr);
-
- if (state->events == nullptr) {
- return;
- }
-
- Tox_Event_File_Recv_Control *file_recv_control = tox_events_add_file_recv_control(state->events);
+ Tox_Event_File_Recv_Control *file_recv_control = tox_event_file_recv_control_alloc(user_data);
if (file_recv_control == nullptr) {
- state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
return;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/friend_connection_status.c b/protocols/Tox/libtox/src/toxcore/events/friend_connection_status.c
index 3d325ef29f..330554b05e 100644
--- a/protocols/Tox/libtox/src/toxcore/events/friend_connection_status.c
+++ b/protocols/Tox/libtox/src/toxcore/events/friend_connection_status.c
@@ -1,190 +1,174 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2022 The TokTok team.
+ * Copyright © 2023-2024 The TokTok team.
*/
#include "events_alloc.h"
#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
+#include "../attributes.h"
#include "../bin_pack.h"
#include "../bin_unpack.h"
#include "../ccompat.h"
+#include "../mem.h"
#include "../tox.h"
#include "../tox_events.h"
+#include "../tox_pack.h"
#include "../tox_unpack.h"
-
/*****************************************************
*
* :: struct and accessors
*
*****************************************************/
-
struct Tox_Event_Friend_Connection_Status {
uint32_t friend_number;
Tox_Connection connection_status;
};
non_null()
-static void tox_event_friend_connection_status_construct(Tox_Event_Friend_Connection_Status *friend_connection_status)
-{
- *friend_connection_status = (Tox_Event_Friend_Connection_Status) {
- 0
- };
-}
-non_null()
-static void tox_event_friend_connection_status_destruct(Tox_Event_Friend_Connection_Status *friend_connection_status)
-{
- return;
-}
-
-non_null()
-static void tox_event_friend_connection_status_set_friend_number(Tox_Event_Friend_Connection_Status
- *friend_connection_status, uint32_t friend_number)
+static void tox_event_friend_connection_status_set_friend_number(Tox_Event_Friend_Connection_Status *friend_connection_status,
+ uint32_t friend_number)
{
assert(friend_connection_status != nullptr);
friend_connection_status->friend_number = friend_number;
}
-uint32_t tox_event_friend_connection_status_get_friend_number(const Tox_Event_Friend_Connection_Status
- *friend_connection_status)
+uint32_t tox_event_friend_connection_status_get_friend_number(const Tox_Event_Friend_Connection_Status *friend_connection_status)
{
assert(friend_connection_status != nullptr);
return friend_connection_status->friend_number;
}
non_null()
-static void tox_event_friend_connection_status_set_connection_status(Tox_Event_Friend_Connection_Status
- *friend_connection_status, Tox_Connection connection_status)
+static void tox_event_friend_connection_status_set_connection_status(Tox_Event_Friend_Connection_Status *friend_connection_status,
+ Tox_Connection connection_status)
{
assert(friend_connection_status != nullptr);
friend_connection_status->connection_status = connection_status;
}
-Tox_Connection tox_event_friend_connection_status_get_connection_status(const Tox_Event_Friend_Connection_Status
- *friend_connection_status)
+Tox_Connection tox_event_friend_connection_status_get_connection_status(const Tox_Event_Friend_Connection_Status *friend_connection_status)
{
assert(friend_connection_status != nullptr);
return friend_connection_status->connection_status;
}
non_null()
-static bool tox_event_friend_connection_status_pack(
+static void tox_event_friend_connection_status_construct(Tox_Event_Friend_Connection_Status *friend_connection_status)
+{
+ *friend_connection_status = (Tox_Event_Friend_Connection_Status) {
+ 0
+ };
+}
+non_null()
+static void tox_event_friend_connection_status_destruct(Tox_Event_Friend_Connection_Status *friend_connection_status, const Memory *mem)
+{
+ return;
+}
+
+bool tox_event_friend_connection_status_pack(
const Tox_Event_Friend_Connection_Status *event, Bin_Pack *bp)
{
- assert(event != nullptr);
return bin_pack_array(bp, 2)
- && bin_pack_u32(bp, TOX_EVENT_FRIEND_CONNECTION_STATUS)
- && bin_pack_array(bp, 2)
&& bin_pack_u32(bp, event->friend_number)
- && bin_pack_u32(bp, event->connection_status);
+ && tox_connection_pack(event->connection_status, bp);
}
non_null()
-static bool tox_event_friend_connection_status_unpack(
+static bool tox_event_friend_connection_status_unpack_into(
Tox_Event_Friend_Connection_Status *event, Bin_Unpack *bu)
{
assert(event != nullptr);
- if (!bin_unpack_array_fixed(bu, 2)) {
+ if (!bin_unpack_array_fixed(bu, 2, nullptr)) {
return false;
}
return bin_unpack_u32(bu, &event->friend_number)
- && tox_unpack_connection(bu, &event->connection_status);
+ && tox_connection_unpack(&event->connection_status, bu);
}
-
/*****************************************************
*
- * :: add/clear/get
+ * :: new/free/add/get/size/unpack
*
*****************************************************/
-
-non_null()
-static Tox_Event_Friend_Connection_Status *tox_events_add_friend_connection_status(Tox_Events *events)
+const Tox_Event_Friend_Connection_Status *tox_event_get_friend_connection_status(const Tox_Event *event)
{
- if (events->friend_connection_status_size == UINT32_MAX) {
- return nullptr;
- }
-
- if (events->friend_connection_status_size == events->friend_connection_status_capacity) {
- const uint32_t new_friend_connection_status_capacity = events->friend_connection_status_capacity * 2 + 1;
- Tox_Event_Friend_Connection_Status *new_friend_connection_status = (Tox_Event_Friend_Connection_Status *)realloc(
- events->friend_connection_status, new_friend_connection_status_capacity * sizeof(Tox_Event_Friend_Connection_Status));
+ return event->type == TOX_EVENT_FRIEND_CONNECTION_STATUS ? event->data.friend_connection_status : nullptr;
+}
- if (new_friend_connection_status == nullptr) {
- return nullptr;
- }
+Tox_Event_Friend_Connection_Status *tox_event_friend_connection_status_new(const Memory *mem)
+{
+ Tox_Event_Friend_Connection_Status *const friend_connection_status =
+ (Tox_Event_Friend_Connection_Status *)mem_alloc(mem, sizeof(Tox_Event_Friend_Connection_Status));
- events->friend_connection_status = new_friend_connection_status;
- events->friend_connection_status_capacity = new_friend_connection_status_capacity;
+ if (friend_connection_status == nullptr) {
+ return nullptr;
}
- Tox_Event_Friend_Connection_Status *const friend_connection_status =
- &events->friend_connection_status[events->friend_connection_status_size];
tox_event_friend_connection_status_construct(friend_connection_status);
- ++events->friend_connection_status_size;
return friend_connection_status;
}
-void tox_events_clear_friend_connection_status(Tox_Events *events)
+void tox_event_friend_connection_status_free(Tox_Event_Friend_Connection_Status *friend_connection_status, const Memory *mem)
{
- if (events == nullptr) {
- return;
- }
-
- for (uint32_t i = 0; i < events->friend_connection_status_size; ++i) {
- tox_event_friend_connection_status_destruct(&events->friend_connection_status[i]);
+ if (friend_connection_status != nullptr) {
+ tox_event_friend_connection_status_destruct(friend_connection_status, mem);
}
-
- free(events->friend_connection_status);
- events->friend_connection_status = nullptr;
- events->friend_connection_status_size = 0;
- events->friend_connection_status_capacity = 0;
+ mem_delete(mem, friend_connection_status);
}
-uint32_t tox_events_get_friend_connection_status_size(const Tox_Events *events)
+non_null()
+static Tox_Event_Friend_Connection_Status *tox_events_add_friend_connection_status(Tox_Events *events, const Memory *mem)
{
- if (events == nullptr) {
- return 0;
+ Tox_Event_Friend_Connection_Status *const friend_connection_status = tox_event_friend_connection_status_new(mem);
+
+ if (friend_connection_status == nullptr) {
+ return nullptr;
}
- return events->friend_connection_status_size;
-}
+ Tox_Event event;
+ event.type = TOX_EVENT_FRIEND_CONNECTION_STATUS;
+ event.data.friend_connection_status = friend_connection_status;
-const Tox_Event_Friend_Connection_Status *tox_events_get_friend_connection_status(const Tox_Events *events,
- uint32_t index)
-{
- assert(index < events->friend_connection_status_size);
- assert(events->friend_connection_status != nullptr);
- return &events->friend_connection_status[index];
+ tox_events_add(events, &event);
+ return friend_connection_status;
}
-bool tox_events_pack_friend_connection_status(const Tox_Events *events, Bin_Pack *bp)
+bool tox_event_friend_connection_status_unpack(
+ Tox_Event_Friend_Connection_Status **event, Bin_Unpack *bu, const Memory *mem)
{
- const uint32_t size = tox_events_get_friend_connection_status_size(events);
+ assert(event != nullptr);
+ assert(*event == nullptr);
+ *event = tox_event_friend_connection_status_new(mem);
- for (uint32_t i = 0; i < size; ++i) {
- if (!tox_event_friend_connection_status_pack(tox_events_get_friend_connection_status(events, i), bp)) {
- return false;
- }
+ if (*event == nullptr) {
+ return false;
}
- return true;
+
+ return tox_event_friend_connection_status_unpack_into(*event, bu);
}
-bool tox_events_unpack_friend_connection_status(Tox_Events *events, Bin_Unpack *bu)
+non_null()
+static Tox_Event_Friend_Connection_Status *tox_event_friend_connection_status_alloc(void *user_data)
{
- Tox_Event_Friend_Connection_Status *event = tox_events_add_friend_connection_status(events);
+ Tox_Events_State *state = tox_events_alloc(user_data);
+ assert(state != nullptr);
- if (event == nullptr) {
- return false;
+ if (state->events == nullptr) {
+ return nullptr;
}
- return tox_event_friend_connection_status_unpack(event, bu);
-}
+ Tox_Event_Friend_Connection_Status *friend_connection_status = tox_events_add_friend_connection_status(state->events, state->mem);
+ if (friend_connection_status == nullptr) {
+ state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
+ return nullptr;
+ }
+
+ return friend_connection_status;
+}
/*****************************************************
*
@@ -192,21 +176,13 @@ bool tox_events_unpack_friend_connection_status(Tox_Events *events, Bin_Unpack *
*
*****************************************************/
-
-void tox_events_handle_friend_connection_status(Tox *tox, uint32_t friend_number, Tox_Connection connection_status,
- void *user_data)
+void tox_events_handle_friend_connection_status(
+ Tox *tox, uint32_t friend_number, Tox_Connection connection_status,
+ void *user_data)
{
- Tox_Events_State *state = tox_events_alloc(user_data);
- assert(state != nullptr);
-
- if (state->events == nullptr) {
- return;
- }
-
- Tox_Event_Friend_Connection_Status *friend_connection_status = tox_events_add_friend_connection_status(state->events);
+ Tox_Event_Friend_Connection_Status *friend_connection_status = tox_event_friend_connection_status_alloc(user_data);
if (friend_connection_status == nullptr) {
- state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
return;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/friend_lossless_packet.c b/protocols/Tox/libtox/src/toxcore/events/friend_lossless_packet.c
index 944abd46c7..17e8fad926 100644
--- a/protocols/Tox/libtox/src/toxcore/events/friend_lossless_packet.c
+++ b/protocols/Tox/libtox/src/toxcore/events/friend_lossless_packet.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2022 The TokTok team.
+ * Copyright © 2023-2024 The TokTok team.
*/
#include "events_alloc.h"
@@ -8,20 +8,20 @@
#include <stdlib.h>
#include <string.h>
+#include "../attributes.h"
#include "../bin_pack.h"
#include "../bin_unpack.h"
#include "../ccompat.h"
+#include "../mem.h"
#include "../tox.h"
#include "../tox_events.h"
-
/*****************************************************
*
* :: struct and accessors
*
*****************************************************/
-
struct Tox_Event_Friend_Lossless_Packet {
uint32_t friend_number;
uint8_t *data;
@@ -29,33 +29,19 @@ struct Tox_Event_Friend_Lossless_Packet {
};
non_null()
-static void tox_event_friend_lossless_packet_construct(Tox_Event_Friend_Lossless_Packet *friend_lossless_packet)
-{
- *friend_lossless_packet = (Tox_Event_Friend_Lossless_Packet) {
- 0
- };
-}
-non_null()
-static void tox_event_friend_lossless_packet_destruct(Tox_Event_Friend_Lossless_Packet *friend_lossless_packet)
-{
- free(friend_lossless_packet->data);
-}
-
-non_null()
static void tox_event_friend_lossless_packet_set_friend_number(Tox_Event_Friend_Lossless_Packet *friend_lossless_packet,
uint32_t friend_number)
{
assert(friend_lossless_packet != nullptr);
friend_lossless_packet->friend_number = friend_number;
}
-uint32_t tox_event_friend_lossless_packet_get_friend_number(const Tox_Event_Friend_Lossless_Packet
- *friend_lossless_packet)
+uint32_t tox_event_friend_lossless_packet_get_friend_number(const Tox_Event_Friend_Lossless_Packet *friend_lossless_packet)
{
assert(friend_lossless_packet != nullptr);
return friend_lossless_packet->friend_number;
}
-non_null()
+non_null(1) nullable(2)
static bool tox_event_friend_lossless_packet_set_data(Tox_Event_Friend_Lossless_Packet *friend_lossless_packet,
const uint8_t *data, uint32_t data_length)
{
@@ -67,13 +53,19 @@ static bool tox_event_friend_lossless_packet_set_data(Tox_Event_Friend_Lossless_
friend_lossless_packet->data_length = 0;
}
- friend_lossless_packet->data = (uint8_t *)malloc(data_length);
+ if (data == nullptr) {
+ assert(data_length == 0);
+ return true;
+ }
+
+ uint8_t *data_copy = (uint8_t *)malloc(data_length);
- if (friend_lossless_packet->data == nullptr) {
+ if (data_copy == nullptr) {
return false;
}
- memcpy(friend_lossless_packet->data, data, data_length);
+ memcpy(data_copy, data, data_length);
+ friend_lossless_packet->data = data_copy;
friend_lossless_packet->data_length = data_length;
return true;
}
@@ -89,23 +81,32 @@ const uint8_t *tox_event_friend_lossless_packet_get_data(const Tox_Event_Friend_
}
non_null()
-static bool tox_event_friend_lossless_packet_pack(
+static void tox_event_friend_lossless_packet_construct(Tox_Event_Friend_Lossless_Packet *friend_lossless_packet)
+{
+ *friend_lossless_packet = (Tox_Event_Friend_Lossless_Packet) {
+ 0
+ };
+}
+non_null()
+static void tox_event_friend_lossless_packet_destruct(Tox_Event_Friend_Lossless_Packet *friend_lossless_packet, const Memory *mem)
+{
+ free(friend_lossless_packet->data);
+}
+
+bool tox_event_friend_lossless_packet_pack(
const Tox_Event_Friend_Lossless_Packet *event, Bin_Pack *bp)
{
- assert(event != nullptr);
return bin_pack_array(bp, 2)
- && bin_pack_u32(bp, TOX_EVENT_FRIEND_LOSSLESS_PACKET)
- && bin_pack_array(bp, 2)
&& bin_pack_u32(bp, event->friend_number)
&& bin_pack_bin(bp, event->data, event->data_length);
}
non_null()
-static bool tox_event_friend_lossless_packet_unpack(
+static bool tox_event_friend_lossless_packet_unpack_into(
Tox_Event_Friend_Lossless_Packet *event, Bin_Unpack *bu)
{
assert(event != nullptr);
- if (!bin_unpack_array_fixed(bu, 2)) {
+ if (!bin_unpack_array_fixed(bu, 2, nullptr)) {
return false;
}
@@ -113,96 +114,88 @@ static bool tox_event_friend_lossless_packet_unpack(
&& bin_unpack_bin(bu, &event->data, &event->data_length);
}
-
/*****************************************************
*
- * :: add/clear/get
+ * :: new/free/add/get/size/unpack
*
*****************************************************/
-
-non_null()
-static Tox_Event_Friend_Lossless_Packet *tox_events_add_friend_lossless_packet(Tox_Events *events)
+const Tox_Event_Friend_Lossless_Packet *tox_event_get_friend_lossless_packet(const Tox_Event *event)
{
- if (events->friend_lossless_packet_size == UINT32_MAX) {
- return nullptr;
- }
-
- if (events->friend_lossless_packet_size == events->friend_lossless_packet_capacity) {
- const uint32_t new_friend_lossless_packet_capacity = events->friend_lossless_packet_capacity * 2 + 1;
- Tox_Event_Friend_Lossless_Packet *new_friend_lossless_packet = (Tox_Event_Friend_Lossless_Packet *)realloc(
- events->friend_lossless_packet, new_friend_lossless_packet_capacity * sizeof(Tox_Event_Friend_Lossless_Packet));
+ return event->type == TOX_EVENT_FRIEND_LOSSLESS_PACKET ? event->data.friend_lossless_packet : nullptr;
+}
- if (new_friend_lossless_packet == nullptr) {
- return nullptr;
- }
+Tox_Event_Friend_Lossless_Packet *tox_event_friend_lossless_packet_new(const Memory *mem)
+{
+ Tox_Event_Friend_Lossless_Packet *const friend_lossless_packet =
+ (Tox_Event_Friend_Lossless_Packet *)mem_alloc(mem, sizeof(Tox_Event_Friend_Lossless_Packet));
- events->friend_lossless_packet = new_friend_lossless_packet;
- events->friend_lossless_packet_capacity = new_friend_lossless_packet_capacity;
+ if (friend_lossless_packet == nullptr) {
+ return nullptr;
}
- Tox_Event_Friend_Lossless_Packet *const friend_lossless_packet =
- &events->friend_lossless_packet[events->friend_lossless_packet_size];
tox_event_friend_lossless_packet_construct(friend_lossless_packet);
- ++events->friend_lossless_packet_size;
return friend_lossless_packet;
}
-void tox_events_clear_friend_lossless_packet(Tox_Events *events)
+void tox_event_friend_lossless_packet_free(Tox_Event_Friend_Lossless_Packet *friend_lossless_packet, const Memory *mem)
{
- if (events == nullptr) {
- return;
+ if (friend_lossless_packet != nullptr) {
+ tox_event_friend_lossless_packet_destruct(friend_lossless_packet, mem);
}
-
- for (uint32_t i = 0; i < events->friend_lossless_packet_size; ++i) {
- tox_event_friend_lossless_packet_destruct(&events->friend_lossless_packet[i]);
- }
-
- free(events->friend_lossless_packet);
- events->friend_lossless_packet = nullptr;
- events->friend_lossless_packet_size = 0;
- events->friend_lossless_packet_capacity = 0;
+ mem_delete(mem, friend_lossless_packet);
}
-uint32_t tox_events_get_friend_lossless_packet_size(const Tox_Events *events)
+non_null()
+static Tox_Event_Friend_Lossless_Packet *tox_events_add_friend_lossless_packet(Tox_Events *events, const Memory *mem)
{
- if (events == nullptr) {
- return 0;
+ Tox_Event_Friend_Lossless_Packet *const friend_lossless_packet = tox_event_friend_lossless_packet_new(mem);
+
+ if (friend_lossless_packet == nullptr) {
+ return nullptr;
}
- return events->friend_lossless_packet_size;
-}
+ Tox_Event event;
+ event.type = TOX_EVENT_FRIEND_LOSSLESS_PACKET;
+ event.data.friend_lossless_packet = friend_lossless_packet;
-const Tox_Event_Friend_Lossless_Packet *tox_events_get_friend_lossless_packet(const Tox_Events *events, uint32_t index)
-{
- assert(index < events->friend_lossless_packet_size);
- assert(events->friend_lossless_packet != nullptr);
- return &events->friend_lossless_packet[index];
+ tox_events_add(events, &event);
+ return friend_lossless_packet;
}
-bool tox_events_pack_friend_lossless_packet(const Tox_Events *events, Bin_Pack *bp)
+bool tox_event_friend_lossless_packet_unpack(
+ Tox_Event_Friend_Lossless_Packet **event, Bin_Unpack *bu, const Memory *mem)
{
- const uint32_t size = tox_events_get_friend_lossless_packet_size(events);
+ assert(event != nullptr);
+ assert(*event == nullptr);
+ *event = tox_event_friend_lossless_packet_new(mem);
- for (uint32_t i = 0; i < size; ++i) {
- if (!tox_event_friend_lossless_packet_pack(tox_events_get_friend_lossless_packet(events, i), bp)) {
- return false;
- }
+ if (*event == nullptr) {
+ return false;
}
- return true;
+
+ return tox_event_friend_lossless_packet_unpack_into(*event, bu);
}
-bool tox_events_unpack_friend_lossless_packet(Tox_Events *events, Bin_Unpack *bu)
+non_null()
+static Tox_Event_Friend_Lossless_Packet *tox_event_friend_lossless_packet_alloc(void *user_data)
{
- Tox_Event_Friend_Lossless_Packet *event = tox_events_add_friend_lossless_packet(events);
+ Tox_Events_State *state = tox_events_alloc(user_data);
+ assert(state != nullptr);
- if (event == nullptr) {
- return false;
+ if (state->events == nullptr) {
+ return nullptr;
}
- return tox_event_friend_lossless_packet_unpack(event, bu);
-}
+ Tox_Event_Friend_Lossless_Packet *friend_lossless_packet = tox_events_add_friend_lossless_packet(state->events, state->mem);
+
+ if (friend_lossless_packet == nullptr) {
+ state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
+ return nullptr;
+ }
+ return friend_lossless_packet;
+}
/*****************************************************
*
@@ -210,21 +203,13 @@ bool tox_events_unpack_friend_lossless_packet(Tox_Events *events, Bin_Unpack *bu
*
*****************************************************/
-
-void tox_events_handle_friend_lossless_packet(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length,
- void *user_data)
+void tox_events_handle_friend_lossless_packet(
+ Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length,
+ void *user_data)
{
- Tox_Events_State *state = tox_events_alloc(user_data);
- assert(state != nullptr);
-
- if (state->events == nullptr) {
- return;
- }
-
- Tox_Event_Friend_Lossless_Packet *friend_lossless_packet = tox_events_add_friend_lossless_packet(state->events);
+ Tox_Event_Friend_Lossless_Packet *friend_lossless_packet = tox_event_friend_lossless_packet_alloc(user_data);
if (friend_lossless_packet == nullptr) {
- state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
return;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/friend_lossy_packet.c b/protocols/Tox/libtox/src/toxcore/events/friend_lossy_packet.c
index a787fce0cf..6b2e9ed2b0 100644
--- a/protocols/Tox/libtox/src/toxcore/events/friend_lossy_packet.c
+++ b/protocols/Tox/libtox/src/toxcore/events/friend_lossy_packet.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2022 The TokTok team.
+ * Copyright © 2023-2024 The TokTok team.
*/
#include "events_alloc.h"
@@ -8,20 +8,20 @@
#include <stdlib.h>
#include <string.h>
+#include "../attributes.h"
#include "../bin_pack.h"
#include "../bin_unpack.h"
#include "../ccompat.h"
+#include "../mem.h"
#include "../tox.h"
#include "../tox_events.h"
-
/*****************************************************
*
* :: struct and accessors
*
*****************************************************/
-
struct Tox_Event_Friend_Lossy_Packet {
uint32_t friend_number;
uint8_t *data;
@@ -29,19 +29,6 @@ struct Tox_Event_Friend_Lossy_Packet {
};
non_null()
-static void tox_event_friend_lossy_packet_construct(Tox_Event_Friend_Lossy_Packet *friend_lossy_packet)
-{
- *friend_lossy_packet = (Tox_Event_Friend_Lossy_Packet) {
- 0
- };
-}
-non_null()
-static void tox_event_friend_lossy_packet_destruct(Tox_Event_Friend_Lossy_Packet *friend_lossy_packet)
-{
- free(friend_lossy_packet->data);
-}
-
-non_null()
static void tox_event_friend_lossy_packet_set_friend_number(Tox_Event_Friend_Lossy_Packet *friend_lossy_packet,
uint32_t friend_number)
{
@@ -54,7 +41,7 @@ uint32_t tox_event_friend_lossy_packet_get_friend_number(const Tox_Event_Friend_
return friend_lossy_packet->friend_number;
}
-non_null()
+non_null(1) nullable(2)
static bool tox_event_friend_lossy_packet_set_data(Tox_Event_Friend_Lossy_Packet *friend_lossy_packet,
const uint8_t *data, uint32_t data_length)
{
@@ -66,13 +53,19 @@ static bool tox_event_friend_lossy_packet_set_data(Tox_Event_Friend_Lossy_Packet
friend_lossy_packet->data_length = 0;
}
- friend_lossy_packet->data = (uint8_t *)malloc(data_length);
+ if (data == nullptr) {
+ assert(data_length == 0);
+ return true;
+ }
+
+ uint8_t *data_copy = (uint8_t *)malloc(data_length);
- if (friend_lossy_packet->data == nullptr) {
+ if (data_copy == nullptr) {
return false;
}
- memcpy(friend_lossy_packet->data, data, data_length);
+ memcpy(data_copy, data, data_length);
+ friend_lossy_packet->data = data_copy;
friend_lossy_packet->data_length = data_length;
return true;
}
@@ -88,23 +81,32 @@ const uint8_t *tox_event_friend_lossy_packet_get_data(const Tox_Event_Friend_Los
}
non_null()
-static bool tox_event_friend_lossy_packet_pack(
+static void tox_event_friend_lossy_packet_construct(Tox_Event_Friend_Lossy_Packet *friend_lossy_packet)
+{
+ *friend_lossy_packet = (Tox_Event_Friend_Lossy_Packet) {
+ 0
+ };
+}
+non_null()
+static void tox_event_friend_lossy_packet_destruct(Tox_Event_Friend_Lossy_Packet *friend_lossy_packet, const Memory *mem)
+{
+ free(friend_lossy_packet->data);
+}
+
+bool tox_event_friend_lossy_packet_pack(
const Tox_Event_Friend_Lossy_Packet *event, Bin_Pack *bp)
{
- assert(event != nullptr);
return bin_pack_array(bp, 2)
- && bin_pack_u32(bp, TOX_EVENT_FRIEND_LOSSY_PACKET)
- && bin_pack_array(bp, 2)
&& bin_pack_u32(bp, event->friend_number)
&& bin_pack_bin(bp, event->data, event->data_length);
}
non_null()
-static bool tox_event_friend_lossy_packet_unpack(
+static bool tox_event_friend_lossy_packet_unpack_into(
Tox_Event_Friend_Lossy_Packet *event, Bin_Unpack *bu)
{
assert(event != nullptr);
- if (!bin_unpack_array_fixed(bu, 2)) {
+ if (!bin_unpack_array_fixed(bu, 2, nullptr)) {
return false;
}
@@ -112,96 +114,88 @@ static bool tox_event_friend_lossy_packet_unpack(
&& bin_unpack_bin(bu, &event->data, &event->data_length);
}
-
/*****************************************************
*
- * :: add/clear/get
+ * :: new/free/add/get/size/unpack
*
*****************************************************/
-
-non_null()
-static Tox_Event_Friend_Lossy_Packet *tox_events_add_friend_lossy_packet(Tox_Events *events)
+const Tox_Event_Friend_Lossy_Packet *tox_event_get_friend_lossy_packet(const Tox_Event *event)
{
- if (events->friend_lossy_packet_size == UINT32_MAX) {
- return nullptr;
- }
-
- if (events->friend_lossy_packet_size == events->friend_lossy_packet_capacity) {
- const uint32_t new_friend_lossy_packet_capacity = events->friend_lossy_packet_capacity * 2 + 1;
- Tox_Event_Friend_Lossy_Packet *new_friend_lossy_packet = (Tox_Event_Friend_Lossy_Packet *)realloc(
- events->friend_lossy_packet, new_friend_lossy_packet_capacity * sizeof(Tox_Event_Friend_Lossy_Packet));
+ return event->type == TOX_EVENT_FRIEND_LOSSY_PACKET ? event->data.friend_lossy_packet : nullptr;
+}
- if (new_friend_lossy_packet == nullptr) {
- return nullptr;
- }
+Tox_Event_Friend_Lossy_Packet *tox_event_friend_lossy_packet_new(const Memory *mem)
+{
+ Tox_Event_Friend_Lossy_Packet *const friend_lossy_packet =
+ (Tox_Event_Friend_Lossy_Packet *)mem_alloc(mem, sizeof(Tox_Event_Friend_Lossy_Packet));
- events->friend_lossy_packet = new_friend_lossy_packet;
- events->friend_lossy_packet_capacity = new_friend_lossy_packet_capacity;
+ if (friend_lossy_packet == nullptr) {
+ return nullptr;
}
- Tox_Event_Friend_Lossy_Packet *const friend_lossy_packet =
- &events->friend_lossy_packet[events->friend_lossy_packet_size];
tox_event_friend_lossy_packet_construct(friend_lossy_packet);
- ++events->friend_lossy_packet_size;
return friend_lossy_packet;
}
-void tox_events_clear_friend_lossy_packet(Tox_Events *events)
+void tox_event_friend_lossy_packet_free(Tox_Event_Friend_Lossy_Packet *friend_lossy_packet, const Memory *mem)
{
- if (events == nullptr) {
- return;
+ if (friend_lossy_packet != nullptr) {
+ tox_event_friend_lossy_packet_destruct(friend_lossy_packet, mem);
}
-
- for (uint32_t i = 0; i < events->friend_lossy_packet_size; ++i) {
- tox_event_friend_lossy_packet_destruct(&events->friend_lossy_packet[i]);
- }
-
- free(events->friend_lossy_packet);
- events->friend_lossy_packet = nullptr;
- events->friend_lossy_packet_size = 0;
- events->friend_lossy_packet_capacity = 0;
+ mem_delete(mem, friend_lossy_packet);
}
-uint32_t tox_events_get_friend_lossy_packet_size(const Tox_Events *events)
+non_null()
+static Tox_Event_Friend_Lossy_Packet *tox_events_add_friend_lossy_packet(Tox_Events *events, const Memory *mem)
{
- if (events == nullptr) {
- return 0;
+ Tox_Event_Friend_Lossy_Packet *const friend_lossy_packet = tox_event_friend_lossy_packet_new(mem);
+
+ if (friend_lossy_packet == nullptr) {
+ return nullptr;
}
- return events->friend_lossy_packet_size;
-}
+ Tox_Event event;
+ event.type = TOX_EVENT_FRIEND_LOSSY_PACKET;
+ event.data.friend_lossy_packet = friend_lossy_packet;
-const Tox_Event_Friend_Lossy_Packet *tox_events_get_friend_lossy_packet(const Tox_Events *events, uint32_t index)
-{
- assert(index < events->friend_lossy_packet_size);
- assert(events->friend_lossy_packet != nullptr);
- return &events->friend_lossy_packet[index];
+ tox_events_add(events, &event);
+ return friend_lossy_packet;
}
-bool tox_events_pack_friend_lossy_packet(const Tox_Events *events, Bin_Pack *bp)
+bool tox_event_friend_lossy_packet_unpack(
+ Tox_Event_Friend_Lossy_Packet **event, Bin_Unpack *bu, const Memory *mem)
{
- const uint32_t size = tox_events_get_friend_lossy_packet_size(events);
+ assert(event != nullptr);
+ assert(*event == nullptr);
+ *event = tox_event_friend_lossy_packet_new(mem);
- for (uint32_t i = 0; i < size; ++i) {
- if (!tox_event_friend_lossy_packet_pack(tox_events_get_friend_lossy_packet(events, i), bp)) {
- return false;
- }
+ if (*event == nullptr) {
+ return false;
}
- return true;
+
+ return tox_event_friend_lossy_packet_unpack_into(*event, bu);
}
-bool tox_events_unpack_friend_lossy_packet(Tox_Events *events, Bin_Unpack *bu)
+non_null()
+static Tox_Event_Friend_Lossy_Packet *tox_event_friend_lossy_packet_alloc(void *user_data)
{
- Tox_Event_Friend_Lossy_Packet *event = tox_events_add_friend_lossy_packet(events);
+ Tox_Events_State *state = tox_events_alloc(user_data);
+ assert(state != nullptr);
- if (event == nullptr) {
- return false;
+ if (state->events == nullptr) {
+ return nullptr;
}
- return tox_event_friend_lossy_packet_unpack(event, bu);
-}
+ Tox_Event_Friend_Lossy_Packet *friend_lossy_packet = tox_events_add_friend_lossy_packet(state->events, state->mem);
+
+ if (friend_lossy_packet == nullptr) {
+ state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
+ return nullptr;
+ }
+ return friend_lossy_packet;
+}
/*****************************************************
*
@@ -209,21 +203,13 @@ bool tox_events_unpack_friend_lossy_packet(Tox_Events *events, Bin_Unpack *bu)
*
*****************************************************/
-
-void tox_events_handle_friend_lossy_packet(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length,
- void *user_data)
+void tox_events_handle_friend_lossy_packet(
+ Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length,
+ void *user_data)
{
- Tox_Events_State *state = tox_events_alloc(user_data);
- assert(state != nullptr);
-
- if (state->events == nullptr) {
- return;
- }
-
- Tox_Event_Friend_Lossy_Packet *friend_lossy_packet = tox_events_add_friend_lossy_packet(state->events);
+ Tox_Event_Friend_Lossy_Packet *friend_lossy_packet = tox_event_friend_lossy_packet_alloc(user_data);
if (friend_lossy_packet == nullptr) {
- state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
return;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/friend_message.c b/protocols/Tox/libtox/src/toxcore/events/friend_message.c
index 8fa6a19e34..befcc74a24 100644
--- a/protocols/Tox/libtox/src/toxcore/events/friend_message.c
+++ b/protocols/Tox/libtox/src/toxcore/events/friend_message.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2022 The TokTok team.
+ * Copyright © 2023-2024 The TokTok team.
*/
#include "events_alloc.h"
@@ -8,21 +8,22 @@
#include <stdlib.h>
#include <string.h>
+#include "../attributes.h"
#include "../bin_pack.h"
#include "../bin_unpack.h"
#include "../ccompat.h"
+#include "../mem.h"
#include "../tox.h"
#include "../tox_events.h"
+#include "../tox_pack.h"
#include "../tox_unpack.h"
-
/*****************************************************
*
* :: struct and accessors
*
*****************************************************/
-
struct Tox_Event_Friend_Message {
uint32_t friend_number;
Tox_Message_Type type;
@@ -31,19 +32,6 @@ struct Tox_Event_Friend_Message {
};
non_null()
-static void tox_event_friend_message_construct(Tox_Event_Friend_Message *friend_message)
-{
- *friend_message = (Tox_Event_Friend_Message) {
- 0
- };
-}
-non_null()
-static void tox_event_friend_message_destruct(Tox_Event_Friend_Message *friend_message)
-{
- free(friend_message->message);
-}
-
-non_null()
static void tox_event_friend_message_set_friend_number(Tox_Event_Friend_Message *friend_message,
uint32_t friend_number)
{
@@ -57,7 +45,8 @@ uint32_t tox_event_friend_message_get_friend_number(const Tox_Event_Friend_Messa
}
non_null()
-static void tox_event_friend_message_set_type(Tox_Event_Friend_Message *friend_message, Tox_Message_Type type)
+static void tox_event_friend_message_set_type(Tox_Event_Friend_Message *friend_message,
+ Tox_Message_Type type)
{
assert(friend_message != nullptr);
friend_message->type = type;
@@ -68,9 +57,9 @@ Tox_Message_Type tox_event_friend_message_get_type(const Tox_Event_Friend_Messag
return friend_message->type;
}
-non_null()
-static bool tox_event_friend_message_set_message(Tox_Event_Friend_Message *friend_message, const uint8_t *message,
- uint32_t message_length)
+non_null(1) nullable(2)
+static bool tox_event_friend_message_set_message(Tox_Event_Friend_Message *friend_message,
+ const uint8_t *message, uint32_t message_length)
{
assert(friend_message != nullptr);
@@ -80,13 +69,19 @@ static bool tox_event_friend_message_set_message(Tox_Event_Friend_Message *frien
friend_message->message_length = 0;
}
- friend_message->message = (uint8_t *)malloc(message_length);
+ if (message == nullptr) {
+ assert(message_length == 0);
+ return true;
+ }
+
+ uint8_t *message_copy = (uint8_t *)malloc(message_length);
- if (friend_message->message == nullptr) {
+ if (message_copy == nullptr) {
return false;
}
- memcpy(friend_message->message, message, message_length);
+ memcpy(message_copy, message, message_length);
+ friend_message->message = message_copy;
friend_message->message_length = message_length;
return true;
}
@@ -102,121 +97,123 @@ const uint8_t *tox_event_friend_message_get_message(const Tox_Event_Friend_Messa
}
non_null()
-static bool tox_event_friend_message_pack(
+static void tox_event_friend_message_construct(Tox_Event_Friend_Message *friend_message)
+{
+ *friend_message = (Tox_Event_Friend_Message) {
+ 0
+ };
+}
+non_null()
+static void tox_event_friend_message_destruct(Tox_Event_Friend_Message *friend_message, const Memory *mem)
+{
+ free(friend_message->message);
+}
+
+bool tox_event_friend_message_pack(
const Tox_Event_Friend_Message *event, Bin_Pack *bp)
{
- assert(event != nullptr);
- return bin_pack_array(bp, 2)
- && bin_pack_u32(bp, TOX_EVENT_FRIEND_MESSAGE)
- && bin_pack_array(bp, 3)
+ return bin_pack_array(bp, 3)
&& bin_pack_u32(bp, event->friend_number)
- && bin_pack_u32(bp, event->type)
+ && tox_message_type_pack(event->type, bp)
&& bin_pack_bin(bp, event->message, event->message_length);
}
non_null()
-static bool tox_event_friend_message_unpack(
+static bool tox_event_friend_message_unpack_into(
Tox_Event_Friend_Message *event, Bin_Unpack *bu)
{
assert(event != nullptr);
- if (!bin_unpack_array_fixed(bu, 3)) {
+ if (!bin_unpack_array_fixed(bu, 3, nullptr)) {
return false;
}
return bin_unpack_u32(bu, &event->friend_number)
- && tox_unpack_message_type(bu, &event->type)
+ && tox_message_type_unpack(&event->type, bu)
&& bin_unpack_bin(bu, &event->message, &event->message_length);
}
-
/*****************************************************
*
- * :: add/clear/get
+ * :: new/free/add/get/size/unpack
*
*****************************************************/
-
-non_null()
-static Tox_Event_Friend_Message *tox_events_add_friend_message(Tox_Events *events)
+const Tox_Event_Friend_Message *tox_event_get_friend_message(const Tox_Event *event)
{
- if (events->friend_message_size == UINT32_MAX) {
- return nullptr;
- }
-
- if (events->friend_message_size == events->friend_message_capacity) {
- const uint32_t new_friend_message_capacity = events->friend_message_capacity * 2 + 1;
- Tox_Event_Friend_Message *new_friend_message = (Tox_Event_Friend_Message *)realloc(
- events->friend_message, new_friend_message_capacity * sizeof(Tox_Event_Friend_Message));
+ return event->type == TOX_EVENT_FRIEND_MESSAGE ? event->data.friend_message : nullptr;
+}
- if (new_friend_message == nullptr) {
- return nullptr;
- }
+Tox_Event_Friend_Message *tox_event_friend_message_new(const Memory *mem)
+{
+ Tox_Event_Friend_Message *const friend_message =
+ (Tox_Event_Friend_Message *)mem_alloc(mem, sizeof(Tox_Event_Friend_Message));
- events->friend_message = new_friend_message;
- events->friend_message_capacity = new_friend_message_capacity;
+ if (friend_message == nullptr) {
+ return nullptr;
}
- Tox_Event_Friend_Message *const friend_message = &events->friend_message[events->friend_message_size];
tox_event_friend_message_construct(friend_message);
- ++events->friend_message_size;
return friend_message;
}
-void tox_events_clear_friend_message(Tox_Events *events)
+void tox_event_friend_message_free(Tox_Event_Friend_Message *friend_message, const Memory *mem)
{
- if (events == nullptr) {
- return;
- }
-
- for (uint32_t i = 0; i < events->friend_message_size; ++i) {
- tox_event_friend_message_destruct(&events->friend_message[i]);
+ if (friend_message != nullptr) {
+ tox_event_friend_message_destruct(friend_message, mem);
}
-
- free(events->friend_message);
- events->friend_message = nullptr;
- events->friend_message_size = 0;
- events->friend_message_capacity = 0;
+ mem_delete(mem, friend_message);
}
-uint32_t tox_events_get_friend_message_size(const Tox_Events *events)
+non_null()
+static Tox_Event_Friend_Message *tox_events_add_friend_message(Tox_Events *events, const Memory *mem)
{
- if (events == nullptr) {
- return 0;
+ Tox_Event_Friend_Message *const friend_message = tox_event_friend_message_new(mem);
+
+ if (friend_message == nullptr) {
+ return nullptr;
}
- return events->friend_message_size;
-}
+ Tox_Event event;
+ event.type = TOX_EVENT_FRIEND_MESSAGE;
+ event.data.friend_message = friend_message;
-const Tox_Event_Friend_Message *tox_events_get_friend_message(const Tox_Events *events, uint32_t index)
-{
- assert(index < events->friend_message_size);
- assert(events->friend_message != nullptr);
- return &events->friend_message[index];
+ tox_events_add(events, &event);
+ return friend_message;
}
-bool tox_events_pack_friend_message(const Tox_Events *events, Bin_Pack *bp)
+bool tox_event_friend_message_unpack(
+ Tox_Event_Friend_Message **event, Bin_Unpack *bu, const Memory *mem)
{
- const uint32_t size = tox_events_get_friend_message_size(events);
+ assert(event != nullptr);
+ assert(*event == nullptr);
+ *event = tox_event_friend_message_new(mem);
- for (uint32_t i = 0; i < size; ++i) {
- if (!tox_event_friend_message_pack(tox_events_get_friend_message(events, i), bp)) {
- return false;
- }
+ if (*event == nullptr) {
+ return false;
}
- return true;
+
+ return tox_event_friend_message_unpack_into(*event, bu);
}
-bool tox_events_unpack_friend_message(Tox_Events *events, Bin_Unpack *bu)
+non_null()
+static Tox_Event_Friend_Message *tox_event_friend_message_alloc(void *user_data)
{
- Tox_Event_Friend_Message *event = tox_events_add_friend_message(events);
+ Tox_Events_State *state = tox_events_alloc(user_data);
+ assert(state != nullptr);
- if (event == nullptr) {
- return false;
+ if (state->events == nullptr) {
+ return nullptr;
}
- return tox_event_friend_message_unpack(event, bu);
-}
+ Tox_Event_Friend_Message *friend_message = tox_events_add_friend_message(state->events, state->mem);
+
+ if (friend_message == nullptr) {
+ state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
+ return nullptr;
+ }
+ return friend_message;
+}
/*****************************************************
*
@@ -224,21 +221,13 @@ bool tox_events_unpack_friend_message(Tox_Events *events, Bin_Unpack *bu)
*
*****************************************************/
-
-void tox_events_handle_friend_message(Tox *tox, uint32_t friend_number, Tox_Message_Type type, const uint8_t *message,
- size_t length, void *user_data)
+void tox_events_handle_friend_message(
+ Tox *tox, uint32_t friend_number, Tox_Message_Type type, const uint8_t *message, size_t length,
+ void *user_data)
{
- Tox_Events_State *state = tox_events_alloc(user_data);
- assert(state != nullptr);
-
- if (state->events == nullptr) {
- return;
- }
-
- Tox_Event_Friend_Message *friend_message = tox_events_add_friend_message(state->events);
+ Tox_Event_Friend_Message *friend_message = tox_event_friend_message_alloc(user_data);
if (friend_message == nullptr) {
- state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
return;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/friend_name.c b/protocols/Tox/libtox/src/toxcore/events/friend_name.c
index 123918386a..dfa9b39608 100644
--- a/protocols/Tox/libtox/src/toxcore/events/friend_name.c
+++ b/protocols/Tox/libtox/src/toxcore/events/friend_name.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2022 The TokTok team.
+ * Copyright © 2023-2024 The TokTok team.
*/
#include "events_alloc.h"
@@ -8,20 +8,20 @@
#include <stdlib.h>
#include <string.h>
+#include "../attributes.h"
#include "../bin_pack.h"
#include "../bin_unpack.h"
#include "../ccompat.h"
+#include "../mem.h"
#include "../tox.h"
#include "../tox_events.h"
-
/*****************************************************
*
* :: struct and accessors
*
*****************************************************/
-
struct Tox_Event_Friend_Name {
uint32_t friend_number;
uint8_t *name;
@@ -29,19 +29,6 @@ struct Tox_Event_Friend_Name {
};
non_null()
-static void tox_event_friend_name_construct(Tox_Event_Friend_Name *friend_name)
-{
- *friend_name = (Tox_Event_Friend_Name) {
- 0
- };
-}
-non_null()
-static void tox_event_friend_name_destruct(Tox_Event_Friend_Name *friend_name)
-{
- free(friend_name->name);
-}
-
-non_null()
static void tox_event_friend_name_set_friend_number(Tox_Event_Friend_Name *friend_name,
uint32_t friend_number)
{
@@ -54,9 +41,9 @@ uint32_t tox_event_friend_name_get_friend_number(const Tox_Event_Friend_Name *fr
return friend_name->friend_number;
}
-non_null()
-static bool tox_event_friend_name_set_name(Tox_Event_Friend_Name *friend_name, const uint8_t *name,
- uint32_t name_length)
+non_null(1) nullable(2)
+static bool tox_event_friend_name_set_name(Tox_Event_Friend_Name *friend_name,
+ const uint8_t *name, uint32_t name_length)
{
assert(friend_name != nullptr);
@@ -66,13 +53,19 @@ static bool tox_event_friend_name_set_name(Tox_Event_Friend_Name *friend_name, c
friend_name->name_length = 0;
}
- friend_name->name = (uint8_t *)malloc(name_length);
+ if (name == nullptr) {
+ assert(name_length == 0);
+ return true;
+ }
+
+ uint8_t *name_copy = (uint8_t *)malloc(name_length);
- if (friend_name->name == nullptr) {
+ if (name_copy == nullptr) {
return false;
}
- memcpy(friend_name->name, name, name_length);
+ memcpy(name_copy, name, name_length);
+ friend_name->name = name_copy;
friend_name->name_length = name_length;
return true;
}
@@ -88,23 +81,32 @@ const uint8_t *tox_event_friend_name_get_name(const Tox_Event_Friend_Name *frien
}
non_null()
-static bool tox_event_friend_name_pack(
+static void tox_event_friend_name_construct(Tox_Event_Friend_Name *friend_name)
+{
+ *friend_name = (Tox_Event_Friend_Name) {
+ 0
+ };
+}
+non_null()
+static void tox_event_friend_name_destruct(Tox_Event_Friend_Name *friend_name, const Memory *mem)
+{
+ free(friend_name->name);
+}
+
+bool tox_event_friend_name_pack(
const Tox_Event_Friend_Name *event, Bin_Pack *bp)
{
- assert(event != nullptr);
return bin_pack_array(bp, 2)
- && bin_pack_u32(bp, TOX_EVENT_FRIEND_NAME)
- && bin_pack_array(bp, 2)
&& bin_pack_u32(bp, event->friend_number)
&& bin_pack_bin(bp, event->name, event->name_length);
}
non_null()
-static bool tox_event_friend_name_unpack(
+static bool tox_event_friend_name_unpack_into(
Tox_Event_Friend_Name *event, Bin_Unpack *bu)
{
assert(event != nullptr);
- if (!bin_unpack_array_fixed(bu, 2)) {
+ if (!bin_unpack_array_fixed(bu, 2, nullptr)) {
return false;
}
@@ -112,95 +114,88 @@ static bool tox_event_friend_name_unpack(
&& bin_unpack_bin(bu, &event->name, &event->name_length);
}
-
/*****************************************************
*
- * :: add/clear/get
+ * :: new/free/add/get/size/unpack
*
*****************************************************/
-
-non_null()
-static Tox_Event_Friend_Name *tox_events_add_friend_name(Tox_Events *events)
+const Tox_Event_Friend_Name *tox_event_get_friend_name(const Tox_Event *event)
{
- if (events->friend_name_size == UINT32_MAX) {
- return nullptr;
- }
-
- if (events->friend_name_size == events->friend_name_capacity) {
- const uint32_t new_friend_name_capacity = events->friend_name_capacity * 2 + 1;
- Tox_Event_Friend_Name *new_friend_name = (Tox_Event_Friend_Name *)realloc(
- events->friend_name, new_friend_name_capacity * sizeof(Tox_Event_Friend_Name));
+ return event->type == TOX_EVENT_FRIEND_NAME ? event->data.friend_name : nullptr;
+}
- if (new_friend_name == nullptr) {
- return nullptr;
- }
+Tox_Event_Friend_Name *tox_event_friend_name_new(const Memory *mem)
+{
+ Tox_Event_Friend_Name *const friend_name =
+ (Tox_Event_Friend_Name *)mem_alloc(mem, sizeof(Tox_Event_Friend_Name));
- events->friend_name = new_friend_name;
- events->friend_name_capacity = new_friend_name_capacity;
+ if (friend_name == nullptr) {
+ return nullptr;
}
- Tox_Event_Friend_Name *const friend_name = &events->friend_name[events->friend_name_size];
tox_event_friend_name_construct(friend_name);
- ++events->friend_name_size;
return friend_name;
}
-void tox_events_clear_friend_name(Tox_Events *events)
+void tox_event_friend_name_free(Tox_Event_Friend_Name *friend_name, const Memory *mem)
{
- if (events == nullptr) {
- return;
- }
-
- for (uint32_t i = 0; i < events->friend_name_size; ++i) {
- tox_event_friend_name_destruct(&events->friend_name[i]);
+ if (friend_name != nullptr) {
+ tox_event_friend_name_destruct(friend_name, mem);
}
-
- free(events->friend_name);
- events->friend_name = nullptr;
- events->friend_name_size = 0;
- events->friend_name_capacity = 0;
+ mem_delete(mem, friend_name);
}
-uint32_t tox_events_get_friend_name_size(const Tox_Events *events)
+non_null()
+static Tox_Event_Friend_Name *tox_events_add_friend_name(Tox_Events *events, const Memory *mem)
{
- if (events == nullptr) {
- return 0;
+ Tox_Event_Friend_Name *const friend_name = tox_event_friend_name_new(mem);
+
+ if (friend_name == nullptr) {
+ return nullptr;
}
- return events->friend_name_size;
-}
+ Tox_Event event;
+ event.type = TOX_EVENT_FRIEND_NAME;
+ event.data.friend_name = friend_name;
-const Tox_Event_Friend_Name *tox_events_get_friend_name(const Tox_Events *events, uint32_t index)
-{
- assert(index < events->friend_name_size);
- assert(events->friend_name != nullptr);
- return &events->friend_name[index];
+ tox_events_add(events, &event);
+ return friend_name;
}
-bool tox_events_pack_friend_name(const Tox_Events *events, Bin_Pack *bp)
+bool tox_event_friend_name_unpack(
+ Tox_Event_Friend_Name **event, Bin_Unpack *bu, const Memory *mem)
{
- const uint32_t size = tox_events_get_friend_name_size(events);
+ assert(event != nullptr);
+ assert(*event == nullptr);
+ *event = tox_event_friend_name_new(mem);
- for (uint32_t i = 0; i < size; ++i) {
- if (!tox_event_friend_name_pack(tox_events_get_friend_name(events, i), bp)) {
- return false;
- }
+ if (*event == nullptr) {
+ return false;
}
- return true;
+
+ return tox_event_friend_name_unpack_into(*event, bu);
}
-bool tox_events_unpack_friend_name(Tox_Events *events, Bin_Unpack *bu)
+non_null()
+static Tox_Event_Friend_Name *tox_event_friend_name_alloc(void *user_data)
{
- Tox_Event_Friend_Name *event = tox_events_add_friend_name(events);
+ Tox_Events_State *state = tox_events_alloc(user_data);
+ assert(state != nullptr);
- if (event == nullptr) {
- return false;
+ if (state->events == nullptr) {
+ return nullptr;
}
- return tox_event_friend_name_unpack(event, bu);
-}
+ Tox_Event_Friend_Name *friend_name = tox_events_add_friend_name(state->events, state->mem);
+
+ if (friend_name == nullptr) {
+ state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
+ return nullptr;
+ }
+ return friend_name;
+}
/*****************************************************
*
@@ -208,21 +203,13 @@ bool tox_events_unpack_friend_name(Tox_Events *events, Bin_Unpack *bu)
*
*****************************************************/
-
-void tox_events_handle_friend_name(Tox *tox, uint32_t friend_number, const uint8_t *name, size_t length,
- void *user_data)
+void tox_events_handle_friend_name(
+ Tox *tox, uint32_t friend_number, const uint8_t *name, size_t length,
+ void *user_data)
{
- Tox_Events_State *state = tox_events_alloc(user_data);
- assert(state != nullptr);
-
- if (state->events == nullptr) {
- return;
- }
-
- Tox_Event_Friend_Name *friend_name = tox_events_add_friend_name(state->events);
+ Tox_Event_Friend_Name *friend_name = tox_event_friend_name_alloc(user_data);
if (friend_name == nullptr) {
- state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
return;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/friend_read_receipt.c b/protocols/Tox/libtox/src/toxcore/events/friend_read_receipt.c
index 1485b67cca..e5f2f9db52 100644
--- a/protocols/Tox/libtox/src/toxcore/events/friend_read_receipt.c
+++ b/protocols/Tox/libtox/src/toxcore/events/friend_read_receipt.c
@@ -1,46 +1,31 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2022 The TokTok team.
+ * Copyright © 2023-2024 The TokTok team.
*/
#include "events_alloc.h"
#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
+#include "../attributes.h"
#include "../bin_pack.h"
#include "../bin_unpack.h"
#include "../ccompat.h"
+#include "../mem.h"
#include "../tox.h"
#include "../tox_events.h"
-
/*****************************************************
*
* :: struct and accessors
*
*****************************************************/
-
struct Tox_Event_Friend_Read_Receipt {
uint32_t friend_number;
uint32_t message_id;
};
non_null()
-static void tox_event_friend_read_receipt_construct(Tox_Event_Friend_Read_Receipt *friend_read_receipt)
-{
- *friend_read_receipt = (Tox_Event_Friend_Read_Receipt) {
- 0
- };
-}
-non_null()
-static void tox_event_friend_read_receipt_destruct(Tox_Event_Friend_Read_Receipt *friend_read_receipt)
-{
- return;
-}
-
-non_null()
static void tox_event_friend_read_receipt_set_friend_number(Tox_Event_Friend_Read_Receipt *friend_read_receipt,
uint32_t friend_number)
{
@@ -67,23 +52,32 @@ uint32_t tox_event_friend_read_receipt_get_message_id(const Tox_Event_Friend_Rea
}
non_null()
-static bool tox_event_friend_read_receipt_pack(
+static void tox_event_friend_read_receipt_construct(Tox_Event_Friend_Read_Receipt *friend_read_receipt)
+{
+ *friend_read_receipt = (Tox_Event_Friend_Read_Receipt) {
+ 0
+ };
+}
+non_null()
+static void tox_event_friend_read_receipt_destruct(Tox_Event_Friend_Read_Receipt *friend_read_receipt, const Memory *mem)
+{
+ return;
+}
+
+bool tox_event_friend_read_receipt_pack(
const Tox_Event_Friend_Read_Receipt *event, Bin_Pack *bp)
{
- assert(event != nullptr);
return bin_pack_array(bp, 2)
- && bin_pack_u32(bp, TOX_EVENT_FRIEND_READ_RECEIPT)
- && bin_pack_array(bp, 2)
&& bin_pack_u32(bp, event->friend_number)
&& bin_pack_u32(bp, event->message_id);
}
non_null()
-static bool tox_event_friend_read_receipt_unpack(
+static bool tox_event_friend_read_receipt_unpack_into(
Tox_Event_Friend_Read_Receipt *event, Bin_Unpack *bu)
{
assert(event != nullptr);
- if (!bin_unpack_array_fixed(bu, 2)) {
+ if (!bin_unpack_array_fixed(bu, 2, nullptr)) {
return false;
}
@@ -91,96 +85,88 @@ static bool tox_event_friend_read_receipt_unpack(
&& bin_unpack_u32(bu, &event->message_id);
}
-
/*****************************************************
*
- * :: add/clear/get
+ * :: new/free/add/get/size/unpack
*
*****************************************************/
-
-non_null()
-static Tox_Event_Friend_Read_Receipt *tox_events_add_friend_read_receipt(Tox_Events *events)
+const Tox_Event_Friend_Read_Receipt *tox_event_get_friend_read_receipt(const Tox_Event *event)
{
- if (events->friend_read_receipt_size == UINT32_MAX) {
- return nullptr;
- }
-
- if (events->friend_read_receipt_size == events->friend_read_receipt_capacity) {
- const uint32_t new_friend_read_receipt_capacity = events->friend_read_receipt_capacity * 2 + 1;
- Tox_Event_Friend_Read_Receipt *new_friend_read_receipt = (Tox_Event_Friend_Read_Receipt *)realloc(
- events->friend_read_receipt, new_friend_read_receipt_capacity * sizeof(Tox_Event_Friend_Read_Receipt));
+ return event->type == TOX_EVENT_FRIEND_READ_RECEIPT ? event->data.friend_read_receipt : nullptr;
+}
- if (new_friend_read_receipt == nullptr) {
- return nullptr;
- }
+Tox_Event_Friend_Read_Receipt *tox_event_friend_read_receipt_new(const Memory *mem)
+{
+ Tox_Event_Friend_Read_Receipt *const friend_read_receipt =
+ (Tox_Event_Friend_Read_Receipt *)mem_alloc(mem, sizeof(Tox_Event_Friend_Read_Receipt));
- events->friend_read_receipt = new_friend_read_receipt;
- events->friend_read_receipt_capacity = new_friend_read_receipt_capacity;
+ if (friend_read_receipt == nullptr) {
+ return nullptr;
}
- Tox_Event_Friend_Read_Receipt *const friend_read_receipt =
- &events->friend_read_receipt[events->friend_read_receipt_size];
tox_event_friend_read_receipt_construct(friend_read_receipt);
- ++events->friend_read_receipt_size;
return friend_read_receipt;
}
-void tox_events_clear_friend_read_receipt(Tox_Events *events)
+void tox_event_friend_read_receipt_free(Tox_Event_Friend_Read_Receipt *friend_read_receipt, const Memory *mem)
{
- if (events == nullptr) {
- return;
- }
-
- for (uint32_t i = 0; i < events->friend_read_receipt_size; ++i) {
- tox_event_friend_read_receipt_destruct(&events->friend_read_receipt[i]);
+ if (friend_read_receipt != nullptr) {
+ tox_event_friend_read_receipt_destruct(friend_read_receipt, mem);
}
-
- free(events->friend_read_receipt);
- events->friend_read_receipt = nullptr;
- events->friend_read_receipt_size = 0;
- events->friend_read_receipt_capacity = 0;
+ mem_delete(mem, friend_read_receipt);
}
-uint32_t tox_events_get_friend_read_receipt_size(const Tox_Events *events)
+non_null()
+static Tox_Event_Friend_Read_Receipt *tox_events_add_friend_read_receipt(Tox_Events *events, const Memory *mem)
{
- if (events == nullptr) {
- return 0;
+ Tox_Event_Friend_Read_Receipt *const friend_read_receipt = tox_event_friend_read_receipt_new(mem);
+
+ if (friend_read_receipt == nullptr) {
+ return nullptr;
}
- return events->friend_read_receipt_size;
-}
+ Tox_Event event;
+ event.type = TOX_EVENT_FRIEND_READ_RECEIPT;
+ event.data.friend_read_receipt = friend_read_receipt;
-const Tox_Event_Friend_Read_Receipt *tox_events_get_friend_read_receipt(const Tox_Events *events, uint32_t index)
-{
- assert(index < events->friend_read_receipt_size);
- assert(events->friend_read_receipt != nullptr);
- return &events->friend_read_receipt[index];
+ tox_events_add(events, &event);
+ return friend_read_receipt;
}
-bool tox_events_pack_friend_read_receipt(const Tox_Events *events, Bin_Pack *bp)
+bool tox_event_friend_read_receipt_unpack(
+ Tox_Event_Friend_Read_Receipt **event, Bin_Unpack *bu, const Memory *mem)
{
- const uint32_t size = tox_events_get_friend_read_receipt_size(events);
+ assert(event != nullptr);
+ assert(*event == nullptr);
+ *event = tox_event_friend_read_receipt_new(mem);
- for (uint32_t i = 0; i < size; ++i) {
- if (!tox_event_friend_read_receipt_pack(tox_events_get_friend_read_receipt(events, i), bp)) {
- return false;
- }
+ if (*event == nullptr) {
+ return false;
}
- return true;
+
+ return tox_event_friend_read_receipt_unpack_into(*event, bu);
}
-bool tox_events_unpack_friend_read_receipt(Tox_Events *events, Bin_Unpack *bu)
+non_null()
+static Tox_Event_Friend_Read_Receipt *tox_event_friend_read_receipt_alloc(void *user_data)
{
- Tox_Event_Friend_Read_Receipt *event = tox_events_add_friend_read_receipt(events);
+ Tox_Events_State *state = tox_events_alloc(user_data);
+ assert(state != nullptr);
- if (event == nullptr) {
- return false;
+ if (state->events == nullptr) {
+ return nullptr;
}
- return tox_event_friend_read_receipt_unpack(event, bu);
-}
+ Tox_Event_Friend_Read_Receipt *friend_read_receipt = tox_events_add_friend_read_receipt(state->events, state->mem);
+ if (friend_read_receipt == nullptr) {
+ state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
+ return nullptr;
+ }
+
+ return friend_read_receipt;
+}
/*****************************************************
*
@@ -188,20 +174,13 @@ bool tox_events_unpack_friend_read_receipt(Tox_Events *events, Bin_Unpack *bu)
*
*****************************************************/
-
-void tox_events_handle_friend_read_receipt(Tox *tox, uint32_t friend_number, uint32_t message_id, void *user_data)
+void tox_events_handle_friend_read_receipt(
+ Tox *tox, uint32_t friend_number, uint32_t message_id,
+ void *user_data)
{
- Tox_Events_State *state = tox_events_alloc(user_data);
- assert(state != nullptr);
-
- if (state->events == nullptr) {
- return;
- }
-
- Tox_Event_Friend_Read_Receipt *friend_read_receipt = tox_events_add_friend_read_receipt(state->events);
+ Tox_Event_Friend_Read_Receipt *friend_read_receipt = tox_event_friend_read_receipt_alloc(user_data);
if (friend_read_receipt == nullptr) {
- state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
return;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/friend_request.c b/protocols/Tox/libtox/src/toxcore/events/friend_request.c
index 3366f54fe4..b492c15147 100644
--- a/protocols/Tox/libtox/src/toxcore/events/friend_request.c
+++ b/protocols/Tox/libtox/src/toxcore/events/friend_request.c
@@ -5,15 +5,16 @@
#include "events_alloc.h"
#include <assert.h>
-#include <stdlib.h>
#include <string.h>
+#include "../attributes.h"
#include "../bin_pack.h"
#include "../bin_unpack.h"
#include "../ccompat.h"
+#include "../mem.h"
#include "../tox.h"
#include "../tox_events.h"
-
+#include "../tox_private.h"
/*****************************************************
*
@@ -21,7 +22,6 @@
*
*****************************************************/
-
struct Tox_Event_Friend_Request {
uint8_t public_key[TOX_PUBLIC_KEY_SIZE];
uint8_t *message;
@@ -29,19 +29,6 @@ struct Tox_Event_Friend_Request {
};
non_null()
-static void tox_event_friend_request_construct(Tox_Event_Friend_Request *friend_request)
-{
- *friend_request = (Tox_Event_Friend_Request) {
- 0
- };
-}
-non_null()
-static void tox_event_friend_request_destruct(Tox_Event_Friend_Request *friend_request)
-{
- free(friend_request->message);
-}
-
-non_null()
static bool tox_event_friend_request_set_public_key(Tox_Event_Friend_Request *friend_request, const uint8_t *public_key)
{
assert(friend_request != nullptr);
@@ -56,24 +43,25 @@ const uint8_t *tox_event_friend_request_get_public_key(const Tox_Event_Friend_Re
}
non_null()
-static bool tox_event_friend_request_set_message(Tox_Event_Friend_Request *friend_request, const uint8_t *message,
- uint32_t message_length)
+static bool tox_event_friend_request_set_message(Tox_Event_Friend_Request *friend_request,
+ const uint8_t *message, uint32_t message_length, const Memory *mem)
{
assert(friend_request != nullptr);
if (friend_request->message != nullptr) {
- free(friend_request->message);
+ mem_delete(mem, friend_request->message);
friend_request->message = nullptr;
friend_request->message_length = 0;
}
- friend_request->message = (uint8_t *)malloc(message_length);
+ uint8_t *message_copy = (uint8_t *)mem_balloc(mem, message_length);
- if (friend_request->message == nullptr) {
+ if (message_copy == nullptr) {
return false;
}
- memcpy(friend_request->message, message, message_length);
+ memcpy(message_copy, message, message_length);
+ friend_request->message = message_copy;
friend_request->message_length = message_length;
return true;
}
@@ -89,23 +77,34 @@ const uint8_t *tox_event_friend_request_get_message(const Tox_Event_Friend_Reque
}
non_null()
-static bool tox_event_friend_request_pack(
+static void tox_event_friend_request_construct(Tox_Event_Friend_Request *friend_request)
+{
+ *friend_request = (Tox_Event_Friend_Request) {
+ {
+ 0
+ }
+ };
+}
+non_null()
+static void tox_event_friend_request_destruct(Tox_Event_Friend_Request *friend_request, const Memory *mem)
+{
+ mem_delete(mem, friend_request->message);
+}
+
+bool tox_event_friend_request_pack(
const Tox_Event_Friend_Request *event, Bin_Pack *bp)
{
- assert(event != nullptr);
return bin_pack_array(bp, 2)
- && bin_pack_u32(bp, TOX_EVENT_FRIEND_REQUEST)
- && bin_pack_array(bp, 2)
&& bin_pack_bin(bp, event->public_key, TOX_PUBLIC_KEY_SIZE)
&& bin_pack_bin(bp, event->message, event->message_length);
}
non_null()
-static bool tox_event_friend_request_unpack(
+static bool tox_event_friend_request_unpack_into(
Tox_Event_Friend_Request *event, Bin_Unpack *bu)
{
assert(event != nullptr);
- if (!bin_unpack_array_fixed(bu, 2)) {
+ if (!bin_unpack_array_fixed(bu, 2, nullptr)) {
return false;
}
@@ -113,95 +112,83 @@ static bool tox_event_friend_request_unpack(
&& bin_unpack_bin(bu, &event->message, &event->message_length);
}
-
-/*****************************************************
- *
- * :: add/clear/get
- *
- *****************************************************/
-
-
-non_null()
-static Tox_Event_Friend_Request *tox_events_add_friend_request(Tox_Events *events)
+const Tox_Event_Friend_Request *tox_event_get_friend_request(
+ const Tox_Event *event)
{
- if (events->friend_request_size == UINT32_MAX) {
- return nullptr;
- }
-
- if (events->friend_request_size == events->friend_request_capacity) {
- const uint32_t new_friend_request_capacity = events->friend_request_capacity * 2 + 1;
- Tox_Event_Friend_Request *new_friend_request = (Tox_Event_Friend_Request *)realloc(
- events->friend_request, new_friend_request_capacity * sizeof(Tox_Event_Friend_Request));
+ return event->type == TOX_EVENT_FRIEND_REQUEST ? event->data.friend_request : nullptr;
+}
- if (new_friend_request == nullptr) {
- return nullptr;
- }
+Tox_Event_Friend_Request *tox_event_friend_request_new(const Memory *mem)
+{
+ Tox_Event_Friend_Request *const friend_request =
+ (Tox_Event_Friend_Request *)mem_alloc(mem, sizeof(Tox_Event_Friend_Request));
- events->friend_request = new_friend_request;
- events->friend_request_capacity = new_friend_request_capacity;
+ if (friend_request == nullptr) {
+ return nullptr;
}
- Tox_Event_Friend_Request *const friend_request = &events->friend_request[events->friend_request_size];
tox_event_friend_request_construct(friend_request);
- ++events->friend_request_size;
return friend_request;
}
-void tox_events_clear_friend_request(Tox_Events *events)
+void tox_event_friend_request_free(Tox_Event_Friend_Request *friend_request, const Memory *mem)
{
- if (events == nullptr) {
- return;
+ if (friend_request != nullptr) {
+ tox_event_friend_request_destruct(friend_request, mem);
}
-
- for (uint32_t i = 0; i < events->friend_request_size; ++i) {
- tox_event_friend_request_destruct(&events->friend_request[i]);
- }
-
- free(events->friend_request);
- events->friend_request = nullptr;
- events->friend_request_size = 0;
- events->friend_request_capacity = 0;
+ mem_delete(mem, friend_request);
}
-uint32_t tox_events_get_friend_request_size(const Tox_Events *events)
+non_null()
+static Tox_Event_Friend_Request *tox_events_add_friend_request(Tox_Events *events, const Memory *mem)
{
- if (events == nullptr) {
- return 0;
+ Tox_Event_Friend_Request *const friend_request = tox_event_friend_request_new(mem);
+
+ if (friend_request == nullptr) {
+ return nullptr;
}
- return events->friend_request_size;
-}
+ Tox_Event event;
+ event.type = TOX_EVENT_FRIEND_REQUEST;
+ event.data.friend_request = friend_request;
-const Tox_Event_Friend_Request *tox_events_get_friend_request(const Tox_Events *events, uint32_t index)
-{
- assert(index < events->friend_request_size);
- assert(events->friend_request != nullptr);
- return &events->friend_request[index];
+ tox_events_add(events, &event);
+ return friend_request;
}
-bool tox_events_pack_friend_request(const Tox_Events *events, Bin_Pack *bp)
+bool tox_event_friend_request_unpack(
+ Tox_Event_Friend_Request **event, Bin_Unpack *bu, const Memory *mem)
{
- const uint32_t size = tox_events_get_friend_request_size(events);
+ assert(event != nullptr);
+ assert(*event == nullptr);
+ *event = tox_event_friend_request_new(mem);
- for (uint32_t i = 0; i < size; ++i) {
- if (!tox_event_friend_request_pack(tox_events_get_friend_request(events, i), bp)) {
- return false;
- }
+ if (*event == nullptr) {
+ return false;
}
- return true;
+
+ return tox_event_friend_request_unpack_into(*event, bu);
}
-bool tox_events_unpack_friend_request(Tox_Events *events, Bin_Unpack *bu)
+non_null()
+static Tox_Event_Friend_Request *tox_event_friend_request_alloc(void *user_data)
{
- Tox_Event_Friend_Request *event = tox_events_add_friend_request(events);
+ Tox_Events_State *state = tox_events_alloc(user_data);
+ assert(state != nullptr);
- if (event == nullptr) {
- return false;
+ if (state->events == nullptr) {
+ return nullptr;
}
- return tox_event_friend_request_unpack(event, bu);
-}
+ Tox_Event_Friend_Request *friend_request = tox_events_add_friend_request(state->events, state->mem);
+
+ if (friend_request == nullptr) {
+ state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
+ return nullptr;
+ }
+ return friend_request;
+}
/*****************************************************
*
@@ -209,24 +196,17 @@ bool tox_events_unpack_friend_request(Tox_Events *events, Bin_Unpack *bu)
*
*****************************************************/
-
void tox_events_handle_friend_request(Tox *tox, const uint8_t *public_key, const uint8_t *message, size_t length,
void *user_data)
{
- Tox_Events_State *state = tox_events_alloc(user_data);
- assert(state != nullptr);
-
- if (state->events == nullptr) {
- return;
- }
-
- Tox_Event_Friend_Request *friend_request = tox_events_add_friend_request(state->events);
+ Tox_Event_Friend_Request *friend_request = tox_event_friend_request_alloc(user_data);
if (friend_request == nullptr) {
- state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
return;
}
+ const Tox_System *sys = tox_get_system(tox);
+
tox_event_friend_request_set_public_key(friend_request, public_key);
- tox_event_friend_request_set_message(friend_request, message, length);
+ tox_event_friend_request_set_message(friend_request, message, length, sys->mem);
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/friend_status.c b/protocols/Tox/libtox/src/toxcore/events/friend_status.c
index c6eabdaa47..3d7499722b 100644
--- a/protocols/Tox/libtox/src/toxcore/events/friend_status.c
+++ b/protocols/Tox/libtox/src/toxcore/events/friend_status.c
@@ -1,47 +1,33 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2022 The TokTok team.
+ * Copyright © 2023-2024 The TokTok team.
*/
#include "events_alloc.h"
#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include "../bin_unpack.h"
+#include "../attributes.h"
#include "../bin_pack.h"
+#include "../bin_unpack.h"
#include "../ccompat.h"
+#include "../mem.h"
#include "../tox.h"
#include "../tox_events.h"
+#include "../tox_pack.h"
#include "../tox_unpack.h"
-
/*****************************************************
*
* :: struct and accessors
*
*****************************************************/
-
struct Tox_Event_Friend_Status {
uint32_t friend_number;
Tox_User_Status status;
};
non_null()
-static void tox_event_friend_status_construct(Tox_Event_Friend_Status *friend_status)
-{
- *friend_status = (Tox_Event_Friend_Status) {
- 0
- };
-}
-non_null()
-static void tox_event_friend_status_destruct(Tox_Event_Friend_Status *friend_status)
-{
- return;
-}
-
-non_null()
static void tox_event_friend_status_set_friend_number(Tox_Event_Friend_Status *friend_status,
uint32_t friend_number)
{
@@ -68,119 +54,121 @@ Tox_User_Status tox_event_friend_status_get_status(const Tox_Event_Friend_Status
}
non_null()
-static bool tox_event_friend_status_pack(
+static void tox_event_friend_status_construct(Tox_Event_Friend_Status *friend_status)
+{
+ *friend_status = (Tox_Event_Friend_Status) {
+ 0
+ };
+}
+non_null()
+static void tox_event_friend_status_destruct(Tox_Event_Friend_Status *friend_status, const Memory *mem)
+{
+ return;
+}
+
+bool tox_event_friend_status_pack(
const Tox_Event_Friend_Status *event, Bin_Pack *bp)
{
- assert(event != nullptr);
return bin_pack_array(bp, 2)
- && bin_pack_u32(bp, TOX_EVENT_FRIEND_STATUS)
- && bin_pack_array(bp, 2)
&& bin_pack_u32(bp, event->friend_number)
- && bin_pack_u32(bp, event->status);
+ && tox_user_status_pack(event->status, bp);
}
non_null()
-static bool tox_event_friend_status_unpack(
+static bool tox_event_friend_status_unpack_into(
Tox_Event_Friend_Status *event, Bin_Unpack *bu)
{
assert(event != nullptr);
- if (!bin_unpack_array_fixed(bu, 2)) {
+ if (!bin_unpack_array_fixed(bu, 2, nullptr)) {
return false;
}
return bin_unpack_u32(bu, &event->friend_number)
- && tox_unpack_user_status(bu, &event->status);
+ && tox_user_status_unpack(&event->status, bu);
}
-
/*****************************************************
*
- * :: add/clear/get
+ * :: new/free/add/get/size/unpack
*
*****************************************************/
-
-non_null()
-static Tox_Event_Friend_Status *tox_events_add_friend_status(Tox_Events *events)
+const Tox_Event_Friend_Status *tox_event_get_friend_status(const Tox_Event *event)
{
- if (events->friend_status_size == UINT32_MAX) {
- return nullptr;
- }
-
- if (events->friend_status_size == events->friend_status_capacity) {
- const uint32_t new_friend_status_capacity = events->friend_status_capacity * 2 + 1;
- Tox_Event_Friend_Status *new_friend_status = (Tox_Event_Friend_Status *)realloc(
- events->friend_status, new_friend_status_capacity * sizeof(Tox_Event_Friend_Status));
+ return event->type == TOX_EVENT_FRIEND_STATUS ? event->data.friend_status : nullptr;
+}
- if (new_friend_status == nullptr) {
- return nullptr;
- }
+Tox_Event_Friend_Status *tox_event_friend_status_new(const Memory *mem)
+{
+ Tox_Event_Friend_Status *const friend_status =
+ (Tox_Event_Friend_Status *)mem_alloc(mem, sizeof(Tox_Event_Friend_Status));
- events->friend_status = new_friend_status;
- events->friend_status_capacity = new_friend_status_capacity;
+ if (friend_status == nullptr) {
+ return nullptr;
}
- Tox_Event_Friend_Status *const friend_status = &events->friend_status[events->friend_status_size];
tox_event_friend_status_construct(friend_status);
- ++events->friend_status_size;
return friend_status;
}
-void tox_events_clear_friend_status(Tox_Events *events)
+void tox_event_friend_status_free(Tox_Event_Friend_Status *friend_status, const Memory *mem)
{
- if (events == nullptr) {
- return;
- }
-
- for (uint32_t i = 0; i < events->friend_status_size; ++i) {
- tox_event_friend_status_destruct(&events->friend_status[i]);
+ if (friend_status != nullptr) {
+ tox_event_friend_status_destruct(friend_status, mem);
}
-
- free(events->friend_status);
- events->friend_status = nullptr;
- events->friend_status_size = 0;
- events->friend_status_capacity = 0;
+ mem_delete(mem, friend_status);
}
-uint32_t tox_events_get_friend_status_size(const Tox_Events *events)
+non_null()
+static Tox_Event_Friend_Status *tox_events_add_friend_status(Tox_Events *events, const Memory *mem)
{
- if (events == nullptr) {
- return 0;
+ Tox_Event_Friend_Status *const friend_status = tox_event_friend_status_new(mem);
+
+ if (friend_status == nullptr) {
+ return nullptr;
}
- return events->friend_status_size;
-}
+ Tox_Event event;
+ event.type = TOX_EVENT_FRIEND_STATUS;
+ event.data.friend_status = friend_status;
-const Tox_Event_Friend_Status *tox_events_get_friend_status(const Tox_Events *events, uint32_t index)
-{
- assert(index < events->friend_status_size);
- assert(events->friend_status != nullptr);
- return &events->friend_status[index];
+ tox_events_add(events, &event);
+ return friend_status;
}
-bool tox_events_pack_friend_status(const Tox_Events *events, Bin_Pack *bp)
+bool tox_event_friend_status_unpack(
+ Tox_Event_Friend_Status **event, Bin_Unpack *bu, const Memory *mem)
{
- const uint32_t size = tox_events_get_friend_status_size(events);
+ assert(event != nullptr);
+ assert(*event == nullptr);
+ *event = tox_event_friend_status_new(mem);
- for (uint32_t i = 0; i < size; ++i) {
- if (!tox_event_friend_status_pack(tox_events_get_friend_status(events, i), bp)) {
- return false;
- }
+ if (*event == nullptr) {
+ return false;
}
- return true;
+
+ return tox_event_friend_status_unpack_into(*event, bu);
}
-bool tox_events_unpack_friend_status(Tox_Events *events, Bin_Unpack *bu)
+non_null()
+static Tox_Event_Friend_Status *tox_event_friend_status_alloc(void *user_data)
{
- Tox_Event_Friend_Status *event = tox_events_add_friend_status(events);
+ Tox_Events_State *state = tox_events_alloc(user_data);
+ assert(state != nullptr);
- if (event == nullptr) {
- return false;
+ if (state->events == nullptr) {
+ return nullptr;
}
- return tox_event_friend_status_unpack(event, bu);
-}
+ Tox_Event_Friend_Status *friend_status = tox_events_add_friend_status(state->events, state->mem);
+ if (friend_status == nullptr) {
+ state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
+ return nullptr;
+ }
+
+ return friend_status;
+}
/*****************************************************
*
@@ -188,21 +176,13 @@ bool tox_events_unpack_friend_status(Tox_Events *events, Bin_Unpack *bu)
*
*****************************************************/
-
-void tox_events_handle_friend_status(Tox *tox, uint32_t friend_number, Tox_User_Status status,
- void *user_data)
+void tox_events_handle_friend_status(
+ Tox *tox, uint32_t friend_number, Tox_User_Status status,
+ void *user_data)
{
- Tox_Events_State *state = tox_events_alloc(user_data);
- assert(state != nullptr);
-
- if (state->events == nullptr) {
- return;
- }
-
- Tox_Event_Friend_Status *friend_status = tox_events_add_friend_status(state->events);
+ Tox_Event_Friend_Status *friend_status = tox_event_friend_status_alloc(user_data);
if (friend_status == nullptr) {
- state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
return;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/friend_status_message.c b/protocols/Tox/libtox/src/toxcore/events/friend_status_message.c
index 91fa88e321..ad0519911e 100644
--- a/protocols/Tox/libtox/src/toxcore/events/friend_status_message.c
+++ b/protocols/Tox/libtox/src/toxcore/events/friend_status_message.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2022 The TokTok team.
+ * Copyright © 2023-2024 The TokTok team.
*/
#include "events_alloc.h"
@@ -8,20 +8,20 @@
#include <stdlib.h>
#include <string.h>
+#include "../attributes.h"
#include "../bin_pack.h"
#include "../bin_unpack.h"
#include "../ccompat.h"
+#include "../mem.h"
#include "../tox.h"
#include "../tox_events.h"
-
/*****************************************************
*
* :: struct and accessors
*
*****************************************************/
-
struct Tox_Event_Friend_Status_Message {
uint32_t friend_number;
uint8_t *message;
@@ -29,19 +29,6 @@ struct Tox_Event_Friend_Status_Message {
};
non_null()
-static void tox_event_friend_status_message_construct(Tox_Event_Friend_Status_Message *friend_status_message)
-{
- *friend_status_message = (Tox_Event_Friend_Status_Message) {
- 0
- };
-}
-non_null()
-static void tox_event_friend_status_message_destruct(Tox_Event_Friend_Status_Message *friend_status_message)
-{
- free(friend_status_message->message);
-}
-
-non_null()
static void tox_event_friend_status_message_set_friend_number(Tox_Event_Friend_Status_Message *friend_status_message,
uint32_t friend_number)
{
@@ -54,7 +41,7 @@ uint32_t tox_event_friend_status_message_get_friend_number(const Tox_Event_Frien
return friend_status_message->friend_number;
}
-non_null()
+non_null(1) nullable(2)
static bool tox_event_friend_status_message_set_message(Tox_Event_Friend_Status_Message *friend_status_message,
const uint8_t *message, uint32_t message_length)
{
@@ -66,47 +53,60 @@ static bool tox_event_friend_status_message_set_message(Tox_Event_Friend_Status_
friend_status_message->message_length = 0;
}
- friend_status_message->message = (uint8_t *)malloc(message_length);
+ if (message == nullptr) {
+ assert(message_length == 0);
+ return true;
+ }
+
+ uint8_t *message_copy = (uint8_t *)malloc(message_length);
- if (friend_status_message->message == nullptr) {
+ if (message_copy == nullptr) {
return false;
}
- memcpy(friend_status_message->message, message, message_length);
+ memcpy(message_copy, message, message_length);
+ friend_status_message->message = message_copy;
friend_status_message->message_length = message_length;
return true;
}
-uint32_t tox_event_friend_status_message_get_message_length(const Tox_Event_Friend_Status_Message
- *friend_status_message)
+uint32_t tox_event_friend_status_message_get_message_length(const Tox_Event_Friend_Status_Message *friend_status_message)
{
assert(friend_status_message != nullptr);
return friend_status_message->message_length;
}
-const uint8_t *tox_event_friend_status_message_get_message(const Tox_Event_Friend_Status_Message
- *friend_status_message)
+const uint8_t *tox_event_friend_status_message_get_message(const Tox_Event_Friend_Status_Message *friend_status_message)
{
assert(friend_status_message != nullptr);
return friend_status_message->message;
}
non_null()
-static bool tox_event_friend_status_message_pack(
+static void tox_event_friend_status_message_construct(Tox_Event_Friend_Status_Message *friend_status_message)
+{
+ *friend_status_message = (Tox_Event_Friend_Status_Message) {
+ 0
+ };
+}
+non_null()
+static void tox_event_friend_status_message_destruct(Tox_Event_Friend_Status_Message *friend_status_message, const Memory *mem)
+{
+ free(friend_status_message->message);
+}
+
+bool tox_event_friend_status_message_pack(
const Tox_Event_Friend_Status_Message *event, Bin_Pack *bp)
{
- assert(event != nullptr);
return bin_pack_array(bp, 2)
- && bin_pack_u32(bp, TOX_EVENT_FRIEND_STATUS_MESSAGE)
- && bin_pack_array(bp, 2)
&& bin_pack_u32(bp, event->friend_number)
&& bin_pack_bin(bp, event->message, event->message_length);
}
non_null()
-static bool tox_event_friend_status_message_unpack(
+static bool tox_event_friend_status_message_unpack_into(
Tox_Event_Friend_Status_Message *event, Bin_Unpack *bu)
{
assert(event != nullptr);
- if (!bin_unpack_array_fixed(bu, 2)) {
+ if (!bin_unpack_array_fixed(bu, 2, nullptr)) {
return false;
}
@@ -114,96 +114,88 @@ static bool tox_event_friend_status_message_unpack(
&& bin_unpack_bin(bu, &event->message, &event->message_length);
}
-
/*****************************************************
*
- * :: add/clear/get
+ * :: new/free/add/get/size/unpack
*
*****************************************************/
-
-non_null()
-static Tox_Event_Friend_Status_Message *tox_events_add_friend_status_message(Tox_Events *events)
+const Tox_Event_Friend_Status_Message *tox_event_get_friend_status_message(const Tox_Event *event)
{
- if (events->friend_status_message_size == UINT32_MAX) {
- return nullptr;
- }
-
- if (events->friend_status_message_size == events->friend_status_message_capacity) {
- const uint32_t new_friend_status_message_capacity = events->friend_status_message_capacity * 2 + 1;
- Tox_Event_Friend_Status_Message *new_friend_status_message = (Tox_Event_Friend_Status_Message *)realloc(
- events->friend_status_message, new_friend_status_message_capacity * sizeof(Tox_Event_Friend_Status_Message));
+ return event->type == TOX_EVENT_FRIEND_STATUS_MESSAGE ? event->data.friend_status_message : nullptr;
+}
- if (new_friend_status_message == nullptr) {
- return nullptr;
- }
+Tox_Event_Friend_Status_Message *tox_event_friend_status_message_new(const Memory *mem)
+{
+ Tox_Event_Friend_Status_Message *const friend_status_message =
+ (Tox_Event_Friend_Status_Message *)mem_alloc(mem, sizeof(Tox_Event_Friend_Status_Message));
- events->friend_status_message = new_friend_status_message;
- events->friend_status_message_capacity = new_friend_status_message_capacity;
+ if (friend_status_message == nullptr) {
+ return nullptr;
}
- Tox_Event_Friend_Status_Message *const friend_status_message =
- &events->friend_status_message[events->friend_status_message_size];
tox_event_friend_status_message_construct(friend_status_message);
- ++events->friend_status_message_size;
return friend_status_message;
}
-void tox_events_clear_friend_status_message(Tox_Events *events)
+void tox_event_friend_status_message_free(Tox_Event_Friend_Status_Message *friend_status_message, const Memory *mem)
{
- if (events == nullptr) {
- return;
+ if (friend_status_message != nullptr) {
+ tox_event_friend_status_message_destruct(friend_status_message, mem);
}
-
- for (uint32_t i = 0; i < events->friend_status_message_size; ++i) {
- tox_event_friend_status_message_destruct(&events->friend_status_message[i]);
- }
-
- free(events->friend_status_message);
- events->friend_status_message = nullptr;
- events->friend_status_message_size = 0;
- events->friend_status_message_capacity = 0;
+ mem_delete(mem, friend_status_message);
}
-uint32_t tox_events_get_friend_status_message_size(const Tox_Events *events)
+non_null()
+static Tox_Event_Friend_Status_Message *tox_events_add_friend_status_message(Tox_Events *events, const Memory *mem)
{
- if (events == nullptr) {
- return 0;
+ Tox_Event_Friend_Status_Message *const friend_status_message = tox_event_friend_status_message_new(mem);
+
+ if (friend_status_message == nullptr) {
+ return nullptr;
}
- return events->friend_status_message_size;
-}
+ Tox_Event event;
+ event.type = TOX_EVENT_FRIEND_STATUS_MESSAGE;
+ event.data.friend_status_message = friend_status_message;
-const Tox_Event_Friend_Status_Message *tox_events_get_friend_status_message(const Tox_Events *events, uint32_t index)
-{
- assert(index < events->friend_status_message_size);
- assert(events->friend_status_message != nullptr);
- return &events->friend_status_message[index];
+ tox_events_add(events, &event);
+ return friend_status_message;
}
-bool tox_events_pack_friend_status_message(const Tox_Events *events, Bin_Pack *bp)
+bool tox_event_friend_status_message_unpack(
+ Tox_Event_Friend_Status_Message **event, Bin_Unpack *bu, const Memory *mem)
{
- const uint32_t size = tox_events_get_friend_status_message_size(events);
+ assert(event != nullptr);
+ assert(*event == nullptr);
+ *event = tox_event_friend_status_message_new(mem);
- for (uint32_t i = 0; i < size; ++i) {
- if (!tox_event_friend_status_message_pack(tox_events_get_friend_status_message(events, i), bp)) {
- return false;
- }
+ if (*event == nullptr) {
+ return false;
}
- return true;
+
+ return tox_event_friend_status_message_unpack_into(*event, bu);
}
-bool tox_events_unpack_friend_status_message(Tox_Events *events, Bin_Unpack *bu)
+non_null()
+static Tox_Event_Friend_Status_Message *tox_event_friend_status_message_alloc(void *user_data)
{
- Tox_Event_Friend_Status_Message *event = tox_events_add_friend_status_message(events);
+ Tox_Events_State *state = tox_events_alloc(user_data);
+ assert(state != nullptr);
- if (event == nullptr) {
- return false;
+ if (state->events == nullptr) {
+ return nullptr;
}
- return tox_event_friend_status_message_unpack(event, bu);
-}
+ Tox_Event_Friend_Status_Message *friend_status_message = tox_events_add_friend_status_message(state->events, state->mem);
+
+ if (friend_status_message == nullptr) {
+ state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
+ return nullptr;
+ }
+ return friend_status_message;
+}
/*****************************************************
*
@@ -211,21 +203,13 @@ bool tox_events_unpack_friend_status_message(Tox_Events *events, Bin_Unpack *bu)
*
*****************************************************/
-
-void tox_events_handle_friend_status_message(Tox *tox, uint32_t friend_number, const uint8_t *message,
- size_t length, void *user_data)
+void tox_events_handle_friend_status_message(
+ Tox *tox, uint32_t friend_number, const uint8_t *message, size_t length,
+ void *user_data)
{
- Tox_Events_State *state = tox_events_alloc(user_data);
- assert(state != nullptr);
-
- if (state->events == nullptr) {
- return;
- }
-
- Tox_Event_Friend_Status_Message *friend_status_message = tox_events_add_friend_status_message(state->events);
+ Tox_Event_Friend_Status_Message *friend_status_message = tox_event_friend_status_message_alloc(user_data);
if (friend_status_message == nullptr) {
- state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
return;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/friend_typing.c b/protocols/Tox/libtox/src/toxcore/events/friend_typing.c
index 83c4dbac63..692b07fb88 100644
--- a/protocols/Tox/libtox/src/toxcore/events/friend_typing.c
+++ b/protocols/Tox/libtox/src/toxcore/events/friend_typing.c
@@ -1,46 +1,31 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2022 The TokTok team.
+ * Copyright © 2023-2024 The TokTok team.
*/
#include "events_alloc.h"
#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
+#include "../attributes.h"
#include "../bin_pack.h"
#include "../bin_unpack.h"
#include "../ccompat.h"
+#include "../mem.h"
#include "../tox.h"
#include "../tox_events.h"
-
/*****************************************************
*
* :: struct and accessors
*
*****************************************************/
-
struct Tox_Event_Friend_Typing {
uint32_t friend_number;
bool typing;
};
non_null()
-static void tox_event_friend_typing_construct(Tox_Event_Friend_Typing *friend_typing)
-{
- *friend_typing = (Tox_Event_Friend_Typing) {
- 0
- };
-}
-non_null()
-static void tox_event_friend_typing_destruct(Tox_Event_Friend_Typing *friend_typing)
-{
- return;
-}
-
-non_null()
static void tox_event_friend_typing_set_friend_number(Tox_Event_Friend_Typing *friend_typing,
uint32_t friend_number)
{
@@ -54,7 +39,8 @@ uint32_t tox_event_friend_typing_get_friend_number(const Tox_Event_Friend_Typing
}
non_null()
-static void tox_event_friend_typing_set_typing(Tox_Event_Friend_Typing *friend_typing, bool typing)
+static void tox_event_friend_typing_set_typing(Tox_Event_Friend_Typing *friend_typing,
+ bool typing)
{
assert(friend_typing != nullptr);
friend_typing->typing = typing;
@@ -66,23 +52,32 @@ bool tox_event_friend_typing_get_typing(const Tox_Event_Friend_Typing *friend_ty
}
non_null()
-static bool tox_event_friend_typing_pack(
+static void tox_event_friend_typing_construct(Tox_Event_Friend_Typing *friend_typing)
+{
+ *friend_typing = (Tox_Event_Friend_Typing) {
+ 0
+ };
+}
+non_null()
+static void tox_event_friend_typing_destruct(Tox_Event_Friend_Typing *friend_typing, const Memory *mem)
+{
+ return;
+}
+
+bool tox_event_friend_typing_pack(
const Tox_Event_Friend_Typing *event, Bin_Pack *bp)
{
- assert(event != nullptr);
return bin_pack_array(bp, 2)
- && bin_pack_u32(bp, TOX_EVENT_FRIEND_TYPING)
- && bin_pack_array(bp, 2)
&& bin_pack_u32(bp, event->friend_number)
&& bin_pack_bool(bp, event->typing);
}
non_null()
-static bool tox_event_friend_typing_unpack(
+static bool tox_event_friend_typing_unpack_into(
Tox_Event_Friend_Typing *event, Bin_Unpack *bu)
{
assert(event != nullptr);
- if (!bin_unpack_array_fixed(bu, 2)) {
+ if (!bin_unpack_array_fixed(bu, 2, nullptr)) {
return false;
}
@@ -90,95 +85,88 @@ static bool tox_event_friend_typing_unpack(
&& bin_unpack_bool(bu, &event->typing);
}
-
/*****************************************************
*
- * :: add/clear/get
+ * :: new/free/add/get/size/unpack
*
*****************************************************/
-
-non_null()
-static Tox_Event_Friend_Typing *tox_events_add_friend_typing(Tox_Events *events)
+const Tox_Event_Friend_Typing *tox_event_get_friend_typing(const Tox_Event *event)
{
- if (events->friend_typing_size == UINT32_MAX) {
- return nullptr;
- }
-
- if (events->friend_typing_size == events->friend_typing_capacity) {
- const uint32_t new_friend_typing_capacity = events->friend_typing_capacity * 2 + 1;
- Tox_Event_Friend_Typing *new_friend_typing = (Tox_Event_Friend_Typing *)realloc(
- events->friend_typing, new_friend_typing_capacity * sizeof(Tox_Event_Friend_Typing));
+ return event->type == TOX_EVENT_FRIEND_TYPING ? event->data.friend_typing : nullptr;
+}
- if (new_friend_typing == nullptr) {
- return nullptr;
- }
+Tox_Event_Friend_Typing *tox_event_friend_typing_new(const Memory *mem)
+{
+ Tox_Event_Friend_Typing *const friend_typing =
+ (Tox_Event_Friend_Typing *)mem_alloc(mem, sizeof(Tox_Event_Friend_Typing));
- events->friend_typing = new_friend_typing;
- events->friend_typing_capacity = new_friend_typing_capacity;
+ if (friend_typing == nullptr) {
+ return nullptr;
}
- Tox_Event_Friend_Typing *const friend_typing = &events->friend_typing[events->friend_typing_size];
tox_event_friend_typing_construct(friend_typing);
- ++events->friend_typing_size;
return friend_typing;
}
-void tox_events_clear_friend_typing(Tox_Events *events)
+void tox_event_friend_typing_free(Tox_Event_Friend_Typing *friend_typing, const Memory *mem)
{
- if (events == nullptr) {
- return;
+ if (friend_typing != nullptr) {
+ tox_event_friend_typing_destruct(friend_typing, mem);
}
-
- for (uint32_t i = 0; i < events->friend_typing_size; ++i) {
- tox_event_friend_typing_destruct(&events->friend_typing[i]);
- }
-
- free(events->friend_typing);
- events->friend_typing = nullptr;
- events->friend_typing_size = 0;
- events->friend_typing_capacity = 0;
+ mem_delete(mem, friend_typing);
}
-uint32_t tox_events_get_friend_typing_size(const Tox_Events *events)
+non_null()
+static Tox_Event_Friend_Typing *tox_events_add_friend_typing(Tox_Events *events, const Memory *mem)
{
- if (events == nullptr) {
- return 0;
+ Tox_Event_Friend_Typing *const friend_typing = tox_event_friend_typing_new(mem);
+
+ if (friend_typing == nullptr) {
+ return nullptr;
}
- return events->friend_typing_size;
-}
+ Tox_Event event;
+ event.type = TOX_EVENT_FRIEND_TYPING;
+ event.data.friend_typing = friend_typing;
-const Tox_Event_Friend_Typing *tox_events_get_friend_typing(const Tox_Events *events, uint32_t index)
-{
- assert(index < events->friend_typing_size);
- assert(events->friend_typing != nullptr);
- return &events->friend_typing[index];
+ tox_events_add(events, &event);
+ return friend_typing;
}
-bool tox_events_pack_friend_typing(const Tox_Events *events, Bin_Pack *bp)
+bool tox_event_friend_typing_unpack(
+ Tox_Event_Friend_Typing **event, Bin_Unpack *bu, const Memory *mem)
{
- const uint32_t size = tox_events_get_friend_typing_size(events);
+ assert(event != nullptr);
+ assert(*event == nullptr);
+ *event = tox_event_friend_typing_new(mem);
- for (uint32_t i = 0; i < size; ++i) {
- if (!tox_event_friend_typing_pack(tox_events_get_friend_typing(events, i), bp)) {
- return false;
- }
+ if (*event == nullptr) {
+ return false;
}
- return true;
+
+ return tox_event_friend_typing_unpack_into(*event, bu);
}
-bool tox_events_unpack_friend_typing(Tox_Events *events, Bin_Unpack *bu)
+non_null()
+static Tox_Event_Friend_Typing *tox_event_friend_typing_alloc(void *user_data)
{
- Tox_Event_Friend_Typing *event = tox_events_add_friend_typing(events);
+ Tox_Events_State *state = tox_events_alloc(user_data);
+ assert(state != nullptr);
- if (event == nullptr) {
- return false;
+ if (state->events == nullptr) {
+ return nullptr;
}
- return tox_event_friend_typing_unpack(event, bu);
-}
+ Tox_Event_Friend_Typing *friend_typing = tox_events_add_friend_typing(state->events, state->mem);
+ if (friend_typing == nullptr) {
+ state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
+ return nullptr;
+ }
+
+ return friend_typing;
+}
/*****************************************************
*
@@ -186,20 +174,13 @@ bool tox_events_unpack_friend_typing(Tox_Events *events, Bin_Unpack *bu)
*
*****************************************************/
-
-void tox_events_handle_friend_typing(Tox *tox, uint32_t friend_number, bool typing, void *user_data)
+void tox_events_handle_friend_typing(
+ Tox *tox, uint32_t friend_number, bool typing,
+ void *user_data)
{
- Tox_Events_State *state = tox_events_alloc(user_data);
- assert(state != nullptr);
-
- if (state->events == nullptr) {
- return;
- }
-
- Tox_Event_Friend_Typing *friend_typing = tox_events_add_friend_typing(state->events);
+ Tox_Event_Friend_Typing *friend_typing = tox_event_friend_typing_alloc(user_data);
if (friend_typing == nullptr) {
- state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
return;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/group_custom_packet.c b/protocols/Tox/libtox/src/toxcore/events/group_custom_packet.c
new file mode 100644
index 0000000000..a82e2c3a6c
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/events/group_custom_packet.c
@@ -0,0 +1,235 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2023-2024 The TokTok team.
+ */
+
+#include "events_alloc.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../attributes.h"
+#include "../bin_pack.h"
+#include "../bin_unpack.h"
+#include "../ccompat.h"
+#include "../mem.h"
+#include "../tox.h"
+#include "../tox_events.h"
+
+/*****************************************************
+ *
+ * :: struct and accessors
+ *
+ *****************************************************/
+
+struct Tox_Event_Group_Custom_Packet {
+ uint32_t group_number;
+ uint32_t peer_id;
+ uint8_t *data;
+ uint32_t data_length;
+};
+
+non_null()
+static void tox_event_group_custom_packet_set_group_number(Tox_Event_Group_Custom_Packet *group_custom_packet,
+ uint32_t group_number)
+{
+ assert(group_custom_packet != nullptr);
+ group_custom_packet->group_number = group_number;
+}
+uint32_t tox_event_group_custom_packet_get_group_number(const Tox_Event_Group_Custom_Packet *group_custom_packet)
+{
+ assert(group_custom_packet != nullptr);
+ return group_custom_packet->group_number;
+}
+
+non_null()
+static void tox_event_group_custom_packet_set_peer_id(Tox_Event_Group_Custom_Packet *group_custom_packet,
+ uint32_t peer_id)
+{
+ assert(group_custom_packet != nullptr);
+ group_custom_packet->peer_id = peer_id;
+}
+uint32_t tox_event_group_custom_packet_get_peer_id(const Tox_Event_Group_Custom_Packet *group_custom_packet)
+{
+ assert(group_custom_packet != nullptr);
+ return group_custom_packet->peer_id;
+}
+
+non_null(1) nullable(2)
+static bool tox_event_group_custom_packet_set_data(Tox_Event_Group_Custom_Packet *group_custom_packet,
+ const uint8_t *data, uint32_t data_length)
+{
+ assert(group_custom_packet != nullptr);
+
+ if (group_custom_packet->data != nullptr) {
+ free(group_custom_packet->data);
+ group_custom_packet->data = nullptr;
+ group_custom_packet->data_length = 0;
+ }
+
+ if (data == nullptr) {
+ assert(data_length == 0);
+ return true;
+ }
+
+ uint8_t *data_copy = (uint8_t *)malloc(data_length);
+
+ if (data_copy == nullptr) {
+ return false;
+ }
+
+ memcpy(data_copy, data, data_length);
+ group_custom_packet->data = data_copy;
+ group_custom_packet->data_length = data_length;
+ return true;
+}
+uint32_t tox_event_group_custom_packet_get_data_length(const Tox_Event_Group_Custom_Packet *group_custom_packet)
+{
+ assert(group_custom_packet != nullptr);
+ return group_custom_packet->data_length;
+}
+const uint8_t *tox_event_group_custom_packet_get_data(const Tox_Event_Group_Custom_Packet *group_custom_packet)
+{
+ assert(group_custom_packet != nullptr);
+ return group_custom_packet->data;
+}
+
+non_null()
+static void tox_event_group_custom_packet_construct(Tox_Event_Group_Custom_Packet *group_custom_packet)
+{
+ *group_custom_packet = (Tox_Event_Group_Custom_Packet) {
+ 0
+ };
+}
+non_null()
+static void tox_event_group_custom_packet_destruct(Tox_Event_Group_Custom_Packet *group_custom_packet, const Memory *mem)
+{
+ free(group_custom_packet->data);
+}
+
+bool tox_event_group_custom_packet_pack(
+ const Tox_Event_Group_Custom_Packet *event, Bin_Pack *bp)
+{
+ return bin_pack_array(bp, 3)
+ && bin_pack_u32(bp, event->group_number)
+ && bin_pack_u32(bp, event->peer_id)
+ && bin_pack_bin(bp, event->data, event->data_length);
+}
+
+non_null()
+static bool tox_event_group_custom_packet_unpack_into(
+ Tox_Event_Group_Custom_Packet *event, Bin_Unpack *bu)
+{
+ assert(event != nullptr);
+ if (!bin_unpack_array_fixed(bu, 3, nullptr)) {
+ return false;
+ }
+
+ return bin_unpack_u32(bu, &event->group_number)
+ && bin_unpack_u32(bu, &event->peer_id)
+ && bin_unpack_bin(bu, &event->data, &event->data_length);
+}
+
+/*****************************************************
+ *
+ * :: new/free/add/get/size/unpack
+ *
+ *****************************************************/
+
+const Tox_Event_Group_Custom_Packet *tox_event_get_group_custom_packet(const Tox_Event *event)
+{
+ return event->type == TOX_EVENT_GROUP_CUSTOM_PACKET ? event->data.group_custom_packet : nullptr;
+}
+
+Tox_Event_Group_Custom_Packet *tox_event_group_custom_packet_new(const Memory *mem)
+{
+ Tox_Event_Group_Custom_Packet *const group_custom_packet =
+ (Tox_Event_Group_Custom_Packet *)mem_alloc(mem, sizeof(Tox_Event_Group_Custom_Packet));
+
+ if (group_custom_packet == nullptr) {
+ return nullptr;
+ }
+
+ tox_event_group_custom_packet_construct(group_custom_packet);
+ return group_custom_packet;
+}
+
+void tox_event_group_custom_packet_free(Tox_Event_Group_Custom_Packet *group_custom_packet, const Memory *mem)
+{
+ if (group_custom_packet != nullptr) {
+ tox_event_group_custom_packet_destruct(group_custom_packet, mem);
+ }
+ mem_delete(mem, group_custom_packet);
+}
+
+non_null()
+static Tox_Event_Group_Custom_Packet *tox_events_add_group_custom_packet(Tox_Events *events, const Memory *mem)
+{
+ Tox_Event_Group_Custom_Packet *const group_custom_packet = tox_event_group_custom_packet_new(mem);
+
+ if (group_custom_packet == nullptr) {
+ return nullptr;
+ }
+
+ Tox_Event event;
+ event.type = TOX_EVENT_GROUP_CUSTOM_PACKET;
+ event.data.group_custom_packet = group_custom_packet;
+
+ tox_events_add(events, &event);
+ return group_custom_packet;
+}
+
+bool tox_event_group_custom_packet_unpack(
+ Tox_Event_Group_Custom_Packet **event, Bin_Unpack *bu, const Memory *mem)
+{
+ assert(event != nullptr);
+ assert(*event == nullptr);
+ *event = tox_event_group_custom_packet_new(mem);
+
+ if (*event == nullptr) {
+ return false;
+ }
+
+ return tox_event_group_custom_packet_unpack_into(*event, bu);
+}
+
+non_null()
+static Tox_Event_Group_Custom_Packet *tox_event_group_custom_packet_alloc(void *user_data)
+{
+ Tox_Events_State *state = tox_events_alloc(user_data);
+ assert(state != nullptr);
+
+ if (state->events == nullptr) {
+ return nullptr;
+ }
+
+ Tox_Event_Group_Custom_Packet *group_custom_packet = tox_events_add_group_custom_packet(state->events, state->mem);
+
+ if (group_custom_packet == nullptr) {
+ state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
+ return nullptr;
+ }
+
+ return group_custom_packet;
+}
+
+/*****************************************************
+ *
+ * :: event handler
+ *
+ *****************************************************/
+
+void tox_events_handle_group_custom_packet(
+ Tox *tox, uint32_t group_number, uint32_t peer_id, const uint8_t *data, size_t length,
+ void *user_data)
+{
+ Tox_Event_Group_Custom_Packet *group_custom_packet = tox_event_group_custom_packet_alloc(user_data);
+
+ if (group_custom_packet == nullptr) {
+ return;
+ }
+
+ tox_event_group_custom_packet_set_group_number(group_custom_packet, group_number);
+ tox_event_group_custom_packet_set_peer_id(group_custom_packet, peer_id);
+ tox_event_group_custom_packet_set_data(group_custom_packet, data, length);
+}
diff --git a/protocols/Tox/libtox/src/toxcore/events/group_custom_private_packet.c b/protocols/Tox/libtox/src/toxcore/events/group_custom_private_packet.c
new file mode 100644
index 0000000000..56282f0fb8
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/events/group_custom_private_packet.c
@@ -0,0 +1,235 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2023-2024 The TokTok team.
+ */
+
+#include "events_alloc.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../attributes.h"
+#include "../bin_pack.h"
+#include "../bin_unpack.h"
+#include "../ccompat.h"
+#include "../mem.h"
+#include "../tox.h"
+#include "../tox_events.h"
+
+/*****************************************************
+ *
+ * :: struct and accessors
+ *
+ *****************************************************/
+
+struct Tox_Event_Group_Custom_Private_Packet {
+ uint32_t group_number;
+ uint32_t peer_id;
+ uint8_t *data;
+ uint32_t data_length;
+};
+
+non_null()
+static void tox_event_group_custom_private_packet_set_group_number(Tox_Event_Group_Custom_Private_Packet *group_custom_private_packet,
+ uint32_t group_number)
+{
+ assert(group_custom_private_packet != nullptr);
+ group_custom_private_packet->group_number = group_number;
+}
+uint32_t tox_event_group_custom_private_packet_get_group_number(const Tox_Event_Group_Custom_Private_Packet *group_custom_private_packet)
+{
+ assert(group_custom_private_packet != nullptr);
+ return group_custom_private_packet->group_number;
+}
+
+non_null()
+static void tox_event_group_custom_private_packet_set_peer_id(Tox_Event_Group_Custom_Private_Packet *group_custom_private_packet,
+ uint32_t peer_id)
+{
+ assert(group_custom_private_packet != nullptr);
+ group_custom_private_packet->peer_id = peer_id;
+}
+uint32_t tox_event_group_custom_private_packet_get_peer_id(const Tox_Event_Group_Custom_Private_Packet *group_custom_private_packet)
+{
+ assert(group_custom_private_packet != nullptr);
+ return group_custom_private_packet->peer_id;
+}
+
+non_null(1) nullable(2)
+static bool tox_event_group_custom_private_packet_set_data(Tox_Event_Group_Custom_Private_Packet *group_custom_private_packet,
+ const uint8_t *data, uint32_t data_length)
+{
+ assert(group_custom_private_packet != nullptr);
+
+ if (group_custom_private_packet->data != nullptr) {
+ free(group_custom_private_packet->data);
+ group_custom_private_packet->data = nullptr;
+ group_custom_private_packet->data_length = 0;
+ }
+
+ if (data == nullptr) {
+ assert(data_length == 0);
+ return true;
+ }
+
+ uint8_t *data_copy = (uint8_t *)malloc(data_length);
+
+ if (data_copy == nullptr) {
+ return false;
+ }
+
+ memcpy(data_copy, data, data_length);
+ group_custom_private_packet->data = data_copy;
+ group_custom_private_packet->data_length = data_length;
+ return true;
+}
+uint32_t tox_event_group_custom_private_packet_get_data_length(const Tox_Event_Group_Custom_Private_Packet *group_custom_private_packet)
+{
+ assert(group_custom_private_packet != nullptr);
+ return group_custom_private_packet->data_length;
+}
+const uint8_t *tox_event_group_custom_private_packet_get_data(const Tox_Event_Group_Custom_Private_Packet *group_custom_private_packet)
+{
+ assert(group_custom_private_packet != nullptr);
+ return group_custom_private_packet->data;
+}
+
+non_null()
+static void tox_event_group_custom_private_packet_construct(Tox_Event_Group_Custom_Private_Packet *group_custom_private_packet)
+{
+ *group_custom_private_packet = (Tox_Event_Group_Custom_Private_Packet) {
+ 0
+ };
+}
+non_null()
+static void tox_event_group_custom_private_packet_destruct(Tox_Event_Group_Custom_Private_Packet *group_custom_private_packet, const Memory *mem)
+{
+ free(group_custom_private_packet->data);
+}
+
+bool tox_event_group_custom_private_packet_pack(
+ const Tox_Event_Group_Custom_Private_Packet *event, Bin_Pack *bp)
+{
+ return bin_pack_array(bp, 3)
+ && bin_pack_u32(bp, event->group_number)
+ && bin_pack_u32(bp, event->peer_id)
+ && bin_pack_bin(bp, event->data, event->data_length);
+}
+
+non_null()
+static bool tox_event_group_custom_private_packet_unpack_into(
+ Tox_Event_Group_Custom_Private_Packet *event, Bin_Unpack *bu)
+{
+ assert(event != nullptr);
+ if (!bin_unpack_array_fixed(bu, 3, nullptr)) {
+ return false;
+ }
+
+ return bin_unpack_u32(bu, &event->group_number)
+ && bin_unpack_u32(bu, &event->peer_id)
+ && bin_unpack_bin(bu, &event->data, &event->data_length);
+}
+
+/*****************************************************
+ *
+ * :: new/free/add/get/size/unpack
+ *
+ *****************************************************/
+
+const Tox_Event_Group_Custom_Private_Packet *tox_event_get_group_custom_private_packet(const Tox_Event *event)
+{
+ return event->type == TOX_EVENT_GROUP_CUSTOM_PRIVATE_PACKET ? event->data.group_custom_private_packet : nullptr;
+}
+
+Tox_Event_Group_Custom_Private_Packet *tox_event_group_custom_private_packet_new(const Memory *mem)
+{
+ Tox_Event_Group_Custom_Private_Packet *const group_custom_private_packet =
+ (Tox_Event_Group_Custom_Private_Packet *)mem_alloc(mem, sizeof(Tox_Event_Group_Custom_Private_Packet));
+
+ if (group_custom_private_packet == nullptr) {
+ return nullptr;
+ }
+
+ tox_event_group_custom_private_packet_construct(group_custom_private_packet);
+ return group_custom_private_packet;
+}
+
+void tox_event_group_custom_private_packet_free(Tox_Event_Group_Custom_Private_Packet *group_custom_private_packet, const Memory *mem)
+{
+ if (group_custom_private_packet != nullptr) {
+ tox_event_group_custom_private_packet_destruct(group_custom_private_packet, mem);
+ }
+ mem_delete(mem, group_custom_private_packet);
+}
+
+non_null()
+static Tox_Event_Group_Custom_Private_Packet *tox_events_add_group_custom_private_packet(Tox_Events *events, const Memory *mem)
+{
+ Tox_Event_Group_Custom_Private_Packet *const group_custom_private_packet = tox_event_group_custom_private_packet_new(mem);
+
+ if (group_custom_private_packet == nullptr) {
+ return nullptr;
+ }
+
+ Tox_Event event;
+ event.type = TOX_EVENT_GROUP_CUSTOM_PRIVATE_PACKET;
+ event.data.group_custom_private_packet = group_custom_private_packet;
+
+ tox_events_add(events, &event);
+ return group_custom_private_packet;
+}
+
+bool tox_event_group_custom_private_packet_unpack(
+ Tox_Event_Group_Custom_Private_Packet **event, Bin_Unpack *bu, const Memory *mem)
+{
+ assert(event != nullptr);
+ assert(*event == nullptr);
+ *event = tox_event_group_custom_private_packet_new(mem);
+
+ if (*event == nullptr) {
+ return false;
+ }
+
+ return tox_event_group_custom_private_packet_unpack_into(*event, bu);
+}
+
+non_null()
+static Tox_Event_Group_Custom_Private_Packet *tox_event_group_custom_private_packet_alloc(void *user_data)
+{
+ Tox_Events_State *state = tox_events_alloc(user_data);
+ assert(state != nullptr);
+
+ if (state->events == nullptr) {
+ return nullptr;
+ }
+
+ Tox_Event_Group_Custom_Private_Packet *group_custom_private_packet = tox_events_add_group_custom_private_packet(state->events, state->mem);
+
+ if (group_custom_private_packet == nullptr) {
+ state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
+ return nullptr;
+ }
+
+ return group_custom_private_packet;
+}
+
+/*****************************************************
+ *
+ * :: event handler
+ *
+ *****************************************************/
+
+void tox_events_handle_group_custom_private_packet(
+ Tox *tox, uint32_t group_number, uint32_t peer_id, const uint8_t *data, size_t length,
+ void *user_data)
+{
+ Tox_Event_Group_Custom_Private_Packet *group_custom_private_packet = tox_event_group_custom_private_packet_alloc(user_data);
+
+ if (group_custom_private_packet == nullptr) {
+ return;
+ }
+
+ tox_event_group_custom_private_packet_set_group_number(group_custom_private_packet, group_number);
+ tox_event_group_custom_private_packet_set_peer_id(group_custom_private_packet, peer_id);
+ tox_event_group_custom_private_packet_set_data(group_custom_private_packet, data, length);
+}
diff --git a/protocols/Tox/libtox/src/toxcore/events/group_invite.c b/protocols/Tox/libtox/src/toxcore/events/group_invite.c
new file mode 100644
index 0000000000..0691dcd1fe
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/events/group_invite.c
@@ -0,0 +1,263 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2023-2024 The TokTok team.
+ */
+
+#include "events_alloc.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../attributes.h"
+#include "../bin_pack.h"
+#include "../bin_unpack.h"
+#include "../ccompat.h"
+#include "../mem.h"
+#include "../tox.h"
+#include "../tox_events.h"
+
+/*****************************************************
+ *
+ * :: struct and accessors
+ *
+ *****************************************************/
+
+struct Tox_Event_Group_Invite {
+ uint32_t friend_number;
+ uint8_t *invite_data;
+ uint32_t invite_data_length;
+ uint8_t *group_name;
+ uint32_t group_name_length;
+};
+
+non_null()
+static void tox_event_group_invite_set_friend_number(Tox_Event_Group_Invite *group_invite,
+ uint32_t friend_number)
+{
+ assert(group_invite != nullptr);
+ group_invite->friend_number = friend_number;
+}
+uint32_t tox_event_group_invite_get_friend_number(const Tox_Event_Group_Invite *group_invite)
+{
+ assert(group_invite != nullptr);
+ return group_invite->friend_number;
+}
+
+non_null(1) nullable(2)
+static bool tox_event_group_invite_set_invite_data(Tox_Event_Group_Invite *group_invite,
+ const uint8_t *invite_data, uint32_t invite_data_length)
+{
+ assert(group_invite != nullptr);
+
+ if (group_invite->invite_data != nullptr) {
+ free(group_invite->invite_data);
+ group_invite->invite_data = nullptr;
+ group_invite->invite_data_length = 0;
+ }
+
+ if (invite_data == nullptr) {
+ assert(invite_data_length == 0);
+ return true;
+ }
+
+ uint8_t *invite_data_copy = (uint8_t *)malloc(invite_data_length);
+
+ if (invite_data_copy == nullptr) {
+ return false;
+ }
+
+ memcpy(invite_data_copy, invite_data, invite_data_length);
+ group_invite->invite_data = invite_data_copy;
+ group_invite->invite_data_length = invite_data_length;
+ return true;
+}
+uint32_t tox_event_group_invite_get_invite_data_length(const Tox_Event_Group_Invite *group_invite)
+{
+ assert(group_invite != nullptr);
+ return group_invite->invite_data_length;
+}
+const uint8_t *tox_event_group_invite_get_invite_data(const Tox_Event_Group_Invite *group_invite)
+{
+ assert(group_invite != nullptr);
+ return group_invite->invite_data;
+}
+
+non_null(1) nullable(2)
+static bool tox_event_group_invite_set_group_name(Tox_Event_Group_Invite *group_invite,
+ const uint8_t *group_name, uint32_t group_name_length)
+{
+ assert(group_invite != nullptr);
+
+ if (group_invite->group_name != nullptr) {
+ free(group_invite->group_name);
+ group_invite->group_name = nullptr;
+ group_invite->group_name_length = 0;
+ }
+
+ if (group_name == nullptr) {
+ assert(group_name_length == 0);
+ return true;
+ }
+
+ uint8_t *group_name_copy = (uint8_t *)malloc(group_name_length);
+
+ if (group_name_copy == nullptr) {
+ return false;
+ }
+
+ memcpy(group_name_copy, group_name, group_name_length);
+ group_invite->group_name = group_name_copy;
+ group_invite->group_name_length = group_name_length;
+ return true;
+}
+uint32_t tox_event_group_invite_get_group_name_length(const Tox_Event_Group_Invite *group_invite)
+{
+ assert(group_invite != nullptr);
+ return group_invite->group_name_length;
+}
+const uint8_t *tox_event_group_invite_get_group_name(const Tox_Event_Group_Invite *group_invite)
+{
+ assert(group_invite != nullptr);
+ return group_invite->group_name;
+}
+
+non_null()
+static void tox_event_group_invite_construct(Tox_Event_Group_Invite *group_invite)
+{
+ *group_invite = (Tox_Event_Group_Invite) {
+ 0
+ };
+}
+non_null()
+static void tox_event_group_invite_destruct(Tox_Event_Group_Invite *group_invite, const Memory *mem)
+{
+ free(group_invite->invite_data);
+ free(group_invite->group_name);
+}
+
+bool tox_event_group_invite_pack(
+ const Tox_Event_Group_Invite *event, Bin_Pack *bp)
+{
+ return bin_pack_array(bp, 3)
+ && bin_pack_u32(bp, event->friend_number)
+ && bin_pack_bin(bp, event->invite_data, event->invite_data_length)
+ && bin_pack_bin(bp, event->group_name, event->group_name_length);
+}
+
+non_null()
+static bool tox_event_group_invite_unpack_into(
+ Tox_Event_Group_Invite *event, Bin_Unpack *bu)
+{
+ assert(event != nullptr);
+ if (!bin_unpack_array_fixed(bu, 3, nullptr)) {
+ return false;
+ }
+
+ return bin_unpack_u32(bu, &event->friend_number)
+ && bin_unpack_bin(bu, &event->invite_data, &event->invite_data_length)
+ && bin_unpack_bin(bu, &event->group_name, &event->group_name_length);
+}
+
+/*****************************************************
+ *
+ * :: new/free/add/get/size/unpack
+ *
+ *****************************************************/
+
+const Tox_Event_Group_Invite *tox_event_get_group_invite(const Tox_Event *event)
+{
+ return event->type == TOX_EVENT_GROUP_INVITE ? event->data.group_invite : nullptr;
+}
+
+Tox_Event_Group_Invite *tox_event_group_invite_new(const Memory *mem)
+{
+ Tox_Event_Group_Invite *const group_invite =
+ (Tox_Event_Group_Invite *)mem_alloc(mem, sizeof(Tox_Event_Group_Invite));
+
+ if (group_invite == nullptr) {
+ return nullptr;
+ }
+
+ tox_event_group_invite_construct(group_invite);
+ return group_invite;
+}
+
+void tox_event_group_invite_free(Tox_Event_Group_Invite *group_invite, const Memory *mem)
+{
+ if (group_invite != nullptr) {
+ tox_event_group_invite_destruct(group_invite, mem);
+ }
+ mem_delete(mem, group_invite);
+}
+
+non_null()
+static Tox_Event_Group_Invite *tox_events_add_group_invite(Tox_Events *events, const Memory *mem)
+{
+ Tox_Event_Group_Invite *const group_invite = tox_event_group_invite_new(mem);
+
+ if (group_invite == nullptr) {
+ return nullptr;
+ }
+
+ Tox_Event event;
+ event.type = TOX_EVENT_GROUP_INVITE;
+ event.data.group_invite = group_invite;
+
+ tox_events_add(events, &event);
+ return group_invite;
+}
+
+bool tox_event_group_invite_unpack(
+ Tox_Event_Group_Invite **event, Bin_Unpack *bu, const Memory *mem)
+{
+ assert(event != nullptr);
+ assert(*event == nullptr);
+ *event = tox_event_group_invite_new(mem);
+
+ if (*event == nullptr) {
+ return false;
+ }
+
+ return tox_event_group_invite_unpack_into(*event, bu);
+}
+
+non_null()
+static Tox_Event_Group_Invite *tox_event_group_invite_alloc(void *user_data)
+{
+ Tox_Events_State *state = tox_events_alloc(user_data);
+ assert(state != nullptr);
+
+ if (state->events == nullptr) {
+ return nullptr;
+ }
+
+ Tox_Event_Group_Invite *group_invite = tox_events_add_group_invite(state->events, state->mem);
+
+ if (group_invite == nullptr) {
+ state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
+ return nullptr;
+ }
+
+ return group_invite;
+}
+
+/*****************************************************
+ *
+ * :: event handler
+ *
+ *****************************************************/
+
+void tox_events_handle_group_invite(
+ Tox *tox, uint32_t friend_number, const uint8_t *invite_data, size_t length, const uint8_t *group_name, size_t group_name_length,
+ void *user_data)
+{
+ Tox_Event_Group_Invite *group_invite = tox_event_group_invite_alloc(user_data);
+
+ if (group_invite == nullptr) {
+ return;
+ }
+
+ tox_event_group_invite_set_friend_number(group_invite, friend_number);
+ tox_event_group_invite_set_invite_data(group_invite, invite_data, length);
+ tox_event_group_invite_set_group_name(group_invite, group_name, group_name_length);
+}
diff --git a/protocols/Tox/libtox/src/toxcore/events/group_join_fail.c b/protocols/Tox/libtox/src/toxcore/events/group_join_fail.c
new file mode 100644
index 0000000000..b85896858b
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/events/group_join_fail.c
@@ -0,0 +1,191 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2023-2024 The TokTok team.
+ */
+
+#include "events_alloc.h"
+
+#include <assert.h>
+
+#include "../attributes.h"
+#include "../bin_pack.h"
+#include "../bin_unpack.h"
+#include "../ccompat.h"
+#include "../mem.h"
+#include "../tox.h"
+#include "../tox_events.h"
+#include "../tox_pack.h"
+#include "../tox_unpack.h"
+
+/*****************************************************
+ *
+ * :: struct and accessors
+ *
+ *****************************************************/
+
+struct Tox_Event_Group_Join_Fail {
+ uint32_t group_number;
+ Tox_Group_Join_Fail fail_type;
+};
+
+non_null()
+static void tox_event_group_join_fail_set_group_number(Tox_Event_Group_Join_Fail *group_join_fail,
+ uint32_t group_number)
+{
+ assert(group_join_fail != nullptr);
+ group_join_fail->group_number = group_number;
+}
+uint32_t tox_event_group_join_fail_get_group_number(const Tox_Event_Group_Join_Fail *group_join_fail)
+{
+ assert(group_join_fail != nullptr);
+ return group_join_fail->group_number;
+}
+
+non_null()
+static void tox_event_group_join_fail_set_fail_type(Tox_Event_Group_Join_Fail *group_join_fail,
+ Tox_Group_Join_Fail fail_type)
+{
+ assert(group_join_fail != nullptr);
+ group_join_fail->fail_type = fail_type;
+}
+Tox_Group_Join_Fail tox_event_group_join_fail_get_fail_type(const Tox_Event_Group_Join_Fail *group_join_fail)
+{
+ assert(group_join_fail != nullptr);
+ return group_join_fail->fail_type;
+}
+
+non_null()
+static void tox_event_group_join_fail_construct(Tox_Event_Group_Join_Fail *group_join_fail)
+{
+ *group_join_fail = (Tox_Event_Group_Join_Fail) {
+ 0
+ };
+}
+non_null()
+static void tox_event_group_join_fail_destruct(Tox_Event_Group_Join_Fail *group_join_fail, const Memory *mem)
+{
+ return;
+}
+
+bool tox_event_group_join_fail_pack(
+ const Tox_Event_Group_Join_Fail *event, Bin_Pack *bp)
+{
+ return bin_pack_array(bp, 2)
+ && bin_pack_u32(bp, event->group_number)
+ && tox_group_join_fail_pack(event->fail_type, bp);
+}
+
+non_null()
+static bool tox_event_group_join_fail_unpack_into(
+ Tox_Event_Group_Join_Fail *event, Bin_Unpack *bu)
+{
+ assert(event != nullptr);
+ if (!bin_unpack_array_fixed(bu, 2, nullptr)) {
+ return false;
+ }
+
+ return bin_unpack_u32(bu, &event->group_number)
+ && tox_group_join_fail_unpack(&event->fail_type, bu);
+}
+
+/*****************************************************
+ *
+ * :: new/free/add/get/size/unpack
+ *
+ *****************************************************/
+
+const Tox_Event_Group_Join_Fail *tox_event_get_group_join_fail(const Tox_Event *event)
+{
+ return event->type == TOX_EVENT_GROUP_JOIN_FAIL ? event->data.group_join_fail : nullptr;
+}
+
+Tox_Event_Group_Join_Fail *tox_event_group_join_fail_new(const Memory *mem)
+{
+ Tox_Event_Group_Join_Fail *const group_join_fail =
+ (Tox_Event_Group_Join_Fail *)mem_alloc(mem, sizeof(Tox_Event_Group_Join_Fail));
+
+ if (group_join_fail == nullptr) {
+ return nullptr;
+ }
+
+ tox_event_group_join_fail_construct(group_join_fail);
+ return group_join_fail;
+}
+
+void tox_event_group_join_fail_free(Tox_Event_Group_Join_Fail *group_join_fail, const Memory *mem)
+{
+ if (group_join_fail != nullptr) {
+ tox_event_group_join_fail_destruct(group_join_fail, mem);
+ }
+ mem_delete(mem, group_join_fail);
+}
+
+non_null()
+static Tox_Event_Group_Join_Fail *tox_events_add_group_join_fail(Tox_Events *events, const Memory *mem)
+{
+ Tox_Event_Group_Join_Fail *const group_join_fail = tox_event_group_join_fail_new(mem);
+
+ if (group_join_fail == nullptr) {
+ return nullptr;
+ }
+
+ Tox_Event event;
+ event.type = TOX_EVENT_GROUP_JOIN_FAIL;
+ event.data.group_join_fail = group_join_fail;
+
+ tox_events_add(events, &event);
+ return group_join_fail;
+}
+
+bool tox_event_group_join_fail_unpack(
+ Tox_Event_Group_Join_Fail **event, Bin_Unpack *bu, const Memory *mem)
+{
+ assert(event != nullptr);
+ assert(*event == nullptr);
+ *event = tox_event_group_join_fail_new(mem);
+
+ if (*event == nullptr) {
+ return false;
+ }
+
+ return tox_event_group_join_fail_unpack_into(*event, bu);
+}
+
+non_null()
+static Tox_Event_Group_Join_Fail *tox_event_group_join_fail_alloc(void *user_data)
+{
+ Tox_Events_State *state = tox_events_alloc(user_data);
+ assert(state != nullptr);
+
+ if (state->events == nullptr) {
+ return nullptr;
+ }
+
+ Tox_Event_Group_Join_Fail *group_join_fail = tox_events_add_group_join_fail(state->events, state->mem);
+
+ if (group_join_fail == nullptr) {
+ state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
+ return nullptr;
+ }
+
+ return group_join_fail;
+}
+
+/*****************************************************
+ *
+ * :: event handler
+ *
+ *****************************************************/
+
+void tox_events_handle_group_join_fail(
+ Tox *tox, uint32_t group_number, Tox_Group_Join_Fail fail_type,
+ void *user_data)
+{
+ Tox_Event_Group_Join_Fail *group_join_fail = tox_event_group_join_fail_alloc(user_data);
+
+ if (group_join_fail == nullptr) {
+ return;
+ }
+
+ tox_event_group_join_fail_set_group_number(group_join_fail, group_number);
+ tox_event_group_join_fail_set_fail_type(group_join_fail, fail_type);
+}
diff --git a/protocols/Tox/libtox/src/toxcore/events/group_message.c b/protocols/Tox/libtox/src/toxcore/events/group_message.c
new file mode 100644
index 0000000000..a200f84566
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/events/group_message.c
@@ -0,0 +1,271 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2023-2024 The TokTok team.
+ */
+
+#include "events_alloc.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../attributes.h"
+#include "../bin_pack.h"
+#include "../bin_unpack.h"
+#include "../ccompat.h"
+#include "../mem.h"
+#include "../tox.h"
+#include "../tox_events.h"
+#include "../tox_pack.h"
+#include "../tox_unpack.h"
+
+/*****************************************************
+ *
+ * :: struct and accessors
+ *
+ *****************************************************/
+
+struct Tox_Event_Group_Message {
+ uint32_t group_number;
+ uint32_t peer_id;
+ Tox_Message_Type type;
+ uint8_t *message;
+ uint32_t message_length;
+ uint32_t message_id;
+};
+
+non_null()
+static void tox_event_group_message_set_group_number(Tox_Event_Group_Message *group_message,
+ uint32_t group_number)
+{
+ assert(group_message != nullptr);
+ group_message->group_number = group_number;
+}
+uint32_t tox_event_group_message_get_group_number(const Tox_Event_Group_Message *group_message)
+{
+ assert(group_message != nullptr);
+ return group_message->group_number;
+}
+
+non_null()
+static void tox_event_group_message_set_peer_id(Tox_Event_Group_Message *group_message,
+ uint32_t peer_id)
+{
+ assert(group_message != nullptr);
+ group_message->peer_id = peer_id;
+}
+uint32_t tox_event_group_message_get_peer_id(const Tox_Event_Group_Message *group_message)
+{
+ assert(group_message != nullptr);
+ return group_message->peer_id;
+}
+
+non_null()
+static void tox_event_group_message_set_type(Tox_Event_Group_Message *group_message,
+ Tox_Message_Type type)
+{
+ assert(group_message != nullptr);
+ group_message->type = type;
+}
+Tox_Message_Type tox_event_group_message_get_type(const Tox_Event_Group_Message *group_message)
+{
+ assert(group_message != nullptr);
+ return group_message->type;
+}
+
+non_null(1) nullable(2)
+static bool tox_event_group_message_set_message(Tox_Event_Group_Message *group_message,
+ const uint8_t *message, uint32_t message_length)
+{
+ assert(group_message != nullptr);
+
+ if (group_message->message != nullptr) {
+ free(group_message->message);
+ group_message->message = nullptr;
+ group_message->message_length = 0;
+ }
+
+ if (message == nullptr) {
+ assert(message_length == 0);
+ return true;
+ }
+
+ uint8_t *message_copy = (uint8_t *)malloc(message_length);
+
+ if (message_copy == nullptr) {
+ return false;
+ }
+
+ memcpy(message_copy, message, message_length);
+ group_message->message = message_copy;
+ group_message->message_length = message_length;
+ return true;
+}
+uint32_t tox_event_group_message_get_message_length(const Tox_Event_Group_Message *group_message)
+{
+ assert(group_message != nullptr);
+ return group_message->message_length;
+}
+const uint8_t *tox_event_group_message_get_message(const Tox_Event_Group_Message *group_message)
+{
+ assert(group_message != nullptr);
+ return group_message->message;
+}
+
+non_null()
+static void tox_event_group_message_set_message_id(Tox_Event_Group_Message *group_message,
+ uint32_t message_id)
+{
+ assert(group_message != nullptr);
+ group_message->message_id = message_id;
+}
+uint32_t tox_event_group_message_get_message_id(const Tox_Event_Group_Message *group_message)
+{
+ assert(group_message != nullptr);
+ return group_message->message_id;
+}
+
+non_null()
+static void tox_event_group_message_construct(Tox_Event_Group_Message *group_message)
+{
+ *group_message = (Tox_Event_Group_Message) {
+ 0
+ };
+}
+non_null()
+static void tox_event_group_message_destruct(Tox_Event_Group_Message *group_message, const Memory *mem)
+{
+ free(group_message->message);
+}
+
+bool tox_event_group_message_pack(
+ const Tox_Event_Group_Message *event, Bin_Pack *bp)
+{
+ return bin_pack_array(bp, 5)
+ && bin_pack_u32(bp, event->group_number)
+ && bin_pack_u32(bp, event->peer_id)
+ && tox_message_type_pack(event->type, bp)
+ && bin_pack_bin(bp, event->message, event->message_length)
+ && bin_pack_u32(bp, event->message_id);
+}
+
+non_null()
+static bool tox_event_group_message_unpack_into(
+ Tox_Event_Group_Message *event, Bin_Unpack *bu)
+{
+ assert(event != nullptr);
+ if (!bin_unpack_array_fixed(bu, 5, nullptr)) {
+ return false;
+ }
+
+ return bin_unpack_u32(bu, &event->group_number)
+ && bin_unpack_u32(bu, &event->peer_id)
+ && tox_message_type_unpack(&event->type, bu)
+ && bin_unpack_bin(bu, &event->message, &event->message_length)
+ && bin_unpack_u32(bu, &event->message_id);
+}
+
+/*****************************************************
+ *
+ * :: new/free/add/get/size/unpack
+ *
+ *****************************************************/
+
+const Tox_Event_Group_Message *tox_event_get_group_message(const Tox_Event *event)
+{
+ return event->type == TOX_EVENT_GROUP_MESSAGE ? event->data.group_message : nullptr;
+}
+
+Tox_Event_Group_Message *tox_event_group_message_new(const Memory *mem)
+{
+ Tox_Event_Group_Message *const group_message =
+ (Tox_Event_Group_Message *)mem_alloc(mem, sizeof(Tox_Event_Group_Message));
+
+ if (group_message == nullptr) {
+ return nullptr;
+ }
+
+ tox_event_group_message_construct(group_message);
+ return group_message;
+}
+
+void tox_event_group_message_free(Tox_Event_Group_Message *group_message, const Memory *mem)
+{
+ if (group_message != nullptr) {
+ tox_event_group_message_destruct(group_message, mem);
+ }
+ mem_delete(mem, group_message);
+}
+
+non_null()
+static Tox_Event_Group_Message *tox_events_add_group_message(Tox_Events *events, const Memory *mem)
+{
+ Tox_Event_Group_Message *const group_message = tox_event_group_message_new(mem);
+
+ if (group_message == nullptr) {
+ return nullptr;
+ }
+
+ Tox_Event event;
+ event.type = TOX_EVENT_GROUP_MESSAGE;
+ event.data.group_message = group_message;
+
+ tox_events_add(events, &event);
+ return group_message;
+}
+
+bool tox_event_group_message_unpack(
+ Tox_Event_Group_Message **event, Bin_Unpack *bu, const Memory *mem)
+{
+ assert(event != nullptr);
+ assert(*event == nullptr);
+ *event = tox_event_group_message_new(mem);
+
+ if (*event == nullptr) {
+ return false;
+ }
+
+ return tox_event_group_message_unpack_into(*event, bu);
+}
+
+non_null()
+static Tox_Event_Group_Message *tox_event_group_message_alloc(void *user_data)
+{
+ Tox_Events_State *state = tox_events_alloc(user_data);
+ assert(state != nullptr);
+
+ if (state->events == nullptr) {
+ return nullptr;
+ }
+
+ Tox_Event_Group_Message *group_message = tox_events_add_group_message(state->events, state->mem);
+
+ if (group_message == nullptr) {
+ state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
+ return nullptr;
+ }
+
+ return group_message;
+}
+
+/*****************************************************
+ *
+ * :: event handler
+ *
+ *****************************************************/
+
+void tox_events_handle_group_message(
+ Tox *tox, uint32_t group_number, uint32_t peer_id, Tox_Message_Type type, const uint8_t *message, size_t length, uint32_t message_id,
+ void *user_data)
+{
+ Tox_Event_Group_Message *group_message = tox_event_group_message_alloc(user_data);
+
+ if (group_message == nullptr) {
+ return;
+ }
+
+ tox_event_group_message_set_group_number(group_message, group_number);
+ tox_event_group_message_set_peer_id(group_message, peer_id);
+ tox_event_group_message_set_type(group_message, type);
+ tox_event_group_message_set_message(group_message, message, length);
+ tox_event_group_message_set_message_id(group_message, message_id);
+}
diff --git a/protocols/Tox/libtox/src/toxcore/events/group_moderation.c b/protocols/Tox/libtox/src/toxcore/events/group_moderation.c
new file mode 100644
index 0000000000..ba510d5b2a
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/events/group_moderation.c
@@ -0,0 +1,225 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2023-2024 The TokTok team.
+ */
+
+#include "events_alloc.h"
+
+#include <assert.h>
+
+#include "../attributes.h"
+#include "../bin_pack.h"
+#include "../bin_unpack.h"
+#include "../ccompat.h"
+#include "../mem.h"
+#include "../tox.h"
+#include "../tox_events.h"
+#include "../tox_pack.h"
+#include "../tox_unpack.h"
+
+/*****************************************************
+ *
+ * :: struct and accessors
+ *
+ *****************************************************/
+
+struct Tox_Event_Group_Moderation {
+ uint32_t group_number;
+ uint32_t source_peer_id;
+ uint32_t target_peer_id;
+ Tox_Group_Mod_Event mod_type;
+};
+
+non_null()
+static void tox_event_group_moderation_set_group_number(Tox_Event_Group_Moderation *group_moderation,
+ uint32_t group_number)
+{
+ assert(group_moderation != nullptr);
+ group_moderation->group_number = group_number;
+}
+uint32_t tox_event_group_moderation_get_group_number(const Tox_Event_Group_Moderation *group_moderation)
+{
+ assert(group_moderation != nullptr);
+ return group_moderation->group_number;
+}
+
+non_null()
+static void tox_event_group_moderation_set_source_peer_id(Tox_Event_Group_Moderation *group_moderation,
+ uint32_t source_peer_id)
+{
+ assert(group_moderation != nullptr);
+ group_moderation->source_peer_id = source_peer_id;
+}
+uint32_t tox_event_group_moderation_get_source_peer_id(const Tox_Event_Group_Moderation *group_moderation)
+{
+ assert(group_moderation != nullptr);
+ return group_moderation->source_peer_id;
+}
+
+non_null()
+static void tox_event_group_moderation_set_target_peer_id(Tox_Event_Group_Moderation *group_moderation,
+ uint32_t target_peer_id)
+{
+ assert(group_moderation != nullptr);
+ group_moderation->target_peer_id = target_peer_id;
+}
+uint32_t tox_event_group_moderation_get_target_peer_id(const Tox_Event_Group_Moderation *group_moderation)
+{
+ assert(group_moderation != nullptr);
+ return group_moderation->target_peer_id;
+}
+
+non_null()
+static void tox_event_group_moderation_set_mod_type(Tox_Event_Group_Moderation *group_moderation,
+ Tox_Group_Mod_Event mod_type)
+{
+ assert(group_moderation != nullptr);
+ group_moderation->mod_type = mod_type;
+}
+Tox_Group_Mod_Event tox_event_group_moderation_get_mod_type(const Tox_Event_Group_Moderation *group_moderation)
+{
+ assert(group_moderation != nullptr);
+ return group_moderation->mod_type;
+}
+
+non_null()
+static void tox_event_group_moderation_construct(Tox_Event_Group_Moderation *group_moderation)
+{
+ *group_moderation = (Tox_Event_Group_Moderation) {
+ 0
+ };
+}
+non_null()
+static void tox_event_group_moderation_destruct(Tox_Event_Group_Moderation *group_moderation, const Memory *mem)
+{
+ return;
+}
+
+bool tox_event_group_moderation_pack(
+ const Tox_Event_Group_Moderation *event, Bin_Pack *bp)
+{
+ return bin_pack_array(bp, 4)
+ && bin_pack_u32(bp, event->group_number)
+ && bin_pack_u32(bp, event->source_peer_id)
+ && bin_pack_u32(bp, event->target_peer_id)
+ && tox_group_mod_event_pack(event->mod_type, bp);
+}
+
+non_null()
+static bool tox_event_group_moderation_unpack_into(
+ Tox_Event_Group_Moderation *event, Bin_Unpack *bu)
+{
+ assert(event != nullptr);
+ if (!bin_unpack_array_fixed(bu, 4, nullptr)) {
+ return false;
+ }
+
+ return bin_unpack_u32(bu, &event->group_number)
+ && bin_unpack_u32(bu, &event->source_peer_id)
+ && bin_unpack_u32(bu, &event->target_peer_id)
+ && tox_group_mod_event_unpack(&event->mod_type, bu);
+}
+
+/*****************************************************
+ *
+ * :: new/free/add/get/size/unpack
+ *
+ *****************************************************/
+
+const Tox_Event_Group_Moderation *tox_event_get_group_moderation(const Tox_Event *event)
+{
+ return event->type == TOX_EVENT_GROUP_MODERATION ? event->data.group_moderation : nullptr;
+}
+
+Tox_Event_Group_Moderation *tox_event_group_moderation_new(const Memory *mem)
+{
+ Tox_Event_Group_Moderation *const group_moderation =
+ (Tox_Event_Group_Moderation *)mem_alloc(mem, sizeof(Tox_Event_Group_Moderation));
+
+ if (group_moderation == nullptr) {
+ return nullptr;
+ }
+
+ tox_event_group_moderation_construct(group_moderation);
+ return group_moderation;
+}
+
+void tox_event_group_moderation_free(Tox_Event_Group_Moderation *group_moderation, const Memory *mem)
+{
+ if (group_moderation != nullptr) {
+ tox_event_group_moderation_destruct(group_moderation, mem);
+ }
+ mem_delete(mem, group_moderation);
+}
+
+non_null()
+static Tox_Event_Group_Moderation *tox_events_add_group_moderation(Tox_Events *events, const Memory *mem)
+{
+ Tox_Event_Group_Moderation *const group_moderation = tox_event_group_moderation_new(mem);
+
+ if (group_moderation == nullptr) {
+ return nullptr;
+ }
+
+ Tox_Event event;
+ event.type = TOX_EVENT_GROUP_MODERATION;
+ event.data.group_moderation = group_moderation;
+
+ tox_events_add(events, &event);
+ return group_moderation;
+}
+
+bool tox_event_group_moderation_unpack(
+ Tox_Event_Group_Moderation **event, Bin_Unpack *bu, const Memory *mem)
+{
+ assert(event != nullptr);
+ assert(*event == nullptr);
+ *event = tox_event_group_moderation_new(mem);
+
+ if (*event == nullptr) {
+ return false;
+ }
+
+ return tox_event_group_moderation_unpack_into(*event, bu);
+}
+
+non_null()
+static Tox_Event_Group_Moderation *tox_event_group_moderation_alloc(void *user_data)
+{
+ Tox_Events_State *state = tox_events_alloc(user_data);
+ assert(state != nullptr);
+
+ if (state->events == nullptr) {
+ return nullptr;
+ }
+
+ Tox_Event_Group_Moderation *group_moderation = tox_events_add_group_moderation(state->events, state->mem);
+
+ if (group_moderation == nullptr) {
+ state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
+ return nullptr;
+ }
+
+ return group_moderation;
+}
+
+/*****************************************************
+ *
+ * :: event handler
+ *
+ *****************************************************/
+
+void tox_events_handle_group_moderation(
+ Tox *tox, uint32_t group_number, uint32_t source_peer_id, uint32_t target_peer_id, Tox_Group_Mod_Event mod_type,
+ void *user_data)
+{
+ Tox_Event_Group_Moderation *group_moderation = tox_event_group_moderation_alloc(user_data);
+
+ if (group_moderation == nullptr) {
+ return;
+ }
+
+ tox_event_group_moderation_set_group_number(group_moderation, group_number);
+ tox_event_group_moderation_set_source_peer_id(group_moderation, source_peer_id);
+ tox_event_group_moderation_set_target_peer_id(group_moderation, target_peer_id);
+ tox_event_group_moderation_set_mod_type(group_moderation, mod_type);
+}
diff --git a/protocols/Tox/libtox/src/toxcore/events/group_password.c b/protocols/Tox/libtox/src/toxcore/events/group_password.c
new file mode 100644
index 0000000000..ad6e86b9d3
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/events/group_password.c
@@ -0,0 +1,218 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2023-2024 The TokTok team.
+ */
+
+#include "events_alloc.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../attributes.h"
+#include "../bin_pack.h"
+#include "../bin_unpack.h"
+#include "../ccompat.h"
+#include "../mem.h"
+#include "../tox.h"
+#include "../tox_events.h"
+
+/*****************************************************
+ *
+ * :: struct and accessors
+ *
+ *****************************************************/
+
+struct Tox_Event_Group_Password {
+ uint32_t group_number;
+ uint8_t *password;
+ uint32_t password_length;
+};
+
+non_null()
+static void tox_event_group_password_set_group_number(Tox_Event_Group_Password *group_password,
+ uint32_t group_number)
+{
+ assert(group_password != nullptr);
+ group_password->group_number = group_number;
+}
+uint32_t tox_event_group_password_get_group_number(const Tox_Event_Group_Password *group_password)
+{
+ assert(group_password != nullptr);
+ return group_password->group_number;
+}
+
+non_null(1) nullable(2)
+static bool tox_event_group_password_set_password(Tox_Event_Group_Password *group_password,
+ const uint8_t *password, uint32_t password_length)
+{
+ assert(group_password != nullptr);
+
+ if (group_password->password != nullptr) {
+ free(group_password->password);
+ group_password->password = nullptr;
+ group_password->password_length = 0;
+ }
+
+ if (password == nullptr) {
+ assert(password_length == 0);
+ return true;
+ }
+
+ uint8_t *password_copy = (uint8_t *)malloc(password_length);
+
+ if (password_copy == nullptr) {
+ return false;
+ }
+
+ memcpy(password_copy, password, password_length);
+ group_password->password = password_copy;
+ group_password->password_length = password_length;
+ return true;
+}
+uint32_t tox_event_group_password_get_password_length(const Tox_Event_Group_Password *group_password)
+{
+ assert(group_password != nullptr);
+ return group_password->password_length;
+}
+const uint8_t *tox_event_group_password_get_password(const Tox_Event_Group_Password *group_password)
+{
+ assert(group_password != nullptr);
+ return group_password->password;
+}
+
+non_null()
+static void tox_event_group_password_construct(Tox_Event_Group_Password *group_password)
+{
+ *group_password = (Tox_Event_Group_Password) {
+ 0
+ };
+}
+non_null()
+static void tox_event_group_password_destruct(Tox_Event_Group_Password *group_password, const Memory *mem)
+{
+ free(group_password->password);
+}
+
+bool tox_event_group_password_pack(
+ const Tox_Event_Group_Password *event, Bin_Pack *bp)
+{
+ return bin_pack_array(bp, 2)
+ && bin_pack_u32(bp, event->group_number)
+ && bin_pack_bin(bp, event->password, event->password_length);
+}
+
+non_null()
+static bool tox_event_group_password_unpack_into(
+ Tox_Event_Group_Password *event, Bin_Unpack *bu)
+{
+ assert(event != nullptr);
+ if (!bin_unpack_array_fixed(bu, 2, nullptr)) {
+ return false;
+ }
+
+ return bin_unpack_u32(bu, &event->group_number)
+ && bin_unpack_bin(bu, &event->password, &event->password_length);
+}
+
+/*****************************************************
+ *
+ * :: new/free/add/get/size/unpack
+ *
+ *****************************************************/
+
+const Tox_Event_Group_Password *tox_event_get_group_password(const Tox_Event *event)
+{
+ return event->type == TOX_EVENT_GROUP_PASSWORD ? event->data.group_password : nullptr;
+}
+
+Tox_Event_Group_Password *tox_event_group_password_new(const Memory *mem)
+{
+ Tox_Event_Group_Password *const group_password =
+ (Tox_Event_Group_Password *)mem_alloc(mem, sizeof(Tox_Event_Group_Password));
+
+ if (group_password == nullptr) {
+ return nullptr;
+ }
+
+ tox_event_group_password_construct(group_password);
+ return group_password;
+}
+
+void tox_event_group_password_free(Tox_Event_Group_Password *group_password, const Memory *mem)
+{
+ if (group_password != nullptr) {
+ tox_event_group_password_destruct(group_password, mem);
+ }
+ mem_delete(mem, group_password);
+}
+
+non_null()
+static Tox_Event_Group_Password *tox_events_add_group_password(Tox_Events *events, const Memory *mem)
+{
+ Tox_Event_Group_Password *const group_password = tox_event_group_password_new(mem);
+
+ if (group_password == nullptr) {
+ return nullptr;
+ }
+
+ Tox_Event event;
+ event.type = TOX_EVENT_GROUP_PASSWORD;
+ event.data.group_password = group_password;
+
+ tox_events_add(events, &event);
+ return group_password;
+}
+
+bool tox_event_group_password_unpack(
+ Tox_Event_Group_Password **event, Bin_Unpack *bu, const Memory *mem)
+{
+ assert(event != nullptr);
+ assert(*event == nullptr);
+ *event = tox_event_group_password_new(mem);
+
+ if (*event == nullptr) {
+ return false;
+ }
+
+ return tox_event_group_password_unpack_into(*event, bu);
+}
+
+non_null()
+static Tox_Event_Group_Password *tox_event_group_password_alloc(void *user_data)
+{
+ Tox_Events_State *state = tox_events_alloc(user_data);
+ assert(state != nullptr);
+
+ if (state->events == nullptr) {
+ return nullptr;
+ }
+
+ Tox_Event_Group_Password *group_password = tox_events_add_group_password(state->events, state->mem);
+
+ if (group_password == nullptr) {
+ state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
+ return nullptr;
+ }
+
+ return group_password;
+}
+
+/*****************************************************
+ *
+ * :: event handler
+ *
+ *****************************************************/
+
+void tox_events_handle_group_password(
+ Tox *tox, uint32_t group_number, const uint8_t *password, size_t length,
+ void *user_data)
+{
+ Tox_Event_Group_Password *group_password = tox_event_group_password_alloc(user_data);
+
+ if (group_password == nullptr) {
+ return;
+ }
+
+ tox_event_group_password_set_group_number(group_password, group_number);
+ tox_event_group_password_set_password(group_password, password, length);
+}
diff --git a/protocols/Tox/libtox/src/toxcore/events/group_peer_exit.c b/protocols/Tox/libtox/src/toxcore/events/group_peer_exit.c
new file mode 100644
index 0000000000..16d1eba7a6
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/events/group_peer_exit.c
@@ -0,0 +1,299 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2023-2024 The TokTok team.
+ */
+
+#include "events_alloc.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../attributes.h"
+#include "../bin_pack.h"
+#include "../bin_unpack.h"
+#include "../ccompat.h"
+#include "../mem.h"
+#include "../tox.h"
+#include "../tox_events.h"
+#include "../tox_pack.h"
+#include "../tox_unpack.h"
+
+/*****************************************************
+ *
+ * :: struct and accessors
+ *
+ *****************************************************/
+
+struct Tox_Event_Group_Peer_Exit {
+ uint32_t group_number;
+ uint32_t peer_id;
+ Tox_Group_Exit_Type exit_type;
+ uint8_t *name;
+ uint32_t name_length;
+ uint8_t *part_message;
+ uint32_t part_message_length;
+};
+
+non_null()
+static void tox_event_group_peer_exit_set_group_number(Tox_Event_Group_Peer_Exit *group_peer_exit,
+ uint32_t group_number)
+{
+ assert(group_peer_exit != nullptr);
+ group_peer_exit->group_number = group_number;
+}
+uint32_t tox_event_group_peer_exit_get_group_number(const Tox_Event_Group_Peer_Exit *group_peer_exit)
+{
+ assert(group_peer_exit != nullptr);
+ return group_peer_exit->group_number;
+}
+
+non_null()
+static void tox_event_group_peer_exit_set_peer_id(Tox_Event_Group_Peer_Exit *group_peer_exit,
+ uint32_t peer_id)
+{
+ assert(group_peer_exit != nullptr);
+ group_peer_exit->peer_id = peer_id;
+}
+uint32_t tox_event_group_peer_exit_get_peer_id(const Tox_Event_Group_Peer_Exit *group_peer_exit)
+{
+ assert(group_peer_exit != nullptr);
+ return group_peer_exit->peer_id;
+}
+
+non_null()
+static void tox_event_group_peer_exit_set_exit_type(Tox_Event_Group_Peer_Exit *group_peer_exit,
+ Tox_Group_Exit_Type exit_type)
+{
+ assert(group_peer_exit != nullptr);
+ group_peer_exit->exit_type = exit_type;
+}
+Tox_Group_Exit_Type tox_event_group_peer_exit_get_exit_type(const Tox_Event_Group_Peer_Exit *group_peer_exit)
+{
+ assert(group_peer_exit != nullptr);
+ return group_peer_exit->exit_type;
+}
+
+non_null(1) nullable(2)
+static bool tox_event_group_peer_exit_set_name(Tox_Event_Group_Peer_Exit *group_peer_exit,
+ const uint8_t *name, uint32_t name_length)
+{
+ assert(group_peer_exit != nullptr);
+
+ if (group_peer_exit->name != nullptr) {
+ free(group_peer_exit->name);
+ group_peer_exit->name = nullptr;
+ group_peer_exit->name_length = 0;
+ }
+
+ if (name == nullptr) {
+ assert(name_length == 0);
+ return true;
+ }
+
+ uint8_t *name_copy = (uint8_t *)malloc(name_length);
+
+ if (name_copy == nullptr) {
+ return false;
+ }
+
+ memcpy(name_copy, name, name_length);
+ group_peer_exit->name = name_copy;
+ group_peer_exit->name_length = name_length;
+ return true;
+}
+uint32_t tox_event_group_peer_exit_get_name_length(const Tox_Event_Group_Peer_Exit *group_peer_exit)
+{
+ assert(group_peer_exit != nullptr);
+ return group_peer_exit->name_length;
+}
+const uint8_t *tox_event_group_peer_exit_get_name(const Tox_Event_Group_Peer_Exit *group_peer_exit)
+{
+ assert(group_peer_exit != nullptr);
+ return group_peer_exit->name;
+}
+
+non_null(1) nullable(2)
+static bool tox_event_group_peer_exit_set_part_message(Tox_Event_Group_Peer_Exit *group_peer_exit,
+ const uint8_t *part_message, uint32_t part_message_length)
+{
+ assert(group_peer_exit != nullptr);
+
+ if (group_peer_exit->part_message != nullptr) {
+ free(group_peer_exit->part_message);
+ group_peer_exit->part_message = nullptr;
+ group_peer_exit->part_message_length = 0;
+ }
+
+ if (part_message == nullptr) {
+ assert(part_message_length == 0);
+ return true;
+ }
+
+ uint8_t *part_message_copy = (uint8_t *)malloc(part_message_length);
+
+ if (part_message_copy == nullptr) {
+ return false;
+ }
+
+ memcpy(part_message_copy, part_message, part_message_length);
+ group_peer_exit->part_message = part_message_copy;
+ group_peer_exit->part_message_length = part_message_length;
+ return true;
+}
+uint32_t tox_event_group_peer_exit_get_part_message_length(const Tox_Event_Group_Peer_Exit *group_peer_exit)
+{
+ assert(group_peer_exit != nullptr);
+ return group_peer_exit->part_message_length;
+}
+const uint8_t *tox_event_group_peer_exit_get_part_message(const Tox_Event_Group_Peer_Exit *group_peer_exit)
+{
+ assert(group_peer_exit != nullptr);
+ return group_peer_exit->part_message;
+}
+
+non_null()
+static void tox_event_group_peer_exit_construct(Tox_Event_Group_Peer_Exit *group_peer_exit)
+{
+ *group_peer_exit = (Tox_Event_Group_Peer_Exit) {
+ 0
+ };
+}
+non_null()
+static void tox_event_group_peer_exit_destruct(Tox_Event_Group_Peer_Exit *group_peer_exit, const Memory *mem)
+{
+ free(group_peer_exit->name);
+ free(group_peer_exit->part_message);
+}
+
+bool tox_event_group_peer_exit_pack(
+ const Tox_Event_Group_Peer_Exit *event, Bin_Pack *bp)
+{
+ return bin_pack_array(bp, 5)
+ && bin_pack_u32(bp, event->group_number)
+ && bin_pack_u32(bp, event->peer_id)
+ && tox_group_exit_type_pack(event->exit_type, bp)
+ && bin_pack_bin(bp, event->name, event->name_length)
+ && bin_pack_bin(bp, event->part_message, event->part_message_length);
+}
+
+non_null()
+static bool tox_event_group_peer_exit_unpack_into(
+ Tox_Event_Group_Peer_Exit *event, Bin_Unpack *bu)
+{
+ assert(event != nullptr);
+ if (!bin_unpack_array_fixed(bu, 5, nullptr)) {
+ return false;
+ }
+
+ return bin_unpack_u32(bu, &event->group_number)
+ && bin_unpack_u32(bu, &event->peer_id)
+ && tox_group_exit_type_unpack(&event->exit_type, bu)
+ && bin_unpack_bin(bu, &event->name, &event->name_length)
+ && bin_unpack_bin(bu, &event->part_message, &event->part_message_length);
+}
+
+/*****************************************************
+ *
+ * :: new/free/add/get/size/unpack
+ *
+ *****************************************************/
+
+const Tox_Event_Group_Peer_Exit *tox_event_get_group_peer_exit(const Tox_Event *event)
+{
+ return event->type == TOX_EVENT_GROUP_PEER_EXIT ? event->data.group_peer_exit : nullptr;
+}
+
+Tox_Event_Group_Peer_Exit *tox_event_group_peer_exit_new(const Memory *mem)
+{
+ Tox_Event_Group_Peer_Exit *const group_peer_exit =
+ (Tox_Event_Group_Peer_Exit *)mem_alloc(mem, sizeof(Tox_Event_Group_Peer_Exit));
+
+ if (group_peer_exit == nullptr) {
+ return nullptr;
+ }
+
+ tox_event_group_peer_exit_construct(group_peer_exit);
+ return group_peer_exit;
+}
+
+void tox_event_group_peer_exit_free(Tox_Event_Group_Peer_Exit *group_peer_exit, const Memory *mem)
+{
+ if (group_peer_exit != nullptr) {
+ tox_event_group_peer_exit_destruct(group_peer_exit, mem);
+ }
+ mem_delete(mem, group_peer_exit);
+}
+
+non_null()
+static Tox_Event_Group_Peer_Exit *tox_events_add_group_peer_exit(Tox_Events *events, const Memory *mem)
+{
+ Tox_Event_Group_Peer_Exit *const group_peer_exit = tox_event_group_peer_exit_new(mem);
+
+ if (group_peer_exit == nullptr) {
+ return nullptr;
+ }
+
+ Tox_Event event;
+ event.type = TOX_EVENT_GROUP_PEER_EXIT;
+ event.data.group_peer_exit = group_peer_exit;
+
+ tox_events_add(events, &event);
+ return group_peer_exit;
+}
+
+bool tox_event_group_peer_exit_unpack(
+ Tox_Event_Group_Peer_Exit **event, Bin_Unpack *bu, const Memory *mem)
+{
+ assert(event != nullptr);
+ assert(*event == nullptr);
+ *event = tox_event_group_peer_exit_new(mem);
+
+ if (*event == nullptr) {
+ return false;
+ }
+
+ return tox_event_group_peer_exit_unpack_into(*event, bu);
+}
+
+non_null()
+static Tox_Event_Group_Peer_Exit *tox_event_group_peer_exit_alloc(void *user_data)
+{
+ Tox_Events_State *state = tox_events_alloc(user_data);
+ assert(state != nullptr);
+
+ if (state->events == nullptr) {
+ return nullptr;
+ }
+
+ Tox_Event_Group_Peer_Exit *group_peer_exit = tox_events_add_group_peer_exit(state->events, state->mem);
+
+ if (group_peer_exit == nullptr) {
+ state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
+ return nullptr;
+ }
+
+ return group_peer_exit;
+}
+
+/*****************************************************
+ *
+ * :: event handler
+ *
+ *****************************************************/
+
+void tox_events_handle_group_peer_exit(
+ Tox *tox, uint32_t group_number, uint32_t peer_id, Tox_Group_Exit_Type exit_type, const uint8_t *name, size_t name_length, const uint8_t *part_message, size_t part_message_length,
+ void *user_data)
+{
+ Tox_Event_Group_Peer_Exit *group_peer_exit = tox_event_group_peer_exit_alloc(user_data);
+
+ if (group_peer_exit == nullptr) {
+ return;
+ }
+
+ tox_event_group_peer_exit_set_group_number(group_peer_exit, group_number);
+ tox_event_group_peer_exit_set_peer_id(group_peer_exit, peer_id);
+ tox_event_group_peer_exit_set_exit_type(group_peer_exit, exit_type);
+ tox_event_group_peer_exit_set_name(group_peer_exit, name, name_length);
+ tox_event_group_peer_exit_set_part_message(group_peer_exit, part_message, part_message_length);
+}
diff --git a/protocols/Tox/libtox/src/toxcore/events/group_peer_join.c b/protocols/Tox/libtox/src/toxcore/events/group_peer_join.c
new file mode 100644
index 0000000000..af0d006e87
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/events/group_peer_join.c
@@ -0,0 +1,189 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2023-2024 The TokTok team.
+ */
+
+#include "events_alloc.h"
+
+#include <assert.h>
+
+#include "../attributes.h"
+#include "../bin_pack.h"
+#include "../bin_unpack.h"
+#include "../ccompat.h"
+#include "../mem.h"
+#include "../tox.h"
+#include "../tox_events.h"
+
+/*****************************************************
+ *
+ * :: struct and accessors
+ *
+ *****************************************************/
+
+struct Tox_Event_Group_Peer_Join {
+ uint32_t group_number;
+ uint32_t peer_id;
+};
+
+non_null()
+static void tox_event_group_peer_join_set_group_number(Tox_Event_Group_Peer_Join *group_peer_join,
+ uint32_t group_number)
+{
+ assert(group_peer_join != nullptr);
+ group_peer_join->group_number = group_number;
+}
+uint32_t tox_event_group_peer_join_get_group_number(const Tox_Event_Group_Peer_Join *group_peer_join)
+{
+ assert(group_peer_join != nullptr);
+ return group_peer_join->group_number;
+}
+
+non_null()
+static void tox_event_group_peer_join_set_peer_id(Tox_Event_Group_Peer_Join *group_peer_join,
+ uint32_t peer_id)
+{
+ assert(group_peer_join != nullptr);
+ group_peer_join->peer_id = peer_id;
+}
+uint32_t tox_event_group_peer_join_get_peer_id(const Tox_Event_Group_Peer_Join *group_peer_join)
+{
+ assert(group_peer_join != nullptr);
+ return group_peer_join->peer_id;
+}
+
+non_null()
+static void tox_event_group_peer_join_construct(Tox_Event_Group_Peer_Join *group_peer_join)
+{
+ *group_peer_join = (Tox_Event_Group_Peer_Join) {
+ 0
+ };
+}
+non_null()
+static void tox_event_group_peer_join_destruct(Tox_Event_Group_Peer_Join *group_peer_join, const Memory *mem)
+{
+ return;
+}
+
+bool tox_event_group_peer_join_pack(
+ const Tox_Event_Group_Peer_Join *event, Bin_Pack *bp)
+{
+ return bin_pack_array(bp, 2)
+ && bin_pack_u32(bp, event->group_number)
+ && bin_pack_u32(bp, event->peer_id);
+}
+
+non_null()
+static bool tox_event_group_peer_join_unpack_into(
+ Tox_Event_Group_Peer_Join *event, Bin_Unpack *bu)
+{
+ assert(event != nullptr);
+ if (!bin_unpack_array_fixed(bu, 2, nullptr)) {
+ return false;
+ }
+
+ return bin_unpack_u32(bu, &event->group_number)
+ && bin_unpack_u32(bu, &event->peer_id);
+}
+
+/*****************************************************
+ *
+ * :: new/free/add/get/size/unpack
+ *
+ *****************************************************/
+
+const Tox_Event_Group_Peer_Join *tox_event_get_group_peer_join(const Tox_Event *event)
+{
+ return event->type == TOX_EVENT_GROUP_PEER_JOIN ? event->data.group_peer_join : nullptr;
+}
+
+Tox_Event_Group_Peer_Join *tox_event_group_peer_join_new(const Memory *mem)
+{
+ Tox_Event_Group_Peer_Join *const group_peer_join =
+ (Tox_Event_Group_Peer_Join *)mem_alloc(mem, sizeof(Tox_Event_Group_Peer_Join));
+
+ if (group_peer_join == nullptr) {
+ return nullptr;
+ }
+
+ tox_event_group_peer_join_construct(group_peer_join);
+ return group_peer_join;
+}
+
+void tox_event_group_peer_join_free(Tox_Event_Group_Peer_Join *group_peer_join, const Memory *mem)
+{
+ if (group_peer_join != nullptr) {
+ tox_event_group_peer_join_destruct(group_peer_join, mem);
+ }
+ mem_delete(mem, group_peer_join);
+}
+
+non_null()
+static Tox_Event_Group_Peer_Join *tox_events_add_group_peer_join(Tox_Events *events, const Memory *mem)
+{
+ Tox_Event_Group_Peer_Join *const group_peer_join = tox_event_group_peer_join_new(mem);
+
+ if (group_peer_join == nullptr) {
+ return nullptr;
+ }
+
+ Tox_Event event;
+ event.type = TOX_EVENT_GROUP_PEER_JOIN;
+ event.data.group_peer_join = group_peer_join;
+
+ tox_events_add(events, &event);
+ return group_peer_join;
+}
+
+bool tox_event_group_peer_join_unpack(
+ Tox_Event_Group_Peer_Join **event, Bin_Unpack *bu, const Memory *mem)
+{
+ assert(event != nullptr);
+ assert(*event == nullptr);
+ *event = tox_event_group_peer_join_new(mem);
+
+ if (*event == nullptr) {
+ return false;
+ }
+
+ return tox_event_group_peer_join_unpack_into(*event, bu);
+}
+
+non_null()
+static Tox_Event_Group_Peer_Join *tox_event_group_peer_join_alloc(void *user_data)
+{
+ Tox_Events_State *state = tox_events_alloc(user_data);
+ assert(state != nullptr);
+
+ if (state->events == nullptr) {
+ return nullptr;
+ }
+
+ Tox_Event_Group_Peer_Join *group_peer_join = tox_events_add_group_peer_join(state->events, state->mem);
+
+ if (group_peer_join == nullptr) {
+ state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
+ return nullptr;
+ }
+
+ return group_peer_join;
+}
+
+/*****************************************************
+ *
+ * :: event handler
+ *
+ *****************************************************/
+
+void tox_events_handle_group_peer_join(
+ Tox *tox, uint32_t group_number, uint32_t peer_id,
+ void *user_data)
+{
+ Tox_Event_Group_Peer_Join *group_peer_join = tox_event_group_peer_join_alloc(user_data);
+
+ if (group_peer_join == nullptr) {
+ return;
+ }
+
+ tox_event_group_peer_join_set_group_number(group_peer_join, group_number);
+ tox_event_group_peer_join_set_peer_id(group_peer_join, peer_id);
+}
diff --git a/protocols/Tox/libtox/src/toxcore/events/group_peer_limit.c b/protocols/Tox/libtox/src/toxcore/events/group_peer_limit.c
new file mode 100644
index 0000000000..5e2e23558c
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/events/group_peer_limit.c
@@ -0,0 +1,189 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2023-2024 The TokTok team.
+ */
+
+#include "events_alloc.h"
+
+#include <assert.h>
+
+#include "../attributes.h"
+#include "../bin_pack.h"
+#include "../bin_unpack.h"
+#include "../ccompat.h"
+#include "../mem.h"
+#include "../tox.h"
+#include "../tox_events.h"
+
+/*****************************************************
+ *
+ * :: struct and accessors
+ *
+ *****************************************************/
+
+struct Tox_Event_Group_Peer_Limit {
+ uint32_t group_number;
+ uint32_t peer_limit;
+};
+
+non_null()
+static void tox_event_group_peer_limit_set_group_number(Tox_Event_Group_Peer_Limit *group_peer_limit,
+ uint32_t group_number)
+{
+ assert(group_peer_limit != nullptr);
+ group_peer_limit->group_number = group_number;
+}
+uint32_t tox_event_group_peer_limit_get_group_number(const Tox_Event_Group_Peer_Limit *group_peer_limit)
+{
+ assert(group_peer_limit != nullptr);
+ return group_peer_limit->group_number;
+}
+
+non_null()
+static void tox_event_group_peer_limit_set_peer_limit(Tox_Event_Group_Peer_Limit *group_peer_limit,
+ uint32_t peer_limit)
+{
+ assert(group_peer_limit != nullptr);
+ group_peer_limit->peer_limit = peer_limit;
+}
+uint32_t tox_event_group_peer_limit_get_peer_limit(const Tox_Event_Group_Peer_Limit *group_peer_limit)
+{
+ assert(group_peer_limit != nullptr);
+ return group_peer_limit->peer_limit;
+}
+
+non_null()
+static void tox_event_group_peer_limit_construct(Tox_Event_Group_Peer_Limit *group_peer_limit)
+{
+ *group_peer_limit = (Tox_Event_Group_Peer_Limit) {
+ 0
+ };
+}
+non_null()
+static void tox_event_group_peer_limit_destruct(Tox_Event_Group_Peer_Limit *group_peer_limit, const Memory *mem)
+{
+ return;
+}
+
+bool tox_event_group_peer_limit_pack(
+ const Tox_Event_Group_Peer_Limit *event, Bin_Pack *bp)
+{
+ return bin_pack_array(bp, 2)
+ && bin_pack_u32(bp, event->group_number)
+ && bin_pack_u32(bp, event->peer_limit);
+}
+
+non_null()
+static bool tox_event_group_peer_limit_unpack_into(
+ Tox_Event_Group_Peer_Limit *event, Bin_Unpack *bu)
+{
+ assert(event != nullptr);
+ if (!bin_unpack_array_fixed(bu, 2, nullptr)) {
+ return false;
+ }
+
+ return bin_unpack_u32(bu, &event->group_number)
+ && bin_unpack_u32(bu, &event->peer_limit);
+}
+
+/*****************************************************
+ *
+ * :: new/free/add/get/size/unpack
+ *
+ *****************************************************/
+
+const Tox_Event_Group_Peer_Limit *tox_event_get_group_peer_limit(const Tox_Event *event)
+{
+ return event->type == TOX_EVENT_GROUP_PEER_LIMIT ? event->data.group_peer_limit : nullptr;
+}
+
+Tox_Event_Group_Peer_Limit *tox_event_group_peer_limit_new(const Memory *mem)
+{
+ Tox_Event_Group_Peer_Limit *const group_peer_limit =
+ (Tox_Event_Group_Peer_Limit *)mem_alloc(mem, sizeof(Tox_Event_Group_Peer_Limit));
+
+ if (group_peer_limit == nullptr) {
+ return nullptr;
+ }
+
+ tox_event_group_peer_limit_construct(group_peer_limit);
+ return group_peer_limit;
+}
+
+void tox_event_group_peer_limit_free(Tox_Event_Group_Peer_Limit *group_peer_limit, const Memory *mem)
+{
+ if (group_peer_limit != nullptr) {
+ tox_event_group_peer_limit_destruct(group_peer_limit, mem);
+ }
+ mem_delete(mem, group_peer_limit);
+}
+
+non_null()
+static Tox_Event_Group_Peer_Limit *tox_events_add_group_peer_limit(Tox_Events *events, const Memory *mem)
+{
+ Tox_Event_Group_Peer_Limit *const group_peer_limit = tox_event_group_peer_limit_new(mem);
+
+ if (group_peer_limit == nullptr) {
+ return nullptr;
+ }
+
+ Tox_Event event;
+ event.type = TOX_EVENT_GROUP_PEER_LIMIT;
+ event.data.group_peer_limit = group_peer_limit;
+
+ tox_events_add(events, &event);
+ return group_peer_limit;
+}
+
+bool tox_event_group_peer_limit_unpack(
+ Tox_Event_Group_Peer_Limit **event, Bin_Unpack *bu, const Memory *mem)
+{
+ assert(event != nullptr);
+ assert(*event == nullptr);
+ *event = tox_event_group_peer_limit_new(mem);
+
+ if (*event == nullptr) {
+ return false;
+ }
+
+ return tox_event_group_peer_limit_unpack_into(*event, bu);
+}
+
+non_null()
+static Tox_Event_Group_Peer_Limit *tox_event_group_peer_limit_alloc(void *user_data)
+{
+ Tox_Events_State *state = tox_events_alloc(user_data);
+ assert(state != nullptr);
+
+ if (state->events == nullptr) {
+ return nullptr;
+ }
+
+ Tox_Event_Group_Peer_Limit *group_peer_limit = tox_events_add_group_peer_limit(state->events, state->mem);
+
+ if (group_peer_limit == nullptr) {
+ state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
+ return nullptr;
+ }
+
+ return group_peer_limit;
+}
+
+/*****************************************************
+ *
+ * :: event handler
+ *
+ *****************************************************/
+
+void tox_events_handle_group_peer_limit(
+ Tox *tox, uint32_t group_number, uint32_t peer_limit,
+ void *user_data)
+{
+ Tox_Event_Group_Peer_Limit *group_peer_limit = tox_event_group_peer_limit_alloc(user_data);
+
+ if (group_peer_limit == nullptr) {
+ return;
+ }
+
+ tox_event_group_peer_limit_set_group_number(group_peer_limit, group_number);
+ tox_event_group_peer_limit_set_peer_limit(group_peer_limit, peer_limit);
+}
diff --git a/protocols/Tox/libtox/src/toxcore/events/group_peer_name.c b/protocols/Tox/libtox/src/toxcore/events/group_peer_name.c
new file mode 100644
index 0000000000..f8273e94b4
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/events/group_peer_name.c
@@ -0,0 +1,235 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2023-2024 The TokTok team.
+ */
+
+#include "events_alloc.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../attributes.h"
+#include "../bin_pack.h"
+#include "../bin_unpack.h"
+#include "../ccompat.h"
+#include "../mem.h"
+#include "../tox.h"
+#include "../tox_events.h"
+
+/*****************************************************
+ *
+ * :: struct and accessors
+ *
+ *****************************************************/
+
+struct Tox_Event_Group_Peer_Name {
+ uint32_t group_number;
+ uint32_t peer_id;
+ uint8_t *name;
+ uint32_t name_length;
+};
+
+non_null()
+static void tox_event_group_peer_name_set_group_number(Tox_Event_Group_Peer_Name *group_peer_name,
+ uint32_t group_number)
+{
+ assert(group_peer_name != nullptr);
+ group_peer_name->group_number = group_number;
+}
+uint32_t tox_event_group_peer_name_get_group_number(const Tox_Event_Group_Peer_Name *group_peer_name)
+{
+ assert(group_peer_name != nullptr);
+ return group_peer_name->group_number;
+}
+
+non_null()
+static void tox_event_group_peer_name_set_peer_id(Tox_Event_Group_Peer_Name *group_peer_name,
+ uint32_t peer_id)
+{
+ assert(group_peer_name != nullptr);
+ group_peer_name->peer_id = peer_id;
+}
+uint32_t tox_event_group_peer_name_get_peer_id(const Tox_Event_Group_Peer_Name *group_peer_name)
+{
+ assert(group_peer_name != nullptr);
+ return group_peer_name->peer_id;
+}
+
+non_null(1) nullable(2)
+static bool tox_event_group_peer_name_set_name(Tox_Event_Group_Peer_Name *group_peer_name,
+ const uint8_t *name, uint32_t name_length)
+{
+ assert(group_peer_name != nullptr);
+
+ if (group_peer_name->name != nullptr) {
+ free(group_peer_name->name);
+ group_peer_name->name = nullptr;
+ group_peer_name->name_length = 0;
+ }
+
+ if (name == nullptr) {
+ assert(name_length == 0);
+ return true;
+ }
+
+ uint8_t *name_copy = (uint8_t *)malloc(name_length);
+
+ if (name_copy == nullptr) {
+ return false;
+ }
+
+ memcpy(name_copy, name, name_length);
+ group_peer_name->name = name_copy;
+ group_peer_name->name_length = name_length;
+ return true;
+}
+uint32_t tox_event_group_peer_name_get_name_length(const Tox_Event_Group_Peer_Name *group_peer_name)
+{
+ assert(group_peer_name != nullptr);
+ return group_peer_name->name_length;
+}
+const uint8_t *tox_event_group_peer_name_get_name(const Tox_Event_Group_Peer_Name *group_peer_name)
+{
+ assert(group_peer_name != nullptr);
+ return group_peer_name->name;
+}
+
+non_null()
+static void tox_event_group_peer_name_construct(Tox_Event_Group_Peer_Name *group_peer_name)
+{
+ *group_peer_name = (Tox_Event_Group_Peer_Name) {
+ 0
+ };
+}
+non_null()
+static void tox_event_group_peer_name_destruct(Tox_Event_Group_Peer_Name *group_peer_name, const Memory *mem)
+{
+ free(group_peer_name->name);
+}
+
+bool tox_event_group_peer_name_pack(
+ const Tox_Event_Group_Peer_Name *event, Bin_Pack *bp)
+{
+ return bin_pack_array(bp, 3)
+ && bin_pack_u32(bp, event->group_number)
+ && bin_pack_u32(bp, event->peer_id)
+ && bin_pack_bin(bp, event->name, event->name_length);
+}
+
+non_null()
+static bool tox_event_group_peer_name_unpack_into(
+ Tox_Event_Group_Peer_Name *event, Bin_Unpack *bu)
+{
+ assert(event != nullptr);
+ if (!bin_unpack_array_fixed(bu, 3, nullptr)) {
+ return false;
+ }
+
+ return bin_unpack_u32(bu, &event->group_number)
+ && bin_unpack_u32(bu, &event->peer_id)
+ && bin_unpack_bin(bu, &event->name, &event->name_length);
+}
+
+/*****************************************************
+ *
+ * :: new/free/add/get/size/unpack
+ *
+ *****************************************************/
+
+const Tox_Event_Group_Peer_Name *tox_event_get_group_peer_name(const Tox_Event *event)
+{
+ return event->type == TOX_EVENT_GROUP_PEER_NAME ? event->data.group_peer_name : nullptr;
+}
+
+Tox_Event_Group_Peer_Name *tox_event_group_peer_name_new(const Memory *mem)
+{
+ Tox_Event_Group_Peer_Name *const group_peer_name =
+ (Tox_Event_Group_Peer_Name *)mem_alloc(mem, sizeof(Tox_Event_Group_Peer_Name));
+
+ if (group_peer_name == nullptr) {
+ return nullptr;
+ }
+
+ tox_event_group_peer_name_construct(group_peer_name);
+ return group_peer_name;
+}
+
+void tox_event_group_peer_name_free(Tox_Event_Group_Peer_Name *group_peer_name, const Memory *mem)
+{
+ if (group_peer_name != nullptr) {
+ tox_event_group_peer_name_destruct(group_peer_name, mem);
+ }
+ mem_delete(mem, group_peer_name);
+}
+
+non_null()
+static Tox_Event_Group_Peer_Name *tox_events_add_group_peer_name(Tox_Events *events, const Memory *mem)
+{
+ Tox_Event_Group_Peer_Name *const group_peer_name = tox_event_group_peer_name_new(mem);
+
+ if (group_peer_name == nullptr) {
+ return nullptr;
+ }
+
+ Tox_Event event;
+ event.type = TOX_EVENT_GROUP_PEER_NAME;
+ event.data.group_peer_name = group_peer_name;
+
+ tox_events_add(events, &event);
+ return group_peer_name;
+}
+
+bool tox_event_group_peer_name_unpack(
+ Tox_Event_Group_Peer_Name **event, Bin_Unpack *bu, const Memory *mem)
+{
+ assert(event != nullptr);
+ assert(*event == nullptr);
+ *event = tox_event_group_peer_name_new(mem);
+
+ if (*event == nullptr) {
+ return false;
+ }
+
+ return tox_event_group_peer_name_unpack_into(*event, bu);
+}
+
+non_null()
+static Tox_Event_Group_Peer_Name *tox_event_group_peer_name_alloc(void *user_data)
+{
+ Tox_Events_State *state = tox_events_alloc(user_data);
+ assert(state != nullptr);
+
+ if (state->events == nullptr) {
+ return nullptr;
+ }
+
+ Tox_Event_Group_Peer_Name *group_peer_name = tox_events_add_group_peer_name(state->events, state->mem);
+
+ if (group_peer_name == nullptr) {
+ state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
+ return nullptr;
+ }
+
+ return group_peer_name;
+}
+
+/*****************************************************
+ *
+ * :: event handler
+ *
+ *****************************************************/
+
+void tox_events_handle_group_peer_name(
+ Tox *tox, uint32_t group_number, uint32_t peer_id, const uint8_t *name, size_t length,
+ void *user_data)
+{
+ Tox_Event_Group_Peer_Name *group_peer_name = tox_event_group_peer_name_alloc(user_data);
+
+ if (group_peer_name == nullptr) {
+ return;
+ }
+
+ tox_event_group_peer_name_set_group_number(group_peer_name, group_number);
+ tox_event_group_peer_name_set_peer_id(group_peer_name, peer_id);
+ tox_event_group_peer_name_set_name(group_peer_name, name, length);
+}
diff --git a/protocols/Tox/libtox/src/toxcore/events/group_peer_status.c b/protocols/Tox/libtox/src/toxcore/events/group_peer_status.c
new file mode 100644
index 0000000000..4165d90ec2
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/events/group_peer_status.c
@@ -0,0 +1,208 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2023-2024 The TokTok team.
+ */
+
+#include "events_alloc.h"
+
+#include <assert.h>
+
+#include "../attributes.h"
+#include "../bin_pack.h"
+#include "../bin_unpack.h"
+#include "../ccompat.h"
+#include "../mem.h"
+#include "../tox.h"
+#include "../tox_events.h"
+#include "../tox_pack.h"
+#include "../tox_unpack.h"
+
+/*****************************************************
+ *
+ * :: struct and accessors
+ *
+ *****************************************************/
+
+struct Tox_Event_Group_Peer_Status {
+ uint32_t group_number;
+ uint32_t peer_id;
+ Tox_User_Status status;
+};
+
+non_null()
+static void tox_event_group_peer_status_set_group_number(Tox_Event_Group_Peer_Status *group_peer_status,
+ uint32_t group_number)
+{
+ assert(group_peer_status != nullptr);
+ group_peer_status->group_number = group_number;
+}
+uint32_t tox_event_group_peer_status_get_group_number(const Tox_Event_Group_Peer_Status *group_peer_status)
+{
+ assert(group_peer_status != nullptr);
+ return group_peer_status->group_number;
+}
+
+non_null()
+static void tox_event_group_peer_status_set_peer_id(Tox_Event_Group_Peer_Status *group_peer_status,
+ uint32_t peer_id)
+{
+ assert(group_peer_status != nullptr);
+ group_peer_status->peer_id = peer_id;
+}
+uint32_t tox_event_group_peer_status_get_peer_id(const Tox_Event_Group_Peer_Status *group_peer_status)
+{
+ assert(group_peer_status != nullptr);
+ return group_peer_status->peer_id;
+}
+
+non_null()
+static void tox_event_group_peer_status_set_status(Tox_Event_Group_Peer_Status *group_peer_status,
+ Tox_User_Status status)
+{
+ assert(group_peer_status != nullptr);
+ group_peer_status->status = status;
+}
+Tox_User_Status tox_event_group_peer_status_get_status(const Tox_Event_Group_Peer_Status *group_peer_status)
+{
+ assert(group_peer_status != nullptr);
+ return group_peer_status->status;
+}
+
+non_null()
+static void tox_event_group_peer_status_construct(Tox_Event_Group_Peer_Status *group_peer_status)
+{
+ *group_peer_status = (Tox_Event_Group_Peer_Status) {
+ 0
+ };
+}
+non_null()
+static void tox_event_group_peer_status_destruct(Tox_Event_Group_Peer_Status *group_peer_status, const Memory *mem)
+{
+ return;
+}
+
+bool tox_event_group_peer_status_pack(
+ const Tox_Event_Group_Peer_Status *event, Bin_Pack *bp)
+{
+ return bin_pack_array(bp, 3)
+ && bin_pack_u32(bp, event->group_number)
+ && bin_pack_u32(bp, event->peer_id)
+ && tox_user_status_pack(event->status, bp);
+}
+
+non_null()
+static bool tox_event_group_peer_status_unpack_into(
+ Tox_Event_Group_Peer_Status *event, Bin_Unpack *bu)
+{
+ assert(event != nullptr);
+ if (!bin_unpack_array_fixed(bu, 3, nullptr)) {
+ return false;
+ }
+
+ return bin_unpack_u32(bu, &event->group_number)
+ && bin_unpack_u32(bu, &event->peer_id)
+ && tox_user_status_unpack(&event->status, bu);
+}
+
+/*****************************************************
+ *
+ * :: new/free/add/get/size/unpack
+ *
+ *****************************************************/
+
+const Tox_Event_Group_Peer_Status *tox_event_get_group_peer_status(const Tox_Event *event)
+{
+ return event->type == TOX_EVENT_GROUP_PEER_STATUS ? event->data.group_peer_status : nullptr;
+}
+
+Tox_Event_Group_Peer_Status *tox_event_group_peer_status_new(const Memory *mem)
+{
+ Tox_Event_Group_Peer_Status *const group_peer_status =
+ (Tox_Event_Group_Peer_Status *)mem_alloc(mem, sizeof(Tox_Event_Group_Peer_Status));
+
+ if (group_peer_status == nullptr) {
+ return nullptr;
+ }
+
+ tox_event_group_peer_status_construct(group_peer_status);
+ return group_peer_status;
+}
+
+void tox_event_group_peer_status_free(Tox_Event_Group_Peer_Status *group_peer_status, const Memory *mem)
+{
+ if (group_peer_status != nullptr) {
+ tox_event_group_peer_status_destruct(group_peer_status, mem);
+ }
+ mem_delete(mem, group_peer_status);
+}
+
+non_null()
+static Tox_Event_Group_Peer_Status *tox_events_add_group_peer_status(Tox_Events *events, const Memory *mem)
+{
+ Tox_Event_Group_Peer_Status *const group_peer_status = tox_event_group_peer_status_new(mem);
+
+ if (group_peer_status == nullptr) {
+ return nullptr;
+ }
+
+ Tox_Event event;
+ event.type = TOX_EVENT_GROUP_PEER_STATUS;
+ event.data.group_peer_status = group_peer_status;
+
+ tox_events_add(events, &event);
+ return group_peer_status;
+}
+
+bool tox_event_group_peer_status_unpack(
+ Tox_Event_Group_Peer_Status **event, Bin_Unpack *bu, const Memory *mem)
+{
+ assert(event != nullptr);
+ assert(*event == nullptr);
+ *event = tox_event_group_peer_status_new(mem);
+
+ if (*event == nullptr) {
+ return false;
+ }
+
+ return tox_event_group_peer_status_unpack_into(*event, bu);
+}
+
+non_null()
+static Tox_Event_Group_Peer_Status *tox_event_group_peer_status_alloc(void *user_data)
+{
+ Tox_Events_State *state = tox_events_alloc(user_data);
+ assert(state != nullptr);
+
+ if (state->events == nullptr) {
+ return nullptr;
+ }
+
+ Tox_Event_Group_Peer_Status *group_peer_status = tox_events_add_group_peer_status(state->events, state->mem);
+
+ if (group_peer_status == nullptr) {
+ state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
+ return nullptr;
+ }
+
+ return group_peer_status;
+}
+
+/*****************************************************
+ *
+ * :: event handler
+ *
+ *****************************************************/
+
+void tox_events_handle_group_peer_status(
+ Tox *tox, uint32_t group_number, uint32_t peer_id, Tox_User_Status status,
+ void *user_data)
+{
+ Tox_Event_Group_Peer_Status *group_peer_status = tox_event_group_peer_status_alloc(user_data);
+
+ if (group_peer_status == nullptr) {
+ return;
+ }
+
+ tox_event_group_peer_status_set_group_number(group_peer_status, group_number);
+ tox_event_group_peer_status_set_peer_id(group_peer_status, peer_id);
+ tox_event_group_peer_status_set_status(group_peer_status, status);
+}
diff --git a/protocols/Tox/libtox/src/toxcore/events/group_privacy_state.c b/protocols/Tox/libtox/src/toxcore/events/group_privacy_state.c
new file mode 100644
index 0000000000..1c683c255c
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/events/group_privacy_state.c
@@ -0,0 +1,191 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2023-2024 The TokTok team.
+ */
+
+#include "events_alloc.h"
+
+#include <assert.h>
+
+#include "../attributes.h"
+#include "../bin_pack.h"
+#include "../bin_unpack.h"
+#include "../ccompat.h"
+#include "../mem.h"
+#include "../tox.h"
+#include "../tox_events.h"
+#include "../tox_pack.h"
+#include "../tox_unpack.h"
+
+/*****************************************************
+ *
+ * :: struct and accessors
+ *
+ *****************************************************/
+
+struct Tox_Event_Group_Privacy_State {
+ uint32_t group_number;
+ Tox_Group_Privacy_State privacy_state;
+};
+
+non_null()
+static void tox_event_group_privacy_state_set_group_number(Tox_Event_Group_Privacy_State *group_privacy_state,
+ uint32_t group_number)
+{
+ assert(group_privacy_state != nullptr);
+ group_privacy_state->group_number = group_number;
+}
+uint32_t tox_event_group_privacy_state_get_group_number(const Tox_Event_Group_Privacy_State *group_privacy_state)
+{
+ assert(group_privacy_state != nullptr);
+ return group_privacy_state->group_number;
+}
+
+non_null()
+static void tox_event_group_privacy_state_set_privacy_state(Tox_Event_Group_Privacy_State *group_privacy_state,
+ Tox_Group_Privacy_State privacy_state)
+{
+ assert(group_privacy_state != nullptr);
+ group_privacy_state->privacy_state = privacy_state;
+}
+Tox_Group_Privacy_State tox_event_group_privacy_state_get_privacy_state(const Tox_Event_Group_Privacy_State *group_privacy_state)
+{
+ assert(group_privacy_state != nullptr);
+ return group_privacy_state->privacy_state;
+}
+
+non_null()
+static void tox_event_group_privacy_state_construct(Tox_Event_Group_Privacy_State *group_privacy_state)
+{
+ *group_privacy_state = (Tox_Event_Group_Privacy_State) {
+ 0
+ };
+}
+non_null()
+static void tox_event_group_privacy_state_destruct(Tox_Event_Group_Privacy_State *group_privacy_state, const Memory *mem)
+{
+ return;
+}
+
+bool tox_event_group_privacy_state_pack(
+ const Tox_Event_Group_Privacy_State *event, Bin_Pack *bp)
+{
+ return bin_pack_array(bp, 2)
+ && bin_pack_u32(bp, event->group_number)
+ && tox_group_privacy_state_pack(event->privacy_state, bp);
+}
+
+non_null()
+static bool tox_event_group_privacy_state_unpack_into(
+ Tox_Event_Group_Privacy_State *event, Bin_Unpack *bu)
+{
+ assert(event != nullptr);
+ if (!bin_unpack_array_fixed(bu, 2, nullptr)) {
+ return false;
+ }
+
+ return bin_unpack_u32(bu, &event->group_number)
+ && tox_group_privacy_state_unpack(&event->privacy_state, bu);
+}
+
+/*****************************************************
+ *
+ * :: new/free/add/get/size/unpack
+ *
+ *****************************************************/
+
+const Tox_Event_Group_Privacy_State *tox_event_get_group_privacy_state(const Tox_Event *event)
+{
+ return event->type == TOX_EVENT_GROUP_PRIVACY_STATE ? event->data.group_privacy_state : nullptr;
+}
+
+Tox_Event_Group_Privacy_State *tox_event_group_privacy_state_new(const Memory *mem)
+{
+ Tox_Event_Group_Privacy_State *const group_privacy_state =
+ (Tox_Event_Group_Privacy_State *)mem_alloc(mem, sizeof(Tox_Event_Group_Privacy_State));
+
+ if (group_privacy_state == nullptr) {
+ return nullptr;
+ }
+
+ tox_event_group_privacy_state_construct(group_privacy_state);
+ return group_privacy_state;
+}
+
+void tox_event_group_privacy_state_free(Tox_Event_Group_Privacy_State *group_privacy_state, const Memory *mem)
+{
+ if (group_privacy_state != nullptr) {
+ tox_event_group_privacy_state_destruct(group_privacy_state, mem);
+ }
+ mem_delete(mem, group_privacy_state);
+}
+
+non_null()
+static Tox_Event_Group_Privacy_State *tox_events_add_group_privacy_state(Tox_Events *events, const Memory *mem)
+{
+ Tox_Event_Group_Privacy_State *const group_privacy_state = tox_event_group_privacy_state_new(mem);
+
+ if (group_privacy_state == nullptr) {
+ return nullptr;
+ }
+
+ Tox_Event event;
+ event.type = TOX_EVENT_GROUP_PRIVACY_STATE;
+ event.data.group_privacy_state = group_privacy_state;
+
+ tox_events_add(events, &event);
+ return group_privacy_state;
+}
+
+bool tox_event_group_privacy_state_unpack(
+ Tox_Event_Group_Privacy_State **event, Bin_Unpack *bu, const Memory *mem)
+{
+ assert(event != nullptr);
+ assert(*event == nullptr);
+ *event = tox_event_group_privacy_state_new(mem);
+
+ if (*event == nullptr) {
+ return false;
+ }
+
+ return tox_event_group_privacy_state_unpack_into(*event, bu);
+}
+
+non_null()
+static Tox_Event_Group_Privacy_State *tox_event_group_privacy_state_alloc(void *user_data)
+{
+ Tox_Events_State *state = tox_events_alloc(user_data);
+ assert(state != nullptr);
+
+ if (state->events == nullptr) {
+ return nullptr;
+ }
+
+ Tox_Event_Group_Privacy_State *group_privacy_state = tox_events_add_group_privacy_state(state->events, state->mem);
+
+ if (group_privacy_state == nullptr) {
+ state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
+ return nullptr;
+ }
+
+ return group_privacy_state;
+}
+
+/*****************************************************
+ *
+ * :: event handler
+ *
+ *****************************************************/
+
+void tox_events_handle_group_privacy_state(
+ Tox *tox, uint32_t group_number, Tox_Group_Privacy_State privacy_state,
+ void *user_data)
+{
+ Tox_Event_Group_Privacy_State *group_privacy_state = tox_event_group_privacy_state_alloc(user_data);
+
+ if (group_privacy_state == nullptr) {
+ return;
+ }
+
+ tox_event_group_privacy_state_set_group_number(group_privacy_state, group_number);
+ tox_event_group_privacy_state_set_privacy_state(group_privacy_state, privacy_state);
+}
diff --git a/protocols/Tox/libtox/src/toxcore/events/group_private_message.c b/protocols/Tox/libtox/src/toxcore/events/group_private_message.c
new file mode 100644
index 0000000000..648f707880
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/events/group_private_message.c
@@ -0,0 +1,254 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2023-2024 The TokTok team.
+ */
+
+#include "events_alloc.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../attributes.h"
+#include "../bin_pack.h"
+#include "../bin_unpack.h"
+#include "../ccompat.h"
+#include "../mem.h"
+#include "../tox.h"
+#include "../tox_events.h"
+#include "../tox_pack.h"
+#include "../tox_unpack.h"
+
+/*****************************************************
+ *
+ * :: struct and accessors
+ *
+ *****************************************************/
+
+struct Tox_Event_Group_Private_Message {
+ uint32_t group_number;
+ uint32_t peer_id;
+ Tox_Message_Type type;
+ uint8_t *message;
+ uint32_t message_length;
+};
+
+non_null()
+static void tox_event_group_private_message_set_group_number(Tox_Event_Group_Private_Message *group_private_message,
+ uint32_t group_number)
+{
+ assert(group_private_message != nullptr);
+ group_private_message->group_number = group_number;
+}
+uint32_t tox_event_group_private_message_get_group_number(const Tox_Event_Group_Private_Message *group_private_message)
+{
+ assert(group_private_message != nullptr);
+ return group_private_message->group_number;
+}
+
+non_null()
+static void tox_event_group_private_message_set_peer_id(Tox_Event_Group_Private_Message *group_private_message,
+ uint32_t peer_id)
+{
+ assert(group_private_message != nullptr);
+ group_private_message->peer_id = peer_id;
+}
+uint32_t tox_event_group_private_message_get_peer_id(const Tox_Event_Group_Private_Message *group_private_message)
+{
+ assert(group_private_message != nullptr);
+ return group_private_message->peer_id;
+}
+
+non_null()
+static void tox_event_group_private_message_set_type(Tox_Event_Group_Private_Message *group_private_message,
+ Tox_Message_Type type)
+{
+ assert(group_private_message != nullptr);
+ group_private_message->type = type;
+}
+Tox_Message_Type tox_event_group_private_message_get_type(const Tox_Event_Group_Private_Message *group_private_message)
+{
+ assert(group_private_message != nullptr);
+ return group_private_message->type;
+}
+
+non_null(1) nullable(2)
+static bool tox_event_group_private_message_set_message(Tox_Event_Group_Private_Message *group_private_message,
+ const uint8_t *message, uint32_t message_length)
+{
+ assert(group_private_message != nullptr);
+
+ if (group_private_message->message != nullptr) {
+ free(group_private_message->message);
+ group_private_message->message = nullptr;
+ group_private_message->message_length = 0;
+ }
+
+ if (message == nullptr) {
+ assert(message_length == 0);
+ return true;
+ }
+
+ uint8_t *message_copy = (uint8_t *)malloc(message_length);
+
+ if (message_copy == nullptr) {
+ return false;
+ }
+
+ memcpy(message_copy, message, message_length);
+ group_private_message->message = message_copy;
+ group_private_message->message_length = message_length;
+ return true;
+}
+uint32_t tox_event_group_private_message_get_message_length(const Tox_Event_Group_Private_Message *group_private_message)
+{
+ assert(group_private_message != nullptr);
+ return group_private_message->message_length;
+}
+const uint8_t *tox_event_group_private_message_get_message(const Tox_Event_Group_Private_Message *group_private_message)
+{
+ assert(group_private_message != nullptr);
+ return group_private_message->message;
+}
+
+non_null()
+static void tox_event_group_private_message_construct(Tox_Event_Group_Private_Message *group_private_message)
+{
+ *group_private_message = (Tox_Event_Group_Private_Message) {
+ 0
+ };
+}
+non_null()
+static void tox_event_group_private_message_destruct(Tox_Event_Group_Private_Message *group_private_message, const Memory *mem)
+{
+ free(group_private_message->message);
+}
+
+bool tox_event_group_private_message_pack(
+ const Tox_Event_Group_Private_Message *event, Bin_Pack *bp)
+{
+ return bin_pack_array(bp, 4)
+ && bin_pack_u32(bp, event->group_number)
+ && bin_pack_u32(bp, event->peer_id)
+ && tox_message_type_pack(event->type, bp)
+ && bin_pack_bin(bp, event->message, event->message_length);
+}
+
+non_null()
+static bool tox_event_group_private_message_unpack_into(
+ Tox_Event_Group_Private_Message *event, Bin_Unpack *bu)
+{
+ assert(event != nullptr);
+ if (!bin_unpack_array_fixed(bu, 4, nullptr)) {
+ return false;
+ }
+
+ return bin_unpack_u32(bu, &event->group_number)
+ && bin_unpack_u32(bu, &event->peer_id)
+ && tox_message_type_unpack(&event->type, bu)
+ && bin_unpack_bin(bu, &event->message, &event->message_length);
+}
+
+/*****************************************************
+ *
+ * :: new/free/add/get/size/unpack
+ *
+ *****************************************************/
+
+const Tox_Event_Group_Private_Message *tox_event_get_group_private_message(const Tox_Event *event)
+{
+ return event->type == TOX_EVENT_GROUP_PRIVATE_MESSAGE ? event->data.group_private_message : nullptr;
+}
+
+Tox_Event_Group_Private_Message *tox_event_group_private_message_new(const Memory *mem)
+{
+ Tox_Event_Group_Private_Message *const group_private_message =
+ (Tox_Event_Group_Private_Message *)mem_alloc(mem, sizeof(Tox_Event_Group_Private_Message));
+
+ if (group_private_message == nullptr) {
+ return nullptr;
+ }
+
+ tox_event_group_private_message_construct(group_private_message);
+ return group_private_message;
+}
+
+void tox_event_group_private_message_free(Tox_Event_Group_Private_Message *group_private_message, const Memory *mem)
+{
+ if (group_private_message != nullptr) {
+ tox_event_group_private_message_destruct(group_private_message, mem);
+ }
+ mem_delete(mem, group_private_message);
+}
+
+non_null()
+static Tox_Event_Group_Private_Message *tox_events_add_group_private_message(Tox_Events *events, const Memory *mem)
+{
+ Tox_Event_Group_Private_Message *const group_private_message = tox_event_group_private_message_new(mem);
+
+ if (group_private_message == nullptr) {
+ return nullptr;
+ }
+
+ Tox_Event event;
+ event.type = TOX_EVENT_GROUP_PRIVATE_MESSAGE;
+ event.data.group_private_message = group_private_message;
+
+ tox_events_add(events, &event);
+ return group_private_message;
+}
+
+bool tox_event_group_private_message_unpack(
+ Tox_Event_Group_Private_Message **event, Bin_Unpack *bu, const Memory *mem)
+{
+ assert(event != nullptr);
+ assert(*event == nullptr);
+ *event = tox_event_group_private_message_new(mem);
+
+ if (*event == nullptr) {
+ return false;
+ }
+
+ return tox_event_group_private_message_unpack_into(*event, bu);
+}
+
+non_null()
+static Tox_Event_Group_Private_Message *tox_event_group_private_message_alloc(void *user_data)
+{
+ Tox_Events_State *state = tox_events_alloc(user_data);
+ assert(state != nullptr);
+
+ if (state->events == nullptr) {
+ return nullptr;
+ }
+
+ Tox_Event_Group_Private_Message *group_private_message = tox_events_add_group_private_message(state->events, state->mem);
+
+ if (group_private_message == nullptr) {
+ state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
+ return nullptr;
+ }
+
+ return group_private_message;
+}
+
+/*****************************************************
+ *
+ * :: event handler
+ *
+ *****************************************************/
+
+void tox_events_handle_group_private_message(
+ Tox *tox, uint32_t group_number, uint32_t peer_id, Tox_Message_Type type, const uint8_t *message, size_t length,
+ void *user_data)
+{
+ Tox_Event_Group_Private_Message *group_private_message = tox_event_group_private_message_alloc(user_data);
+
+ if (group_private_message == nullptr) {
+ return;
+ }
+
+ tox_event_group_private_message_set_group_number(group_private_message, group_number);
+ tox_event_group_private_message_set_peer_id(group_private_message, peer_id);
+ tox_event_group_private_message_set_type(group_private_message, type);
+ tox_event_group_private_message_set_message(group_private_message, message, length);
+}
diff --git a/protocols/Tox/libtox/src/toxcore/events/group_self_join.c b/protocols/Tox/libtox/src/toxcore/events/group_self_join.c
new file mode 100644
index 0000000000..0745e975f8
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/events/group_self_join.c
@@ -0,0 +1,167 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2023-2024 The TokTok team.
+ */
+
+#include "events_alloc.h"
+
+#include <assert.h>
+
+#include "../attributes.h"
+#include "../bin_pack.h"
+#include "../bin_unpack.h"
+#include "../ccompat.h"
+#include "../mem.h"
+#include "../tox.h"
+#include "../tox_events.h"
+
+/*****************************************************
+ *
+ * :: struct and accessors
+ *
+ *****************************************************/
+
+struct Tox_Event_Group_Self_Join {
+ uint32_t group_number;
+};
+
+non_null()
+static void tox_event_group_self_join_set_group_number(Tox_Event_Group_Self_Join *group_self_join,
+ uint32_t group_number)
+{
+ assert(group_self_join != nullptr);
+ group_self_join->group_number = group_number;
+}
+uint32_t tox_event_group_self_join_get_group_number(const Tox_Event_Group_Self_Join *group_self_join)
+{
+ assert(group_self_join != nullptr);
+ return group_self_join->group_number;
+}
+
+non_null()
+static void tox_event_group_self_join_construct(Tox_Event_Group_Self_Join *group_self_join)
+{
+ *group_self_join = (Tox_Event_Group_Self_Join) {
+ 0
+ };
+}
+non_null()
+static void tox_event_group_self_join_destruct(Tox_Event_Group_Self_Join *group_self_join, const Memory *mem)
+{
+ return;
+}
+
+bool tox_event_group_self_join_pack(
+ const Tox_Event_Group_Self_Join *event, Bin_Pack *bp)
+{
+ return bin_pack_u32(bp, event->group_number);
+}
+
+non_null()
+static bool tox_event_group_self_join_unpack_into(
+ Tox_Event_Group_Self_Join *event, Bin_Unpack *bu)
+{
+ assert(event != nullptr);
+ return bin_unpack_u32(bu, &event->group_number);
+}
+
+/*****************************************************
+ *
+ * :: new/free/add/get/size/unpack
+ *
+ *****************************************************/
+
+const Tox_Event_Group_Self_Join *tox_event_get_group_self_join(const Tox_Event *event)
+{
+ return event->type == TOX_EVENT_GROUP_SELF_JOIN ? event->data.group_self_join : nullptr;
+}
+
+Tox_Event_Group_Self_Join *tox_event_group_self_join_new(const Memory *mem)
+{
+ Tox_Event_Group_Self_Join *const group_self_join =
+ (Tox_Event_Group_Self_Join *)mem_alloc(mem, sizeof(Tox_Event_Group_Self_Join));
+
+ if (group_self_join == nullptr) {
+ return nullptr;
+ }
+
+ tox_event_group_self_join_construct(group_self_join);
+ return group_self_join;
+}
+
+void tox_event_group_self_join_free(Tox_Event_Group_Self_Join *group_self_join, const Memory *mem)
+{
+ if (group_self_join != nullptr) {
+ tox_event_group_self_join_destruct(group_self_join, mem);
+ }
+ mem_delete(mem, group_self_join);
+}
+
+non_null()
+static Tox_Event_Group_Self_Join *tox_events_add_group_self_join(Tox_Events *events, const Memory *mem)
+{
+ Tox_Event_Group_Self_Join *const group_self_join = tox_event_group_self_join_new(mem);
+
+ if (group_self_join == nullptr) {
+ return nullptr;
+ }
+
+ Tox_Event event;
+ event.type = TOX_EVENT_GROUP_SELF_JOIN;
+ event.data.group_self_join = group_self_join;
+
+ tox_events_add(events, &event);
+ return group_self_join;
+}
+
+bool tox_event_group_self_join_unpack(
+ Tox_Event_Group_Self_Join **event, Bin_Unpack *bu, const Memory *mem)
+{
+ assert(event != nullptr);
+ assert(*event == nullptr);
+ *event = tox_event_group_self_join_new(mem);
+
+ if (*event == nullptr) {
+ return false;
+ }
+
+ return tox_event_group_self_join_unpack_into(*event, bu);
+}
+
+non_null()
+static Tox_Event_Group_Self_Join *tox_event_group_self_join_alloc(void *user_data)
+{
+ Tox_Events_State *state = tox_events_alloc(user_data);
+ assert(state != nullptr);
+
+ if (state->events == nullptr) {
+ return nullptr;
+ }
+
+ Tox_Event_Group_Self_Join *group_self_join = tox_events_add_group_self_join(state->events, state->mem);
+
+ if (group_self_join == nullptr) {
+ state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
+ return nullptr;
+ }
+
+ return group_self_join;
+}
+
+/*****************************************************
+ *
+ * :: event handler
+ *
+ *****************************************************/
+
+void tox_events_handle_group_self_join(
+ Tox *tox, uint32_t group_number,
+ void *user_data)
+{
+ Tox_Event_Group_Self_Join *group_self_join = tox_event_group_self_join_alloc(user_data);
+
+ if (group_self_join == nullptr) {
+ return;
+ }
+
+ tox_event_group_self_join_set_group_number(group_self_join, group_number);
+}
diff --git a/protocols/Tox/libtox/src/toxcore/events/group_topic.c b/protocols/Tox/libtox/src/toxcore/events/group_topic.c
new file mode 100644
index 0000000000..23cdd5d354
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/events/group_topic.c
@@ -0,0 +1,235 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2023-2024 The TokTok team.
+ */
+
+#include "events_alloc.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../attributes.h"
+#include "../bin_pack.h"
+#include "../bin_unpack.h"
+#include "../ccompat.h"
+#include "../mem.h"
+#include "../tox.h"
+#include "../tox_events.h"
+
+/*****************************************************
+ *
+ * :: struct and accessors
+ *
+ *****************************************************/
+
+struct Tox_Event_Group_Topic {
+ uint32_t group_number;
+ uint32_t peer_id;
+ uint8_t *topic;
+ uint32_t topic_length;
+};
+
+non_null()
+static void tox_event_group_topic_set_group_number(Tox_Event_Group_Topic *group_topic,
+ uint32_t group_number)
+{
+ assert(group_topic != nullptr);
+ group_topic->group_number = group_number;
+}
+uint32_t tox_event_group_topic_get_group_number(const Tox_Event_Group_Topic *group_topic)
+{
+ assert(group_topic != nullptr);
+ return group_topic->group_number;
+}
+
+non_null()
+static void tox_event_group_topic_set_peer_id(Tox_Event_Group_Topic *group_topic,
+ uint32_t peer_id)
+{
+ assert(group_topic != nullptr);
+ group_topic->peer_id = peer_id;
+}
+uint32_t tox_event_group_topic_get_peer_id(const Tox_Event_Group_Topic *group_topic)
+{
+ assert(group_topic != nullptr);
+ return group_topic->peer_id;
+}
+
+non_null(1) nullable(2)
+static bool tox_event_group_topic_set_topic(Tox_Event_Group_Topic *group_topic,
+ const uint8_t *topic, uint32_t topic_length)
+{
+ assert(group_topic != nullptr);
+
+ if (group_topic->topic != nullptr) {
+ free(group_topic->topic);
+ group_topic->topic = nullptr;
+ group_topic->topic_length = 0;
+ }
+
+ if (topic == nullptr) {
+ assert(topic_length == 0);
+ return true;
+ }
+
+ uint8_t *topic_copy = (uint8_t *)malloc(topic_length);
+
+ if (topic_copy == nullptr) {
+ return false;
+ }
+
+ memcpy(topic_copy, topic, topic_length);
+ group_topic->topic = topic_copy;
+ group_topic->topic_length = topic_length;
+ return true;
+}
+uint32_t tox_event_group_topic_get_topic_length(const Tox_Event_Group_Topic *group_topic)
+{
+ assert(group_topic != nullptr);
+ return group_topic->topic_length;
+}
+const uint8_t *tox_event_group_topic_get_topic(const Tox_Event_Group_Topic *group_topic)
+{
+ assert(group_topic != nullptr);
+ return group_topic->topic;
+}
+
+non_null()
+static void tox_event_group_topic_construct(Tox_Event_Group_Topic *group_topic)
+{
+ *group_topic = (Tox_Event_Group_Topic) {
+ 0
+ };
+}
+non_null()
+static void tox_event_group_topic_destruct(Tox_Event_Group_Topic *group_topic, const Memory *mem)
+{
+ free(group_topic->topic);
+}
+
+bool tox_event_group_topic_pack(
+ const Tox_Event_Group_Topic *event, Bin_Pack *bp)
+{
+ return bin_pack_array(bp, 3)
+ && bin_pack_u32(bp, event->group_number)
+ && bin_pack_u32(bp, event->peer_id)
+ && bin_pack_bin(bp, event->topic, event->topic_length);
+}
+
+non_null()
+static bool tox_event_group_topic_unpack_into(
+ Tox_Event_Group_Topic *event, Bin_Unpack *bu)
+{
+ assert(event != nullptr);
+ if (!bin_unpack_array_fixed(bu, 3, nullptr)) {
+ return false;
+ }
+
+ return bin_unpack_u32(bu, &event->group_number)
+ && bin_unpack_u32(bu, &event->peer_id)
+ && bin_unpack_bin(bu, &event->topic, &event->topic_length);
+}
+
+/*****************************************************
+ *
+ * :: new/free/add/get/size/unpack
+ *
+ *****************************************************/
+
+const Tox_Event_Group_Topic *tox_event_get_group_topic(const Tox_Event *event)
+{
+ return event->type == TOX_EVENT_GROUP_TOPIC ? event->data.group_topic : nullptr;
+}
+
+Tox_Event_Group_Topic *tox_event_group_topic_new(const Memory *mem)
+{
+ Tox_Event_Group_Topic *const group_topic =
+ (Tox_Event_Group_Topic *)mem_alloc(mem, sizeof(Tox_Event_Group_Topic));
+
+ if (group_topic == nullptr) {
+ return nullptr;
+ }
+
+ tox_event_group_topic_construct(group_topic);
+ return group_topic;
+}
+
+void tox_event_group_topic_free(Tox_Event_Group_Topic *group_topic, const Memory *mem)
+{
+ if (group_topic != nullptr) {
+ tox_event_group_topic_destruct(group_topic, mem);
+ }
+ mem_delete(mem, group_topic);
+}
+
+non_null()
+static Tox_Event_Group_Topic *tox_events_add_group_topic(Tox_Events *events, const Memory *mem)
+{
+ Tox_Event_Group_Topic *const group_topic = tox_event_group_topic_new(mem);
+
+ if (group_topic == nullptr) {
+ return nullptr;
+ }
+
+ Tox_Event event;
+ event.type = TOX_EVENT_GROUP_TOPIC;
+ event.data.group_topic = group_topic;
+
+ tox_events_add(events, &event);
+ return group_topic;
+}
+
+bool tox_event_group_topic_unpack(
+ Tox_Event_Group_Topic **event, Bin_Unpack *bu, const Memory *mem)
+{
+ assert(event != nullptr);
+ assert(*event == nullptr);
+ *event = tox_event_group_topic_new(mem);
+
+ if (*event == nullptr) {
+ return false;
+ }
+
+ return tox_event_group_topic_unpack_into(*event, bu);
+}
+
+non_null()
+static Tox_Event_Group_Topic *tox_event_group_topic_alloc(void *user_data)
+{
+ Tox_Events_State *state = tox_events_alloc(user_data);
+ assert(state != nullptr);
+
+ if (state->events == nullptr) {
+ return nullptr;
+ }
+
+ Tox_Event_Group_Topic *group_topic = tox_events_add_group_topic(state->events, state->mem);
+
+ if (group_topic == nullptr) {
+ state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
+ return nullptr;
+ }
+
+ return group_topic;
+}
+
+/*****************************************************
+ *
+ * :: event handler
+ *
+ *****************************************************/
+
+void tox_events_handle_group_topic(
+ Tox *tox, uint32_t group_number, uint32_t peer_id, const uint8_t *topic, size_t length,
+ void *user_data)
+{
+ Tox_Event_Group_Topic *group_topic = tox_event_group_topic_alloc(user_data);
+
+ if (group_topic == nullptr) {
+ return;
+ }
+
+ tox_event_group_topic_set_group_number(group_topic, group_number);
+ tox_event_group_topic_set_peer_id(group_topic, peer_id);
+ tox_event_group_topic_set_topic(group_topic, topic, length);
+}
diff --git a/protocols/Tox/libtox/src/toxcore/events/group_topic_lock.c b/protocols/Tox/libtox/src/toxcore/events/group_topic_lock.c
new file mode 100644
index 0000000000..36fb49393a
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/events/group_topic_lock.c
@@ -0,0 +1,191 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2023-2024 The TokTok team.
+ */
+
+#include "events_alloc.h"
+
+#include <assert.h>
+
+#include "../attributes.h"
+#include "../bin_pack.h"
+#include "../bin_unpack.h"
+#include "../ccompat.h"
+#include "../mem.h"
+#include "../tox.h"
+#include "../tox_events.h"
+#include "../tox_pack.h"
+#include "../tox_unpack.h"
+
+/*****************************************************
+ *
+ * :: struct and accessors
+ *
+ *****************************************************/
+
+struct Tox_Event_Group_Topic_Lock {
+ uint32_t group_number;
+ Tox_Group_Topic_Lock topic_lock;
+};
+
+non_null()
+static void tox_event_group_topic_lock_set_group_number(Tox_Event_Group_Topic_Lock *group_topic_lock,
+ uint32_t group_number)
+{
+ assert(group_topic_lock != nullptr);
+ group_topic_lock->group_number = group_number;
+}
+uint32_t tox_event_group_topic_lock_get_group_number(const Tox_Event_Group_Topic_Lock *group_topic_lock)
+{
+ assert(group_topic_lock != nullptr);
+ return group_topic_lock->group_number;
+}
+
+non_null()
+static void tox_event_group_topic_lock_set_topic_lock(Tox_Event_Group_Topic_Lock *group_topic_lock,
+ Tox_Group_Topic_Lock topic_lock)
+{
+ assert(group_topic_lock != nullptr);
+ group_topic_lock->topic_lock = topic_lock;
+}
+Tox_Group_Topic_Lock tox_event_group_topic_lock_get_topic_lock(const Tox_Event_Group_Topic_Lock *group_topic_lock)
+{
+ assert(group_topic_lock != nullptr);
+ return group_topic_lock->topic_lock;
+}
+
+non_null()
+static void tox_event_group_topic_lock_construct(Tox_Event_Group_Topic_Lock *group_topic_lock)
+{
+ *group_topic_lock = (Tox_Event_Group_Topic_Lock) {
+ 0
+ };
+}
+non_null()
+static void tox_event_group_topic_lock_destruct(Tox_Event_Group_Topic_Lock *group_topic_lock, const Memory *mem)
+{
+ return;
+}
+
+bool tox_event_group_topic_lock_pack(
+ const Tox_Event_Group_Topic_Lock *event, Bin_Pack *bp)
+{
+ return bin_pack_array(bp, 2)
+ && bin_pack_u32(bp, event->group_number)
+ && tox_group_topic_lock_pack(event->topic_lock, bp);
+}
+
+non_null()
+static bool tox_event_group_topic_lock_unpack_into(
+ Tox_Event_Group_Topic_Lock *event, Bin_Unpack *bu)
+{
+ assert(event != nullptr);
+ if (!bin_unpack_array_fixed(bu, 2, nullptr)) {
+ return false;
+ }
+
+ return bin_unpack_u32(bu, &event->group_number)
+ && tox_group_topic_lock_unpack(&event->topic_lock, bu);
+}
+
+/*****************************************************
+ *
+ * :: new/free/add/get/size/unpack
+ *
+ *****************************************************/
+
+const Tox_Event_Group_Topic_Lock *tox_event_get_group_topic_lock(const Tox_Event *event)
+{
+ return event->type == TOX_EVENT_GROUP_TOPIC_LOCK ? event->data.group_topic_lock : nullptr;
+}
+
+Tox_Event_Group_Topic_Lock *tox_event_group_topic_lock_new(const Memory *mem)
+{
+ Tox_Event_Group_Topic_Lock *const group_topic_lock =
+ (Tox_Event_Group_Topic_Lock *)mem_alloc(mem, sizeof(Tox_Event_Group_Topic_Lock));
+
+ if (group_topic_lock == nullptr) {
+ return nullptr;
+ }
+
+ tox_event_group_topic_lock_construct(group_topic_lock);
+ return group_topic_lock;
+}
+
+void tox_event_group_topic_lock_free(Tox_Event_Group_Topic_Lock *group_topic_lock, const Memory *mem)
+{
+ if (group_topic_lock != nullptr) {
+ tox_event_group_topic_lock_destruct(group_topic_lock, mem);
+ }
+ mem_delete(mem, group_topic_lock);
+}
+
+non_null()
+static Tox_Event_Group_Topic_Lock *tox_events_add_group_topic_lock(Tox_Events *events, const Memory *mem)
+{
+ Tox_Event_Group_Topic_Lock *const group_topic_lock = tox_event_group_topic_lock_new(mem);
+
+ if (group_topic_lock == nullptr) {
+ return nullptr;
+ }
+
+ Tox_Event event;
+ event.type = TOX_EVENT_GROUP_TOPIC_LOCK;
+ event.data.group_topic_lock = group_topic_lock;
+
+ tox_events_add(events, &event);
+ return group_topic_lock;
+}
+
+bool tox_event_group_topic_lock_unpack(
+ Tox_Event_Group_Topic_Lock **event, Bin_Unpack *bu, const Memory *mem)
+{
+ assert(event != nullptr);
+ assert(*event == nullptr);
+ *event = tox_event_group_topic_lock_new(mem);
+
+ if (*event == nullptr) {
+ return false;
+ }
+
+ return tox_event_group_topic_lock_unpack_into(*event, bu);
+}
+
+non_null()
+static Tox_Event_Group_Topic_Lock *tox_event_group_topic_lock_alloc(void *user_data)
+{
+ Tox_Events_State *state = tox_events_alloc(user_data);
+ assert(state != nullptr);
+
+ if (state->events == nullptr) {
+ return nullptr;
+ }
+
+ Tox_Event_Group_Topic_Lock *group_topic_lock = tox_events_add_group_topic_lock(state->events, state->mem);
+
+ if (group_topic_lock == nullptr) {
+ state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
+ return nullptr;
+ }
+
+ return group_topic_lock;
+}
+
+/*****************************************************
+ *
+ * :: event handler
+ *
+ *****************************************************/
+
+void tox_events_handle_group_topic_lock(
+ Tox *tox, uint32_t group_number, Tox_Group_Topic_Lock topic_lock,
+ void *user_data)
+{
+ Tox_Event_Group_Topic_Lock *group_topic_lock = tox_event_group_topic_lock_alloc(user_data);
+
+ if (group_topic_lock == nullptr) {
+ return;
+ }
+
+ tox_event_group_topic_lock_set_group_number(group_topic_lock, group_number);
+ tox_event_group_topic_lock_set_topic_lock(group_topic_lock, topic_lock);
+}
diff --git a/protocols/Tox/libtox/src/toxcore/events/group_voice_state.c b/protocols/Tox/libtox/src/toxcore/events/group_voice_state.c
new file mode 100644
index 0000000000..fba0300389
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/events/group_voice_state.c
@@ -0,0 +1,191 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2023-2024 The TokTok team.
+ */
+
+#include "events_alloc.h"
+
+#include <assert.h>
+
+#include "../attributes.h"
+#include "../bin_pack.h"
+#include "../bin_unpack.h"
+#include "../ccompat.h"
+#include "../mem.h"
+#include "../tox.h"
+#include "../tox_events.h"
+#include "../tox_pack.h"
+#include "../tox_unpack.h"
+
+/*****************************************************
+ *
+ * :: struct and accessors
+ *
+ *****************************************************/
+
+struct Tox_Event_Group_Voice_State {
+ uint32_t group_number;
+ Tox_Group_Voice_State voice_state;
+};
+
+non_null()
+static void tox_event_group_voice_state_set_group_number(Tox_Event_Group_Voice_State *group_voice_state,
+ uint32_t group_number)
+{
+ assert(group_voice_state != nullptr);
+ group_voice_state->group_number = group_number;
+}
+uint32_t tox_event_group_voice_state_get_group_number(const Tox_Event_Group_Voice_State *group_voice_state)
+{
+ assert(group_voice_state != nullptr);
+ return group_voice_state->group_number;
+}
+
+non_null()
+static void tox_event_group_voice_state_set_voice_state(Tox_Event_Group_Voice_State *group_voice_state,
+ Tox_Group_Voice_State voice_state)
+{
+ assert(group_voice_state != nullptr);
+ group_voice_state->voice_state = voice_state;
+}
+Tox_Group_Voice_State tox_event_group_voice_state_get_voice_state(const Tox_Event_Group_Voice_State *group_voice_state)
+{
+ assert(group_voice_state != nullptr);
+ return group_voice_state->voice_state;
+}
+
+non_null()
+static void tox_event_group_voice_state_construct(Tox_Event_Group_Voice_State *group_voice_state)
+{
+ *group_voice_state = (Tox_Event_Group_Voice_State) {
+ 0
+ };
+}
+non_null()
+static void tox_event_group_voice_state_destruct(Tox_Event_Group_Voice_State *group_voice_state, const Memory *mem)
+{
+ return;
+}
+
+bool tox_event_group_voice_state_pack(
+ const Tox_Event_Group_Voice_State *event, Bin_Pack *bp)
+{
+ return bin_pack_array(bp, 2)
+ && bin_pack_u32(bp, event->group_number)
+ && tox_group_voice_state_pack(event->voice_state, bp);
+}
+
+non_null()
+static bool tox_event_group_voice_state_unpack_into(
+ Tox_Event_Group_Voice_State *event, Bin_Unpack *bu)
+{
+ assert(event != nullptr);
+ if (!bin_unpack_array_fixed(bu, 2, nullptr)) {
+ return false;
+ }
+
+ return bin_unpack_u32(bu, &event->group_number)
+ && tox_group_voice_state_unpack(&event->voice_state, bu);
+}
+
+/*****************************************************
+ *
+ * :: new/free/add/get/size/unpack
+ *
+ *****************************************************/
+
+const Tox_Event_Group_Voice_State *tox_event_get_group_voice_state(const Tox_Event *event)
+{
+ return event->type == TOX_EVENT_GROUP_VOICE_STATE ? event->data.group_voice_state : nullptr;
+}
+
+Tox_Event_Group_Voice_State *tox_event_group_voice_state_new(const Memory *mem)
+{
+ Tox_Event_Group_Voice_State *const group_voice_state =
+ (Tox_Event_Group_Voice_State *)mem_alloc(mem, sizeof(Tox_Event_Group_Voice_State));
+
+ if (group_voice_state == nullptr) {
+ return nullptr;
+ }
+
+ tox_event_group_voice_state_construct(group_voice_state);
+ return group_voice_state;
+}
+
+void tox_event_group_voice_state_free(Tox_Event_Group_Voice_State *group_voice_state, const Memory *mem)
+{
+ if (group_voice_state != nullptr) {
+ tox_event_group_voice_state_destruct(group_voice_state, mem);
+ }
+ mem_delete(mem, group_voice_state);
+}
+
+non_null()
+static Tox_Event_Group_Voice_State *tox_events_add_group_voice_state(Tox_Events *events, const Memory *mem)
+{
+ Tox_Event_Group_Voice_State *const group_voice_state = tox_event_group_voice_state_new(mem);
+
+ if (group_voice_state == nullptr) {
+ return nullptr;
+ }
+
+ Tox_Event event;
+ event.type = TOX_EVENT_GROUP_VOICE_STATE;
+ event.data.group_voice_state = group_voice_state;
+
+ tox_events_add(events, &event);
+ return group_voice_state;
+}
+
+bool tox_event_group_voice_state_unpack(
+ Tox_Event_Group_Voice_State **event, Bin_Unpack *bu, const Memory *mem)
+{
+ assert(event != nullptr);
+ assert(*event == nullptr);
+ *event = tox_event_group_voice_state_new(mem);
+
+ if (*event == nullptr) {
+ return false;
+ }
+
+ return tox_event_group_voice_state_unpack_into(*event, bu);
+}
+
+non_null()
+static Tox_Event_Group_Voice_State *tox_event_group_voice_state_alloc(void *user_data)
+{
+ Tox_Events_State *state = tox_events_alloc(user_data);
+ assert(state != nullptr);
+
+ if (state->events == nullptr) {
+ return nullptr;
+ }
+
+ Tox_Event_Group_Voice_State *group_voice_state = tox_events_add_group_voice_state(state->events, state->mem);
+
+ if (group_voice_state == nullptr) {
+ state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
+ return nullptr;
+ }
+
+ return group_voice_state;
+}
+
+/*****************************************************
+ *
+ * :: event handler
+ *
+ *****************************************************/
+
+void tox_events_handle_group_voice_state(
+ Tox *tox, uint32_t group_number, Tox_Group_Voice_State voice_state,
+ void *user_data)
+{
+ Tox_Event_Group_Voice_State *group_voice_state = tox_event_group_voice_state_alloc(user_data);
+
+ if (group_voice_state == nullptr) {
+ return;
+ }
+
+ tox_event_group_voice_state_set_group_number(group_voice_state, group_number);
+ tox_event_group_voice_state_set_voice_state(group_voice_state, voice_state);
+}
diff --git a/protocols/Tox/libtox/src/toxcore/events/self_connection_status.c b/protocols/Tox/libtox/src/toxcore/events/self_connection_status.c
index 0e381de7fa..8d8bc803ea 100644
--- a/protocols/Tox/libtox/src/toxcore/events/self_connection_status.c
+++ b/protocols/Tox/libtox/src/toxcore/events/self_connection_status.c
@@ -1,167 +1,153 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2022 The TokTok team.
+ * Copyright © 2023-2024 The TokTok team.
*/
#include "events_alloc.h"
#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
+#include "../attributes.h"
#include "../bin_pack.h"
#include "../bin_unpack.h"
#include "../ccompat.h"
+#include "../mem.h"
#include "../tox.h"
#include "../tox_events.h"
+#include "../tox_pack.h"
#include "../tox_unpack.h"
-
/*****************************************************
*
* :: struct and accessors
*
*****************************************************/
-
struct Tox_Event_Self_Connection_Status {
Tox_Connection connection_status;
};
non_null()
-static void tox_event_self_connection_status_construct(Tox_Event_Self_Connection_Status *self_connection_status)
+static void tox_event_self_connection_status_set_connection_status(Tox_Event_Self_Connection_Status *self_connection_status,
+ Tox_Connection connection_status)
{
- *self_connection_status = (Tox_Event_Self_Connection_Status) {
- TOX_CONNECTION_NONE
- };
+ assert(self_connection_status != nullptr);
+ self_connection_status->connection_status = connection_status;
}
-non_null()
-static void tox_event_self_connection_status_destruct(Tox_Event_Self_Connection_Status *self_connection_status)
+Tox_Connection tox_event_self_connection_status_get_connection_status(const Tox_Event_Self_Connection_Status *self_connection_status)
{
- return;
+ assert(self_connection_status != nullptr);
+ return self_connection_status->connection_status;
}
non_null()
-static void tox_event_self_connection_status_set_connection_status(Tox_Event_Self_Connection_Status
- *self_connection_status, Tox_Connection connection_status)
+static void tox_event_self_connection_status_construct(Tox_Event_Self_Connection_Status *self_connection_status)
{
- assert(self_connection_status != nullptr);
- self_connection_status->connection_status = connection_status;
+ *self_connection_status = (Tox_Event_Self_Connection_Status) {
+ TOX_CONNECTION_NONE
+ };
}
-Tox_Connection tox_event_self_connection_status_get_connection_status(const Tox_Event_Self_Connection_Status
- *self_connection_status)
+non_null()
+static void tox_event_self_connection_status_destruct(Tox_Event_Self_Connection_Status *self_connection_status, const Memory *mem)
{
- assert(self_connection_status != nullptr);
- return self_connection_status->connection_status;
+ return;
}
-non_null()
-static bool tox_event_self_connection_status_pack(
+bool tox_event_self_connection_status_pack(
const Tox_Event_Self_Connection_Status *event, Bin_Pack *bp)
{
- assert(event != nullptr);
- return bin_pack_array(bp, 2)
- && bin_pack_u32(bp, TOX_EVENT_SELF_CONNECTION_STATUS)
- && bin_pack_u32(bp, event->connection_status);
+ return tox_connection_pack(event->connection_status, bp);
}
non_null()
-static bool tox_event_self_connection_status_unpack(
+static bool tox_event_self_connection_status_unpack_into(
Tox_Event_Self_Connection_Status *event, Bin_Unpack *bu)
{
assert(event != nullptr);
- return tox_unpack_connection(bu, &event->connection_status);
+ return tox_connection_unpack(&event->connection_status, bu);
}
-
/*****************************************************
*
- * :: add/clear/get
+ * :: new/free/add/get/size/unpack
*
*****************************************************/
-
-non_null()
-static Tox_Event_Self_Connection_Status *tox_events_add_self_connection_status(Tox_Events *events)
+const Tox_Event_Self_Connection_Status *tox_event_get_self_connection_status(const Tox_Event *event)
{
- if (events->self_connection_status_size == UINT32_MAX) {
- return nullptr;
- }
-
- if (events->self_connection_status_size == events->self_connection_status_capacity) {
- const uint32_t new_self_connection_status_capacity = events->self_connection_status_capacity * 2 + 1;
- Tox_Event_Self_Connection_Status *new_self_connection_status = (Tox_Event_Self_Connection_Status *)realloc(
- events->self_connection_status, new_self_connection_status_capacity * sizeof(Tox_Event_Self_Connection_Status));
+ return event->type == TOX_EVENT_SELF_CONNECTION_STATUS ? event->data.self_connection_status : nullptr;
+}
- if (new_self_connection_status == nullptr) {
- return nullptr;
- }
+Tox_Event_Self_Connection_Status *tox_event_self_connection_status_new(const Memory *mem)
+{
+ Tox_Event_Self_Connection_Status *const self_connection_status =
+ (Tox_Event_Self_Connection_Status *)mem_alloc(mem, sizeof(Tox_Event_Self_Connection_Status));
- events->self_connection_status = new_self_connection_status;
- events->self_connection_status_capacity = new_self_connection_status_capacity;
+ if (self_connection_status == nullptr) {
+ return nullptr;
}
- Tox_Event_Self_Connection_Status *const self_connection_status =
- &events->self_connection_status[events->self_connection_status_size];
tox_event_self_connection_status_construct(self_connection_status);
- ++events->self_connection_status_size;
return self_connection_status;
}
-void tox_events_clear_self_connection_status(Tox_Events *events)
+void tox_event_self_connection_status_free(Tox_Event_Self_Connection_Status *self_connection_status, const Memory *mem)
{
- if (events == nullptr) {
- return;
+ if (self_connection_status != nullptr) {
+ tox_event_self_connection_status_destruct(self_connection_status, mem);
}
-
- for (uint32_t i = 0; i < events->self_connection_status_size; ++i) {
- tox_event_self_connection_status_destruct(&events->self_connection_status[i]);
- }
-
- free(events->self_connection_status);
- events->self_connection_status = nullptr;
- events->self_connection_status_size = 0;
- events->self_connection_status_capacity = 0;
+ mem_delete(mem, self_connection_status);
}
-uint32_t tox_events_get_self_connection_status_size(const Tox_Events *events)
+non_null()
+static Tox_Event_Self_Connection_Status *tox_events_add_self_connection_status(Tox_Events *events, const Memory *mem)
{
- if (events == nullptr) {
- return 0;
+ Tox_Event_Self_Connection_Status *const self_connection_status = tox_event_self_connection_status_new(mem);
+
+ if (self_connection_status == nullptr) {
+ return nullptr;
}
- return events->self_connection_status_size;
-}
+ Tox_Event event;
+ event.type = TOX_EVENT_SELF_CONNECTION_STATUS;
+ event.data.self_connection_status = self_connection_status;
-const Tox_Event_Self_Connection_Status *tox_events_get_self_connection_status(const Tox_Events *events, uint32_t index)
-{
- assert(index < events->self_connection_status_size);
- assert(events->self_connection_status != nullptr);
- return &events->self_connection_status[index];
+ tox_events_add(events, &event);
+ return self_connection_status;
}
-bool tox_events_pack_self_connection_status(const Tox_Events *events, Bin_Pack *bp)
+bool tox_event_self_connection_status_unpack(
+ Tox_Event_Self_Connection_Status **event, Bin_Unpack *bu, const Memory *mem)
{
- const uint32_t size = tox_events_get_self_connection_status_size(events);
+ assert(event != nullptr);
+ assert(*event == nullptr);
+ *event = tox_event_self_connection_status_new(mem);
- for (uint32_t i = 0; i < size; ++i) {
- if (!tox_event_self_connection_status_pack(tox_events_get_self_connection_status(events, i), bp)) {
- return false;
- }
+ if (*event == nullptr) {
+ return false;
}
- return true;
+
+ return tox_event_self_connection_status_unpack_into(*event, bu);
}
-bool tox_events_unpack_self_connection_status(Tox_Events *events, Bin_Unpack *bu)
+non_null()
+static Tox_Event_Self_Connection_Status *tox_event_self_connection_status_alloc(void *user_data)
{
- Tox_Event_Self_Connection_Status *event = tox_events_add_self_connection_status(events);
+ Tox_Events_State *state = tox_events_alloc(user_data);
+ assert(state != nullptr);
- if (event == nullptr) {
- return false;
+ if (state->events == nullptr) {
+ return nullptr;
}
- return tox_event_self_connection_status_unpack(event, bu);
-}
+ Tox_Event_Self_Connection_Status *self_connection_status = tox_events_add_self_connection_status(state->events, state->mem);
+ if (self_connection_status == nullptr) {
+ state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
+ return nullptr;
+ }
+
+ return self_connection_status;
+}
/*****************************************************
*
@@ -169,20 +155,13 @@ bool tox_events_unpack_self_connection_status(Tox_Events *events, Bin_Unpack *bu
*
*****************************************************/
-
-void tox_events_handle_self_connection_status(Tox *tox, Tox_Connection connection_status, void *user_data)
+void tox_events_handle_self_connection_status(
+ Tox *tox, Tox_Connection connection_status,
+ void *user_data)
{
- Tox_Events_State *state = tox_events_alloc(user_data);
- assert(state != nullptr);
-
- if (state->events == nullptr) {
- return;
- }
-
- Tox_Event_Self_Connection_Status *self_connection_status = tox_events_add_self_connection_status(state->events);
+ Tox_Event_Self_Connection_Status *self_connection_status = tox_event_self_connection_status_alloc(user_data);
if (self_connection_status == nullptr) {
- state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
return;
}
diff --git a/protocols/Tox/libtox/src/toxcore/forwarding.c b/protocols/Tox/libtox/src/toxcore/forwarding.c
index 5e885abd21..18ff3203fc 100644
--- a/protocols/Tox/libtox/src/toxcore/forwarding.c
+++ b/protocols/Tox/libtox/src/toxcore/forwarding.c
@@ -9,7 +9,12 @@
#include <string.h>
#include "DHT.h"
+#include "attributes.h"
#include "ccompat.h"
+#include "crypto_core.h"
+#include "logger.h"
+#include "mono_time.h"
+#include "network.h"
#include "timed_auth.h"
struct Forwarding {
@@ -31,14 +36,14 @@ struct Forwarding {
void *forwarded_response_callback_object;
};
-DHT *forwarding_get_dht(Forwarding *forwarding)
+DHT *forwarding_get_dht(const Forwarding *forwarding)
{
return forwarding->dht;
}
#define SENDBACK_TIMEOUT 3600
-bool send_forward_request(Networking_Core *net, const IP_Port *forwarder,
+bool send_forward_request(const Networking_Core *net, const IP_Port *forwarder,
const uint8_t *chain_keys, uint16_t chain_length,
const uint8_t *data, uint16_t data_length)
{
@@ -316,7 +321,7 @@ static int handle_forwarding(void *object, const IP_Port *source, const uint8_t
}
}
-bool forward_reply(Networking_Core *net, const IP_Port *forwarder,
+bool forward_reply(const Networking_Core *net, const IP_Port *forwarder,
const uint8_t *sendback, uint16_t sendback_length,
const uint8_t *data, uint16_t length)
{
diff --git a/protocols/Tox/libtox/src/toxcore/forwarding.h b/protocols/Tox/libtox/src/toxcore/forwarding.h
index 36ce8ad894..bd0ef09e1c 100644
--- a/protocols/Tox/libtox/src/toxcore/forwarding.h
+++ b/protocols/Tox/libtox/src/toxcore/forwarding.h
@@ -6,6 +6,10 @@
#define C_TOXCORE_TOXCORE_FORWARDING_H
#include "DHT.h"
+#include "attributes.h"
+#include "crypto_core.h"
+#include "logger.h"
+#include "mono_time.h"
#include "network.h"
#ifdef __cplusplus
@@ -26,7 +30,7 @@ extern "C" {
typedef struct Forwarding Forwarding;
non_null()
-DHT *forwarding_get_dht(Forwarding *forwarding);
+DHT *forwarding_get_dht(const Forwarding *forwarding);
/**
* @brief Send data to forwarder for forwarding via chain of dht nodes.
@@ -41,7 +45,7 @@ DHT *forwarding_get_dht(Forwarding *forwarding);
* @return true on success, false otherwise.
*/
non_null()
-bool send_forward_request(Networking_Core *net, const IP_Port *forwarder,
+bool send_forward_request(const Networking_Core *net, const IP_Port *forwarder,
const uint8_t *chain_keys, uint16_t chain_length,
const uint8_t *data, uint16_t data_length);
@@ -75,11 +79,10 @@ bool create_forward_chain_packet(const uint8_t *chain_keys, uint16_t chain_lengt
* @return true on success, false otherwise.
*/
non_null()
-bool forward_reply(Networking_Core *net, const IP_Port *forwarder,
+bool forward_reply(const Networking_Core *net, const IP_Port *forwarder,
const uint8_t *sendback, uint16_t sendback_length,
const uint8_t *data, uint16_t length);
-
/**
* @brief Set callback to handle a forwarded request.
* To reply to the packet, callback should use `forward_reply()` to send a reply
@@ -119,7 +122,7 @@ nullable(1)
void kill_forwarding(Forwarding *forwarding);
#ifdef __cplusplus
-} // extern "C"
+} /* extern "C" */
#endif
-#endif
+#endif /* C_TOXCORE_TOXCORE_FORWARDING_H */
diff --git a/protocols/Tox/libtox/src/toxcore/friend_connection.c b/protocols/Tox/libtox/src/toxcore/friend_connection.c
index 7b8537c720..33bfa40d34 100644
--- a/protocols/Tox/libtox/src/toxcore/friend_connection.c
+++ b/protocols/Tox/libtox/src/toxcore/friend_connection.c
@@ -11,8 +11,19 @@
#include <stdlib.h>
#include <string.h>
+#include "DHT.h"
+#include "LAN_discovery.h"
+#include "TCP_connection.h"
+#include "attributes.h"
#include "ccompat.h"
+#include "crypto_core.h"
+#include "logger.h"
#include "mono_time.h"
+#include "net_crypto.h"
+#include "network.h"
+#include "onion.h"
+#include "onion_announce.h"
+#include "onion_client.h"
#include "util.h"
#define PORTS_PER_DISCOVERY 10
@@ -56,7 +67,6 @@ struct Friend_Conn {
static const Friend_Conn empty_friend_conn = {0};
-
struct Friend_Connections {
const Mono_Time *mono_time;
const Logger *logger;
@@ -95,7 +105,6 @@ const IP_Port *friend_conn_get_dht_ip_port(const Friend_Conn *fc)
return &fc->dht_ip_port;
}
-
/**
* @retval true if the friendcon_id is valid.
* @retval false if the friendcon_id is not valid.
@@ -108,7 +117,6 @@ static bool friendconn_id_valid(const Friend_Connections *fr_c, int friendcon_id
fr_c->conns[friendcon_id].status != FRIENDCONN_STATUS_NONE;
}
-
/** @brief Set the size of the friend connections list to num.
*
* @retval false if realloc fails.
@@ -238,7 +246,7 @@ static int friend_add_tcp_relay(Friend_Connections *fr_c, int friendcon_id, cons
if (!net_family_is_unspec(friend_con->dht_ip_port.ip.family)) {
ipp_copy.ip = friend_con->dht_ip_port.ip;
} else {
- friend_con->hosting_tcp_relay = 0;
+ friend_con->hosting_tcp_relay = false;
}
}
@@ -362,7 +370,7 @@ static void dht_ip_callback(void *object, int32_t number, const IP_Port *ip_port
if (friend_con->hosting_tcp_relay) {
friend_add_tcp_relay(fr_c, number, ip_port, friend_con->dht_temp_pk);
- friend_con->hosting_tcp_relay = 0;
+ friend_con->hosting_tcp_relay = false;
}
}
@@ -390,10 +398,10 @@ static void change_dht_pk(Friend_Connections *fr_c, int friendcon_id, const uint
}
non_null()
-static int handle_status(void *object, int number, bool status, void *userdata)
+static int handle_status(void *object, int id, bool status, void *userdata)
{
Friend_Connections *const fr_c = (Friend_Connections *)object;
- Friend_Conn *const friend_con = get_conn(fr_c, number);
+ Friend_Conn *const friend_con = get_conn(fr_c, id);
if (friend_con == nullptr) {
return -1;
@@ -416,12 +424,12 @@ static int handle_status(void *object, int number, bool status, void *userdata)
friend_con->status = FRIENDCONN_STATUS_CONNECTING;
friend_con->crypt_connection_id = -1;
- friend_con->hosting_tcp_relay = 0;
+ friend_con->hosting_tcp_relay = false;
}
if (status_changed) {
if (fr_c->global_status_callback != nullptr) {
- fr_c->global_status_callback(fr_c->global_status_callback_object, number, status, userdata);
+ fr_c->global_status_callback(fr_c->global_status_callback_object, id, status, userdata);
}
for (unsigned i = 0; i < MAX_FRIEND_CONNECTION_CALLBACKS; ++i) {
@@ -461,18 +469,19 @@ static void dht_pk_callback(void *object, int32_t number, const uint8_t *dht_pub
}
friend_new_connection(fr_c, number);
- onion_set_friend_DHT_pubkey(fr_c->onion_c, friend_con->onion_friendnum, dht_public_key);
+ onion_set_friend_dht_pubkey(fr_c->onion_c, friend_con->onion_friendnum, dht_public_key);
}
non_null()
-static int handle_packet(void *object, int number, const uint8_t *data, uint16_t length, void *userdata)
+static int handle_packet(void *object, int id, const uint8_t *data, uint16_t length, void *userdata)
{
+ Friend_Connections *const fr_c = (Friend_Connections *)object;
+
if (length == 0) {
return -1;
}
- Friend_Connections *const fr_c = (Friend_Connections *)object;
- Friend_Conn *friend_con = get_conn(fr_c, number);
+ Friend_Conn *friend_con = get_conn(fr_c, id);
if (friend_con == nullptr) {
return -1;
@@ -500,7 +509,7 @@ static int handle_packet(void *object, int number, const uint8_t *data, uint16_t
}
for (int j = 0; j < n; ++j) {
- friend_add_tcp_relay(fr_c, number, &nodes[j].ip_port, nodes[j].public_key);
+ friend_add_tcp_relay(fr_c, id, &nodes[j].ip_port, nodes[j].public_key);
}
return 0;
@@ -513,7 +522,7 @@ static int handle_packet(void *object, int number, const uint8_t *data, uint16_t
friend_con->callbacks[i].callback_id, data, length, userdata);
}
- friend_con = get_conn(fr_c, number);
+ friend_con = get_conn(fr_c, id);
if (friend_con == nullptr) {
return -1;
@@ -524,14 +533,15 @@ static int handle_packet(void *object, int number, const uint8_t *data, uint16_t
}
non_null()
-static int handle_lossy_packet(void *object, int number, const uint8_t *data, uint16_t length, void *userdata)
+static int handle_lossy_packet(void *object, int id, const uint8_t *data, uint16_t length, void *userdata)
{
+ const Friend_Connections *const fr_c = (const Friend_Connections *)object;
+
if (length == 0) {
return -1;
}
- const Friend_Connections *const fr_c = (const Friend_Connections *)object;
- const Friend_Conn *friend_con = get_conn(fr_c, number);
+ const Friend_Conn *friend_con = get_conn(fr_c, id);
if (friend_con == nullptr) {
return -1;
@@ -544,7 +554,7 @@ static int handle_lossy_packet(void *object, int number, const uint8_t *data, ui
friend_con->callbacks[i].callback_id, data, length, userdata);
}
- friend_con = get_conn(fr_c, number);
+ friend_con = get_conn(fr_c, id);
if (friend_con == nullptr) {
return -1;
@@ -845,7 +855,6 @@ int kill_friend_connection(Friend_Connections *fr_c, int friendcon_id)
return wipe_friend_conn(fr_c, friendcon_id);
}
-
/** @brief Set friend request callback.
*
* This function will be called every time a friend request packet is received.
@@ -876,18 +885,19 @@ int send_friend_request_packet(Friend_Connections *fr_c, int friendcon_id, uint3
return -1;
}
- VLA(uint8_t, packet, 1 + sizeof(nospam_num) + length);
+ const uint16_t packet_size = 1 + sizeof(nospam_num) + length;
+ VLA(uint8_t, packet, packet_size);
memcpy(packet + 1, &nospam_num, sizeof(nospam_num));
memcpy(packet + 1 + sizeof(nospam_num), data, length);
if (friend_con->status == FRIENDCONN_STATUS_CONNECTED) {
packet[0] = PACKET_ID_FRIEND_REQUESTS;
- return write_cryptpacket(fr_c->net_crypto, friend_con->crypt_connection_id, packet, SIZEOF_VLA(packet),
+ return write_cryptpacket(fr_c->net_crypto, friend_con->crypt_connection_id, packet, packet_size,
false) != -1 ? 1 : 0;
}
packet[0] = CRYPTO_PACKET_FRIEND_REQ;
- const int num = send_onion_data(fr_c->onion_c, friend_con->onion_friendnum, packet, SIZEOF_VLA(packet));
+ const int num = send_onion_data(fr_c->onion_c, friend_con->onion_friendnum, packet, packet_size);
if (num <= 0) {
return -1;
@@ -898,8 +908,8 @@ int send_friend_request_packet(Friend_Connections *fr_c, int friendcon_id, uint3
/** Create new friend_connections instance. */
Friend_Connections *new_friend_connections(
- const Logger *logger, const Mono_Time *mono_time, const Network *ns,
- Onion_Client *onion_c, bool local_discovery_enabled)
+ const Logger *logger, const Mono_Time *mono_time, const Network *ns,
+ Onion_Client *onion_c, bool local_discovery_enabled)
{
if (onion_c == nullptr) {
return nullptr;
@@ -911,25 +921,27 @@ Friend_Connections *new_friend_connections(
return nullptr;
}
- temp->mono_time = mono_time;
- temp->logger = logger;
- temp->dht = onion_get_dht(onion_c);
- temp->net_crypto = onion_get_net_crypto(onion_c);
- temp->onion_c = onion_c;
temp->local_discovery_enabled = local_discovery_enabled;
- // Don't include default port in port range
- temp->next_lan_port = TOX_PORTRANGE_FROM + 1;
-
- new_connection_handler(temp->net_crypto, &handle_new_connections, temp);
if (temp->local_discovery_enabled) {
temp->broadcast = lan_discovery_init(ns);
if (temp->broadcast == nullptr) {
LOGGER_ERROR(logger, "could not initialise LAN discovery");
+ temp->local_discovery_enabled = false;
}
}
+ temp->mono_time = mono_time;
+ temp->logger = logger;
+ temp->dht = onion_get_dht(onion_c);
+ temp->net_crypto = onion_get_net_crypto(onion_c);
+ temp->onion_c = onion_c;
+ // Don't include default port in port range
+ temp->next_lan_port = TOX_PORTRANGE_FROM + 1;
+
+ new_connection_handler(temp->net_crypto, &handle_new_connections, temp);
+
return temp;
}
@@ -971,7 +983,7 @@ void do_friend_connections(Friend_Connections *fr_c, void *userdata)
if (friend_con->dht_lock_token > 0) {
dht_delfriend(fr_c->dht, friend_con->dht_temp_pk, friend_con->dht_lock_token);
friend_con->dht_lock_token = 0;
- memset(friend_con->dht_temp_pk, 0, CRYPTO_PUBLIC_KEY_SIZE);
+ memzero(friend_con->dht_temp_pk, CRYPTO_PUBLIC_KEY_SIZE);
}
}
diff --git a/protocols/Tox/libtox/src/toxcore/friend_connection.h b/protocols/Tox/libtox/src/toxcore/friend_connection.h
index 93bd5113ac..bbd4454729 100644
--- a/protocols/Tox/libtox/src/toxcore/friend_connection.h
+++ b/protocols/Tox/libtox/src/toxcore/friend_connection.h
@@ -9,9 +9,15 @@
#ifndef C_TOXCORE_TOXCORE_FRIEND_CONNECTION_H
#define C_TOXCORE_TOXCORE_FRIEND_CONNECTION_H
+#include <stdint.h>
+
#include "DHT.h"
#include "LAN_discovery.h"
+#include "attributes.h"
+#include "logger.h"
+#include "mono_time.h"
#include "net_crypto.h"
+#include "network.h"
#include "onion_client.h"
#define MAX_FRIEND_CONNECTION_CALLBACKS 2
@@ -39,7 +45,6 @@
/** How often we share our TCP relays with each friend connection */
#define SHARE_RELAYS_INTERVAL (60 * 2)
-
typedef enum Friendconn_Status {
FRIENDCONN_STATUS_NONE,
FRIENDCONN_STATUS_CONNECTING,
@@ -84,11 +89,11 @@ int get_friendcon_public_keys(uint8_t *real_pk, uint8_t *dht_temp_pk, const Frie
non_null()
void set_dht_temp_pk(Friend_Connections *fr_c, int friendcon_id, const uint8_t *dht_temp_pk, void *userdata);
-typedef int global_status_cb(void *object, int id, bool status, void *userdata);
+typedef int global_status_cb(void *object, int friendcon_id, bool status, void *userdata);
-typedef int fc_status_cb(void *object, int id, bool status, void *userdata);
-typedef int fc_data_cb(void *object, int id, const uint8_t *data, uint16_t length, void *userdata);
-typedef int fc_lossy_data_cb(void *object, int id, const uint8_t *data, uint16_t length, void *userdata);
+typedef int fc_status_cb(void *object, int friendcon_id, bool status, void *userdata);
+typedef int fc_data_cb(void *object, int friendcon_id, const uint8_t *data, uint16_t length, void *userdata);
+typedef int fc_lossy_data_cb(void *object, int friendcon_id, const uint8_t *data, uint16_t length, void *userdata);
/** Set global status callback for friend connections. */
non_null(1) nullable(2, 3)
@@ -144,7 +149,7 @@ int send_friend_request_packet(
Friend_Connections *fr_c, int friendcon_id, uint32_t nospam_num, const uint8_t *data, uint16_t length);
typedef int fr_request_cb(
- void *object, const uint8_t *source_pubkey, const uint8_t *data, uint16_t len, void *userdata);
+ void *object, const uint8_t *source_pubkey, const uint8_t *data, uint16_t length, void *userdata);
/** @brief Set friend request callback.
*
@@ -156,8 +161,8 @@ void set_friend_request_callback(Friend_Connections *fr_c, fr_request_cb *fr_req
/** Create new friend_connections instance. */
non_null()
Friend_Connections *new_friend_connections(
- const Logger *logger, const Mono_Time *mono_time, const Network *ns,
- Onion_Client *onion_c, bool local_discovery_enabled);
+ const Logger *logger, const Mono_Time *mono_time, const Network *ns,
+ Onion_Client *onion_c, bool local_discovery_enabled);
/** main friend_connections loop. */
non_null()
@@ -173,4 +178,4 @@ non_null() Friend_Conn *get_conn(const Friend_Connections *fr_c, int friendcon_i
non_null() int friend_conn_get_onion_friendnum(const Friend_Conn *fc);
non_null() const IP_Port *friend_conn_get_dht_ip_port(const Friend_Conn *fc);
-#endif
+#endif /* C_TOXCORE_TOXCORE_FRIEND_CONNECTION_H */
diff --git a/protocols/Tox/libtox/src/toxcore/friend_requests.c b/protocols/Tox/libtox/src/toxcore/friend_requests.c
index 7f18b1ff02..8b915449cd 100644
--- a/protocols/Tox/libtox/src/toxcore/friend_requests.c
+++ b/protocols/Tox/libtox/src/toxcore/friend_requests.c
@@ -11,8 +11,14 @@
#include <stdlib.h>
#include <string.h>
+#include "attributes.h"
#include "ccompat.h"
-#include "util.h"
+#include "crypto_core.h"
+#include "friend_connection.h"
+#include "network.h"
+#include "onion.h"
+#include "onion_announce.h"
+#include "onion_client.h"
/**
* NOTE: The following is just a temporary fix for the multiple friend requests received at the same time problem.
@@ -48,7 +54,6 @@ uint32_t get_nospam(const Friend_Requests *fr)
return fr->nospam;
}
-
/** Set the function that will be executed when a friend request for us is received. */
void callback_friendrequest(Friend_Requests *fr, fr_friend_request_cb *function, void *object)
{
@@ -112,9 +117,8 @@ int remove_request_received(Friend_Requests *fr, const uint8_t *real_pk)
return -1;
}
-
non_null()
-static int friendreq_handlepacket(void *object, const uint8_t *source_pubkey, const uint8_t *packet, uint16_t length,
+static int friendreq_handlepacket(void *object, const uint8_t *source_pubkey, const uint8_t *data, uint16_t length,
void *userdata)
{
Friend_Requests *const fr = (Friend_Requests *)object;
@@ -123,7 +127,7 @@ static int friendreq_handlepacket(void *object, const uint8_t *source_pubkey, co
return 1;
}
- ++packet;
+ ++data;
--length;
if (fr->handle_friendrequest_isset == 0) {
@@ -134,22 +138,22 @@ static int friendreq_handlepacket(void *object, const uint8_t *source_pubkey, co
return 1;
}
- if (memcmp(packet, &fr->nospam, sizeof(fr->nospam)) != 0) {
+ if (memcmp(data, &fr->nospam, sizeof(fr->nospam)) != 0) {
return 1;
}
if (fr->filter_function != nullptr) {
- if (fr->filter_function(source_pubkey, fr->filter_function_userdata) != 0) {
+ if (fr->filter_function(fr->filter_function_userdata, source_pubkey) != 0) {
return 1;
}
}
addto_receivedlist(fr, source_pubkey);
- const uint32_t message_len = length - sizeof(fr->nospam);
+ const uint16_t message_len = length - sizeof(fr->nospam);
VLA(uint8_t, message, message_len + 1);
- memcpy(message, packet + sizeof(fr->nospam), message_len);
- message[SIZEOF_VLA(message) - 1] = 0; /* Be sure the message is null terminated. */
+ memcpy(message, data + sizeof(fr->nospam), message_len);
+ message[message_len] = 0; /* Be sure the message is null terminated. TODO(iphydf): But why? */
fr->handle_friendrequest(fr->handle_friendrequest_object, source_pubkey, message, message_len, userdata);
return 0;
diff --git a/protocols/Tox/libtox/src/toxcore/friend_requests.h b/protocols/Tox/libtox/src/toxcore/friend_requests.h
index 2614527163..a78a570dfa 100644
--- a/protocols/Tox/libtox/src/toxcore/friend_requests.h
+++ b/protocols/Tox/libtox/src/toxcore/friend_requests.h
@@ -9,6 +9,9 @@
#ifndef C_TOXCORE_TOXCORE_FRIEND_REQUESTS_H
#define C_TOXCORE_TOXCORE_FRIEND_REQUESTS_H
+#include <stddef.h>
+
+#include "attributes.h"
#include "friend_connection.h"
#define MAX_FRIEND_REQUEST_DATA_SIZE (ONION_CLIENT_MAX_DATA_SIZE - (1 + sizeof(uint32_t)))
@@ -34,7 +37,7 @@ typedef void fr_friend_request_cb(void *object, const uint8_t *public_key, const
non_null()
void callback_friendrequest(Friend_Requests *fr, fr_friend_request_cb *function, void *object);
-typedef int filter_function_cb(const uint8_t *public_key, void *user_data);
+typedef int filter_function_cb(void *object, const uint8_t *public_key);
/** @brief Set the function used to check if a friend request should be displayed to the user or not.
* It must return 0 if the request is ok (anything else if it is bad).
@@ -51,4 +54,4 @@ Friend_Requests *friendreq_new(void);
nullable(1)
void friendreq_kill(Friend_Requests *fr);
-#endif
+#endif /* C_TOXCORE_TOXCORE_FRIEND_REQUESTS_H */
diff --git a/protocols/Tox/libtox/src/toxcore/group.c b/protocols/Tox/libtox/src/toxcore/group.c
index 0e851b1e34..14e61e6ffc 100644
--- a/protocols/Tox/libtox/src/toxcore/group.c
+++ b/protocols/Tox/libtox/src/toxcore/group.c
@@ -12,8 +12,17 @@
#include <stdlib.h>
#include <string.h>
+#include "DHT.h"
+#include "Messenger.h"
+#include "attributes.h"
#include "ccompat.h"
+#include "crypto_core.h"
+#include "friend_connection.h"
+#include "group_common.h"
+#include "logger.h"
#include "mono_time.h"
+#include "net_crypto.h"
+#include "network.h"
#include "state.h"
#include "util.h"
@@ -212,13 +221,13 @@ static bool group_id_eq(const uint8_t *a, const uint8_t *b)
}
non_null()
-static bool g_title_eq(Group_c *g, const uint8_t *title, uint8_t title_len)
+static bool g_title_eq(const Group_c *g, const uint8_t *title, uint8_t title_len)
{
return memeq(g->title, g->title_len, title, title_len);
}
non_null()
-static bool g_peer_nick_eq(Group_Peer *peer, const uint8_t *nick, uint8_t nick_len)
+static bool g_peer_nick_eq(const Group_Peer *peer, const uint8_t *nick, uint8_t nick_len)
{
return memeq(peer->nick, peer->nick_len, nick, nick_len);
}
@@ -235,7 +244,6 @@ static bool is_groupnumber_valid(const Group_Chats *g_c, uint32_t groupnumber)
&& g_c->chats[groupnumber].status != GROUPCHAT_STATUS_NONE;
}
-
/** @brief Set the size of the groupchat list to num.
*
* @retval false if realloc fails.
@@ -421,7 +429,6 @@ static int get_peer_index(const Group_c *g, uint16_t peer_number)
return -1;
}
-
non_null()
static uint64_t calculate_comp_value(const uint8_t *pk1, const uint8_t *pk2)
{
@@ -480,7 +487,7 @@ static bool add_to_closest(Group_c *g, const uint8_t *real_pk, const uint8_t *te
comp_val = calculate_comp_value(real_pk, g->real_pk);
for (unsigned int i = DESIRED_CLOSEST / 2; i < DESIRED_CLOSEST; ++i) {
- uint64_t comp = calculate_comp_value(g->closest_peers[i].real_pk, g->real_pk);
+ const uint64_t comp = calculate_comp_value(g->closest_peers[i].real_pk, g->real_pk);
if (comp > comp_val && comp > comp_d) {
index = i;
@@ -676,7 +683,7 @@ static bool delete_frozen(Group_c *g, uint32_t frozen_index)
g->frozen[frozen_index] = g->frozen[g->numfrozen];
}
- Group_Peer *const frozen_temp = (Group_Peer *)realloc(g->frozen, sizeof(Group_Peer) * g->numfrozen);
+ Group_Peer *const frozen_temp = (Group_Peer *)realloc(g->frozen, g->numfrozen * sizeof(Group_Peer));
if (frozen_temp == nullptr) {
return false;
@@ -717,7 +724,7 @@ static int note_peer_active(Group_Chats *g_c, uint32_t groupnumber, uint16_t pee
/* Now thaw the peer */
- Group_Peer *temp = (Group_Peer *)realloc(g->group, sizeof(Group_Peer) * (g->numpeers + 1));
+ Group_Peer *temp = (Group_Peer *)realloc(g->group, (g->numpeers + 1) * sizeof(Group_Peer));
if (temp == nullptr) {
return -1;
@@ -802,6 +809,7 @@ static int addpeer(Group_Chats *g_c, uint32_t groupnumber, const uint8_t *real_p
if (peer_index != -1) {
if (!pk_equal(g->group[peer_index].real_pk, real_pk)) {
+ LOGGER_ERROR(g_c->m->log, "peer public key is incorrect for peer %d", peer_number);
return -1;
}
@@ -829,7 +837,7 @@ static int addpeer(Group_Chats *g_c, uint32_t groupnumber, const uint8_t *real_p
delete_any_peer_with_pk(g_c, groupnumber, real_pk, userdata);
- Group_Peer *temp = (Group_Peer *)realloc(g->group, sizeof(Group_Peer) * (g->numpeers + 1));
+ Group_Peer *temp = (Group_Peer *)realloc(g->group, (g->numpeers + 1) * sizeof(Group_Peer));
if (temp == nullptr) {
return -1;
@@ -927,7 +935,7 @@ static bool delpeer(Group_Chats *g_c, uint32_t groupnumber, int peer_index, void
g->group[peer_index] = g->group[g->numpeers];
}
- Group_Peer *temp = (Group_Peer *)realloc(g->group, sizeof(Group_Peer) * g->numpeers);
+ Group_Peer *temp = (Group_Peer *)realloc(g->group, g->numpeers * sizeof(Group_Peer));
if (temp == nullptr) {
return false;
@@ -947,11 +955,6 @@ static bool delpeer(Group_Chats *g_c, uint32_t groupnumber, int peer_index, void
return true;
}
-static int cmp_u64(uint64_t a, uint64_t b)
-{
- return (a > b ? 1 : 0) - (a < b ? 1 : 0);
-}
-
/** Order peers with friends first and with more recently active earlier */
non_null()
static int cmp_frozen(const void *a, const void *b)
@@ -963,7 +966,7 @@ static int cmp_frozen(const void *a, const void *b)
return pa->is_friend ? -1 : 1;
}
- return cmp_u64(pb->last_active, pa->last_active);
+ return cmp_uint(pb->last_active, pa->last_active);
}
/** @brief Delete frozen peers as necessary to ensure at most `g->maxfrozen` remain.
@@ -986,7 +989,7 @@ static bool delete_old_frozen(Group_c *g)
qsort(g->frozen, g->numfrozen, sizeof(Group_Peer), cmp_frozen);
- Group_Peer *temp = (Group_Peer *)realloc(g->frozen, sizeof(Group_Peer) * g->maxfrozen);
+ Group_Peer *temp = (Group_Peer *)realloc(g->frozen, g->maxfrozen * sizeof(Group_Peer));
if (temp == nullptr) {
return false;
@@ -1011,7 +1014,7 @@ static bool freeze_peer(Group_Chats *g_c, uint32_t groupnumber, int peer_index,
return false;
}
- Group_Peer *temp = (Group_Peer *)realloc(g->frozen, sizeof(Group_Peer) * (g->numfrozen + 1));
+ Group_Peer *temp = (Group_Peer *)realloc(g->frozen, (g->numfrozen + 1) * sizeof(Group_Peer));
if (temp == nullptr) {
return false;
@@ -1034,7 +1037,6 @@ static bool freeze_peer(Group_Chats *g_c, uint32_t groupnumber, int peer_index,
return true;
}
-
/** @brief Set the nick for a peer.
*
* do_gc_callback indicates whether we want to trigger callbacks set by the client
@@ -1396,7 +1398,6 @@ static const Group_Peer *peer_in_list(const Group_c *g, uint32_t peernumber, boo
return &list[peernumber];
}
-
/**
* @brief Copy the public key of (frozen, if frozen is true) peernumber who is in
* groupnumber to pk.
@@ -1613,12 +1614,13 @@ static bool send_packet_group_peer(const Friend_Connections *fr_c, int friendcon
}
group_num = net_htons(group_num);
- VLA(uint8_t, packet, 1 + sizeof(uint16_t) + length);
+ const uint32_t packet_size = 1 + sizeof(uint16_t) + length;
+ VLA(uint8_t, packet, packet_size);
packet[0] = packet_id;
memcpy(packet + 1, &group_num, sizeof(uint16_t));
memcpy(packet + 1 + sizeof(uint16_t), data, length);
- return write_cryptpacket(friendconn_net_crypto(fr_c), friend_connection_crypt_connection_id(fr_c, friendcon_id), packet,
- SIZEOF_VLA(packet), false) != -1;
+ return write_cryptpacket(friendconn_net_crypto(fr_c), friend_connection_crypt_connection_id(fr_c, friendcon_id),
+ packet, packet_size, false) != -1;
}
/** @brief Send a group lossy packet to friendcon_id.
@@ -1635,12 +1637,13 @@ static bool send_lossy_group_peer(const Friend_Connections *fr_c, int friendcon_
}
group_num = net_htons(group_num);
- VLA(uint8_t, packet, 1 + sizeof(uint16_t) + length);
+ const uint32_t packet_size = 1 + sizeof(uint16_t) + length;
+ VLA(uint8_t, packet, packet_size);
packet[0] = packet_id;
memcpy(packet + 1, &group_num, sizeof(uint16_t));
memcpy(packet + 1 + sizeof(uint16_t), data, length);
return send_lossy_cryptpacket(friendconn_net_crypto(fr_c), friend_connection_crypt_connection_id(fr_c, friendcon_id),
- packet, SIZEOF_VLA(packet)) != -1;
+ packet, packet_size) != -1;
}
/** @brief invite friendnumber to groupnumber.
@@ -1773,7 +1776,8 @@ static bool send_invite_response(Group_Chats *g_c, int groupnumber, uint32_t fri
const bool member = g->status == GROUPCHAT_STATUS_CONNECTED;
- VLA(uint8_t, response, member ? INVITE_MEMBER_PACKET_SIZE : INVITE_ACCEPT_PACKET_SIZE);
+ const uint32_t response_size = member ? INVITE_MEMBER_PACKET_SIZE : INVITE_ACCEPT_PACKET_SIZE;
+ VLA(uint8_t, response, response_size);
response[0] = member ? INVITE_MEMBER_ID : INVITE_ACCEPT_ID;
net_pack_u16(response + 1, groupnumber);
memcpy(response + 1 + sizeof(uint16_t), data, length);
@@ -1782,7 +1786,7 @@ static bool send_invite_response(Group_Chats *g_c, int groupnumber, uint32_t fri
net_pack_u16(response + 1 + sizeof(uint16_t) + length, g->peer_number);
}
- if (!send_conference_invite_packet(g_c->m, friendnumber, response, SIZEOF_VLA(response))) {
+ if (!send_conference_invite_packet(g_c->m, friendnumber, response, response_size)) {
return false;
}
@@ -2004,7 +2008,6 @@ static bool group_leave(const Group_Chats *g_c, uint32_t groupnumber, bool perma
}
}
-
/** @brief set the group's title, limited to MAX_NAME_LENGTH.
* @retval 0 on success
* @retval -1 if groupnumber is invalid.
@@ -2106,8 +2109,8 @@ static bool get_peer_number(const Group_c *g, const uint8_t *real_pk, uint16_t *
}
non_null(1, 3) nullable(5)
-static void handle_friend_invite_packet(Messenger *m, uint32_t friendnumber, const uint8_t *data, uint16_t length,
- void *userdata)
+static void handle_friend_invite_packet(Messenger *m, uint32_t friend_number, const uint8_t *cookie, uint16_t length,
+ void *user_data)
{
Group_Chats *g_c = m->conferences_object;
@@ -2115,20 +2118,20 @@ static void handle_friend_invite_packet(Messenger *m, uint32_t friendnumber, con
return;
}
- switch (data[0]) {
+ switch (cookie[0]) {
case INVITE_ID: {
if (length != INVITE_PACKET_SIZE) {
return;
}
- const int groupnumber = get_group_num(g_c, data[1 + sizeof(uint16_t)], data + 1 + sizeof(uint16_t) + 1);
+ const int groupnumber = get_group_num(g_c, cookie[1 + sizeof(uint16_t)], cookie + 1 + sizeof(uint16_t) + 1);
- const uint8_t *invite_data = data + 1;
+ const uint8_t *invite_data = cookie + 1;
const uint16_t invite_length = length - 1;
if (groupnumber == -1) {
if (g_c->invite_callback != nullptr) {
- g_c->invite_callback(m, friendnumber, invite_data[sizeof(uint16_t)], invite_data, invite_length, userdata);
+ g_c->invite_callback(m, friend_number, invite_data[sizeof(uint16_t)], invite_data, invite_length, user_data);
}
return;
@@ -2136,7 +2139,7 @@ static void handle_friend_invite_packet(Messenger *m, uint32_t friendnumber, con
const Group_c *g = get_group_c(g_c, groupnumber);
if (g != nullptr && g->status == GROUPCHAT_STATUS_CONNECTED) {
- send_invite_response(g_c, groupnumber, friendnumber, invite_data, invite_length);
+ send_invite_response(g_c, groupnumber, friend_number, invite_data, invite_length);
}
}
@@ -2145,7 +2148,7 @@ static void handle_friend_invite_packet(Messenger *m, uint32_t friendnumber, con
case INVITE_ACCEPT_ID:
case INVITE_MEMBER_ID: {
- const bool member = data[0] == INVITE_MEMBER_ID;
+ const bool member = cookie[0] == INVITE_MEMBER_ID;
if (length != (member ? INVITE_MEMBER_PACKET_SIZE : INVITE_ACCEPT_PACKET_SIZE)) {
return;
@@ -2153,8 +2156,8 @@ static void handle_friend_invite_packet(Messenger *m, uint32_t friendnumber, con
uint16_t other_groupnum;
uint16_t groupnum;
- net_unpack_u16(data + 1, &other_groupnum);
- net_unpack_u16(data + 1 + sizeof(uint16_t), &groupnum);
+ net_unpack_u16(cookie + 1, &other_groupnum);
+ net_unpack_u16(cookie + 1 + sizeof(uint16_t), &groupnum);
Group_c *g = get_group_c(g_c, groupnum);
@@ -2162,18 +2165,18 @@ static void handle_friend_invite_packet(Messenger *m, uint32_t friendnumber, con
return;
}
- if (data[1 + sizeof(uint16_t) * 2] != g->type) {
+ if (cookie[1 + sizeof(uint16_t) * 2] != g->type) {
return;
}
- if (!group_id_eq(data + 1 + sizeof(uint16_t) * 2 + 1, g->id)) {
+ if (!group_id_eq(cookie + 1 + sizeof(uint16_t) * 2 + 1, g->id)) {
return;
}
uint16_t peer_number;
if (member) {
- net_unpack_u16(data + 1 + sizeof(uint16_t) * 2 + 1 + GROUP_ID_LENGTH, &peer_number);
+ net_unpack_u16(cookie + 1 + sizeof(uint16_t) * 2 + 1 + GROUP_ID_LENGTH, &peer_number);
} else {
/* TODO(irungentoo): what if two people enter the group at the
* same time and are given the same peer_number by different
@@ -2192,7 +2195,7 @@ static void handle_friend_invite_packet(Messenger *m, uint32_t friendnumber, con
}
}
- const int friendcon_id = getfriendcon_id(m, friendnumber);
+ const int friendcon_id = getfriendcon_id(m, friend_number);
if (friendcon_id == -1) {
// TODO(iphydf): Log something?
@@ -2203,7 +2206,7 @@ static void handle_friend_invite_packet(Messenger *m, uint32_t friendnumber, con
uint8_t temp_pk[CRYPTO_PUBLIC_KEY_SIZE];
get_friendcon_public_keys(real_pk, temp_pk, g_c->fr_c, friendcon_id);
- addpeer(g_c, groupnum, real_pk, temp_pk, peer_number, userdata, true, true);
+ addpeer(g_c, groupnum, real_pk, temp_pk, peer_number, user_data, true, true);
const int connection_index = add_conn_to_groupchat(g_c, friendcon_id, g,
GROUPCHAT_CONNECTION_REASON_INTRODUCING, true);
@@ -2377,7 +2380,6 @@ static int handle_packet_rejoin(Group_Chats *g_c, int friendcon_id, const uint8_
return 0;
}
-
// we could send title with invite, but then if it changes between sending and accepting inv, joinee won't see it
/**
@@ -2391,7 +2393,6 @@ static bool send_peer_introduced(const Group_Chats *g_c, int friendcon_id, uint1
return send_packet_group_peer(g_c->fr_c, friendcon_id, PACKET_ID_DIRECT_CONFERENCE, group_num, packet, sizeof(packet));
}
-
/**
* @retval true on success.
* @retval false on failure
@@ -2448,11 +2449,12 @@ static unsigned int send_peers(const Group_Chats *g_c, const Group_c *g, int fri
}
if (g->title_len > 0) {
- VLA(uint8_t, title_packet, 1 + g->title_len);
+ const uint32_t title_packet_size = 1 + g->title_len;
+ VLA(uint8_t, title_packet, title_packet_size);
title_packet[0] = PEER_TITLE_ID;
memcpy(title_packet + 1, g->title, g->title_len);
- send_packet_group_peer(g_c->fr_c, friendcon_id, PACKET_ID_DIRECT_CONFERENCE, group_num, title_packet,
- SIZEOF_VLA(title_packet));
+ send_packet_group_peer(g_c->fr_c, friendcon_id, PACKET_ID_DIRECT_CONFERENCE, group_num,
+ title_packet, title_packet_size);
}
return sent;
@@ -2545,13 +2547,11 @@ static void handle_direct_packet(Group_Chats *g_c, uint32_t groupnumber, const u
break;
}
-
case PEER_RESPONSE_ID: {
handle_send_peers(g_c, groupnumber, data + 1, length - 1, userdata);
break;
}
-
case PEER_TITLE_ID: {
if (!g->title_fresh) {
settitle(g_c, groupnumber, -1, data + 1, length - 1, userdata);
@@ -2687,7 +2687,8 @@ static int send_message_group(const Group_Chats *g_c, uint32_t groupnumber, uint
return -3;
}
- VLA(uint8_t, packet, sizeof(uint16_t) + sizeof(uint32_t) + 1 + len);
+ const uint16_t packet_size = sizeof(uint16_t) + sizeof(uint32_t) + 1 + len;
+ VLA(uint8_t, packet, packet_size);
const uint16_t peer_num = net_htons(g->peer_number);
memcpy(packet, &peer_num, sizeof(peer_num));
@@ -2706,7 +2707,7 @@ static int send_message_group(const Group_Chats *g_c, uint32_t groupnumber, uint
memcpy(packet + sizeof(uint16_t) + sizeof(uint32_t) + 1, data, len);
}
- const unsigned int ret = send_message_all_connections(g_c, g, packet, SIZEOF_VLA(packet), -1);
+ const unsigned int ret = send_message_all_connections(g_c, g, packet, packet_size, -1);
if (ret == 0) {
return -4;
@@ -2759,14 +2760,15 @@ int send_group_lossy_packet(const Group_Chats *g_c, uint32_t groupnumber, const
return -1;
}
- VLA(uint8_t, packet, sizeof(uint16_t) * 2 + length);
+ const uint16_t packet_size = sizeof(uint16_t) * 2 + length;
+ VLA(uint8_t, packet, packet_size);
const uint16_t peer_number = net_htons(g->peer_number);
memcpy(packet, &peer_number, sizeof(uint16_t));
const uint16_t message_num = net_htons(g->lossy_message_number);
memcpy(packet + sizeof(uint16_t), &message_num, sizeof(uint16_t));
memcpy(packet + sizeof(uint16_t) * 2, data, length);
- if (send_lossy_all_connections(g_c, g, packet, SIZEOF_VLA(packet), -1) == 0) {
+ if (send_lossy_all_connections(g_c, g, packet, packet_size, -1) == 0) {
return -1;
}
@@ -3679,6 +3681,7 @@ static State_Load_Status load_conferences_helper(Group_Chats *g_c, const uint8_t
if (groupnumber == -1) {
// If this fails there's a serious problem, don't bother with cleanup
+ LOGGER_ERROR(g_c->m->log, "conference creation failed");
return STATE_LOAD_STATUS_ERROR;
}
@@ -3696,6 +3699,7 @@ static State_Load_Status load_conferences_helper(Group_Chats *g_c, const uint8_t
assert(ret);
}
+ LOGGER_ERROR(g_c->m->log, "conference loading failed");
return STATE_LOAD_STATUS_ERROR;
}
@@ -3705,6 +3709,7 @@ static State_Load_Status load_conferences_helper(Group_Chats *g_c, const uint8_t
nullptr, true, false);
if (peer_index == -1) {
+ LOGGER_ERROR(g_c->m->log, "adding peer %d failed", g->peer_number);
return STATE_LOAD_STATUS_ERROR;
}
@@ -3746,7 +3751,6 @@ bool conferences_load_state_section(Group_Chats *g_c, const uint8_t *data, uint3
return true;
}
-
/** Create new groupchat instance. */
Group_Chats *new_groupchats(const Mono_Time *mono_time, Messenger *m)
{
@@ -3763,7 +3767,6 @@ Group_Chats *new_groupchats(const Mono_Time *mono_time, Messenger *m)
temp->mono_time = mono_time;
temp->m = m;
temp->fr_c = m->fr_c;
- m->conferences_object = temp;
m_callback_conference_invite(m, &handle_friend_invite_packet);
set_global_status_callback(m->fr_c, &g_handle_any_status, temp);
diff --git a/protocols/Tox/libtox/src/toxcore/group.h b/protocols/Tox/libtox/src/toxcore/group.h
index e6f6c44733..5ce03275ec 100644
--- a/protocols/Tox/libtox/src/toxcore/group.h
+++ b/protocols/Tox/libtox/src/toxcore/group.h
@@ -9,7 +9,14 @@
#ifndef C_TOXCORE_TOXCORE_GROUP_H
#define C_TOXCORE_TOXCORE_GROUP_H
+#include <stddef.h>
+#include <stdint.h>
+
#include "Messenger.h"
+#include "attributes.h"
+#include "crypto_core.h"
+#include "mono_time.h"
+#include "state.h"
typedef enum Groupchat_Type {
GROUPCHAT_TYPE_TEXT,
@@ -72,7 +79,6 @@ void g_callback_group_connected(Group_Chats *g_c, g_conference_connected_cb *fun
non_null()
void g_callback_group_message(Group_Chats *g_c, g_conference_message_cb *function);
-
/** Set callback function for title changes. */
non_null()
void g_callback_group_title(Group_Chats *g_c, title_cb *function);
@@ -217,7 +223,6 @@ int group_action_send(const Group_Chats *g_c, uint32_t groupnumber, const uint8_
non_null()
int group_title_send(const Group_Chats *g_c, uint32_t groupnumber, const uint8_t *title, uint8_t title_len);
-
/** @brief return the group's title size.
* @retval -1 of groupnumber is invalid.
* @retval -2 if title is too long or empty.
@@ -395,4 +400,4 @@ void do_groupchats(Group_Chats *g_c, void *userdata);
nullable(1)
void kill_groupchats(Group_Chats *g_c);
-#endif
+#endif /* C_TOXCORE_TOXCORE_GROUP_H */
diff --git a/protocols/Tox/libtox/src/toxcore/group_announce.c b/protocols/Tox/libtox/src/toxcore/group_announce.c
index 896b043dbd..ee083198c1 100644
--- a/protocols/Tox/libtox/src/toxcore/group_announce.c
+++ b/protocols/Tox/libtox/src/toxcore/group_announce.c
@@ -8,10 +8,13 @@
#include <stdlib.h>
#include <string.h>
-#include "LAN_discovery.h"
+#include "DHT.h"
+#include "attributes.h"
#include "ccompat.h"
+#include "crypto_core.h"
+#include "logger.h"
#include "mono_time.h"
-#include "util.h"
+#include "network.h"
/**
* Removes `announces` from `gc_announces_list`.
@@ -75,7 +78,7 @@ int gca_get_announces(const GC_Announces_List *gc_announces_list, GC_Announce *g
for (size_t i = 0; i < announces->index && i < GCA_MAX_SAVED_ANNOUNCES_PER_GC && added_count < max_nodes; ++i) {
const size_t index = i % GCA_MAX_SAVED_ANNOUNCES_PER_GC;
- if (memcmp(except_public_key, &announces->peer_announces[index].base_announce.peer_public_key,
+ if (memcmp(except_public_key, announces->peer_announces[index].base_announce.peer_public_key,
ENC_PUBLIC_KEY_SIZE) == 0) {
continue;
}
@@ -83,7 +86,7 @@ int gca_get_announces(const GC_Announces_List *gc_announces_list, GC_Announce *g
bool already_added = false;
for (size_t j = 0; j < added_count; ++j) {
- if (memcmp(&gc_announces[j].peer_public_key, &announces->peer_announces[index].base_announce.peer_public_key,
+ if (memcmp(gc_announces[j].peer_public_key, announces->peer_announces[index].base_announce.peer_public_key,
ENC_PUBLIC_KEY_SIZE) == 0) {
already_added = true;
break;
@@ -338,6 +341,31 @@ int gca_unpack_announces_list(const Logger *log, const uint8_t *data, uint16_t l
return announces_count;
}
+non_null()
+static GC_Announces *gca_new_announces(
+ GC_Announces_List *gc_announces_list,
+ const GC_Public_Announce *public_announce)
+{
+ GC_Announces *announces = (GC_Announces *)calloc(1, sizeof(GC_Announces));
+
+ if (announces == nullptr) {
+ return nullptr;
+ }
+
+ announces->index = 0;
+ announces->prev_announce = nullptr;
+
+ if (gc_announces_list->root_announces != nullptr) {
+ gc_announces_list->root_announces->prev_announce = announces;
+ }
+
+ announces->next_announce = gc_announces_list->root_announces;
+ gc_announces_list->root_announces = announces;
+ memcpy(announces->chat_id, public_announce->chat_public_key, CHAT_ID_SIZE);
+
+ return announces;
+}
+
GC_Peer_Announce *gca_add_announce(const Mono_Time *mono_time, GC_Announces_List *gc_announces_list,
const GC_Public_Announce *public_announce)
{
@@ -349,22 +377,11 @@ GC_Peer_Announce *gca_add_announce(const Mono_Time *mono_time, GC_Announces_List
// No entry for this chat_id exists so we create one
if (announces == nullptr) {
- announces = (GC_Announces *)calloc(1, sizeof(GC_Announces));
+ announces = gca_new_announces(gc_announces_list, public_announce);
if (announces == nullptr) {
return nullptr;
}
-
- announces->index = 0;
- announces->prev_announce = nullptr;
-
- if (gc_announces_list->root_announces != nullptr) {
- gc_announces_list->root_announces->prev_announce = announces;
- }
-
- announces->next_announce = gc_announces_list->root_announces;
- gc_announces_list->root_announces = announces;
- memcpy(announces->chat_id, public_announce->chat_public_key, CHAT_ID_SIZE);
}
const uint64_t cur_time = mono_time_get(mono_time);
@@ -395,8 +412,7 @@ bool gca_is_valid_announce(const GC_Announce *announce)
GC_Announces_List *new_gca_list(void)
{
- GC_Announces_List *announces_list = (GC_Announces_List *)calloc(1, sizeof(GC_Announces_List));
- return announces_list;
+ return (GC_Announces_List *)calloc(1, sizeof(GC_Announces_List));
}
void kill_gca(GC_Announces_List *announces_list)
diff --git a/protocols/Tox/libtox/src/toxcore/group_announce.h b/protocols/Tox/libtox/src/toxcore/group_announce.h
index 801363d6b2..72f2cfc1b8 100644
--- a/protocols/Tox/libtox/src/toxcore/group_announce.h
+++ b/protocols/Tox/libtox/src/toxcore/group_announce.h
@@ -6,12 +6,18 @@
/**
* Similar to ping.h, but designed for group chat purposes
*/
-#ifndef GROUP_ANNOUNCE_H
-#define GROUP_ANNOUNCE_H
+#ifndef C_TOXCORE_TOXCORE_GROUP_ANNOUNCE_H
+#define C_TOXCORE_TOXCORE_GROUP_ANNOUNCE_H
#include <stdbool.h>
+#include <stdint.h>
#include "DHT.h"
+#include "attributes.h"
+#include "crypto_core.h"
+#include "logger.h"
+#include "mono_time.h"
+#include "network.h"
#ifdef __cplusplus
extern "C" {
@@ -77,7 +83,6 @@ struct GC_Announces_List {
uint64_t last_timeout_check;
};
-
/** @brief Returns a new group announces list.
*
* The caller is responsible for freeing the memory with `kill_gca`.
@@ -212,7 +217,7 @@ non_null()
bool gca_is_valid_announce(const GC_Announce *announce);
#ifdef __cplusplus
-} // extern "C"
+} /* extern "C" */
#endif
-#endif // GROUP_ANNOUNCE_H
+#endif /* C_TOXCORE_TOXCORE_GROUP_ANNOUNCE_H */
diff --git a/protocols/Tox/libtox/src/toxcore/group_chats.c b/protocols/Tox/libtox/src/toxcore/group_chats.c
index f9cb2d18fb..96f647cc2e 100644
--- a/protocols/Tox/libtox/src/toxcore/group_chats.c
+++ b/protocols/Tox/libtox/src/toxcore/group_chats.c
@@ -9,29 +9,34 @@
#include "group_chats.h"
-#include <assert.h>
-
-#ifndef VANILLA_NACL
#include <sodium.h>
-#endif
+#include <assert.h>
+#include <stdlib.h>
#include <string.h>
#include "DHT.h"
-#include "LAN_discovery.h"
#include "Messenger.h"
#include "TCP_connection.h"
+#include "attributes.h"
+#include "bin_pack.h"
+#include "bin_unpack.h"
#include "ccompat.h"
+#include "crypto_core.h"
#include "friend_connection.h"
+#include "group_announce.h"
#include "group_common.h"
+#include "group_connection.h"
#include "group_moderation.h"
#include "group_pack.h"
+#include "logger.h"
#include "mono_time.h"
+#include "net_crypto.h"
#include "network.h"
+#include "onion_announce.h"
+#include "onion_client.h"
#include "util.h"
-#ifndef VANILLA_NACL
-
/* The minimum size of a plaintext group handshake packet */
#define GC_MIN_HS_PACKET_PAYLOAD_SIZE (1 + ENC_PUBLIC_KEY_SIZE + SIG_PUBLIC_KEY_SIZE + 1 + 1)
@@ -108,10 +113,19 @@ static_assert(GCC_BUFFER_SIZE <= UINT16_MAX,
static_assert(MAX_GC_PACKET_CHUNK_SIZE < MAX_GC_PACKET_SIZE,
"MAX_GC_PACKET_CHUNK_SIZE must be < MAX_GC_PACKET_SIZE");
+static_assert(MAX_GC_PACKET_INCOMING_CHUNK_SIZE < MAX_GC_PACKET_SIZE,
+ "MAX_GC_PACKET_INCOMING_CHUNK_SIZE must be < MAX_GC_PACKET_SIZE");
+
+static_assert(MAX_GC_PACKET_INCOMING_CHUNK_SIZE >= MAX_GC_PACKET_CHUNK_SIZE,
+ "MAX_GC_PACKET_INCOMING_CHUNK_SIZE must be >= MAX_GC_PACKET_CHUNK_SIZE");
+
// size of a lossless handshake packet - lossless packets can't/shouldn't be split up
static_assert(MAX_GC_PACKET_CHUNK_SIZE >= 171,
"MAX_GC_PACKET_CHUNK_SIZE must be >= 171");
+static_assert(MAX_GC_PACKET_INCOMING_CHUNK_SIZE >= 171,
+ "MAX_GC_PACKET_INCOMING_CHUNK_SIZE must be >= 171");
+
// group_moderation constants assume this is the max packet size.
static_assert(MAX_GC_PACKET_SIZE >= 50000,
"MAX_GC_PACKET_SIZE doesn't match constants in group_moderation.h");
@@ -119,6 +133,9 @@ static_assert(MAX_GC_PACKET_SIZE >= 50000,
static_assert(MAX_GC_PACKET_SIZE <= UINT16_MAX - MAX_GC_PACKET_CHUNK_SIZE,
"MAX_GC_PACKET_SIZE must be <= UINT16_MAX - MAX_GC_PACKET_CHUNK_SIZE");
+static_assert(MAX_GC_PACKET_SIZE <= UINT16_MAX - MAX_GC_PACKET_INCOMING_CHUNK_SIZE,
+ "MAX_GC_PACKET_SIZE must be <= UINT16_MAX - MAX_GC_PACKET_INCOMING_CHUNK_SIZE");
+
/** Types of broadcast messages. */
typedef enum Group_Message_Type {
GC_MESSAGE_TYPE_NORMAL = 0x00,
@@ -148,7 +165,7 @@ non_null() static bool self_gc_is_founder(const GC_Chat *chat);
non_null() static bool group_number_valid(const GC_Session *c, int group_number);
non_null() static int peer_update(const GC_Chat *chat, const GC_Peer *peer, uint32_t peer_number);
non_null() static void group_delete(GC_Session *c, GC_Chat *chat);
-non_null() static void group_cleanup(GC_Session *c, GC_Chat *chat);
+non_null() static void group_cleanup(const GC_Session *c, GC_Chat *chat);
non_null() static bool group_exists(const GC_Session *c, const uint8_t *chat_id);
non_null() static void add_tcp_relays_to_chat(const GC_Session *c, GC_Chat *chat);
non_null(1, 2) nullable(4)
@@ -160,6 +177,35 @@ non_null() static bool saved_peer_is_valid(const GC_SavedPeerInfo *saved_peer);
static const GC_Chat empty_gc_chat = {nullptr};
+#define GC_INVALID_PEER_ID_VALUE ((force GC_Peer_Id_Value)-1)
+
+static GC_Peer_Id gc_invalid_peer_id(void)
+{
+ const GC_Peer_Id invalid = {GC_INVALID_PEER_ID_VALUE};
+ return invalid;
+}
+
+static bool gc_peer_id_is_valid(GC_Peer_Id peer_id)
+{
+ return peer_id.value != GC_INVALID_PEER_ID_VALUE;
+}
+
+GC_Peer_Id gc_peer_id_from_int(uint32_t value)
+{
+ const GC_Peer_Id peer_id = {(force GC_Peer_Id_Value)value};
+ return peer_id;
+}
+
+uint32_t gc_peer_id_to_int(GC_Peer_Id peer_id)
+{
+ return (force uint32_t)peer_id.value;
+}
+
+static GC_Peer_Id gc_unknown_peer_id(void)
+{
+ return gc_peer_id_from_int(0);
+}
+
non_null()
static void kill_group_friend_connection(const GC_Session *c, const GC_Chat *chat)
{
@@ -170,7 +216,7 @@ static void kill_group_friend_connection(const GC_Session *c, const GC_Chat *cha
uint16_t gc_get_wrapped_packet_size(uint16_t length, Net_Packet_Type packet_type)
{
- assert(length <= MAX_GC_PACKET_CHUNK_SIZE);
+ assert(length <= (packet_type == NET_PACKET_GC_LOSSY ? MAX_GC_CUSTOM_LOSSY_PACKET_SIZE : MAX_GC_PACKET_CHUNK_SIZE));
const uint16_t min_header_size = packet_type == NET_PACKET_GC_LOSSY
? GC_MIN_LOSSY_PAYLOAD_SIZE
@@ -214,10 +260,20 @@ GC_Connection *get_gc_connection(const GC_Chat *chat, int peer_number)
return &peer->gconn;
}
+/** Returns the max packet size, not wrapped */
+static uint16_t group_packet_max_packet_size(Net_Packet_Type net_packet_type)
+{
+ if (net_packet_type == NET_PACKET_GC_LOSSY) {
+ return MAX_GC_CUSTOM_LOSSY_PACKET_SIZE;
+ } else {
+ return MAX_GC_PACKET_CHUNK_SIZE;
+ }
+}
+
/** Returns the amount of empty padding a packet of designated length should have. */
-static uint16_t group_packet_padding_length(uint16_t length)
+static uint16_t group_packet_padding_length(uint16_t length, uint16_t max_length)
{
- return (MAX_GC_PACKET_CHUNK_SIZE - length) % GC_MAX_PACKET_PADDING;
+ return (max_length - length) % GC_MAX_PACKET_PADDING;
}
void gc_get_self_nick(const GC_Chat *chat, uint8_t *nick)
@@ -302,7 +358,7 @@ static void self_gc_set_status(const GC_Chat *chat, Group_Peer_Status status)
LOGGER_WARNING(chat->log, "Attempting to set user status with invalid status: %u", (uint8_t)status);
}
-uint32_t gc_get_self_peer_id(const GC_Chat *chat)
+GC_Peer_Id gc_get_self_peer_id(const GC_Chat *chat)
{
const GC_Peer *peer = get_gc_peer(chat, 0);
assert(peer != nullptr);
@@ -330,7 +386,7 @@ static bool self_gc_is_founder(const GC_Chat *chat)
void gc_get_self_public_key(const GC_Chat *chat, uint8_t *public_key)
{
if (public_key != nullptr) {
- memcpy(public_key, chat->self_public_key, ENC_PUBLIC_KEY_SIZE);
+ memcpy(public_key, chat->self_public_key.enc, ENC_PUBLIC_KEY_SIZE);
}
}
@@ -339,12 +395,12 @@ void gc_get_self_public_key(const GC_Chat *chat, uint8_t *public_key)
* If `ext_public_key` is null this function has no effect.
*/
non_null()
-static void self_gc_set_ext_public_key(const GC_Chat *chat, const uint8_t *ext_public_key)
+static void self_gc_set_ext_public_key(const GC_Chat *chat, const Extended_Public_Key *ext_public_key)
{
if (ext_public_key != nullptr) {
GC_Connection *gconn = get_gc_connection(chat, 0);
assert(gconn != nullptr);
- memcpy(gconn->addr.public_key, ext_public_key, EXT_PUBLIC_KEY_SIZE);
+ gconn->addr.public_key = *ext_public_key;
}
}
@@ -523,7 +579,7 @@ static GC_Chat *get_chat_by_id(const GC_Session *c, const uint8_t *id)
continue;
}
- if (memcmp(id, chat->self_public_key, ENC_PUBLIC_KEY_SIZE) == 0) {
+ if (memcmp(id, chat->self_public_key.enc, ENC_PUBLIC_KEY_SIZE) == 0) {
return chat;
}
@@ -585,7 +641,7 @@ int get_peer_number_of_enc_pk(const GC_Chat *chat, const uint8_t *public_enc_key
continue;
}
- if (memcmp(gconn->addr.public_key, public_enc_key, ENC_PUBLIC_KEY_SIZE) == 0) {
+ if (memcmp(gconn->addr.public_key.enc, public_enc_key, ENC_PUBLIC_KEY_SIZE) == 0) {
return i;
}
}
@@ -606,7 +662,7 @@ static int get_peer_number_of_sig_pk(const GC_Chat *chat, const uint8_t *public_
assert(gconn != nullptr);
- if (memcmp(get_sig_pk(gconn->addr.public_key), public_sig_key, SIG_PUBLIC_KEY_SIZE) == 0) {
+ if (memcmp(get_sig_pk(&gconn->addr.public_key), public_sig_key, SIG_PUBLIC_KEY_SIZE) == 0) {
return i;
}
}
@@ -622,7 +678,7 @@ static bool gc_get_enc_pk_from_sig_pk(const GC_Chat *chat, uint8_t *public_key,
assert(gconn != nullptr);
- const uint8_t *full_pk = gconn->addr.public_key;
+ const Extended_Public_Key *full_pk = &gconn->addr.public_key;
if (memcmp(public_sig_key, get_sig_pk(full_pk), SIG_PUBLIC_KEY_SIZE) == 0) {
memcpy(public_key, get_enc_key(full_pk), ENC_PUBLIC_KEY_SIZE);
@@ -662,10 +718,10 @@ static GC_Connection *random_gc_connection(const GC_Chat *chat)
* Returns -1 if peer_id is invalid.
*/
non_null()
-static int get_peer_number_of_peer_id(const GC_Chat *chat, uint32_t peer_id)
+static int get_peer_number_of_peer_id(const GC_Chat *chat, GC_Peer_Id peer_id)
{
for (uint32_t i = 0; i < chat->numpeers; ++i) {
- if (chat->group[i].peer_id == peer_id) {
+ if (chat->group[i].peer_id.value == peer_id.value) {
return i;
}
}
@@ -680,15 +736,16 @@ static int get_peer_number_of_peer_id(const GC_Chat *chat, uint32_t peer_id)
* considered arbitrary values.
*/
non_null()
-static uint32_t get_new_peer_id(const GC_Chat *chat)
+static GC_Peer_Id get_new_peer_id(const GC_Chat *chat)
{
for (uint32_t i = 0; i < UINT32_MAX - 1; ++i) {
- if (get_peer_number_of_peer_id(chat, i) == -1) {
- return i;
+ const GC_Peer_Id peer_id = gc_peer_id_from_int(i);
+ if (get_peer_number_of_peer_id(chat, peer_id) == -1) {
+ return peer_id;
}
}
- return UINT32_MAX;
+ return gc_invalid_peer_id();
}
/** @brief Sets the password for the group (locally only).
@@ -704,7 +761,7 @@ static bool set_gc_password_local(GC_Chat *chat, const uint8_t *passwd, uint16_t
if (passwd == nullptr || length == 0) {
chat->shared_state.password_length = 0;
- memset(chat->shared_state.password, 0, MAX_GC_PASSWORD_SIZE);
+ memzero(chat->shared_state.password, MAX_GC_PASSWORD_SIZE);
} else {
chat->shared_state.password_length = length;
crypto_memlock(chat->shared_state.password, sizeof(chat->shared_state.password));
@@ -732,12 +789,12 @@ static void set_gc_shared_state_version(GC_Chat *chat, uint32_t version)
* Return true on success.
*/
non_null()
-static bool expand_chat_id(uint8_t *dest, const uint8_t *chat_id)
+static bool expand_chat_id(Extended_Public_Key *dest, const uint8_t *chat_id)
{
assert(dest != nullptr);
- const int ret = crypto_sign_ed25519_pk_to_curve25519(dest, chat_id);
- memcpy(dest + ENC_PUBLIC_KEY_SIZE, chat_id, SIG_PUBLIC_KEY_SIZE);
+ const int ret = crypto_sign_ed25519_pk_to_curve25519(dest->enc, chat_id);
+ memcpy(dest->sig, chat_id, SIG_PUBLIC_KEY_SIZE);
return ret != -1;
}
@@ -753,7 +810,7 @@ static void copy_gc_saved_peer(const Random *rng, const GC_Connection *gconn, GC
}
addr->ip_port = gconn->addr.ip_port;
- memcpy(addr->public_key, gconn->addr.public_key, ENC_PUBLIC_KEY_SIZE);
+ memcpy(addr->public_key, gconn->addr.public_key.enc, ENC_PUBLIC_KEY_SIZE);
}
/** Return true if `saved_peer` has either a valid IP_Port or a valid TCP relay. */
@@ -837,7 +894,7 @@ static int saved_peers_get_new_index(const GC_Chat *chat, const uint8_t *public_
non_null()
static void add_gc_saved_peers(GC_Chat *chat, const GC_Connection *gconn)
{
- const int idx = saved_peers_get_new_index(chat, gconn->addr.public_key);
+ const int idx = saved_peers_get_new_index(chat, gconn->addr.public_key.enc);
if (idx == -1) {
return;
@@ -872,7 +929,7 @@ static void refresh_gc_saved_peers(GC_Chat *chat)
continue;
}
- if (saved_peer_index(chat, gconn->addr.public_key) == -1) {
+ if (saved_peer_index(chat, gconn->addr.public_key.enc) == -1) {
GC_SavedPeerInfo *saved_peer = &chat->saved_peers[idx];
copy_gc_saved_peer(chat->rng, gconn, saved_peer);
return;
@@ -917,7 +974,7 @@ static bool peer_is_observer(const GC_Chat *chat, uint32_t peer_number)
return false;
}
- return sanctions_list_is_observer(&chat->moderation, get_enc_key(gconn->addr.public_key));
+ return sanctions_list_is_observer(&chat->moderation, get_enc_key(&gconn->addr.public_key));
}
/** Returns true if peer designated by `peer_number` is the group founder. */
@@ -931,7 +988,7 @@ static bool peer_is_founder(const GC_Chat *chat, uint32_t peer_number)
return false;
}
- return memcmp(chat->shared_state.founder_public_key, gconn->addr.public_key, ENC_PUBLIC_KEY_SIZE) == 0;
+ return memcmp(chat->shared_state.founder_public_key.enc, gconn->addr.public_key.enc, ENC_PUBLIC_KEY_SIZE) == 0;
}
/** Returns true if peer designated by `peer_number` is in the moderator list or is the founder. */
@@ -948,7 +1005,7 @@ static bool peer_is_moderator(const GC_Chat *chat, uint32_t peer_number)
return false;
}
- return mod_list_verify_sig_pk(&chat->moderation, get_sig_pk(gconn->addr.public_key));
+ return mod_list_verify_sig_pk(&chat->moderation, get_sig_pk(&gconn->addr.public_key));
}
/** @brief Iterates through the peerlist and updates group roles according to the
@@ -977,7 +1034,7 @@ static void update_gc_peer_roles(GC_Chat *chat)
continue;
}
- const uint8_t first_byte = gconn->addr.public_key[0];
+ const uint8_t first_byte = gconn->addr.public_key.enc[0];
const bool is_founder = peer_is_founder(chat, i);
if (is_founder) {
@@ -1059,43 +1116,16 @@ static bool prune_gc_mod_list(GC_Chat *chat)
&& update_gc_topic(chat, public_sig_key);
}
-/** @brief Removes the first found offline sanctioned peer from the sanctions list and sends the
- * event to the rest of the group.
- *
- * @retval false on failure or if no presently sanctioned peer is offline.
- */
non_null()
-static bool prune_gc_sanctions_list(GC_Chat *chat)
+static bool prune_gc_sanctions_list_inner(
+ GC_Chat *chat, const Mod_Sanction *sanction,
+ const uint8_t target_ext_pk[ENC_PUBLIC_KEY_SIZE + SIG_PUBLIC_KEY_SIZE])
{
- if (chat->moderation.num_sanctions == 0) {
- return true;
- }
-
- const Mod_Sanction *sanction = nullptr;
- uint8_t target_ext_pk[ENC_PUBLIC_KEY_SIZE + SIG_PUBLIC_KEY_SIZE];
-
- for (uint16_t i = 0; i < chat->moderation.num_sanctions; ++i) {
- const int peer_number = get_peer_number_of_enc_pk(chat, chat->moderation.sanctions[i].target_public_enc_key, true);
-
- if (peer_number == -1) {
- sanction = &chat->moderation.sanctions[i];
- memcpy(target_ext_pk, sanction->target_public_enc_key, ENC_PUBLIC_KEY_SIZE);
- memcpy(target_ext_pk + ENC_PUBLIC_KEY_SIZE, sanction->setter_public_sig_key, SIG_PUBLIC_KEY_SIZE);
- break;
- }
- }
-
- if (sanction == nullptr) {
- return false;
- }
-
if (!sanctions_list_remove_observer(&chat->moderation, sanction->target_public_enc_key, nullptr)) {
LOGGER_WARNING(chat->log, "Failed to remove entry from observer list");
return false;
}
- sanction = nullptr;
-
uint8_t data[MOD_SANCTIONS_CREDS_SIZE];
const uint16_t length = sanctions_creds_pack(&chat->moderation.sanctions_creds, data);
@@ -1112,6 +1142,33 @@ static bool prune_gc_sanctions_list(GC_Chat *chat)
return true;
}
+/** @brief Removes the first found offline sanctioned peer from the sanctions list and sends the
+ * event to the rest of the group.
+ *
+ * @retval false on failure or if no presently sanctioned peer is offline.
+ */
+non_null()
+static bool prune_gc_sanctions_list(GC_Chat *chat)
+{
+ if (chat->moderation.num_sanctions == 0) {
+ return true;
+ }
+
+ for (uint16_t i = 0; i < chat->moderation.num_sanctions; ++i) {
+ const int peer_number = get_peer_number_of_enc_pk(chat, chat->moderation.sanctions[i].target_public_enc_key, true);
+
+ if (peer_number == -1) {
+ const Mod_Sanction *sanction = &chat->moderation.sanctions[i];
+ uint8_t target_ext_pk[ENC_PUBLIC_KEY_SIZE + SIG_PUBLIC_KEY_SIZE];
+ memcpy(target_ext_pk, sanction->target_public_enc_key, ENC_PUBLIC_KEY_SIZE);
+ memcpy(target_ext_pk + ENC_PUBLIC_KEY_SIZE, sanction->setter_public_sig_key, SIG_PUBLIC_KEY_SIZE);
+ return prune_gc_sanctions_list_inner(chat, sanction, target_ext_pk);
+ }
+ }
+
+ return false;
+}
+
/** @brief Size of peer data that we pack for transfer (nick length must be accounted for separately).
* packed data consists of: nick length, nick, and status.
*/
@@ -1188,8 +1245,10 @@ static uint16_t pack_gc_shared_state(uint8_t *data, uint16_t length, const GC_Sh
net_pack_u32(data + packed_len, shared_state->version);
packed_len += sizeof(uint32_t);
- memcpy(data + packed_len, shared_state->founder_public_key, EXT_PUBLIC_KEY_SIZE);
- packed_len += EXT_PUBLIC_KEY_SIZE;
+ memcpy(data + packed_len, shared_state->founder_public_key.enc, ENC_PUBLIC_KEY_SIZE);
+ packed_len += ENC_PUBLIC_KEY_SIZE;
+ memcpy(data + packed_len, shared_state->founder_public_key.sig, SIG_PUBLIC_KEY_SIZE);
+ packed_len += SIG_PUBLIC_KEY_SIZE;
net_pack_u16(data + packed_len, shared_state->maxpeers);
packed_len += sizeof(uint16_t);
net_pack_u16(data + packed_len, shared_state->group_name_len);
@@ -1231,8 +1290,10 @@ static uint16_t unpack_gc_shared_state(GC_SharedState *shared_state, const uint8
net_unpack_u32(data + len_processed, &shared_state->version);
len_processed += sizeof(uint32_t);
- memcpy(shared_state->founder_public_key, data + len_processed, EXT_PUBLIC_KEY_SIZE);
- len_processed += EXT_PUBLIC_KEY_SIZE;
+ memcpy(shared_state->founder_public_key.enc, data + len_processed, ENC_PUBLIC_KEY_SIZE);
+ len_processed += ENC_PUBLIC_KEY_SIZE;
+ memcpy(shared_state->founder_public_key.sig, data + len_processed, SIG_PUBLIC_KEY_SIZE);
+ len_processed += SIG_PUBLIC_KEY_SIZE;
net_unpack_u16(data + len_processed, &shared_state->maxpeers);
len_processed += sizeof(uint16_t);
net_unpack_u16(data + len_processed, &shared_state->group_name_len);
@@ -1258,8 +1319,8 @@ static uint16_t unpack_gc_shared_state(GC_SharedState *shared_state, const uint8
memcpy(&voice_state, data + len_processed, sizeof(uint8_t));
len_processed += sizeof(uint8_t);
- shared_state->voice_state = (Group_Voice_State)voice_state;
- shared_state->privacy_state = (Group_Privacy_State)privacy_state;
+ group_voice_state_from_int(voice_state, &shared_state->voice_state);
+ group_privacy_state_from_int(privacy_state, &shared_state->privacy_state);
return len_processed;
}
@@ -1356,7 +1417,7 @@ static int make_gc_shared_state_packet(const GC_Chat *chat, uint8_t *data, uint1
return -1;
}
- return (int)(header_len + packed_len);
+ return header_len + packed_len;
}
/** @brief Creates a signature for the group's shared state in packed form.
@@ -1390,7 +1451,7 @@ static bool sign_gc_shared_state(GC_Chat *chat)
}
const int ret = crypto_sign_detached(chat->shared_state_sig, nullptr, shared_state, packed_len,
- get_sig_sk(chat->chat_secret_key));
+ get_sig_sk(&chat->chat_secret_key));
if (ret != 0) {
set_gc_shared_state_version(chat, chat->shared_state.version - 1);
@@ -1416,6 +1477,9 @@ non_null(1, 2, 3, 5, 6) nullable(4)
static int group_packet_unwrap(const Logger *log, const GC_Connection *gconn, uint8_t *data, uint64_t *message_id,
uint8_t *packet_type, const uint8_t *packet, uint16_t length)
{
+ assert(data != nullptr);
+ assert(packet != nullptr);
+
if (length <= CRYPTO_NONCE_SIZE) {
LOGGER_FATAL(log, "Invalid packet length: %u", length);
return -1;
@@ -1471,9 +1535,10 @@ static int group_packet_unwrap(const Logger *log, const GC_Connection *gconn, ui
int group_packet_wrap(
const Logger *log, const Random *rng, const uint8_t *self_pk, const uint8_t *shared_key, uint8_t *packet,
uint16_t packet_size, const uint8_t *data, uint16_t length, uint64_t message_id,
- uint8_t gp_packet_type, uint8_t net_packet_type)
+ uint8_t gp_packet_type, Net_Packet_Type net_packet_type)
{
- const uint16_t padding_len = group_packet_padding_length(length);
+ const uint16_t max_packet_size = group_packet_max_packet_size(net_packet_type);
+ const uint16_t padding_len = group_packet_padding_length(length, max_packet_size);
const uint16_t min_packet_size = net_packet_type == NET_PACKET_GC_LOSSLESS
? length + padding_len + CRYPTO_MAC_SIZE + 1 + ENC_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + GC_MESSAGE_ID_BYTES + 1
: length + padding_len + CRYPTO_MAC_SIZE + 1 + ENC_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + 1;
@@ -1483,8 +1548,8 @@ int group_packet_wrap(
return -1;
}
- if (length > MAX_GC_PACKET_CHUNK_SIZE) {
- LOGGER_ERROR(log, "Packet payload size (%u) exceeds maximum (%u)", length, MAX_GC_PACKET_CHUNK_SIZE);
+ if (length > max_packet_size) {
+ LOGGER_ERROR(log, "Packet payload size (%u) exceeds maximum (%u)", length, max_packet_size);
return -1;
}
@@ -1496,7 +1561,7 @@ int group_packet_wrap(
assert(padding_len < packet_size);
- memset(plain, 0, padding_len);
+ memzero(plain, padding_len);
uint16_t enc_header_len = sizeof(uint8_t);
plain[padding_len] = gp_packet_type;
@@ -1551,7 +1616,7 @@ non_null()
static bool send_lossy_group_packet(const GC_Chat *chat, const GC_Connection *gconn, const uint8_t *data,
uint16_t length, uint8_t packet_type)
{
- assert(length <= MAX_GC_PACKET_CHUNK_SIZE);
+ assert(length <= MAX_GC_CUSTOM_LOSSY_PACKET_SIZE);
if (!gconn->handshaked || gconn->pending_delete) {
return false;
@@ -1569,7 +1634,7 @@ static bool send_lossy_group_packet(const GC_Chat *chat, const GC_Connection *gc
}
const int len = group_packet_wrap(
- chat->log, chat->rng, chat->self_public_key, gconn->session_shared_key, packet,
+ chat->log, chat->rng, chat->self_public_key.enc, gconn->session_shared_key, packet,
packet_size, data, length, 0, packet_type, NET_PACKET_GC_LOSSY);
if (len < 0) {
@@ -1669,7 +1734,7 @@ static bool unpack_gc_sync_announce(GC_Chat *chat, const uint8_t *data, const ui
return false;
}
- if (memcmp(announce.peer_public_key, chat->self_public_key, ENC_PUBLIC_KEY_SIZE) == 0) {
+ if (memcmp(announce.peer_public_key, chat->self_public_key.enc, ENC_PUBLIC_KEY_SIZE) == 0) {
LOGGER_WARNING(chat->log, "Attempted to unpack our own announce");
return true;
}
@@ -1738,7 +1803,7 @@ static bool unpack_gc_sync_announce(GC_Chat *chat, const uint8_t *data, const ui
* Return -1 if the group is full or the peer failed to unpack.
* Return -2 if `peer_number` does not designate a valid peer.
*/
-non_null(1, 2, 4) nullable(6)
+non_null(1, 2) nullable(4, 6)
static int handle_gc_sync_response(const GC_Session *c, GC_Chat *chat, uint32_t peer_number, const uint8_t *data,
uint16_t length, void *userdata)
{
@@ -1779,7 +1844,6 @@ non_null() static bool send_peer_mod_list(const GC_Chat *chat, GC_Connection *gc
non_null() static bool send_peer_sanctions_list(const GC_Chat *chat, GC_Connection *gconn);
non_null() static bool send_peer_topic(const GC_Chat *chat, GC_Connection *gconn);
-
/** @brief Creates a sync announce for peer designated by `gconn` and puts it in `announce`, which
* must be zeroed by the caller.
*
@@ -1993,7 +2057,6 @@ static int handle_gc_sync_request(GC_Chat *chat, uint32_t peer_number, const uin
non_null() static void copy_self(const GC_Chat *chat, GC_Peer *peer);
non_null() static bool send_gc_peer_info_request(const GC_Chat *chat, GC_Connection *gconn);
-
/** @brief Shares our TCP relays with peer and adds shared relays to our connection with them.
*
* Returns true on success or if we're not connected to any TCP relays.
@@ -2080,16 +2143,17 @@ static int handle_gc_tcp_relays(GC_Chat *chat, GC_Connection *gconn, const uint8
non_null()
static bool send_gc_invite_request(const GC_Chat *chat, GC_Connection *gconn)
{
- uint16_t length = 0;
+ if (!chat_is_password_protected(chat)) {
+ return send_lossless_group_packet(chat, gconn, nullptr, 0, GP_INVITE_REQUEST);
+ }
+
uint8_t data[sizeof(uint16_t) + MAX_GC_PASSWORD_SIZE];
- if (chat_is_password_protected(chat)) {
- net_pack_u16(data, chat->shared_state.password_length);
- length += sizeof(uint16_t);
+ net_pack_u16(data, chat->shared_state.password_length);
+ uint16_t length = sizeof(uint16_t);
- memcpy(data + length, chat->shared_state.password, MAX_GC_PASSWORD_SIZE);
- length += MAX_GC_PASSWORD_SIZE;
- }
+ memcpy(data + length, chat->shared_state.password, MAX_GC_PASSWORD_SIZE);
+ length += MAX_GC_PASSWORD_SIZE;
return send_lossless_group_packet(chat, gconn, data, length, GP_INVITE_REQUEST);
}
@@ -2181,7 +2245,7 @@ static bool send_gc_invite_response_reject(const GC_Chat *chat, const GC_Connect
* Return -3 if we fail to send an invite response.
* Return -4 if peer_number does not designate a valid peer.
*/
-non_null()
+non_null(1) nullable(3)
static int handle_gc_invite_request(GC_Chat *chat, uint32_t peer_number, const uint8_t *data, uint16_t length)
{
if (chat->shared_state.version == 0) { // we aren't synced yet; ignore request
@@ -2234,34 +2298,64 @@ FAILED_INVITE:
return ret;
}
-/** @brief Sends a lossless packet of type and length to all confirmed peers. */
+/** @brief Sends a lossless packet of type and length to all confirmed peers.
+ *
+ * Return true if packet is successfully sent to at least one peer or the
+ * group is empty.
+ */
non_null()
-static void send_gc_lossless_packet_all_peers(const GC_Chat *chat, const uint8_t *data, uint16_t length, uint8_t type)
+static bool send_gc_lossless_packet_all_peers(const GC_Chat *chat, const uint8_t *data, uint16_t length, uint8_t type)
{
+ uint32_t sent = 0;
+ uint32_t confirmed_peers = 0;
+
for (uint32_t i = 1; i < chat->numpeers; ++i) {
GC_Connection *gconn = get_gc_connection(chat, i);
assert(gconn != nullptr);
- if (gconn->confirmed) {
- send_lossless_group_packet(chat, gconn, data, length, type);
+ if (!gconn->confirmed) {
+ continue;
+ }
+
+ ++confirmed_peers;
+
+ if (send_lossless_group_packet(chat, gconn, data, length, type)) {
+ ++sent;
}
}
+
+ return sent > 0 || confirmed_peers == 0;
}
-/** @brief Sends a lossy packet of type and length to all confirmed peers. */
+/** @brief Sends a lossy packet of type and length to all confirmed peers.
+ *
+ * Return true if packet is successfully sent to at least one peer or the
+ * group is empty.
+ */
non_null()
-static void send_gc_lossy_packet_all_peers(const GC_Chat *chat, const uint8_t *data, uint16_t length, uint8_t type)
+static bool send_gc_lossy_packet_all_peers(const GC_Chat *chat, const uint8_t *data, uint16_t length, uint8_t type)
{
+ uint32_t sent = 0;
+ uint32_t confirmed_peers = 0;
+
for (uint32_t i = 1; i < chat->numpeers; ++i) {
const GC_Connection *gconn = get_gc_connection(chat, i);
assert(gconn != nullptr);
- if (gconn->confirmed) {
- send_lossy_group_packet(chat, gconn, data, length, type);
+ if (!gconn->confirmed) {
+ continue;
+ }
+
+ ++confirmed_peers;
+
+ if (send_lossy_group_packet(chat, gconn, data, length, type)) {
+ ++sent;
}
}
+
+ return sent > 0 || confirmed_peers == 0;
}
/** @brief Creates packet with broadcast header info followed by data of length.
@@ -2301,11 +2395,11 @@ static bool send_gc_broadcast_message(const GC_Chat *chat, const uint8_t *data,
const uint16_t packet_len = make_gc_broadcast_header(data, length, packet, bc_type);
- send_gc_lossless_packet_all_peers(chat, packet, packet_len, GP_BROADCAST);
+ const bool ret = send_gc_lossless_packet_all_peers(chat, packet, packet_len, GP_BROADCAST);
free(packet);
- return true;
+ return ret;
}
non_null()
@@ -2431,8 +2525,7 @@ static int handle_gc_ping(GC_Chat *chat, GC_Connection *gconn, const uint8_t *da
do_gc_peer_state_sync(chat, gconn, data, length);
if (length > GC_PING_PACKET_MIN_DATA_SIZE) {
- IP_Port ip_port;
- memset(&ip_port, 0, sizeof(IP_Port));
+ IP_Port ip_port = {{{0}}};
if (unpack_ip_port(&ip_port, data + GC_PING_PACKET_MIN_DATA_SIZE,
length - GC_PING_PACKET_MIN_DATA_SIZE, false) > 0) {
@@ -2494,7 +2587,7 @@ static int handle_gc_status(const GC_Session *c, const GC_Chat *chat, GC_Peer *p
return 0;
}
-uint8_t gc_get_status(const GC_Chat *chat, uint32_t peer_id)
+uint8_t gc_get_status(const GC_Chat *chat, GC_Peer_Id peer_id)
{
const int peer_number = get_peer_number_of_peer_id(chat, peer_id);
@@ -2507,7 +2600,7 @@ uint8_t gc_get_status(const GC_Chat *chat, uint32_t peer_id)
return peer->status;
}
-uint8_t gc_get_role(const GC_Chat *chat, uint32_t peer_id)
+uint8_t gc_get_role(const GC_Chat *chat, GC_Peer_Id peer_id)
{
const int peer_number = get_peer_number_of_peer_id(chat, peer_id);
@@ -2523,7 +2616,7 @@ uint8_t gc_get_role(const GC_Chat *chat, uint32_t peer_id)
void gc_get_chat_id(const GC_Chat *chat, uint8_t *dest)
{
if (dest != nullptr) {
- memcpy(dest, get_chat_id(chat->chat_public_key), CHAT_ID_SIZE);
+ memcpy(dest, get_chat_id(&chat->chat_public_key), CHAT_ID_SIZE);
}
}
@@ -2759,9 +2852,7 @@ static bool broadcast_gc_shared_state(const GC_Chat *chat)
return false;
}
- send_gc_lossless_packet_all_peers(chat, packet, (uint16_t)packet_len, GP_SHARED_STATE);
-
- return true;
+ return send_gc_lossless_packet_all_peers(chat, packet, (uint16_t)packet_len, GP_SHARED_STATE);
}
/** @brief Helper function for `do_gc_shared_state_changes()`.
@@ -2781,7 +2872,7 @@ static void do_privacy_state_change(const GC_Session *c, GC_Chat *chat, void *us
}
} else {
kill_group_friend_connection(c, chat);
- cleanup_gca(c->announces_list, get_chat_id(chat->chat_public_key));
+ cleanup_gca(c->announces_list, get_chat_id(&chat->chat_public_key));
chat->join_type = HJ_PRIVATE;
}
@@ -2905,7 +2996,7 @@ static int handle_gc_shared_state(const GC_Session *c, GC_Chat *chat, GC_Connect
const uint16_t ss_length = length - SIGNATURE_SIZE;
if (crypto_sign_verify_detached(signature, ss_data, GC_PACKED_SHARED_STATE_SIZE,
- get_sig_pk(chat->chat_public_key)) == -1) {
+ get_sig_pk(&chat->chat_public_key)) == -1) {
LOGGER_DEBUG(chat->log, "Failed to validate shared state signature");
return handle_gc_shared_state_error(chat, gconn);
}
@@ -2919,7 +3010,7 @@ static int handle_gc_shared_state(const GC_Session *c, GC_Chat *chat, GC_Connect
return 0;
}
- GC_SharedState old_shared_state = chat->shared_state;
+ const GC_SharedState old_shared_state = chat->shared_state;
GC_SharedState new_shared_state;
if (unpack_gc_shared_state(&new_shared_state, ss_data, ss_length) == 0) {
@@ -2934,7 +3025,7 @@ static int handle_gc_shared_state(const GC_Session *c, GC_Chat *chat, GC_Connect
if (chat->shared_state.version == 0) { // init founder public sig key in moderation object
memcpy(chat->moderation.founder_public_sig_key,
- get_sig_pk(new_shared_state.founder_public_key), SIG_PUBLIC_KEY_SIZE);
+ get_sig_pk(&new_shared_state.founder_public_key), SIG_PUBLIC_KEY_SIZE);
}
chat->shared_state = new_shared_state;
@@ -3012,7 +3103,7 @@ static int handle_gc_mod_list(const GC_Session *c, GC_Chat *chat, const uint8_t
update_gc_peer_roles(chat);
if (chat->connection_state == CS_CONNECTED && c->moderation != nullptr) {
- c->moderation(c->messenger, chat->group_number, (uint32_t) -1, (uint32_t) -1, MV_MOD, userdata);
+ c->moderation(c->messenger, chat->group_number, gc_invalid_peer_id(), gc_invalid_peer_id(), MV_MOD, userdata);
}
return 0;
@@ -3133,7 +3224,7 @@ static int handle_gc_sanctions_list(const GC_Session *c, GC_Chat *chat, const ui
if (chat->connection_state == CS_CONNECTED) {
if (c->moderation != nullptr) {
- c->moderation(c->messenger, chat->group_number, (uint32_t) -1, (uint32_t) -1, MV_OBSERVER, userdata);
+ c->moderation(c->messenger, chat->group_number, gc_invalid_peer_id(), gc_invalid_peer_id(), MV_OBSERVER, userdata);
}
}
@@ -3222,7 +3313,7 @@ static int make_gc_sanctions_list_packet(const GC_Chat *chat, uint8_t *data, uin
return -1;
}
- return (int)(length + packed_len);
+ return length + packed_len;
}
/** @brief Sends the sanctions list to peer.
@@ -3282,11 +3373,11 @@ static bool broadcast_gc_sanctions_list(const GC_Chat *chat)
return false;
}
- send_gc_lossless_packet_all_peers(chat, packet, (uint16_t)packet_len, GP_SANCTIONS_LIST);
+ const bool ret = send_gc_lossless_packet_all_peers(chat, packet, (uint16_t)packet_len, GP_SANCTIONS_LIST);
free(packet);
- return true;
+ return ret;
}
/** @brief Re-signs all sanctions list entries signed by public_sig_key and broadcasts
@@ -3328,11 +3419,11 @@ static bool broadcast_gc_mod_list(const GC_Chat *chat)
return false;
}
- send_gc_lossless_packet_all_peers(chat, packet, length, GP_MOD_LIST);
+ const bool ret = send_gc_lossless_packet_all_peers(chat, packet, length, GP_MOD_LIST);
free(packet);
- return true;
+ return ret;
}
/** @brief Sends a parting signal to the group.
@@ -3394,7 +3485,7 @@ int gc_set_self_nick(const Messenger *m, int group_number, const uint8_t *nick,
return 0;
}
-bool gc_get_peer_nick(const GC_Chat *chat, uint32_t peer_id, uint8_t *name)
+bool gc_get_peer_nick(const GC_Chat *chat, GC_Peer_Id peer_id, uint8_t *name)
{
const int peer_number = get_peer_number_of_peer_id(chat, peer_id);
@@ -3411,7 +3502,7 @@ bool gc_get_peer_nick(const GC_Chat *chat, uint32_t peer_id, uint8_t *name)
return true;
}
-int gc_get_peer_nick_size(const GC_Chat *chat, uint32_t peer_id)
+int gc_get_peer_nick_size(const GC_Chat *chat, GC_Peer_Id peer_id)
{
const int peer_number = get_peer_number_of_peer_id(chat, peer_id);
@@ -3470,12 +3561,12 @@ static int get_gc_peer_public_key(const GC_Chat *chat, uint32_t peer_number, uin
return -2;
}
- memcpy(public_key, gconn->addr.public_key, ENC_PUBLIC_KEY_SIZE);
+ memcpy(public_key, gconn->addr.public_key.enc, ENC_PUBLIC_KEY_SIZE);
return 0;
}
-int gc_get_peer_public_key_by_peer_id(const GC_Chat *chat, uint32_t peer_id, uint8_t *public_key)
+int gc_get_peer_public_key_by_peer_id(const GC_Chat *chat, GC_Peer_Id peer_id, uint8_t *public_key)
{
const int peer_number = get_peer_number_of_peer_id(chat, peer_id);
@@ -3489,17 +3580,74 @@ int gc_get_peer_public_key_by_peer_id(const GC_Chat *chat, uint32_t peer_id, uin
return -2;
}
- memcpy(public_key, gconn->addr.public_key, ENC_PUBLIC_KEY_SIZE);
+ memcpy(public_key, gconn->addr.public_key.enc, ENC_PUBLIC_KEY_SIZE);
return 0;
}
-unsigned int gc_get_peer_connection_status(const GC_Chat *chat, uint32_t peer_id)
+/** @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, GC_Peer_Id 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 (peer_number_is_self(peer_number)) { // we cannot have a connection with ourselves
- return 0;
+ 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, GC_Peer_Id 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, GC_Peer_Id peer_id)
+{
+ const int peer_number = get_peer_number_of_peer_id(chat, peer_id);
+
+ if (peer_number_is_self(peer_number)) {
+ return chat->self_udp_status == SELF_UDP_STATUS_NONE ? 1 : 2;
}
const GC_Connection *gconn = get_gc_connection(chat, peer_number);
@@ -3632,11 +3780,11 @@ static bool broadcast_gc_topic(const GC_Chat *chat)
return false;
}
- send_gc_lossless_packet_all_peers(chat, packet, packet_buf_size, GP_TOPIC);
+ const bool ret = send_gc_lossless_packet_all_peers(chat, packet, packet_buf_size, GP_TOPIC);
free(packet);
- return true;
+ return ret;
}
int gc_set_topic(GC_Chat *chat, const uint8_t *topic, uint16_t length)
@@ -3676,10 +3824,10 @@ int gc_set_topic(GC_Chat *chat, const uint8_t *topic, uint16_t length)
assert(topic != nullptr);
memcpy(chat->topic_info.topic, topic, length);
} else {
- memset(chat->topic_info.topic, 0, sizeof(chat->topic_info.topic));
+ memzero(chat->topic_info.topic, sizeof(chat->topic_info.topic));
}
- memcpy(chat->topic_info.public_sig_key, get_sig_pk(chat->self_public_key), SIG_PUBLIC_KEY_SIZE);
+ memcpy(chat->topic_info.public_sig_key, get_sig_pk(&chat->self_public_key), SIG_PUBLIC_KEY_SIZE);
chat->topic_info.checksum = get_gc_topic_checksum(&chat->topic_info);
@@ -3699,7 +3847,7 @@ int gc_set_topic(GC_Chat *chat, const uint8_t *topic, uint16_t length)
}
if (crypto_sign_detached(chat->topic_sig, nullptr, packed_topic, packet_buf_size,
- get_sig_sk(chat->self_secret_key)) == -1) {
+ get_sig_sk(&chat->self_secret_key)) == -1) {
goto ON_ERROR;
}
@@ -3746,6 +3894,7 @@ static bool update_gc_topic(GC_Chat *chat, const uint8_t *public_sig_key)
return true;
}
+ LOGGER_TRACE(chat->log, "founder is re-signing topic");
return gc_set_topic(chat, chat->topic_info.topic, chat->topic_info.length) == 0;
}
@@ -3855,7 +4004,7 @@ static int handle_gc_topic(const GC_Session *c, GC_Chat *chat, const GC_Peer *pe
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 uint32_t peer_id = setter_peer_number >= 0 ? chat->group[setter_peer_number].peer_id : 0;
+ 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);
}
@@ -3914,6 +4063,11 @@ static int handle_gc_key_exchange(const GC_Chat *chat, GC_Connection *gconn, con
memcpy(response + 1, new_session_pk, ENC_PUBLIC_KEY_SIZE);
if (!send_lossless_group_packet(chat, gconn, response, sizeof(response), GP_KEY_ROTATION)) {
+ // Don't really care about zeroing the secret key here, because we failed, but
+ // we're doing it anyway for symmetry with the memzero+munlock below, where we
+ // really do care about it.
+ crypto_memzero(new_session_sk, sizeof(new_session_sk));
+ crypto_memunlock(new_session_sk, sizeof(new_session_sk));
return -3;
}
@@ -3923,6 +4077,7 @@ static int handle_gc_key_exchange(const GC_Chat *chat, GC_Connection *gconn, con
gcc_make_session_shared_key(gconn, sender_public_session_key);
+ crypto_memzero(new_session_sk, sizeof(new_session_sk));
crypto_memunlock(new_session_sk, sizeof(new_session_sk));
gconn->last_key_rotation = mono_time_get(chat->mono_time);
@@ -3960,17 +4115,11 @@ int gc_founder_set_password(GC_Chat *chat, const uint8_t *password, uint16_t pas
return -1;
}
- uint8_t *oldpasswd = nullptr;
const uint16_t oldlen = chat->shared_state.password_length;
+ uint8_t *oldpasswd = memdup(chat->shared_state.password, oldlen);
- if (oldlen > 0) {
- oldpasswd = (uint8_t *)malloc(oldlen);
-
- if (oldpasswd == nullptr) {
- return -4;
- }
-
- memcpy(oldpasswd, chat->shared_state.password, oldlen);
+ if (oldpasswd == nullptr && oldlen > 0) {
+ return -4;
}
if (!set_gc_password_local(chat, password, password_length)) {
@@ -4117,7 +4266,7 @@ static bool send_gc_set_mod(const GC_Chat *chat, const GC_Connection *gconn, boo
net_pack_bool(&data[0], add_mod);
- memcpy(data + 1, get_sig_pk(gconn->addr.public_key), SIG_PUBLIC_KEY_SIZE);
+ memcpy(data + 1, get_sig_pk(&gconn->addr.public_key), SIG_PUBLIC_KEY_SIZE);
if (!send_gc_broadcast_message(chat, data, length, GM_SET_MOD)) {
free(data);
@@ -4149,16 +4298,16 @@ static bool founder_gc_set_moderator(GC_Chat *chat, const GC_Connection *gconn,
}
}
- if (!mod_list_add_entry(&chat->moderation, get_sig_pk(gconn->addr.public_key))) {
+ if (!mod_list_add_entry(&chat->moderation, get_sig_pk(&gconn->addr.public_key))) {
return false;
}
} else {
- if (!mod_list_remove_entry(&chat->moderation, get_sig_pk(gconn->addr.public_key))) {
+ if (!mod_list_remove_entry(&chat->moderation, get_sig_pk(&gconn->addr.public_key))) {
return false;
}
- if (!update_gc_sanctions_list(chat, get_sig_pk(gconn->addr.public_key))
- || !update_gc_topic(chat, get_sig_pk(gconn->addr.public_key))) {
+ if (!update_gc_sanctions_list(chat, get_sig_pk(&gconn->addr.public_key))
+ || !update_gc_topic(chat, get_sig_pk(&gconn->addr.public_key))) {
return false;
}
}
@@ -4287,7 +4436,6 @@ static int handle_gc_set_observer(const GC_Session *c, GC_Chat *chat, uint32_t p
return -2;
}
-
if (ret == 1) {
return 0;
}
@@ -4374,7 +4522,7 @@ static bool mod_gc_set_observer(GC_Chat *chat, uint32_t peer_number, bool add_ob
Mod_Sanction sanction;
- if (!sanctions_list_make_entry(&chat->moderation, gconn->addr.public_key, &sanction, SA_OBSERVER)) {
+ if (!sanctions_list_make_entry(&chat->moderation, gconn->addr.public_key.enc, &sanction, SA_OBSERVER)) {
LOGGER_WARNING(chat->log, "sanctions_list_make_entry failed in mod_gc_set_observer");
return false;
}
@@ -4388,7 +4536,7 @@ static bool mod_gc_set_observer(GC_Chat *chat, uint32_t peer_number, bool add_ob
length += packed_len;
} else {
- if (!sanctions_list_remove_observer(&chat->moderation, gconn->addr.public_key, nullptr)) {
+ if (!sanctions_list_remove_observer(&chat->moderation, gconn->addr.public_key.enc, nullptr)) {
LOGGER_WARNING(chat->log, "failed to remove sanction");
return false;
}
@@ -4409,7 +4557,7 @@ static bool mod_gc_set_observer(GC_Chat *chat, uint32_t peer_number, bool add_ob
update_gc_peer_roles(chat);
- return send_gc_set_observer(chat, gconn->addr.public_key, sanction_data, length, add_obs);
+ return send_gc_set_observer(chat, gconn->addr.public_key.enc, sanction_data, length, add_obs);
}
/** @brief Sets the role of `peer_number` to `new_role`. If necessary this function will first
@@ -4476,7 +4624,7 @@ static bool apply_new_gc_role(GC_Chat *chat, uint32_t peer_number, Group_Role cu
return true;
}
-int gc_set_peer_role(const Messenger *m, int group_number, uint32_t peer_id, Group_Role new_role)
+int gc_set_peer_role(const Messenger *m, int group_number, GC_Peer_Id peer_id, Group_Role new_role)
{
const GC_Session *c = m->group_handler;
GC_Chat *chat = gc_get_group(c, group_number);
@@ -4672,7 +4820,7 @@ int gc_founder_set_privacy_state(const Messenger *m, int group_number, Group_Pri
}
if (new_privacy_state == GI_PRIVATE) {
- cleanup_gca(c->announces_list, get_chat_id(chat->chat_public_key));
+ cleanup_gca(c->announces_list, get_chat_id(&chat->chat_public_key));
kill_group_friend_connection(c, chat);
chat->join_type = HJ_PRIVATE;
} else {
@@ -4805,7 +4953,7 @@ static int handle_gc_message(const GC_Session *c, const GC_Chat *chat, const GC_
return 0;
}
-int gc_send_private_message(const GC_Chat *chat, uint32_t peer_id, uint8_t type, const uint8_t *message,
+int gc_send_private_message(const GC_Chat *chat, GC_Peer_Id peer_id, uint8_t type, const uint8_t *message,
uint16_t length)
{
if (length > MAX_GC_MESSAGE_SIZE) {
@@ -4896,20 +5044,10 @@ static int handle_gc_private_message(const GC_Session *c, const GC_Chat *chat, c
/** @brief Returns false if a custom packet is too large. */
static bool custom_gc_packet_length_is_valid(uint16_t length, bool lossless)
{
- if (lossless) {
- if (length > MAX_GC_CUSTOM_LOSSLESS_PACKET_SIZE) {
- return false;
- }
- } else {
- if (length > MAX_GC_CUSTOM_LOSSY_PACKET_SIZE) {
- return false;
- }
- }
-
- return true;
+ return length <= (lossless ? MAX_GC_CUSTOM_LOSSLESS_PACKET_SIZE : MAX_GC_CUSTOM_LOSSY_PACKET_SIZE);
}
-int gc_send_custom_private_packet(const GC_Chat *chat, bool lossless, uint32_t peer_id, const uint8_t *message,
+int gc_send_custom_private_packet(const GC_Chat *chat, bool lossless, GC_Peer_Id peer_id, const uint8_t *message,
uint16_t length)
{
if (!custom_gc_packet_length_is_valid(length, lossless)) {
@@ -4943,8 +5081,6 @@ int gc_send_custom_private_packet(const GC_Chat *chat, bool lossless, uint32_t p
return ret ? 0 : -5;
}
-
-
/** @brief Handles a custom private packet.
*
* @retval 0 if packet is handled correctly.
@@ -4987,13 +5123,15 @@ int gc_send_custom_packet(const GC_Chat *chat, bool lossless, const uint8_t *dat
return -3;
}
+ bool success;
+
if (lossless) {
- send_gc_lossless_packet_all_peers(chat, data, length, GP_CUSTOM_PACKET);
+ success = send_gc_lossless_packet_all_peers(chat, data, length, GP_CUSTOM_PACKET);
} else {
- send_gc_lossy_packet_all_peers(chat, data, length, GP_CUSTOM_PACKET);
+ success = send_gc_lossy_packet_all_peers(chat, data, length, GP_CUSTOM_PACKET);
}
- return 0;
+ return success ? 0 : -4;
}
/** @brief Handles a custom packet.
@@ -5093,12 +5231,12 @@ non_null()
static bool send_gc_kick_peer(const GC_Chat *chat, const GC_Connection *gconn)
{
uint8_t packet[ENC_PUBLIC_KEY_SIZE];
- memcpy(packet, gconn->addr.public_key, ENC_PUBLIC_KEY_SIZE);
+ memcpy(packet, gconn->addr.public_key.enc, ENC_PUBLIC_KEY_SIZE);
return send_gc_broadcast_message(chat, packet, ENC_PUBLIC_KEY_SIZE, GM_KICK_PEER);
}
-int gc_kick_peer(const Messenger *m, int group_number, uint32_t peer_id)
+int gc_kick_peer(const Messenger *m, int group_number, GC_Peer_Id peer_id)
{
const GC_Session *c = m->group_handler;
GC_Chat *chat = gc_get_group(c, group_number);
@@ -5211,7 +5349,7 @@ static int handle_gc_message_ack(const GC_Chat *chat, GC_Connection *gconn, cons
if (gcc_encrypt_and_send_lossless_packet(chat, gconn, gconn->send_array[idx].data,
gconn->send_array[idx].data_length,
gconn->send_array[idx].message_id,
- gconn->send_array[idx].packet_type)) {
+ gconn->send_array[idx].packet_type) == 0) {
gconn->send_array[idx].last_send_try = tm;
LOGGER_DEBUG(chat->log, "Re-sent requested packet %llu", (unsigned long long)message_id);
} else {
@@ -5250,7 +5388,7 @@ static int handle_gc_hs_response_ack(const GC_Chat *chat, GC_Connection *gconn)
return 0;
}
-int gc_set_ignore(const GC_Chat *chat, uint32_t peer_id, bool ignore)
+int gc_set_ignore(const GC_Chat *chat, GC_Peer_Id peer_id, bool ignore)
{
const int peer_number = get_peer_number_of_peer_id(chat, peer_id);
@@ -5452,12 +5590,12 @@ static int make_gc_handshake_packet(const GC_Chat *chat, const GC_Connection *gc
uint8_t request_type, uint8_t join_type, uint8_t *packet, size_t packet_size,
const Node_format *node)
{
- if (packet_size != GC_MIN_ENCRYPTED_HS_PAYLOAD_SIZE + sizeof(Node_format)) {
- LOGGER_FATAL(chat->log, "invalid packet size: %zu", packet_size);
+ if (chat == nullptr || gconn == nullptr || node == nullptr) {
return -1;
}
- if (chat == nullptr || gconn == nullptr || node == nullptr) {
+ if (packet_size != GC_MIN_ENCRYPTED_HS_PAYLOAD_SIZE + sizeof(Node_format)) {
+ LOGGER_FATAL(chat->log, "invalid packet size: %zu", packet_size);
return -1;
}
@@ -5468,7 +5606,7 @@ static int make_gc_handshake_packet(const GC_Chat *chat, const GC_Connection *gc
data[0] = handshake_type;
memcpy(data + length, gconn->session_public_key, ENC_PUBLIC_KEY_SIZE);
length += ENC_PUBLIC_KEY_SIZE;
- memcpy(data + length, get_sig_pk(chat->self_public_key), SIG_PUBLIC_KEY_SIZE);
+ memcpy(data + length, get_sig_pk(&chat->self_public_key), SIG_PUBLIC_KEY_SIZE);
length += SIG_PUBLIC_KEY_SIZE;
memcpy(data + length, &request_type, sizeof(uint8_t));
length += sizeof(uint8_t);
@@ -5484,8 +5622,8 @@ static int make_gc_handshake_packet(const GC_Chat *chat, const GC_Connection *gc
}
const int enc_len = wrap_group_handshake_packet(
- chat->log, chat->rng, chat->self_public_key, chat->self_secret_key,
- gconn->addr.public_key, packet, (uint16_t)packet_size, data, length);
+ chat->log, chat->rng, chat->self_public_key.enc, chat->self_secret_key.enc,
+ gconn->addr.public_key.enc, packet, (uint16_t)packet_size, data, length);
if (enc_len != GC_MIN_ENCRYPTED_HS_PAYLOAD_SIZE + nodes_size) {
LOGGER_WARNING(chat->log, "Failed to wrap handshake packet: %d", enc_len);
@@ -5509,8 +5647,7 @@ static bool send_gc_handshake_packet(const GC_Chat *chat, GC_Connection *gconn,
return false;
}
- Node_format node;
- memset(&node, 0, sizeof(node));
+ Node_format node = {{0}};
if (!gcc_copy_tcp_relay(chat->rng, &node, gconn)) {
LOGGER_TRACE(chat->log, "Failed to copy TCP relay during handshake (%u TCP relays)", gconn->tcp_relays_count);
@@ -5565,8 +5702,7 @@ static bool send_gc_oob_handshake_request(const GC_Chat *chat, const GC_Connecti
return false;
}
- Node_format node;
- memset(&node, 0, sizeof(node));
+ Node_format node = {{0}};
if (!gcc_copy_tcp_relay(chat->rng, &node, gconn)) {
LOGGER_WARNING(chat->log, "Failed to copy TCP relay");
@@ -5582,7 +5718,7 @@ static bool send_gc_oob_handshake_request(const GC_Chat *chat, const GC_Connecti
return false;
}
- return tcp_send_oob_packet_using_relay(chat->tcp_conn, gconn->oob_relay_pk, gconn->addr.public_key,
+ return tcp_send_oob_packet_using_relay(chat->tcp_conn, gconn->oob_relay_pk, gconn->addr.public_key.enc,
packet, (uint16_t)length) == 0;
}
@@ -5620,7 +5756,7 @@ static int handle_gc_handshake_response(const GC_Chat *chat, const uint8_t *send
gcc_make_session_shared_key(gconn, sender_session_pk);
- set_sig_pk(gconn->addr.public_key, data + ENC_PUBLIC_KEY_SIZE);
+ set_sig_pk(&gconn->addr.public_key, data + ENC_PUBLIC_KEY_SIZE);
gcc_set_recv_message_id(gconn, 2); // handshake response is always second packet
@@ -5691,13 +5827,13 @@ static int handle_gc_handshake_request(GC_Chat *chat, const IP_Port *ipp, const
return -1;
}
- if (chat->connection_O_metre >= GC_NEW_PEER_CONNECTION_LIMIT) {
+ 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;
+ ++chat->connection_o_metre;
const uint8_t *public_sig_key = data + ENC_PUBLIC_KEY_SIZE;
@@ -5779,7 +5915,7 @@ static int handle_gc_handshake_request(GC_Chat *chat, const IP_Port *ipp, const
gcc_make_session_shared_key(gconn, sender_session_pk);
- set_sig_pk(gconn->addr.public_key, public_sig_key);
+ set_sig_pk(&gconn->addr.public_key, public_sig_key);
if (join_type == HJ_PUBLIC && !is_public_chat(chat)) {
gcc_mark_for_deletion(gconn, chat->tcp_conn, GC_EXIT_TYPE_DISCONNECTED, nullptr, 0);
@@ -5815,7 +5951,7 @@ static int handle_gc_handshake_packet(GC_Chat *chat, const uint8_t *sender_pk, c
return -1;
}
- const int plain_len = unwrap_group_handshake_packet(chat->log, chat->self_secret_key, sender_pk, data,
+ const int plain_len = unwrap_group_handshake_packet(chat->log, chat->self_secret_key.enc, sender_pk, data,
data_buf_size, packet, length);
if (plain_len < GC_MIN_HS_PACKET_PAYLOAD_SIZE) {
@@ -6127,6 +6263,39 @@ static bool handle_gc_lossless_packet(const GC_Session *c, GC_Chat *chat, const
return true;
}
+non_null(1, 2, 3, 4, 6) nullable(8)
+static int handle_gc_lossy_packet_decoded(
+ const GC_Session *c, GC_Chat *chat, GC_Connection *gconn, const GC_Peer *peer,
+ uint8_t packet_type, const uint8_t *data, uint16_t payload_len, void *userdata)
+{
+ switch (packet_type) {
+ case GP_MESSAGE_ACK: {
+ return handle_gc_message_ack(chat, gconn, data, payload_len);
+ }
+
+ case GP_PING: {
+ return handle_gc_ping(chat, gconn, data, payload_len);
+ }
+
+ case GP_INVITE_RESPONSE_REJECT: {
+ return handle_gc_invite_response_reject(c, chat, data, payload_len, userdata);
+ }
+
+ case GP_CUSTOM_PACKET: {
+ return handle_gc_custom_packet(c, chat, peer, data, payload_len, false, userdata);
+ }
+
+ case GP_CUSTOM_PRIVATE_PACKET: {
+ return handle_gc_custom_private_packet(c, chat, peer, data, payload_len, false, userdata);
+ }
+
+ default: {
+ LOGGER_WARNING(chat->log, "Warning: handling invalid lossy group packet type 0x%02x", packet_type);
+ return -1;
+ }
+ }
+}
+
/** @brief Handles lossy groupchat message packets.
*
* This function assumes the length has already been validated.
@@ -6175,41 +6344,7 @@ static bool handle_gc_lossy_packet(const GC_Session *c, GC_Chat *chat, const uin
return false;
}
- int ret = -1;
- const uint16_t payload_len = (uint16_t)len;
-
- switch (packet_type) {
- case GP_MESSAGE_ACK: {
- ret = handle_gc_message_ack(chat, gconn, data, payload_len);
- break;
- }
-
- case GP_PING: {
- ret = handle_gc_ping(chat, gconn, data, payload_len);
- break;
- }
-
- case GP_INVITE_RESPONSE_REJECT: {
- ret = handle_gc_invite_response_reject(c, chat, data, payload_len, userdata);
- break;
- }
-
- case GP_CUSTOM_PACKET: {
- ret = handle_gc_custom_packet(c, chat, peer, data, payload_len, false, userdata);
- break;
- }
-
- case GP_CUSTOM_PRIVATE_PACKET: {
- ret = handle_gc_custom_private_packet(c, chat, peer, data, payload_len, false, userdata);
- break;
- }
-
- default: {
- LOGGER_WARNING(chat->log, "Warning: handling invalid lossy group packet type 0x%02x", packet_type);
- free(data);
- return false;
- }
- }
+ const int ret = handle_gc_lossy_packet_decoded(c, chat, gconn, peer, packet_type, data, (uint16_t)len, userdata);
free(data);
@@ -6245,7 +6380,7 @@ static bool group_can_handle_packets(const GC_Chat *chat)
*/
#define MIN_TCP_PACKET_SIZE (1 + ENC_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_MAC_SIZE)
non_null(1, 3) nullable(5)
-static int handle_gc_tcp_packet(void *object, int id, const uint8_t *packet, uint16_t length, void *userdata)
+static int handle_gc_tcp_packet(void *object, int crypt_connection_id, const uint8_t *packet, uint16_t length, void *userdata)
{
const Messenger *m = (Messenger *)object;
@@ -6255,13 +6390,13 @@ static int handle_gc_tcp_packet(void *object, int id, const uint8_t *packet, uin
if (length <= MIN_TCP_PACKET_SIZE) {
LOGGER_WARNING(m->log, "Got tcp packet with invalid length: %u (expected %u to %u)", length,
- MIN_TCP_PACKET_SIZE, MAX_GC_PACKET_CHUNK_SIZE + MIN_TCP_PACKET_SIZE + ENC_PUBLIC_KEY_SIZE);
+ MIN_TCP_PACKET_SIZE, MAX_GC_PACKET_INCOMING_CHUNK_SIZE + MIN_TCP_PACKET_SIZE + ENC_PUBLIC_KEY_SIZE);
return -1;
}
- if (length > MAX_GC_PACKET_CHUNK_SIZE + MIN_TCP_PACKET_SIZE + ENC_PUBLIC_KEY_SIZE) {
+ if (length > MAX_GC_PACKET_INCOMING_CHUNK_SIZE + MIN_TCP_PACKET_SIZE + ENC_PUBLIC_KEY_SIZE) {
LOGGER_WARNING(m->log, "Got tcp packet with invalid length: %u (expected %u to %u)", length,
- MIN_TCP_PACKET_SIZE, MAX_GC_PACKET_CHUNK_SIZE + MIN_TCP_PACKET_SIZE + ENC_PUBLIC_KEY_SIZE);
+ MIN_TCP_PACKET_SIZE, MAX_GC_PACKET_INCOMING_CHUNK_SIZE + MIN_TCP_PACKET_SIZE + ENC_PUBLIC_KEY_SIZE);
return -1;
}
@@ -6336,13 +6471,13 @@ static int handle_gc_tcp_oob_packet(void *object, const uint8_t *public_key, uns
if (length <= GC_MIN_HS_PACKET_PAYLOAD_SIZE) {
LOGGER_WARNING(m->log, "Got tcp oob packet with invalid length: %u (expected %u to %u)", length,
- GC_MIN_HS_PACKET_PAYLOAD_SIZE, MAX_GC_PACKET_CHUNK_SIZE + CRYPTO_MAC_SIZE + CRYPTO_NONCE_SIZE);
+ GC_MIN_HS_PACKET_PAYLOAD_SIZE, MAX_GC_PACKET_INCOMING_CHUNK_SIZE + CRYPTO_MAC_SIZE + CRYPTO_NONCE_SIZE);
return -1;
}
- if (length > MAX_GC_PACKET_CHUNK_SIZE + CRYPTO_MAC_SIZE + CRYPTO_NONCE_SIZE) {
+ if (length > MAX_GC_PACKET_INCOMING_CHUNK_SIZE + CRYPTO_MAC_SIZE + CRYPTO_NONCE_SIZE) {
LOGGER_WARNING(m->log, "Got tcp oob packet with invalid length: %u (expected %u to %u)", length,
- GC_MIN_HS_PACKET_PAYLOAD_SIZE, MAX_GC_PACKET_CHUNK_SIZE + CRYPTO_MAC_SIZE + CRYPTO_NONCE_SIZE);
+ GC_MIN_HS_PACKET_PAYLOAD_SIZE, MAX_GC_PACKET_INCOMING_CHUNK_SIZE + CRYPTO_MAC_SIZE + CRYPTO_NONCE_SIZE);
return -1;
}
@@ -6381,7 +6516,7 @@ static int handle_gc_tcp_oob_packet(void *object, const uint8_t *public_key, uns
#define MIN_UDP_PACKET_SIZE (1 + ENC_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_MAC_SIZE)
non_null(1, 2, 3) nullable(5)
-static int handle_gc_udp_packet(void *object, const IP_Port *ipp, const uint8_t *packet, uint16_t length,
+static int handle_gc_udp_packet(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length,
void *userdata)
{
const Messenger *m = (Messenger *)object;
@@ -6392,13 +6527,13 @@ static int handle_gc_udp_packet(void *object, const IP_Port *ipp, const uint8_t
if (length <= MIN_UDP_PACKET_SIZE) {
LOGGER_WARNING(m->log, "Got UDP packet with invalid length: %u (expected %u to %u)", length,
- MIN_UDP_PACKET_SIZE, MAX_GC_PACKET_CHUNK_SIZE + MIN_UDP_PACKET_SIZE + ENC_PUBLIC_KEY_SIZE);
+ MIN_UDP_PACKET_SIZE, MAX_GC_PACKET_INCOMING_CHUNK_SIZE + MIN_UDP_PACKET_SIZE + ENC_PUBLIC_KEY_SIZE);
return -1;
}
- if (length > MAX_GC_PACKET_CHUNK_SIZE + MIN_UDP_PACKET_SIZE + ENC_PUBLIC_KEY_SIZE) {
+ if (length > MAX_GC_PACKET_INCOMING_CHUNK_SIZE + MIN_UDP_PACKET_SIZE + ENC_PUBLIC_KEY_SIZE) {
LOGGER_WARNING(m->log, "Got UDP packet with invalid length: %u (expected %u to %u)", length,
- MIN_UDP_PACKET_SIZE, MAX_GC_PACKET_CHUNK_SIZE + MIN_UDP_PACKET_SIZE + ENC_PUBLIC_KEY_SIZE);
+ MIN_UDP_PACKET_SIZE, MAX_GC_PACKET_INCOMING_CHUNK_SIZE + MIN_UDP_PACKET_SIZE + ENC_PUBLIC_KEY_SIZE);
return -1;
}
@@ -6446,7 +6581,7 @@ static int handle_gc_udp_packet(void *object, const IP_Port *ipp, const uint8_t
payload_len = payload_len - ENC_PUBLIC_KEY_SIZE;
payload = payload + ENC_PUBLIC_KEY_SIZE;
- ret = handle_gc_handshake_packet(chat, sender_pk, ipp, payload, payload_len, true, userdata) != -1;
+ ret = handle_gc_handshake_packet(chat, sender_pk, source, payload, payload_len, true, userdata) != -1;
break;
}
@@ -6577,7 +6712,7 @@ static bool peer_delete(const GC_Session *c, GC_Chat *chat, uint32_t peer_number
// We need to save some peer info for the callback before deleting it
const bool peer_confirmed = peer->gconn.confirmed;
- const uint32_t peer_id = peer->peer_id;
+ const GC_Peer_Id peer_id = peer->peer_id;
uint8_t nick[MAX_GC_NICK_SIZE];
const uint16_t nick_length = peer->nick_length;
const GC_Exit_Info exit_info = peer->gconn.exit_info;
@@ -6655,9 +6790,9 @@ int peer_add(GC_Chat *chat, const IP_Port *ipp, const uint8_t *public_key)
return -2;
}
- const uint32_t peer_id = get_new_peer_id(chat);
+ const GC_Peer_Id peer_id = get_new_peer_id(chat);
- if (peer_id == UINT32_MAX) {
+ if (!gc_peer_id_is_valid(peer_id)) {
LOGGER_WARNING(chat->log, "Failed to add peer: all peer ID's are taken?");
return -1;
}
@@ -6724,9 +6859,9 @@ int peer_add(GC_Chat *chat, const IP_Port *ipp, const uint8_t *public_key)
create_gc_session_keypair(chat->log, chat->rng, gconn->session_public_key, gconn->session_secret_key);
if (peer_number > 0) {
- memcpy(gconn->addr.public_key, public_key, ENC_PUBLIC_KEY_SIZE); // we get the sig key in the handshake
+ memcpy(gconn->addr.public_key.enc, public_key, ENC_PUBLIC_KEY_SIZE); // we get the sig key in the handshake
} else {
- memcpy(gconn->addr.public_key, chat->self_public_key, EXT_PUBLIC_KEY_SIZE);
+ gconn->addr.public_key = chat->self_public_key;
}
const uint64_t tm = mono_time_get(chat->mono_time);
@@ -6738,9 +6873,9 @@ int peer_add(GC_Chat *chat, const IP_Port *ipp, const uint8_t *public_key)
gconn->tcp_connection_num = tcp_connection_num;
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),
- get_enc_key(chat->self_public_key),
- get_enc_key(gconn->addr.public_key)) == 1;
+ gconn->self_is_closer = id_closest(get_chat_id(&chat->chat_public_key),
+ get_enc_key(&chat->self_public_key),
+ get_enc_key(&gconn->addr.public_key)) == 1;
return peer_number;
}
@@ -6884,23 +7019,30 @@ non_null(1, 2) nullable(3)
static void do_peer_delete(const GC_Session *c, GC_Chat *chat, void *userdata)
{
for (uint32_t i = 1; i < chat->numpeers; ++i) {
- const GC_Connection *gconn = get_gc_connection(chat, i);
+ GC_Connection *gconn = get_gc_connection(chat, i);
assert(gconn != nullptr);
- if (gconn->pending_delete) {
- const GC_Exit_Info *exit_info = &gconn->exit_info;
+ if (!gconn->pending_delete) {
+ continue;
+ }
- if (exit_info->exit_type == GC_EXIT_TYPE_TIMEOUT && gconn->confirmed) {
- add_gc_peer_timeout_list(chat, gconn);
- }
+ if (!gconn->delete_this_iteration) {
+ gconn->delete_this_iteration = true;
+ continue;
+ }
- if (!peer_delete(c, chat, i, userdata)) {
- LOGGER_ERROR(chat->log, "Failed to delete peer %u", i);
- }
+ const GC_Exit_Info *exit_info = &gconn->exit_info;
- if (i >= chat->numpeers) {
- break;
- }
+ if (exit_info->exit_type == GC_EXIT_TYPE_TIMEOUT && gconn->confirmed) {
+ add_gc_peer_timeout_list(chat, gconn);
+ }
+
+ if (!peer_delete(c, chat, i, userdata)) {
+ LOGGER_ERROR(chat->log, "Failed to delete peer %u", i);
+ }
+
+ if (i >= chat->numpeers) {
+ break;
}
}
}
@@ -6961,12 +7103,12 @@ static bool ping_peer(const GC_Chat *chat, const GC_Connection *gconn)
if (!send_lossy_group_packet(chat, gconn, data, packed_len, GP_PING)) {
free(data);
- return true;
+ return false;
}
free(data);
- return false;
+ return true;
}
/**
@@ -7015,7 +7157,7 @@ static void do_gc_ping_and_key_rotation(GC_Chat *chat)
non_null()
static void do_new_connection_cooldown(GC_Chat *chat)
{
- if (chat->connection_O_metre == 0) {
+ if (chat->connection_o_metre == 0) {
return;
}
@@ -7023,9 +7165,9 @@ static void do_new_connection_cooldown(GC_Chat *chat)
if (chat->connection_cooldown_timer < tm) {
chat->connection_cooldown_timer = tm;
- --chat->connection_O_metre;
+ --chat->connection_o_metre;
- if (chat->connection_O_metre == 0 && chat->block_handshakes) {
+ if (chat->connection_o_metre == 0 && chat->block_handshakes) {
chat->block_handshakes = false;
LOGGER_DEBUG(chat->log, "Unblocking handshakes");
}
@@ -7165,6 +7307,10 @@ void do_gc(GC_Session *c, void *userdata)
do_new_connection_cooldown(chat);
do_peer_delete(c, chat, userdata);
+
+ if (chat->flag_exit) { // should always come last as it modifies the chats array
+ group_delete(c, chat);
+ }
}
}
@@ -7212,7 +7358,9 @@ static int get_new_group_index(GC_Session *c)
c->chats[new_index] = empty_gc_chat;
- memset(&c->chats[new_index].saved_invites, -1, sizeof(c->chats[new_index].saved_invites));
+ for (size_t i = 0; i < sizeof(c->chats[new_index].saved_invites) / sizeof(*c->chats[new_index].saved_invites); ++i) {
+ c->chats[new_index].saved_invites[i] = -1;
+ }
++c->chats_index;
@@ -7250,7 +7398,7 @@ static bool init_gc_tcp_connection(const GC_Session *c, GC_Chat *chat)
{
const Messenger *m = c->messenger;
- chat->tcp_conn = new_tcp_connections(chat->log, chat->rng, m->ns, chat->mono_time, chat->self_secret_key,
+ chat->tcp_conn = new_tcp_connections(chat->log, chat->mem, chat->rng, m->ns, chat->mono_time, chat->self_secret_key.enc,
&m->options.proxy_info);
if (chat->tcp_conn == nullptr) {
@@ -7267,7 +7415,7 @@ static bool init_gc_tcp_connection(const GC_Session *c, GC_Chat *chat)
/** Initializes default shared state values. */
non_null()
-static void init_gc_shared_state(GC_Chat *chat, const Group_Privacy_State privacy_state)
+static void init_gc_shared_state(GC_Chat *chat, Group_Privacy_State privacy_state)
{
chat->shared_state.maxpeers = MAX_GC_PEERS_DEFAULT;
chat->shared_state.privacy_state = privacy_state;
@@ -7283,7 +7431,7 @@ non_null()
static bool init_gc_shared_state_founder(GC_Chat *chat, Group_Privacy_State privacy_state, const uint8_t *group_name,
uint16_t name_length)
{
- memcpy(chat->shared_state.founder_public_key, chat->self_public_key, EXT_PUBLIC_KEY_SIZE);
+ chat->shared_state.founder_public_key = chat->self_public_key;
memcpy(chat->shared_state.group_name, group_name, name_length);
chat->shared_state.group_name_len = name_length;
chat->shared_state.privacy_state = privacy_state;
@@ -7300,11 +7448,12 @@ non_null()
static void init_gc_moderation(GC_Chat *chat)
{
memcpy(chat->moderation.founder_public_sig_key,
- get_sig_pk(chat->shared_state.founder_public_key), SIG_PUBLIC_KEY_SIZE);
- memcpy(chat->moderation.self_public_sig_key, get_sig_pk(chat->self_public_key), SIG_PUBLIC_KEY_SIZE);
- memcpy(chat->moderation.self_secret_sig_key, get_sig_pk(chat->self_secret_key), SIG_SECRET_KEY_SIZE);
+ get_sig_pk(&chat->shared_state.founder_public_key), SIG_PUBLIC_KEY_SIZE);
+ memcpy(chat->moderation.self_public_sig_key, get_sig_pk(&chat->self_public_key), SIG_PUBLIC_KEY_SIZE);
+ memcpy(chat->moderation.self_secret_sig_key, get_sig_sk(&chat->self_secret_key), SIG_SECRET_KEY_SIZE);
chat->moderation.shared_state_version = chat->shared_state.version;
chat->moderation.log = chat->log;
+ chat->moderation.mem = chat->mem;
}
non_null()
@@ -7332,6 +7481,7 @@ static int create_new_group(GC_Session *c, const uint8_t *nick, size_t nick_leng
GC_Chat *chat = &c->chats[group_number];
chat->log = m->log;
+ chat->mem = m->mem;
chat->rng = m->rng;
const uint64_t tm = mono_time_get(m->mono_time);
@@ -7350,12 +7500,15 @@ static int create_new_group(GC_Session *c, const uint8_t *nick, size_t nick_leng
return -1;
}
+ init_gc_shared_state(chat, privacy_state);
+ init_gc_moderation(chat);
+
if (!init_gc_tcp_connection(c, chat)) {
group_delete(c, chat);
return -1;
}
- if (peer_add(chat, nullptr, chat->self_public_key) != 0) { /* you are always peer_number/index 0 */
+ if (peer_add(chat, nullptr, chat->self_public_key.enc) != 0) { /* you are always peer_number/index 0 */
group_delete(c, chat);
return -1;
}
@@ -7368,10 +7521,7 @@ static int create_new_group(GC_Session *c, const uint8_t *nick, size_t nick_leng
self_gc_set_status(chat, GS_NONE);
self_gc_set_role(chat, founder ? GR_FOUNDER : GR_USER);
self_gc_set_confirmed(chat, true);
- self_gc_set_ext_public_key(chat, chat->self_public_key);
-
- init_gc_shared_state(chat, privacy_state);
- init_gc_moderation(chat);
+ self_gc_set_ext_public_key(chat, &chat->self_public_key);
return group_number;
}
@@ -7476,10 +7626,15 @@ int gc_group_load(GC_Session *c, Bin_Unpack *bu)
chat->net = m->net;
chat->mono_time = m->mono_time;
chat->log = m->log;
+ chat->mem = m->mem;
chat->rng = m->rng;
chat->last_ping_interval = tm;
chat->friend_connection_id = -1;
+ // Initialise these first, because we may need to log/dealloc things on cleanup.
+ chat->moderation.log = m->log;
+ chat->moderation.mem = m->mem;
+
if (!gc_load_unpack_group(chat, bu)) {
LOGGER_ERROR(chat->log, "Failed to unpack group");
return -1;
@@ -7505,8 +7660,8 @@ int gc_group_load(GC_Session *c, Bin_Unpack *bu)
return group_number;
}
-int gc_group_add(GC_Session *c, Group_Privacy_State privacy_state, const uint8_t *group_name,
- uint16_t group_name_length,
+int gc_group_add(GC_Session *c, Group_Privacy_State privacy_state,
+ const uint8_t *group_name, uint16_t group_name_length,
const uint8_t *nick, size_t nick_length)
{
if (group_name_length > MAX_GC_GROUP_NAME_SIZE) {
@@ -7537,9 +7692,9 @@ int gc_group_add(GC_Session *c, Group_Privacy_State privacy_state, const uint8_t
return -3;
}
- crypto_memlock(chat->chat_secret_key, sizeof(chat->chat_secret_key));
+ crypto_memlock(&chat->chat_secret_key, sizeof(chat->chat_secret_key));
- create_extended_keypair(chat->chat_public_key, chat->chat_secret_key);
+ create_extended_keypair(&chat->chat_public_key, &chat->chat_secret_key, chat->rng);
if (!init_gc_shared_state_founder(chat, privacy_state, group_name, group_name_length)) {
group_delete(c, chat);
@@ -7604,7 +7759,7 @@ int gc_group_join(GC_Session *c, const uint8_t *chat_id, const uint8_t *nick, si
return -1;
}
- if (!expand_chat_id(chat->chat_public_key, chat_id)) {
+ if (!expand_chat_id(&chat->chat_public_key, chat_id)) {
group_delete(c, chat);
return -1;
}
@@ -7636,7 +7791,9 @@ bool gc_disconnect_from_group(const GC_Session *c, GC_Chat *chat)
chat->connection_state = CS_DISCONNECTED;
- send_gc_broadcast_message(chat, nullptr, 0, GM_PEER_EXIT);
+ if (!send_gc_broadcast_message(chat, nullptr, 0, GM_PEER_EXIT)) {
+ LOGGER_DEBUG(chat->log, "Failed to broadcast group exit packet");
+ }
for (uint32_t i = 1; i < chat->numpeers; ++i) {
GC_Connection *gconn = get_gc_connection(chat, i);
@@ -7712,13 +7869,12 @@ int gc_invite_friend(const GC_Session *c, GC_Chat *chat, int32_t friend_number,
packet[0] = GP_FRIEND_INVITE;
packet[1] = GROUP_INVITE;
- memcpy(packet + 2, get_chat_id(chat->chat_public_key), CHAT_ID_SIZE);
+ memcpy(packet + 2, get_chat_id(&chat->chat_public_key), CHAT_ID_SIZE);
uint16_t length = 2 + CHAT_ID_SIZE;
- memcpy(packet + length, chat->self_public_key, ENC_PUBLIC_KEY_SIZE);
+ memcpy(packet + length, chat->self_public_key.enc, ENC_PUBLIC_KEY_SIZE);
length += ENC_PUBLIC_KEY_SIZE;
-
memcpy(packet + length, chat->shared_state.group_name, group_name_length);
length += group_name_length;
@@ -7759,10 +7915,10 @@ static int send_gc_invite_accepted_packet(const Messenger *m, const GC_Chat *cha
packet[0] = GP_FRIEND_INVITE;
packet[1] = GROUP_INVITE_ACCEPTED;
- memcpy(packet + 2, get_chat_id(chat->chat_public_key), CHAT_ID_SIZE);
+ memcpy(packet + 2, get_chat_id(&chat->chat_public_key), CHAT_ID_SIZE);
uint16_t length = 2 + CHAT_ID_SIZE;
- memcpy(packet + length, chat->self_public_key, ENC_PUBLIC_KEY_SIZE);
+ memcpy(packet + length, chat->self_public_key.enc, ENC_PUBLIC_KEY_SIZE);
length += ENC_PUBLIC_KEY_SIZE;
if (!send_group_invite_packet(m, friend_number, packet, length)) {
@@ -7982,7 +8138,7 @@ bool handle_gc_invite_accepted_packet(const GC_Session *c, int friend_number, co
uint8_t out_data[GC_JOIN_DATA_LENGTH + (GCC_MAX_TCP_SHARED_RELAYS * PACKED_NODE_SIZE_IP6)];
memcpy(out_data, chat_id, CHAT_ID_SIZE);
- memcpy(out_data + CHAT_ID_SIZE, chat->self_public_key, ENC_PUBLIC_KEY_SIZE);
+ memcpy(out_data + CHAT_ID_SIZE, chat->self_public_key.enc, ENC_PUBLIC_KEY_SIZE);
if (num_tcp_relays > 0) {
const uint32_t tcp_relays_added = add_gc_tcp_relays(chat, gconn, tcp_relays, num_tcp_relays);
@@ -8039,7 +8195,7 @@ int gc_accept_invite(GC_Session *c, int32_t friend_number, const uint8_t *data,
return -2;
}
- if (!expand_chat_id(chat->chat_public_key, chat_id)) {
+ if (!expand_chat_id(&chat->chat_public_key, chat_id)) {
group_delete(c, chat);
return -2;
}
@@ -8093,7 +8249,7 @@ GC_Session *new_dht_groupchats(Messenger *m)
return c;
}
-static void group_cleanup(GC_Session *c, GC_Chat *chat)
+static void group_cleanup(const GC_Session *c, GC_Chat *chat)
{
kill_group_friend_connection(c, chat);
@@ -8111,8 +8267,8 @@ static void group_cleanup(GC_Session *c, GC_Chat *chat)
chat->group = nullptr;
}
- crypto_memunlock(chat->self_secret_key, sizeof(chat->self_secret_key));
- crypto_memunlock(chat->chat_secret_key, sizeof(chat->chat_secret_key));
+ crypto_memunlock(&chat->self_secret_key, sizeof(chat->self_secret_key));
+ crypto_memunlock(&chat->chat_secret_key, sizeof(chat->chat_secret_key));
crypto_memunlock(chat->shared_state.password, sizeof(chat->shared_state.password));
}
@@ -8143,14 +8299,21 @@ static void group_delete(GC_Session *c, GC_Chat *chat)
c->chats_index = i;
if (!realloc_groupchats(c, c->chats_index)) {
- LOGGER_ERROR(chat->log, "Failed to reallocate groupchats array");
+ LOGGER_ERROR(c->messenger->log, "Failed to reallocate groupchats array");
}
}
}
int gc_group_exit(GC_Session *c, GC_Chat *chat, const uint8_t *message, uint16_t length)
{
- const int ret = group_can_handle_packets(chat) ? send_gc_self_exit(chat, message, length) : 0;
+ chat->flag_exit = true;
+ return group_can_handle_packets(chat) ? send_gc_self_exit(chat, message, length) : 0;
+}
+
+non_null()
+static int kill_group(GC_Session *c, GC_Chat *chat)
+{
+ const int ret = gc_group_exit(c, chat, nullptr, 0);
group_delete(c, chat);
return ret;
}
@@ -8168,11 +8331,9 @@ void kill_dht_groupchats(GC_Session *c)
continue;
}
- if (group_can_handle_packets(chat)) {
- send_gc_self_exit(chat, nullptr, 0);
+ if (kill_group(c, chat) != 0) {
+ LOGGER_WARNING(c->messenger->log, "Failed to send group exit packet");
}
-
- group_cleanup(c, chat);
}
networking_registerhandler(c->messenger->net, NET_PACKET_GC_LOSSY, nullptr, nullptr);
@@ -8236,7 +8397,7 @@ GC_Chat *gc_get_group_by_public_key(const GC_Session *c, const uint8_t *public_k
continue;
}
- if (memcmp(public_key, get_chat_id(chat->chat_public_key), CHAT_ID_SIZE) == 0) {
+ if (memcmp(public_key, get_chat_id(&chat->chat_public_key), CHAT_ID_SIZE) == 0) {
return chat;
}
}
@@ -8254,7 +8415,7 @@ static bool group_exists(const GC_Session *c, const uint8_t *chat_id)
continue;
}
- if (memcmp(get_chat_id(chat->chat_public_key), chat_id, CHAT_ID_SIZE) == 0) {
+ if (memcmp(get_chat_id(&chat->chat_public_key), chat_id, CHAT_ID_SIZE) == 0) {
return true;
}
}
@@ -8280,10 +8441,10 @@ static void create_gc_session_keypair(const Logger *log, const Random *rng, uint
non_null()
static bool create_new_chat_ext_keypair(GC_Chat *chat)
{
- crypto_memlock(chat->self_secret_key, sizeof(chat->self_secret_key));
+ crypto_memlock(&chat->self_secret_key, sizeof(chat->self_secret_key));
- if (!create_extended_keypair(chat->self_public_key, chat->self_secret_key)) {
- crypto_memunlock(chat->self_secret_key, sizeof(chat->self_secret_key));
+ if (!create_extended_keypair(&chat->self_public_key, &chat->self_secret_key, chat->rng)) {
+ crypto_memunlock(&chat->self_secret_key, sizeof(chat->self_secret_key));
return false;
}
@@ -8407,4 +8568,3 @@ int gc_add_peers_from_announces(GC_Chat *chat, const GC_Announce *announces, uin
return added_peers;
}
-#endif // VANILLA_NACL
diff --git a/protocols/Tox/libtox/src/toxcore/group_chats.h b/protocols/Tox/libtox/src/toxcore/group_chats.h
index 821e629a64..32a7323dc4 100644
--- a/protocols/Tox/libtox/src/toxcore/group_chats.h
+++ b/protocols/Tox/libtox/src/toxcore/group_chats.h
@@ -7,19 +7,22 @@
* An implementation of massive text only group chats.
*/
-#ifndef GROUP_CHATS_H
-#define GROUP_CHATS_H
+#ifndef C_TOXCORE_TOXCORE_GROUP_CHATS_H
+#define C_TOXCORE_TOXCORE_GROUP_CHATS_H
#include <stdbool.h>
#include <stdint.h>
#include "TCP_connection.h"
+#include "attributes.h"
#include "bin_pack.h"
#include "bin_unpack.h"
+#include "crypto_core.h"
#include "group_announce.h"
#include "group_common.h"
#include "group_connection.h"
#include "logger.h"
+#include "network.h"
#define GC_PING_TIMEOUT 12
#define GC_SEND_IP_PORT_INTERVAL (GC_PING_TIMEOUT * 5)
@@ -142,7 +145,7 @@ non_null(1, 2, 3, 4, 5) nullable(7)
int group_packet_wrap(
const Logger *log, const Random *rng, const uint8_t *self_pk, const uint8_t *shared_key, uint8_t *packet,
uint16_t packet_size, const uint8_t *data, uint16_t length, uint64_t message_id,
- uint8_t gp_packet_type, uint8_t net_packet_type);
+ uint8_t gp_packet_type, Net_Packet_Type net_packet_type);
/** @brief Returns the size of a wrapped/encrypted packet with a plain size of `length`.
*
@@ -162,7 +165,7 @@ uint16_t gc_get_wrapped_packet_size(uint16_t length, Net_Packet_Type packet_type
* Returns -4 if the sender does not have permission to speak.
* Returns -5 if the packet fails to send.
*/
-non_null(1, 2, 3, 4) nullable(5)
+non_null(1, 2) nullable(5)
int gc_send_message(const GC_Chat *chat, const uint8_t *message, uint16_t length, uint8_t type,
uint32_t *message_id);
@@ -179,7 +182,7 @@ int gc_send_message(const GC_Chat *chat, const uint8_t *message, uint16_t length
* Returns -6 if the packet fails to send.
*/
non_null()
-int gc_send_private_message(const GC_Chat *chat, uint32_t peer_id, uint8_t type, const uint8_t *message,
+int gc_send_private_message(const GC_Chat *chat, GC_Peer_Id peer_id, uint8_t type, const uint8_t *message,
uint16_t length);
/** @brief Sends a custom packet to the group. If lossless is true, the packet will be lossless.
@@ -190,6 +193,7 @@ int gc_send_private_message(const GC_Chat *chat, uint32_t peer_id, uint8_t type,
* Returns -1 if the message is too long.
* Returns -2 if the message pointer is NULL or length is zero.
* Returns -3 if the sender has the observer role.
+ * Returns -4 if the packet did not successfully send to any peer.
*/
non_null()
int gc_send_custom_packet(const GC_Chat *chat, bool lossless, const uint8_t *data, uint16_t length);
@@ -206,7 +210,7 @@ int gc_send_custom_packet(const GC_Chat *chat, bool lossless, const uint8_t *dat
* @retval -5 if the packet fails to send.
*/
non_null()
-int gc_send_custom_private_packet(const GC_Chat *chat, bool lossless, uint32_t peer_id, const uint8_t *message,
+int gc_send_custom_private_packet(const GC_Chat *chat, bool lossless, GC_Peer_Id peer_id, const uint8_t *message,
uint16_t length);
/** @brief Sets ignore for peer_id.
@@ -216,7 +220,7 @@ int gc_send_custom_private_packet(const GC_Chat *chat, bool lossless, uint32_t p
* Returns -2 if the caller attempted to ignore himself.
*/
non_null()
-int gc_set_ignore(const GC_Chat *chat, uint32_t peer_id, bool ignore);
+int gc_set_ignore(const GC_Chat *chat, GC_Peer_Id peer_id, bool ignore);
/** @brief Sets the group topic and broadcasts it to the group.
*
@@ -341,7 +345,7 @@ uint8_t gc_get_self_status(const GC_Chat *chat);
/** @brief Returns your own peer id. */
non_null()
-uint32_t gc_get_self_peer_id(const GC_Chat *chat);
+GC_Peer_Id gc_get_self_peer_id(const GC_Chat *chat);
/** @brief Copies self public key to `public_key`.
*
@@ -364,7 +368,7 @@ void gc_get_self_public_key(const GC_Chat *chat, uint8_t *public_key);
* Returns false if peer_id is invalid.
*/
non_null(1) nullable(3)
-bool gc_get_peer_nick(const GC_Chat *chat, uint32_t peer_id, uint8_t *name);
+bool gc_get_peer_nick(const GC_Chat *chat, GC_Peer_Id peer_id, uint8_t *name);
/** @brief Returns the length of the nick for the peer designated by `peer_id`.
* Returns -1 if peer_id is invalid.
@@ -373,7 +377,7 @@ bool gc_get_peer_nick(const GC_Chat *chat, uint32_t peer_id, uint8_t *name);
* nick_change callback.
*/
non_null()
-int gc_get_peer_nick_size(const GC_Chat *chat, uint32_t peer_id);
+int gc_get_peer_nick_size(const GC_Chat *chat, GC_Peer_Id peer_id);
/** @brief Copies peer_id's public key to `public_key`.
*
@@ -388,18 +392,44 @@ int gc_get_peer_nick_size(const GC_Chat *chat, uint32_t peer_id);
* Returns -2 if `public_key` is null.
*/
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);
+int gc_get_peer_public_key_by_peer_id(const GC_Chat *chat, GC_Peer_Id 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, GC_Peer_Id 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, GC_Peer_Id 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
+ * of making UDP connections with other peers, or are limited to TCP connections.
+ *
* Returns 2 if we have a direct (UDP) connection with a peer.
* Returns 1 if we have an indirect (TCP) connection with a peer.
- * Returns 0 if peer_id is invalid or corresponds to ourselves.
+ * Returns 0 if peer_id is invalid.
*
* Note: Return values must correspond to Tox_Connection enum in API.
*/
non_null()
-unsigned int gc_get_peer_connection_status(const GC_Chat *chat, uint32_t peer_id);
+unsigned int gc_get_peer_connection_status(const GC_Chat *chat, GC_Peer_Id peer_id);
/** @brief Sets the caller's status to `status`.
*
@@ -417,7 +447,7 @@ int gc_set_self_status(const Messenger *m, int group_number, Group_Peer_Status s
* callback.
*/
non_null()
-uint8_t gc_get_status(const GC_Chat *chat, uint32_t peer_id);
+uint8_t gc_get_status(const GC_Chat *chat, GC_Peer_Id peer_id);
/** @brief Returns the group role of peer designated by `peer_id`.
* Returns UINT8_MAX on failure.
@@ -425,7 +455,7 @@ uint8_t gc_get_status(const GC_Chat *chat, uint32_t peer_id);
* The role returned is equal to the last role received through the moderation callback.
*/
non_null()
-uint8_t gc_get_role(const GC_Chat *chat, uint32_t peer_id);
+uint8_t gc_get_role(const GC_Chat *chat, GC_Peer_Id peer_id);
/** @brief Sets the role of peer_id. role must be one of: GR_MODERATOR, GR_USER, GR_OBSERVER
*
@@ -438,7 +468,7 @@ uint8_t gc_get_role(const GC_Chat *chat, uint32_t peer_id);
* Returns -6 if the caller attempted to kick himself.
*/
non_null()
-int gc_set_peer_role(const Messenger *m, int group_number, uint32_t peer_id, Group_Role new_role);
+int gc_set_peer_role(const Messenger *m, int group_number, GC_Peer_Id peer_id, Group_Role new_role);
/** @brief Sets the group password and distributes the new shared state to the group.
*
@@ -533,7 +563,7 @@ int gc_founder_set_max_peers(GC_Chat *chat, uint16_t max_peers);
* Returns -6 if the caller attempted to kick himself.
*/
non_null()
-int gc_kick_peer(const Messenger *m, int group_number, uint32_t peer_id);
+int gc_kick_peer(const Messenger *m, int group_number, GC_Peer_Id peer_id);
/** @brief Copies the chat_id to dest. If dest is null this function has no effect.
*
@@ -542,7 +572,6 @@ int gc_kick_peer(const Messenger *m, int group_number, uint32_t peer_id);
non_null(1) nullable(2)
void gc_get_chat_id(const GC_Chat *chat, uint8_t *dest);
-
/** Group callbacks */
non_null(1) nullable(2) void gc_callback_message(const Messenger *m, gc_message_cb *function);
non_null(1) nullable(2) void gc_callback_private_message(const Messenger *m, gc_private_message_cb *function);
@@ -779,4 +808,4 @@ GC_Chat *gc_get_group_by_public_key(const GC_Session *c, const uint8_t *public_k
non_null()
int gc_add_peers_from_announces(GC_Chat *chat, const GC_Announce *announces, uint8_t gc_announces_count);
-#endif // GROUP_CHATS_H
+#endif /* C_TOXCORE_TOXCORE_GROUP_CHATS_H */
diff --git a/protocols/Tox/libtox/src/toxcore/group_common.h b/protocols/Tox/libtox/src/toxcore/group_common.h
index ef901e8a3a..bb1e6f9a64 100644
--- a/protocols/Tox/libtox/src/toxcore/group_common.h
+++ b/protocols/Tox/libtox/src/toxcore/group_common.h
@@ -6,15 +6,21 @@
* Common groupchat data structures.
*/
-#ifndef GROUP_COMMON_H
-#define GROUP_COMMON_H
+#ifndef C_TOXCORE_TOXCORE_GROUP_COMMON_H
+#define C_TOXCORE_TOXCORE_GROUP_COMMON_H
#include <stdbool.h>
#include <stdint.h>
#include "DHT.h"
#include "TCP_connection.h"
+#include "attributes.h"
+#include "crypto_core.h"
#include "group_moderation.h"
+#include "logger.h"
+#include "mem.h"
+#include "mono_time.h"
+#include "network.h"
#define MAX_GC_PART_MESSAGE_SIZE 128
#define MAX_GC_NICK_SIZE 128
@@ -28,11 +34,13 @@
* For an explanation on why this value was chosen, see the following link: https://archive.ph/vsCOG
*/
#define MAX_GC_PACKET_CHUNK_SIZE 500
+/* Max size of an incoming packet chunk that is allowed */
+#define MAX_GC_PACKET_INCOMING_CHUNK_SIZE 1372
#define MAX_GC_MESSAGE_SIZE GROUP_MAX_MESSAGE_LENGTH
#define MAX_GC_MESSAGE_RAW_SIZE (MAX_GC_MESSAGE_SIZE + GC_MESSAGE_PSEUDO_ID_SIZE)
#define MAX_GC_CUSTOM_LOSSLESS_PACKET_SIZE 1373
-#define MAX_GC_CUSTOM_LOSSY_PACKET_SIZE MAX_GC_PACKET_CHUNK_SIZE
+#define MAX_GC_CUSTOM_LOSSY_PACKET_SIZE 1373
#define MAX_GC_PASSWORD_SIZE 32
#define MAX_GC_SAVED_INVITES 10
#define MAX_GC_PEERS_DEFAULT 100
@@ -71,7 +79,7 @@ typedef struct GC_Exit_Info {
} GC_Exit_Info;
typedef struct GC_PeerAddress {
- uint8_t public_key[EXT_PUBLIC_KEY_SIZE];
+ Extended_Public_Key public_key;
IP_Port ip_port;
} GC_PeerAddress;
@@ -131,6 +139,7 @@ typedef struct GC_Connection {
bool pending_key_rotation_request;
bool pending_delete; /* true if this peer has been marked for deletion */
+ bool delete_this_iteration; /* true if this peer should be deleted this do_gc() iteration*/
GC_Exit_Info exit_info;
} GC_Connection;
@@ -208,6 +217,15 @@ typedef struct GC_TimedOutPeer {
uint64_t last_reconn_try; // the last time we tried to establish a new connection
} GC_TimedOutPeer;
+typedef bitwise uint32_t GC_Peer_Id_Value;
+
+typedef struct GC_Peer_Id {
+ GC_Peer_Id_Value value;
+} GC_Peer_Id;
+
+GC_Peer_Id gc_peer_id_from_int(uint32_t value);
+uint32_t gc_peer_id_to_int(GC_Peer_Id peer_id);
+
typedef struct GC_Peer {
/* Below state is sent to other peers in peer info exchange */
uint8_t nick[MAX_GC_NICK_SIZE];
@@ -216,7 +234,7 @@ typedef struct GC_Peer {
/* Below state is local only */
Group_Role role;
- uint32_t peer_id; // permanent ID (used for the public API)
+ GC_Peer_Id peer_id; // permanent ID (used for the public API)
bool ignore;
GC_Connection gconn;
@@ -224,7 +242,7 @@ typedef struct GC_Peer {
typedef struct GC_SharedState {
uint32_t version;
- uint8_t founder_public_key[EXT_PUBLIC_KEY_SIZE];
+ Extended_Public_Key founder_public_key;
uint16_t maxpeers;
uint16_t group_name_len;
uint8_t group_name[MAX_GC_GROUP_NAME_SIZE];
@@ -247,6 +265,7 @@ typedef struct GC_TopicInfo {
typedef struct GC_Chat {
Mono_Time *mono_time;
const Logger *log;
+ const Memory *mem;
const Random *rng;
uint32_t connected_tcp_relays;
@@ -278,11 +297,11 @@ typedef struct GC_Chat {
uint32_t numpeers;
int group_number;
- uint8_t chat_public_key[EXT_PUBLIC_KEY_SIZE]; // the chat_id is the sig portion
- uint8_t chat_secret_key[EXT_SECRET_KEY_SIZE]; // only used by the founder
+ Extended_Public_Key chat_public_key; // the chat_id is the sig portion
+ Extended_Secret_Key chat_secret_key; // only used by the founder
- uint8_t self_public_key[EXT_PUBLIC_KEY_SIZE];
- uint8_t self_secret_key[EXT_SECRET_KEY_SIZE];
+ Extended_Public_Key self_public_key;
+ Extended_Secret_Key self_secret_key;
uint64_t time_connected;
uint64_t last_ping_interval;
@@ -291,7 +310,7 @@ typedef struct GC_Chat {
uint64_t last_time_peers_loaded;
/* keeps track of frequency of new inbound connections */
- uint8_t connection_O_metre;
+ uint8_t connection_o_metre;
uint64_t connection_cooldown_timer;
bool block_handshakes;
@@ -317,6 +336,8 @@ typedef struct GC_Chat {
uint8_t m_group_public_key[CRYPTO_PUBLIC_KEY_SIZE]; // public key for group's messenger friend connection
int friend_connection_id; // identifier for group's messenger friend connection
+
+ bool flag_exit; // true if the group will be deleted after the next do_gc() iteration
} GC_Chat;
#ifndef MESSENGER_DEFINED
@@ -324,34 +345,34 @@ typedef struct GC_Chat {
typedef struct Messenger Messenger;
#endif /* MESSENGER_DEFINED */
-typedef void gc_message_cb(const Messenger *m, uint32_t group_number, uint32_t peer_id, unsigned int type,
- const uint8_t *data, size_t length, uint32_t message_id, void *user_data);
-typedef void gc_private_message_cb(const Messenger *m, uint32_t group_number, uint32_t peer_id, unsigned int type,
- const uint8_t *data, size_t length, void *user_data);
-typedef void gc_custom_packet_cb(const Messenger *m, uint32_t group_number, uint32_t peer_id, const uint8_t *data,
+typedef void gc_message_cb(const Messenger *m, uint32_t group_number, GC_Peer_Id peer_id, unsigned int type,
+ const uint8_t *message, size_t length, uint32_t message_id, void *user_data);
+typedef void gc_private_message_cb(const Messenger *m, uint32_t group_number, GC_Peer_Id peer_id, unsigned int type,
+ const uint8_t *message, size_t length, void *user_data);
+typedef void gc_custom_packet_cb(const Messenger *m, uint32_t group_number, GC_Peer_Id peer_id, const uint8_t *data,
size_t length, void *user_data);
-typedef void gc_custom_private_packet_cb(const Messenger *m, uint32_t group_number, uint32_t peer_id,
- const uint8_t *data,
- size_t length, void *user_data);
-typedef void gc_moderation_cb(const Messenger *m, uint32_t group_number, uint32_t peer_id, uint32_t target_peer,
- unsigned int mod_event, void *user_data);
-typedef void gc_nick_change_cb(const Messenger *m, uint32_t group_number, uint32_t peer_id, const uint8_t *data,
+typedef void gc_custom_private_packet_cb(const Messenger *m, uint32_t group_number, GC_Peer_Id peer_id,
+ const uint8_t *data, size_t length, void *user_data);
+typedef void gc_moderation_cb(const Messenger *m, uint32_t group_number, GC_Peer_Id source_peer_number,
+ GC_Peer_Id target_peer_number, unsigned int mod_type, void *user_data);
+typedef void gc_nick_change_cb(const Messenger *m, uint32_t group_number, GC_Peer_Id peer_id, const uint8_t *name,
size_t length, void *user_data);
-typedef void gc_status_change_cb(const Messenger *m, uint32_t group_number, uint32_t peer_id, unsigned int status,
+typedef void gc_status_change_cb(const Messenger *m, uint32_t group_number, GC_Peer_Id peer_id, unsigned int status,
void *user_data);
-typedef void gc_topic_change_cb(const Messenger *m, uint32_t group_number, uint32_t peer_id, const uint8_t *data,
+typedef void gc_topic_change_cb(const Messenger *m, uint32_t group_number, GC_Peer_Id peer_id, const uint8_t *topic,
size_t length, void *user_data);
typedef void gc_topic_lock_cb(const Messenger *m, uint32_t group_number, unsigned int topic_lock, void *user_data);
typedef void gc_voice_state_cb(const Messenger *m, uint32_t group_number, unsigned int voice_state, void *user_data);
-typedef void gc_peer_limit_cb(const Messenger *m, uint32_t group_number, uint32_t max_peers, void *user_data);
-typedef void gc_privacy_state_cb(const Messenger *m, uint32_t group_number, unsigned int state, void *user_data);
-typedef void gc_password_cb(const Messenger *m, uint32_t group_number, const uint8_t *data, size_t length,
+typedef void gc_peer_limit_cb(const Messenger *m, uint32_t group_number, uint32_t peer_limit, void *user_data);
+typedef void gc_privacy_state_cb(const Messenger *m, uint32_t group_number, unsigned int privacy_state, void *user_data);
+typedef void gc_password_cb(const Messenger *m, uint32_t group_number, const uint8_t *password, size_t length,
void *user_data);
-typedef void gc_peer_join_cb(const Messenger *m, uint32_t group_number, uint32_t peer_id, void *user_data);
-typedef void gc_peer_exit_cb(const Messenger *m, uint32_t group_number, uint32_t peer_id, unsigned int exit_type,
- const uint8_t *nick, size_t nick_len, const uint8_t *data, size_t length, void *user_data);
+typedef void gc_peer_join_cb(const Messenger *m, uint32_t group_number, GC_Peer_Id peer_id, void *user_data);
+typedef void gc_peer_exit_cb(const Messenger *m, uint32_t group_number, GC_Peer_Id peer_id, unsigned int exit_type,
+ const uint8_t *name, size_t name_length, const uint8_t *part_message, size_t length,
+ void *user_data);
typedef void gc_self_join_cb(const Messenger *m, uint32_t group_number, void *user_data);
-typedef void gc_rejected_cb(const Messenger *m, uint32_t group_number, unsigned int type, void *user_data);
+typedef void gc_rejected_cb(const Messenger *m, uint32_t group_number, unsigned int fail_type, void *user_data);
typedef struct GC_Session {
Messenger *messenger;
@@ -398,7 +419,8 @@ int unpack_gc_saved_peers(GC_Chat *chat, const uint8_t *data, uint16_t length);
/** @brief Packs all valid entries from saved peerlist into `data`.
*
- * If `processed` is non-null it will be set to the length of the packed data.
+ * If `processed` is non-null it will be set to the length of the packed data
+ * on success, and will be untouched on error.
*
* Return the number of packed saved peers on success.
* Return -1 if buffer is too small.
@@ -406,4 +428,4 @@ int unpack_gc_saved_peers(GC_Chat *chat, const uint8_t *data, uint16_t length);
non_null(1, 2) nullable(4)
int pack_gc_saved_peers(const GC_Chat *chat, uint8_t *data, uint16_t length, uint16_t *processed);
-#endif // GROUP_COMMON_H
+#endif /* C_TOXCORE_TOXCORE_GROUP_COMMON_H */
diff --git a/protocols/Tox/libtox/src/toxcore/group_connection.c b/protocols/Tox/libtox/src/toxcore/group_connection.c
index 86c353c00c..1c2d1ec3da 100644
--- a/protocols/Tox/libtox/src/toxcore/group_connection.c
+++ b/protocols/Tox/libtox/src/toxcore/group_connection.c
@@ -15,15 +15,17 @@
#include <string.h>
#include "DHT.h"
+#include "TCP_connection.h"
+#include "attributes.h"
#include "ccompat.h"
#include "crypto_core.h"
#include "group_chats.h"
#include "group_common.h"
+#include "logger.h"
#include "mono_time.h"
+#include "network.h"
#include "util.h"
-#ifndef VANILLA_NACL
-
/** Seconds since last direct UDP packet was received before the connection is considered dead */
#define GCC_UDP_DIRECT_TIMEOUT (GC_PING_TIMEOUT + 4)
@@ -39,9 +41,7 @@ static bool array_entry_is_empty(const GC_Message_Array_Entry *array_entry)
non_null()
static void clear_array_entry(GC_Message_Array_Entry *const array_entry)
{
- if (array_entry->data != nullptr) {
- free(array_entry->data);
- }
+ free(array_entry->data);
*array_entry = (GC_Message_Array_Entry) {
nullptr
@@ -85,29 +85,43 @@ void gcc_set_recv_message_id(GC_Connection *gconn, uint64_t id)
/** @brief Puts packet data in array_entry.
*
+ * Requires an empty array entry to be passed, and must not modify the passed
+ * array entry on error.
+ *
* Return true on success.
*/
-non_null(1, 2) nullable(3)
-static bool create_array_entry(const Mono_Time *mono_time, GC_Message_Array_Entry *array_entry, const uint8_t *data,
- uint16_t length, uint8_t packet_type, uint64_t message_id)
+non_null(1, 2, 3) nullable(4)
+static bool create_array_entry(const Logger *log, const Mono_Time *mono_time, GC_Message_Array_Entry *array_entry,
+ const uint8_t *data, uint16_t length, uint8_t packet_type, uint64_t message_id)
{
- if (length > 0) {
- if (data == nullptr) {
+ if (!array_entry_is_empty(array_entry)) {
+ LOGGER_WARNING(log, "Failed to create array entry; entry is not empty.");
+ return false;
+ }
+
+ if (length == 0) {
+ array_entry->data = nullptr;
+ array_entry->data_length = 0;
+ } else {
+ if (data == nullptr) { // should never happen
+ LOGGER_FATAL(log, "Got null data with non-zero length (length: %u, type %u)",
+ length, packet_type);
return false;
}
- array_entry->data = (uint8_t *)malloc(sizeof(uint8_t) * length);
+ uint8_t *entry_data = (uint8_t *)malloc(length);
- if (array_entry->data == nullptr) {
+ if (entry_data == nullptr) {
return false;
}
- memcpy(array_entry->data, data, length);
+ memcpy(entry_data, data, length);
+ array_entry->data = entry_data;
+ array_entry->data_length = length;
}
const uint64_t tm = mono_time_get(mono_time);
- array_entry->data_length = length;
array_entry->packet_type = packet_type;
array_entry->message_id = message_id;
array_entry->time_added = tm;
@@ -118,7 +132,7 @@ static bool create_array_entry(const Mono_Time *mono_time, GC_Message_Array_Entr
/** @brief Adds data of length to gconn's send_array.
*
- * Returns true on success and increments gconn's send_message_id.
+ * Returns true and increments gconn's send_message_id on success.
*/
non_null(1, 2, 3) nullable(4)
static bool add_to_send_array(const Logger *log, const Mono_Time *mono_time, GC_Connection *gconn, const uint8_t *data,
@@ -133,13 +147,7 @@ static bool add_to_send_array(const Logger *log, const Mono_Time *mono_time, GC_
const uint16_t idx = gcc_get_array_index(gconn->send_message_id);
GC_Message_Array_Entry *array_entry = &gconn->send_array[idx];
- if (!array_entry_is_empty(array_entry)) {
- LOGGER_DEBUG(log, "Send array entry isn't empty");
- return false;
- }
-
- if (!create_array_entry(mono_time, array_entry, data, length, packet_type, gconn->send_message_id)) {
- LOGGER_WARNING(log, "Failed to create array entry");
+ if (!create_array_entry(log, mono_time, array_entry, data, length, packet_type, gconn->send_message_id)) {
return false;
}
@@ -158,15 +166,21 @@ int gcc_send_lossless_packet(const GC_Chat *chat, GC_Connection *gconn, const ui
return -1;
}
- if (!gcc_encrypt_and_send_lossless_packet(chat, gconn, data, length, message_id, packet_type)) {
- LOGGER_DEBUG(chat->log, "Failed to send payload: (type: 0x%02x, length: %d)", packet_type, length);
+ // If the packet fails to wrap/encrypt, we remove it from the send array, since trying to-resend
+ // the same bad packet probably won't help much. Otherwise we don't care if it doesn't successfully
+ // send through the wire as it will keep retrying until the connection times out.
+ if (gcc_encrypt_and_send_lossless_packet(chat, gconn, data, length, message_id, packet_type) == -1) {
+ const uint16_t idx = gcc_get_array_index(message_id);
+ GC_Message_Array_Entry *array_entry = &gconn->send_array[idx];
+ clear_array_entry(array_entry);
+ gconn->send_message_id = message_id;
+ LOGGER_ERROR(chat->log, "Failed to encrypt payload: (type: 0x%02x, length: %d)", packet_type, length);
return -2;
}
return 0;
}
-
bool gcc_send_lossless_packet_fragments(const GC_Chat *chat, GC_Connection *gconn, const uint8_t *data,
uint16_t length, uint8_t packet_type)
{
@@ -211,7 +225,7 @@ bool gcc_send_lossless_packet_fragments(const GC_Chat *chat, GC_Connection *gcon
const uint16_t end_idx = gcc_get_array_index(gconn->send_message_id);
for (uint16_t i = start_idx; i != end_idx; i = (i + 1) % GCC_BUFFER_SIZE) {
- GC_Message_Array_Entry *entry = &gconn->send_array[i];
+ const GC_Message_Array_Entry *entry = &gconn->send_array[i];
if (array_entry_is_empty(entry)) {
LOGGER_FATAL(chat->log, "array entry for packet chunk is empty");
@@ -330,17 +344,7 @@ static bool store_in_recv_array(const Logger *log, const Mono_Time *mono_time, G
const uint16_t idx = gcc_get_array_index(message_id);
GC_Message_Array_Entry *ary_entry = &gconn->recv_array[idx];
- if (!array_entry_is_empty(ary_entry)) {
- LOGGER_DEBUG(log, "Recv array is not empty");
- return false;
- }
-
- if (!create_array_entry(mono_time, ary_entry, data, length, packet_type, message_id)) {
- LOGGER_WARNING(log, "Failed to create array entry");
- return false;
- }
-
- return true;
+ return create_array_entry(log, mono_time, ary_entry, data, length, packet_type, message_id);
}
/**
@@ -366,7 +370,7 @@ static uint16_t reassemble_packet(const Logger *log, GC_Connection *gconn, uint8
// search backwards in recv array until we find an empty slot or a non-fragment packet type
while (!array_entry_is_empty(entry) && entry->packet_type == GP_FRAGMENT) {
assert(entry->data != nullptr);
- assert(entry->data_length <= MAX_GC_PACKET_CHUNK_SIZE);
+ assert(entry->data_length <= MAX_GC_PACKET_INCOMING_CHUNK_SIZE);
const uint16_t diff = packet_length + entry->data_length;
@@ -391,10 +395,9 @@ static uint16_t reassemble_packet(const Logger *log, GC_Connection *gconn, uint8
return 0;
}
- assert(*payload == nullptr);
- *payload = (uint8_t *)malloc(packet_length);
+ uint8_t *tmp_payload = (uint8_t *)malloc(packet_length);
- if (*payload == nullptr) {
+ if (tmp_payload == nullptr) {
LOGGER_ERROR(log, "Failed to allocate %u bytes for payload buffer", packet_length);
return 0;
}
@@ -408,12 +411,15 @@ static uint16_t reassemble_packet(const Logger *log, GC_Connection *gconn, uint8
entry = &gconn->recv_array[i];
assert(processed + entry->data_length <= packet_length);
- memcpy(*payload + processed, entry->data, entry->data_length);
+ memcpy(tmp_payload + processed, entry->data, entry->data_length);
processed += entry->data_length;
clear_array_entry(entry);
}
+ assert(*payload == nullptr);
+ *payload = tmp_payload;
+
return processed;
}
@@ -433,7 +439,7 @@ int gcc_handle_packet_fragment(const GC_Session *c, GC_Chat *chat, uint32_t peer
}
uint8_t sender_pk[ENC_PUBLIC_KEY_SIZE];
- memcpy(sender_pk, get_enc_key(gconn->addr.public_key), ENC_PUBLIC_KEY_SIZE);
+ memcpy(sender_pk, get_enc_key(&gconn->addr.public_key), ENC_PUBLIC_KEY_SIZE);
uint8_t *payload = nullptr;
const uint16_t processed_len = reassemble_packet(chat->log, gconn, &payload, message_id);
@@ -453,6 +459,7 @@ int gcc_handle_packet_fragment(const GC_Session *c, GC_Chat *chat, uint32_t peer
gconn = get_gc_connection(chat, peer_number);
if (gconn == nullptr) {
+ free(payload);
return 0;
}
@@ -506,7 +513,7 @@ static bool process_recv_array_entry(const GC_Session *c, GC_Chat *chat, GC_Conn
GC_Message_Array_Entry *const array_entry, void *userdata)
{
uint8_t sender_pk[ENC_PUBLIC_KEY_SIZE];
- memcpy(sender_pk, get_enc_key(gconn->addr.public_key), ENC_PUBLIC_KEY_SIZE);
+ memcpy(sender_pk, get_enc_key(&gconn->addr.public_key), ENC_PUBLIC_KEY_SIZE);
const bool ret = handle_gc_lossless_helper(c, chat, peer_number, array_entry->data, array_entry->data_length,
array_entry->packet_type, userdata);
@@ -610,7 +617,7 @@ bool gcc_send_packet(const GC_Chat *chat, const GC_Connection *gconn, const uint
return ret == 0 || direct_send_attempt;
}
-bool gcc_encrypt_and_send_lossless_packet(const GC_Chat *chat, const GC_Connection *gconn, const uint8_t *data,
+int gcc_encrypt_and_send_lossless_packet(const GC_Chat *chat, const GC_Connection *gconn, const uint8_t *data,
uint16_t length, uint64_t message_id, uint8_t packet_type)
{
const uint16_t packet_size = gc_get_wrapped_packet_size(length, NET_PACKET_GC_LOSSLESS);
@@ -618,28 +625,28 @@ bool gcc_encrypt_and_send_lossless_packet(const GC_Chat *chat, const GC_Connecti
if (packet == nullptr) {
LOGGER_ERROR(chat->log, "Failed to allocate memory for packet buffer");
- return false;
+ return -1;
}
const int enc_len = group_packet_wrap(
- chat->log, chat->rng, chat->self_public_key, gconn->session_shared_key, packet,
+ chat->log, chat->rng, chat->self_public_key.enc, gconn->session_shared_key, packet,
packet_size, data, length, message_id, packet_type, NET_PACKET_GC_LOSSLESS);
if (enc_len < 0) {
LOGGER_ERROR(chat->log, "Failed to wrap packet (type: 0x%02x, error: %d)", packet_type, enc_len);
free(packet);
- return false;
+ return -1;
}
if (!gcc_send_packet(chat, gconn, packet, (uint16_t)enc_len)) {
LOGGER_DEBUG(chat->log, "Failed to send packet (type: 0x%02x, enc_len: %d)", packet_type, enc_len);
free(packet);
- return false;
+ return -2;
}
free(packet);
- return true;
+ return 0;
}
void gcc_make_session_shared_key(GC_Connection *gconn, const uint8_t *sender_pk)
@@ -703,5 +710,3 @@ void gcc_cleanup(const GC_Chat *chat)
gcc_peer_cleanup(gconn);
}
}
-
-#endif // VANILLA_NACL
diff --git a/protocols/Tox/libtox/src/toxcore/group_connection.h b/protocols/Tox/libtox/src/toxcore/group_connection.h
index 2202c7ab36..4a9ccad0b3 100644
--- a/protocols/Tox/libtox/src/toxcore/group_connection.h
+++ b/protocols/Tox/libtox/src/toxcore/group_connection.h
@@ -7,10 +7,17 @@
* An implementation of massive text only group chats.
*/
-#ifndef GROUP_CONNECTION_H
-#define GROUP_CONNECTION_H
+#ifndef C_TOXCORE_TOXCORE_GROUP_CONNECTION_H
+#define C_TOXCORE_TOXCORE_GROUP_CONNECTION_H
+#include "DHT.h"
+#include "TCP_connection.h"
+#include "attributes.h"
+#include "crypto_core.h"
#include "group_common.h"
+#include "logger.h"
+#include "mono_time.h"
+#include "network.h"
/* Max number of TCP relays we share with a peer on handshake */
#define GCC_MAX_TCP_SHARED_RELAYS 3
@@ -143,11 +150,11 @@ bool gcc_send_packet(const GC_Chat *chat, const GC_Connection *gconn, const uint
/** @brief Sends a lossless packet to `gconn` comprised of `data` of size `length`.
*
* This function will add the packet to the lossless send array, encrypt/wrap it using the
- * shared key associated with `gconn`, and send it over the wire.
+ * shared key associated with `gconn`, and try to send it over the wire.
*
- * Return 0 on success.
+ * Return 0 if the packet was successfully encrypted and added to the send array.
* Return -1 if the packet couldn't be added to the send array.
- * Return -2 if the packet failed to be encrypted or failed to send.
+ * Return -2 if the packet failed to be wrapped or encrypted.
*/
non_null(1, 2) nullable(3)
int gcc_send_lossless_packet(const GC_Chat *chat, GC_Connection *gconn, const uint8_t *data, uint16_t length,
@@ -166,16 +173,17 @@ non_null()
bool gcc_send_lossless_packet_fragments(const GC_Chat *chat, GC_Connection *gconn, const uint8_t *data,
uint16_t length, uint8_t packet_type);
-
/** @brief Encrypts `data` of `length` bytes, designated by `message_id`, using the shared key
* associated with `gconn` and sends lossless packet over the wire.
*
* This function does not add the packet to the send array.
*
- * Return true on success.
+ * Return 0 on success.
+ * Return -1 if packet wrapping and encryption fails.
+ * Return -2 if the packet fails to send.
*/
non_null(1, 2) nullable(3)
-bool gcc_encrypt_and_send_lossless_packet(const GC_Chat *chat, const GC_Connection *gconn, const uint8_t *data,
+int gcc_encrypt_and_send_lossless_packet(const GC_Chat *chat, const GC_Connection *gconn, const uint8_t *data,
uint16_t length, uint64_t message_id, uint8_t packet_type);
/** @brief Called when a peer leaves the group. */
@@ -186,4 +194,4 @@ void gcc_peer_cleanup(GC_Connection *gconn);
non_null()
void gcc_cleanup(const GC_Chat *chat);
-#endif // GROUP_CONNECTION_H
+#endif /* C_TOXCORE_TOXCORE_GROUP_CONNECTION_H */
diff --git a/protocols/Tox/libtox/src/toxcore/group_moderation.c b/protocols/Tox/libtox/src/toxcore/group_moderation.c
index b16c397cbe..3cb69e9403 100644
--- a/protocols/Tox/libtox/src/toxcore/group_moderation.c
+++ b/protocols/Tox/libtox/src/toxcore/group_moderation.c
@@ -15,9 +15,11 @@
#include <string.h>
#include <time.h>
+#include "DHT.h"
+#include "attributes.h"
#include "ccompat.h"
#include "crypto_core.h"
-#include "mono_time.h"
+#include "logger.h"
#include "network.h"
#include "util.h"
@@ -58,14 +60,16 @@ int mod_list_unpack(Moderation *moderation, const uint8_t *data, uint16_t length
uint16_t unpacked_len = 0;
for (uint16_t i = 0; i < num_mods; ++i) {
- tmp_list[i] = (uint8_t *)malloc(sizeof(uint8_t) * MOD_LIST_ENTRY_SIZE);
+ uint8_t *entry = (uint8_t *)malloc(MOD_LIST_ENTRY_SIZE);
- if (tmp_list[i] == nullptr) {
- free_uint8_t_pointer_array(tmp_list, i);
+ if (entry == nullptr) {
+ free_uint8_t_pointer_array(moderation->mem, tmp_list, i);
return -1;
}
- memcpy(tmp_list[i], &data[i * MOD_LIST_ENTRY_SIZE], MOD_LIST_ENTRY_SIZE);
+ memcpy(entry, &data[i * MOD_LIST_ENTRY_SIZE], MOD_LIST_ENTRY_SIZE);
+ tmp_list[i] = entry;
+
unpacked_len += MOD_LIST_ENTRY_SIZE;
}
@@ -90,7 +94,7 @@ void mod_list_get_data_hash(uint8_t *hash, const uint8_t *packed_mod_list, uint1
bool mod_list_make_hash(const Moderation *moderation, uint8_t *hash)
{
if (moderation->num_mods == 0) {
- memset(hash, 0, MOD_MODERATION_HASH_SIZE);
+ memzero(hash, MOD_MODERATION_HASH_SIZE);
return true;
}
@@ -207,13 +211,15 @@ bool mod_list_add_entry(Moderation *moderation, const uint8_t *mod_data)
moderation->mod_list = tmp_list;
- tmp_list[moderation->num_mods] = (uint8_t *)malloc(sizeof(uint8_t) * MOD_LIST_ENTRY_SIZE);
+ uint8_t *entry = (uint8_t *)malloc(MOD_LIST_ENTRY_SIZE);
- if (tmp_list[moderation->num_mods] == nullptr) {
+ if (entry == nullptr) {
return false;
}
- memcpy(tmp_list[moderation->num_mods], mod_data, MOD_LIST_ENTRY_SIZE);
+ memcpy(entry, mod_data, MOD_LIST_ENTRY_SIZE);
+
+ tmp_list[moderation->num_mods] = entry;
++moderation->num_mods;
return true;
@@ -221,7 +227,7 @@ bool mod_list_add_entry(Moderation *moderation, const uint8_t *mod_data)
void mod_list_cleanup(Moderation *moderation)
{
- free_uint8_t_pointer_array(moderation->mod_list, moderation->num_mods);
+ free_uint8_t_pointer_array(moderation->mem, moderation->mod_list, moderation->num_mods);
moderation->num_mods = 0;
moderation->mod_list = nullptr;
}
@@ -230,15 +236,15 @@ uint16_t sanctions_creds_pack(const Mod_Sanction_Creds *creds, uint8_t *data)
{
uint16_t packed_len = 0;
- net_pack_u32(data + packed_len, creds->version);
+ net_pack_u32(&data[packed_len], creds->version);
packed_len += sizeof(uint32_t);
- memcpy(data + packed_len, creds->hash, MOD_SANCTION_HASH_SIZE);
+ memcpy(&data[packed_len], creds->hash, MOD_SANCTION_HASH_SIZE);
packed_len += MOD_SANCTION_HASH_SIZE;
- net_pack_u16(data + packed_len, creds->checksum);
+ net_pack_u16(&data[packed_len], creds->checksum);
packed_len += sizeof(uint16_t);
- memcpy(data + packed_len, creds->sig_pk, SIG_PUBLIC_KEY_SIZE);
+ memcpy(&data[packed_len], creds->sig_pk, SIG_PUBLIC_KEY_SIZE);
packed_len += SIG_PUBLIC_KEY_SIZE;
- memcpy(data + packed_len, creds->sig, SIGNATURE_SIZE);
+ memcpy(&data[packed_len], creds->sig, SIGNATURE_SIZE);
packed_len += SIGNATURE_SIZE;
return packed_len;
@@ -262,11 +268,11 @@ int sanctions_list_pack(uint8_t *data, uint16_t length, const Mod_Sanction *sanc
return -1;
}
- memcpy(data + packed_len, &sanctions[i].type, sizeof(uint8_t));
+ memcpy(&data[packed_len], &sanctions[i].type, sizeof(uint8_t));
packed_len += sizeof(uint8_t);
- memcpy(data + packed_len, sanctions[i].setter_public_sig_key, SIG_PUBLIC_KEY_SIZE);
+ memcpy(&data[packed_len], sanctions[i].setter_public_sig_key, SIG_PUBLIC_KEY_SIZE);
packed_len += SIG_PUBLIC_KEY_SIZE;
- net_pack_u64(data + packed_len, sanctions[i].time_set);
+ net_pack_u64(&data[packed_len], sanctions[i].time_set);
packed_len += TIME_STAMP_SIZE;
const uint8_t sanctions_type = sanctions[i].type;
@@ -276,7 +282,7 @@ int sanctions_list_pack(uint8_t *data, uint16_t length, const Mod_Sanction *sanc
return -1;
}
- memcpy(data + packed_len, sanctions[i].target_public_enc_key, ENC_PUBLIC_KEY_SIZE);
+ memcpy(&data[packed_len], sanctions[i].target_public_enc_key, ENC_PUBLIC_KEY_SIZE);
packed_len += ENC_PUBLIC_KEY_SIZE;
} else {
return -1;
@@ -287,7 +293,7 @@ int sanctions_list_pack(uint8_t *data, uint16_t length, const Mod_Sanction *sanc
}
/* Signature must be packed last */
- memcpy(data + packed_len, sanctions[i].signature, SIGNATURE_SIZE);
+ memcpy(&data[packed_len], sanctions[i].signature, SIGNATURE_SIZE);
packed_len += SIGNATURE_SIZE;
}
@@ -299,28 +305,28 @@ int sanctions_list_pack(uint8_t *data, uint16_t length, const Mod_Sanction *sanc
return -1;
}
- const uint16_t cred_len = sanctions_creds_pack(creds, data + packed_len);
+ const uint16_t cred_len = sanctions_creds_pack(creds, &data[packed_len]);
if (cred_len != MOD_SANCTIONS_CREDS_SIZE) {
return -1;
}
- return (int)(packed_len + cred_len);
+ return packed_len + cred_len;
}
uint16_t sanctions_creds_unpack(Mod_Sanction_Creds *creds, const uint8_t *data)
{
uint16_t len_processed = 0;
- net_unpack_u32(data + len_processed, &creds->version);
+ net_unpack_u32(&data[len_processed], &creds->version);
len_processed += sizeof(uint32_t);
- memcpy(creds->hash, data + len_processed, MOD_SANCTION_HASH_SIZE);
+ memcpy(creds->hash, &data[len_processed], MOD_SANCTION_HASH_SIZE);
len_processed += MOD_SANCTION_HASH_SIZE;
- net_unpack_u16(data + len_processed, &creds->checksum);
+ net_unpack_u16(&data[len_processed], &creds->checksum);
len_processed += sizeof(uint16_t);
- memcpy(creds->sig_pk, data + len_processed, SIG_PUBLIC_KEY_SIZE);
+ memcpy(creds->sig_pk, &data[len_processed], SIG_PUBLIC_KEY_SIZE);
len_processed += SIG_PUBLIC_KEY_SIZE;
- memcpy(creds->sig, data + len_processed, SIGNATURE_SIZE);
+ memcpy(creds->sig, &data[len_processed], SIGNATURE_SIZE);
len_processed += SIGNATURE_SIZE;
return len_processed;
@@ -337,11 +343,11 @@ int sanctions_list_unpack(Mod_Sanction *sanctions, Mod_Sanction_Creds *creds, ui
return -1;
}
- memcpy(&sanctions[num].type, data + len_processed, sizeof(uint8_t));
+ memcpy(&sanctions[num].type, &data[len_processed], sizeof(uint8_t));
len_processed += sizeof(uint8_t);
- memcpy(sanctions[num].setter_public_sig_key, data + len_processed, SIG_PUBLIC_KEY_SIZE);
+ memcpy(sanctions[num].setter_public_sig_key, &data[len_processed], SIG_PUBLIC_KEY_SIZE);
len_processed += SIG_PUBLIC_KEY_SIZE;
- net_unpack_u64(data + len_processed, &sanctions[num].time_set);
+ net_unpack_u64(&data[len_processed], &sanctions[num].time_set);
len_processed += TIME_STAMP_SIZE;
if (sanctions[num].type == SA_OBSERVER) {
@@ -349,7 +355,7 @@ int sanctions_list_unpack(Mod_Sanction *sanctions, Mod_Sanction_Creds *creds, ui
return -1;
}
- memcpy(sanctions[num].target_public_enc_key, data + len_processed, ENC_PUBLIC_KEY_SIZE);
+ memcpy(sanctions[num].target_public_enc_key, &data[len_processed], ENC_PUBLIC_KEY_SIZE);
len_processed += ENC_PUBLIC_KEY_SIZE;
} else {
return -1;
@@ -359,7 +365,7 @@ int sanctions_list_unpack(Mod_Sanction *sanctions, Mod_Sanction_Creds *creds, ui
return -1;
}
- memcpy(sanctions[num].signature, data + len_processed, SIGNATURE_SIZE);
+ memcpy(sanctions[num].signature, &data[len_processed], SIGNATURE_SIZE);
len_processed += SIGNATURE_SIZE;
++num;
@@ -377,7 +383,7 @@ int sanctions_list_unpack(Mod_Sanction *sanctions, Mod_Sanction_Creds *creds, ui
return num;
}
- const uint16_t creds_len = sanctions_creds_unpack(creds, data + len_processed);
+ const uint16_t creds_len = sanctions_creds_unpack(creds, &data[len_processed]);
if (creds_len != MOD_SANCTIONS_CREDS_SIZE) {
return -1;
@@ -390,7 +396,6 @@ int sanctions_list_unpack(Mod_Sanction *sanctions, Mod_Sanction_Creds *creds, ui
return num;
}
-
/** @brief Creates a new sanction list hash and puts it in hash.
*
* The hash is derived from the signature of all entries plus the version number.
@@ -405,7 +410,7 @@ static bool sanctions_list_make_hash(const Mod_Sanction *sanctions, uint32_t new
uint8_t *hash)
{
if (num_sanctions == 0 || sanctions == nullptr) {
- memset(hash, 0, MOD_SANCTION_HASH_SIZE);
+ memzero(hash, MOD_SANCTION_HASH_SIZE);
return true;
}
@@ -457,7 +462,7 @@ static bool sanctions_list_validate_entry(const Moderation *moderation, const Mo
uint8_t packed_data[MOD_SANCTION_PACKED_SIZE];
const int packed_len = sanctions_list_pack(packed_data, sizeof(packed_data), sanction, 1, nullptr);
- if (packed_len <= (int) SIGNATURE_SIZE) {
+ if (packed_len <= SIGNATURE_SIZE) {
return false;
}
@@ -785,7 +790,7 @@ static bool sanctions_list_sign_entry(const Moderation *moderation, Mod_Sanction
uint8_t packed_data[MOD_SANCTION_PACKED_SIZE];
const int packed_len = sanctions_list_pack(packed_data, sizeof(packed_data), sanction, 1, nullptr);
- if (packed_len <= (int) SIGNATURE_SIZE) {
+ if (packed_len <= SIGNATURE_SIZE) {
LOGGER_ERROR(moderation->log, "Failed to pack sanctions list: %d", packed_len);
return false;
}
@@ -859,9 +864,7 @@ uint16_t sanctions_list_replace_sig(Moderation *moderation, const uint8_t *publi
void sanctions_list_cleanup(Moderation *moderation)
{
- if (moderation->sanctions != nullptr) {
- free(moderation->sanctions);
- }
+ free(moderation->sanctions);
moderation->sanctions = nullptr;
moderation->num_sanctions = 0;
diff --git a/protocols/Tox/libtox/src/toxcore/group_moderation.h b/protocols/Tox/libtox/src/toxcore/group_moderation.h
index 8b2a73869a..eeab32fc0a 100644
--- a/protocols/Tox/libtox/src/toxcore/group_moderation.h
+++ b/protocols/Tox/libtox/src/toxcore/group_moderation.h
@@ -14,7 +14,10 @@
#include <stdint.h>
#include "DHT.h"
+#include "attributes.h"
+#include "crypto_core.h"
#include "logger.h"
+#include "mem.h"
#ifdef __cplusplus
extern "C" {
@@ -78,6 +81,7 @@ typedef struct Mod_Sanction {
} Mod_Sanction;
typedef struct Moderation {
+ const Memory *mem;
const Logger *log;
Mod_Sanction *sanctions;
@@ -290,7 +294,7 @@ non_null()
void sanctions_list_cleanup(Moderation *moderation);
#ifdef __cplusplus
-} // extern "C"
+} /* extern "C" */
#endif
-#endif // C_TOXCORE_TOXCORE_GROUP_MODERATION_H
+#endif /* C_TOXCORE_TOXCORE_GROUP_MODERATION_H */
diff --git a/protocols/Tox/libtox/src/toxcore/group_onion_announce.c b/protocols/Tox/libtox/src/toxcore/group_onion_announce.c
index b797770e52..d05db09a07 100644
--- a/protocols/Tox/libtox/src/toxcore/group_onion_announce.c
+++ b/protocols/Tox/libtox/src/toxcore/group_onion_announce.c
@@ -8,7 +8,16 @@
#include <assert.h>
#include <string.h>
+#include "DHT.h"
+#include "attributes.h"
#include "ccompat.h"
+#include "crypto_core.h"
+#include "group_announce.h"
+#include "logger.h"
+#include "mono_time.h"
+#include "network.h"
+#include "onion_announce.h"
+#include "timed_auth.h"
static_assert(GCA_ANNOUNCE_MAX_SIZE <= ONION_MAX_EXTRA_DATA_SIZE,
"GC_Announce does not fit into the onion packet extra data");
@@ -66,8 +75,6 @@ void gca_onion_init(GC_Announces_List *group_announce, Onion_Announce *onion_a)
group_announce);
}
-#ifndef VANILLA_NACL
-
int create_gca_announce_request(
const Random *rng, uint8_t *packet, uint16_t max_packet_length, const uint8_t *dest_client_id,
const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *ping_id,
@@ -112,4 +119,3 @@ int create_gca_announce_request(
return full_length;
}
-#endif // VANILLA_NACL
diff --git a/protocols/Tox/libtox/src/toxcore/group_onion_announce.h b/protocols/Tox/libtox/src/toxcore/group_onion_announce.h
index 5c6d64ec59..5fbac02e0a 100644
--- a/protocols/Tox/libtox/src/toxcore/group_onion_announce.h
+++ b/protocols/Tox/libtox/src/toxcore/group_onion_announce.h
@@ -6,6 +6,8 @@
#ifndef C_TOXCORE_TOXCORE_GROUP_ONION_ANNOUNCE_H
#define C_TOXCORE_TOXCORE_GROUP_ONION_ANNOUNCE_H
+#include "attributes.h"
+#include "crypto_core.h"
#include "group_announce.h"
#include "onion_announce.h"
@@ -19,4 +21,4 @@ int create_gca_announce_request(
const uint8_t *client_id, const uint8_t *data_public_key, uint64_t sendback_data,
const uint8_t *gc_data, uint16_t gc_data_length);
-#endif // C_TOXCORE_TOXCORE_GROUP_ONION_ANNOUNCE_H
+#endif /* C_TOXCORE_TOXCORE_GROUP_ONION_ANNOUNCE_H */
diff --git a/protocols/Tox/libtox/src/toxcore/group_pack.c b/protocols/Tox/libtox/src/toxcore/group_pack.c
index ecdd965610..e3af82c67a 100644
--- a/protocols/Tox/libtox/src/toxcore/group_pack.c
+++ b/protocols/Tox/libtox/src/toxcore/group_pack.c
@@ -9,20 +9,72 @@
#include "group_pack.h"
-#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
+#include "DHT.h"
+#include "attributes.h"
#include "bin_pack.h"
#include "bin_unpack.h"
#include "ccompat.h"
+#include "crypto_core.h"
+#include "crypto_core_pack.h"
+#include "group_common.h"
+#include "group_moderation.h"
+#include "logger.h"
+#include "network.h"
#include "util.h"
+bool group_privacy_state_from_int(uint8_t value, Group_Privacy_State *out)
+{
+ switch (value) {
+ case GI_PUBLIC: {
+ *out = GI_PUBLIC;
+ return true;
+ }
+
+ case GI_PRIVATE: {
+ *out = GI_PRIVATE;
+ return true;
+ }
+
+ default: {
+ *out = GI_PUBLIC;
+ return false;
+ }
+ }
+}
+
+bool group_voice_state_from_int(uint8_t value, Group_Voice_State *out)
+{
+ switch (value) {
+ case GV_ALL: {
+ *out = GV_ALL;
+ return true;
+ }
+
+ case GV_MODS: {
+ *out = GV_MODS;
+ return true;
+ }
+
+ case GV_FOUNDER: {
+ *out = GV_FOUNDER;
+ return true;
+ }
+
+ default: {
+ *out = GV_ALL;
+ return false;
+ }
+ }
+}
+
non_null()
static bool load_unpack_state_values(GC_Chat *chat, Bin_Unpack *bu)
{
- if (!bin_unpack_array_fixed(bu, 8)) {
+ if (!bin_unpack_array_fixed(bu, 8, nullptr)) {
LOGGER_ERROR(chat->log, "Group state values array malformed");
return false;
}
@@ -44,8 +96,8 @@ static bool load_unpack_state_values(GC_Chat *chat, Bin_Unpack *bu)
}
chat->connection_state = manually_disconnected ? CS_DISCONNECTED : CS_CONNECTING;
- chat->shared_state.privacy_state = (Group_Privacy_State)privacy_state;
- chat->shared_state.voice_state = (Group_Voice_State)voice_state;
+ group_privacy_state_from_int(privacy_state, &chat->shared_state.privacy_state);
+ group_voice_state_from_int(voice_state, &chat->shared_state.voice_state);
// we always load saved groups as private in case the group became private while we were offline.
// this will have no detrimental effect if the group is public, as the correct privacy
@@ -58,15 +110,23 @@ static bool load_unpack_state_values(GC_Chat *chat, Bin_Unpack *bu)
non_null()
static bool load_unpack_state_bin(GC_Chat *chat, Bin_Unpack *bu)
{
- if (!bin_unpack_array_fixed(bu, 5)) {
+ if (!bin_unpack_array_fixed(bu, 5, nullptr)) {
LOGGER_ERROR(chat->log, "Group state binary array malformed");
return false;
}
- if (!(bin_unpack_bin_fixed(bu, chat->shared_state_sig, SIGNATURE_SIZE)
- && bin_unpack_bin_fixed(bu, chat->shared_state.founder_public_key, EXT_PUBLIC_KEY_SIZE)
- && bin_unpack_bin_fixed(bu, chat->shared_state.group_name, chat->shared_state.group_name_len)
- && bin_unpack_bin_fixed(bu, chat->shared_state.password, chat->shared_state.password_length)
+ if (!bin_unpack_bin_fixed(bu, chat->shared_state_sig, SIGNATURE_SIZE)) {
+ LOGGER_ERROR(chat->log, "Failed to unpack shared state signature");
+ return false;
+ }
+
+ if (!unpack_extended_public_key(&chat->shared_state.founder_public_key, bu)) {
+ LOGGER_ERROR(chat->log, "Failed to unpack founder public key");
+ return false;
+ }
+
+ if (!(bin_unpack_bin_max(bu, chat->shared_state.group_name, &chat->shared_state.group_name_len, sizeof(chat->shared_state.group_name))
+ && bin_unpack_bin_max(bu, chat->shared_state.password, &chat->shared_state.password_length, sizeof(chat->shared_state.password))
&& bin_unpack_bin_fixed(bu, chat->shared_state.mod_list_hash, MOD_MODERATION_HASH_SIZE))) {
LOGGER_ERROR(chat->log, "Failed to unpack state binary data");
return false;
@@ -78,7 +138,7 @@ static bool load_unpack_state_bin(GC_Chat *chat, Bin_Unpack *bu)
non_null()
static bool load_unpack_topic_info(GC_Chat *chat, Bin_Unpack *bu)
{
- if (!bin_unpack_array_fixed(bu, 6)) {
+ if (!bin_unpack_array_fixed(bu, 6, nullptr)) {
LOGGER_ERROR(chat->log, "Group topic array malformed");
return false;
}
@@ -86,7 +146,7 @@ static bool load_unpack_topic_info(GC_Chat *chat, Bin_Unpack *bu)
if (!(bin_unpack_u32(bu, &chat->topic_info.version)
&& bin_unpack_u16(bu, &chat->topic_info.length)
&& bin_unpack_u16(bu, &chat->topic_info.checksum)
- && bin_unpack_bin_fixed(bu, chat->topic_info.topic, chat->topic_info.length)
+ && bin_unpack_bin_max(bu, chat->topic_info.topic, &chat->topic_info.length, sizeof(chat->topic_info.topic))
&& bin_unpack_bin_fixed(bu, chat->topic_info.public_sig_key, SIG_PUBLIC_KEY_SIZE)
&& bin_unpack_bin_fixed(bu, chat->topic_sig, SIGNATURE_SIZE))) {
LOGGER_ERROR(chat->log, "Failed to unpack topic info");
@@ -99,8 +159,9 @@ static bool load_unpack_topic_info(GC_Chat *chat, Bin_Unpack *bu)
non_null()
static bool load_unpack_mod_list(GC_Chat *chat, Bin_Unpack *bu)
{
- if (!bin_unpack_array_fixed(bu, 2)) {
- LOGGER_ERROR(chat->log, "Group mod list array malformed");
+ uint32_t actual_size = 0;
+ if (!bin_unpack_array_fixed(bu, 2, &actual_size)) {
+ LOGGER_ERROR(chat->log, "Group mod list array malformed: %d != 2", actual_size);
return false;
}
@@ -116,7 +177,7 @@ static bool load_unpack_mod_list(GC_Chat *chat, Bin_Unpack *bu)
if (chat->moderation.num_mods > MOD_MAX_NUM_MODERATORS) {
LOGGER_ERROR(chat->log, "moderation count %u exceeds maximum %u", chat->moderation.num_mods, MOD_MAX_NUM_MODERATORS);
- return false;
+ chat->moderation.num_mods = MOD_MAX_NUM_MODERATORS;
}
uint8_t *packed_mod_list = (uint8_t *)malloc(chat->moderation.num_mods * MOD_LIST_ENTRY_SIZE);
@@ -148,15 +209,15 @@ static bool load_unpack_mod_list(GC_Chat *chat, Bin_Unpack *bu)
non_null()
static bool load_unpack_keys(GC_Chat *chat, Bin_Unpack *bu)
{
- if (!bin_unpack_array_fixed(bu, 4)) {
+ if (!bin_unpack_array_fixed(bu, 4, nullptr)) {
LOGGER_ERROR(chat->log, "Group keys array malformed");
return false;
}
- if (!(bin_unpack_bin_fixed(bu, chat->chat_public_key, EXT_PUBLIC_KEY_SIZE)
- && bin_unpack_bin_fixed(bu, chat->chat_secret_key, EXT_SECRET_KEY_SIZE)
- && bin_unpack_bin_fixed(bu, chat->self_public_key, EXT_PUBLIC_KEY_SIZE)
- && bin_unpack_bin_fixed(bu, chat->self_secret_key, EXT_SECRET_KEY_SIZE))) {
+ if (!(unpack_extended_public_key(&chat->chat_public_key, bu)
+ && unpack_extended_secret_key(&chat->chat_secret_key, bu)
+ && unpack_extended_public_key(&chat->self_public_key, bu)
+ && unpack_extended_secret_key(&chat->self_secret_key, bu))) {
LOGGER_ERROR(chat->log, "Failed to unpack keys");
return false;
}
@@ -167,7 +228,7 @@ static bool load_unpack_keys(GC_Chat *chat, Bin_Unpack *bu)
non_null()
static bool load_unpack_self_info(GC_Chat *chat, Bin_Unpack *bu)
{
- if (!bin_unpack_array_fixed(bu, 4)) {
+ if (!bin_unpack_array_fixed(bu, 4, nullptr)) {
LOGGER_ERROR(chat->log, "Group self info array malformed");
return false;
}
@@ -184,7 +245,10 @@ static bool load_unpack_self_info(GC_Chat *chat, Bin_Unpack *bu)
return false;
}
- assert(self_nick_len <= MAX_GC_NICK_SIZE);
+ if (self_nick_len > MAX_GC_NICK_SIZE) {
+ LOGGER_ERROR(chat->log, "self_nick too big (%u bytes), truncating to %d", self_nick_len, MAX_GC_NICK_SIZE);
+ self_nick_len = MAX_GC_NICK_SIZE;
+ }
if (!bin_unpack_bin_fixed(bu, self_nick, self_nick_len)) {
LOGGER_ERROR(chat->log, "Failed to unpack self nick bytes");
@@ -192,16 +256,19 @@ static bool load_unpack_self_info(GC_Chat *chat, Bin_Unpack *bu)
}
// we have to add ourself before setting self info
- if (peer_add(chat, nullptr, chat->self_public_key) != 0) {
+ if (peer_add(chat, nullptr, chat->self_public_key.enc) != 0) {
LOGGER_ERROR(chat->log, "Failed to add self to peer list");
return false;
}
- assert(chat->numpeers > 0);
+ if (chat->numpeers == 0) {
+ LOGGER_ERROR(chat->log, "Failed to unpack self: numpeers should be > 0");
+ return false;
+ }
GC_Peer *self = &chat->group[0];
- memcpy(self->gconn.addr.public_key, chat->self_public_key, EXT_PUBLIC_KEY_SIZE);
+ self->gconn.addr.public_key = chat->self_public_key;
memcpy(self->nick, self_nick, self_nick_len);
self->nick_length = self_nick_len;
self->role = (Group_Role)self_role;
@@ -214,7 +281,7 @@ static bool load_unpack_self_info(GC_Chat *chat, Bin_Unpack *bu)
non_null()
static bool load_unpack_saved_peers(GC_Chat *chat, Bin_Unpack *bu)
{
- if (!bin_unpack_array_fixed(bu, 2)) {
+ if (!bin_unpack_array_fixed(bu, 2, nullptr)) {
LOGGER_ERROR(chat->log, "Group saved peers array malformed");
return false;
}
@@ -256,8 +323,9 @@ static bool load_unpack_saved_peers(GC_Chat *chat, Bin_Unpack *bu)
bool gc_load_unpack_group(GC_Chat *chat, Bin_Unpack *bu)
{
- if (!bin_unpack_array_fixed(bu, 7)) {
- LOGGER_ERROR(chat->log, "Group info array malformed");
+ uint32_t actual_size;
+ if (!bin_unpack_array_fixed(bu, 7, &actual_size)) {
+ LOGGER_ERROR(chat->log, "Group info array malformed: %d != 7", actual_size);
return false;
}
@@ -290,7 +358,7 @@ static void save_pack_state_bin(const GC_Chat *chat, Bin_Pack *bp)
bin_pack_array(bp, 5);
bin_pack_bin(bp, chat->shared_state_sig, SIGNATURE_SIZE); // 1
- bin_pack_bin(bp, chat->shared_state.founder_public_key, EXT_PUBLIC_KEY_SIZE); // 2
+ pack_extended_public_key(&chat->shared_state.founder_public_key, bp); // 2
bin_pack_bin(bp, chat->shared_state.group_name, chat->shared_state.group_name_len); // 3
bin_pack_bin(bp, chat->shared_state.password, chat->shared_state.password_length); // 4
bin_pack_bin(bp, chat->shared_state.mod_list_hash, MOD_MODERATION_HASH_SIZE); // 5
@@ -348,10 +416,10 @@ static void save_pack_keys(const GC_Chat *chat, Bin_Pack *bp)
{
bin_pack_array(bp, 4);
- bin_pack_bin(bp, chat->chat_public_key, EXT_PUBLIC_KEY_SIZE); // 1
- bin_pack_bin(bp, chat->chat_secret_key, EXT_SECRET_KEY_SIZE); // 2
- bin_pack_bin(bp, chat->self_public_key, EXT_PUBLIC_KEY_SIZE); // 3
- bin_pack_bin(bp, chat->self_secret_key, EXT_SECRET_KEY_SIZE); // 4
+ pack_extended_public_key(&chat->chat_public_key, bp); // 1
+ pack_extended_secret_key(&chat->chat_secret_key, bp); // 2
+ pack_extended_public_key(&chat->self_public_key, bp); // 3
+ pack_extended_secret_key(&chat->self_secret_key, bp); // 4
}
non_null()
@@ -359,13 +427,16 @@ static void save_pack_self_info(const GC_Chat *chat, Bin_Pack *bp)
{
bin_pack_array(bp, 4);
- const GC_Peer *self = &chat->group[0];
+ GC_Peer *self = &chat->group[0];
- assert(self->nick_length <= MAX_GC_NICK_SIZE);
+ if (self->nick_length > MAX_GC_NICK_SIZE) {
+ LOGGER_ERROR(chat->log, "self_nick is too big (%u). Truncating to %d", self->nick_length, MAX_GC_NICK_SIZE);
+ self->nick_length = MAX_GC_NICK_SIZE;
+ }
bin_pack_u16(bp, self->nick_length); // 1
bin_pack_u08(bp, (uint8_t)self->role); // 2
- bin_pack_u08(bp, (uint8_t)self->status); // 3
+ bin_pack_u08(bp, self->status); // 3
bin_pack_bin(bp, self->nick, self->nick_length); // 4
}
diff --git a/protocols/Tox/libtox/src/toxcore/group_pack.h b/protocols/Tox/libtox/src/toxcore/group_pack.h
index ae831ac708..03252fb86d 100644
--- a/protocols/Tox/libtox/src/toxcore/group_pack.h
+++ b/protocols/Tox/libtox/src/toxcore/group_pack.h
@@ -7,11 +7,12 @@
* Packer and unpacker functions for saving and loading groups.
*/
-#ifndef GROUP_PACK_H
-#define GROUP_PACK_H
+#ifndef C_TOXCORE_TOXCORE_GROUP_PACK_H
+#define C_TOXCORE_TOXCORE_GROUP_PACK_H
#include <stdbool.h>
+#include "attributes.h"
#include "bin_pack.h"
#include "bin_unpack.h"
#include "group_common.h"
@@ -32,4 +33,9 @@ void gc_save_pack_group(const GC_Chat *chat, Bin_Pack *bp);
non_null()
bool gc_load_unpack_group(GC_Chat *chat, Bin_Unpack *bu);
-#endif // GROUP_PACK_H
+non_null()
+bool group_privacy_state_from_int(uint8_t value, Group_Privacy_State *out);
+non_null()
+bool group_voice_state_from_int(uint8_t value, Group_Voice_State *out);
+
+#endif /* C_TOXCORE_TOXCORE_GROUP_PACK_H */
diff --git a/protocols/Tox/libtox/src/toxcore/list.c b/protocols/Tox/libtox/src/toxcore/list.c
index e367487380..bf3db247f1 100644
--- a/protocols/Tox/libtox/src/toxcore/list.c
+++ b/protocols/Tox/libtox/src/toxcore/list.c
@@ -10,10 +10,12 @@
*/
#include "list.h"
+#include <assert.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
+#include "attributes.h"
#include "ccompat.h"
/**
@@ -28,8 +30,7 @@
* - some considerations since the array size is never perfect
*/
-static int32_t
-list_index(uint32_t i)
+static int32_t list_index(uint32_t i)
{
return ~i;
}
@@ -59,7 +60,7 @@ static int find(const BS_List *list, const uint8_t *data)
// closest match is found if we move back to where we have already been
while (true) {
- const int r = memcmp(data, list->data + list->element_size * i, list->element_size);
+ const int r = list->cmp_callback(data, list->data + list->element_size * i, list->element_size);
if (r == 0) {
return i;
@@ -122,7 +123,7 @@ static bool resize(BS_List *list, uint32_t new_size)
list->data = data;
- int *ids = (int *)realloc(list->ids, sizeof(int) * new_size);
+ int *ids = (int *)realloc(list->ids, new_size * sizeof(int));
if (ids == nullptr) {
return false;
@@ -133,8 +134,7 @@ static bool resize(BS_List *list, uint32_t new_size)
return true;
}
-
-int bs_list_init(BS_List *list, uint32_t element_size, uint32_t initial_capacity)
+int bs_list_init(BS_List *list, uint32_t element_size, uint32_t initial_capacity, bs_list_cmp_cb *cmp_callback)
{
// set initial values
list->n = 0;
@@ -142,6 +142,7 @@ int bs_list_init(BS_List *list, uint32_t element_size, uint32_t initial_capacity
list->capacity = 0;
list->data = nullptr;
list->ids = nullptr;
+ list->cmp_callback = cmp_callback;
if (initial_capacity != 0) {
if (!resize(list, initial_capacity)) {
@@ -206,6 +207,7 @@ bool bs_list_add(BS_List *list, const uint8_t *data, int id)
}
// insert data to element array
+ assert(list->data != nullptr);
memmove(list->data + (i + 1) * list->element_size, list->data + i * list->element_size,
(list->n - i) * list->element_size);
memcpy(list->data + i * list->element_size, data, list->element_size);
diff --git a/protocols/Tox/libtox/src/toxcore/list.h b/protocols/Tox/libtox/src/toxcore/list.h
index a7c0e56c06..1dc66d01a4 100644
--- a/protocols/Tox/libtox/src/toxcore/list.h
+++ b/protocols/Tox/libtox/src/toxcore/list.h
@@ -12,6 +12,7 @@
#define C_TOXCORE_TOXCORE_LIST_H
#include <stdbool.h>
+#include <stddef.h> // size_t
#include <stdint.h>
#include "attributes.h"
@@ -20,12 +21,15 @@
extern "C" {
#endif
+typedef int bs_list_cmp_cb(const void *a, const void *b, size_t size);
+
typedef struct BS_List {
uint32_t n; // number of elements
uint32_t capacity; // number of elements memory is allocated for
uint32_t element_size; // size of the elements
uint8_t *data; // array of elements
int *ids; // array of element ids
+ bs_list_cmp_cb *cmp_callback;
} BS_List;
/** @brief Initialize a list.
@@ -37,7 +41,7 @@ typedef struct BS_List {
* @retval 0 failure
*/
non_null()
-int bs_list_init(BS_List *list, uint32_t element_size, uint32_t initial_capacity);
+int bs_list_init(BS_List *list, uint32_t element_size, uint32_t initial_capacity, bs_list_cmp_cb *cmp_callback);
/** Free a list initiated with list_init */
nullable(1)
@@ -68,7 +72,7 @@ non_null()
bool bs_list_remove(BS_List *list, const uint8_t *data, int id);
#ifdef __cplusplus
-} // extern "C"
+} /* extern "C" */
#endif
-#endif
+#endif /* C_TOXCORE_TOXCORE_LIST_H */
diff --git a/protocols/Tox/libtox/src/toxcore/logger.c b/protocols/Tox/libtox/src/toxcore/logger.c
index d281a66085..67fa52330b 100644
--- a/protocols/Tox/libtox/src/toxcore/logger.c
+++ b/protocols/Tox/libtox/src/toxcore/logger.c
@@ -8,12 +8,12 @@
*/
#include "logger.h"
-#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include "attributes.h"
#include "ccompat.h"
struct Logger {
@@ -44,7 +44,7 @@ static const char *logger_level_name(Logger_Level level)
return "<unknown>";
}
-#endif
+#endif /* NDEBUG */
non_null(1, 3, 5, 6) nullable(7)
static void logger_stderr_handler(void *context, Logger_Level level, const char *file, int line, const char *func,
@@ -55,7 +55,7 @@ static void logger_stderr_handler(void *context, Logger_Level level, const char
fprintf(stderr, "[GL] %s %s:%d(%s): %s\n", logger_level_name(level), file, line, func, message);
fprintf(stderr, "Default stderr logger triggered; aborting program\n");
abort();
-#endif
+#endif /* NDEBUG */
}
static const Logger logger_stderr = {
@@ -106,7 +106,7 @@ void logger_write(const Logger *log, Logger_Level level, const char *file, int l
// one too.
const char *windows_filename = strrchr(file, '\\');
file = windows_filename != nullptr ? windows_filename + 1 : file;
-#endif
+#endif /* WIN32 */
// Format message
char msg[1024];
@@ -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();
+}
diff --git a/protocols/Tox/libtox/src/toxcore/logger.h b/protocols/Tox/libtox/src/toxcore/logger.h
index ee5838ae73..830db883aa 100644
--- a/protocols/Tox/libtox/src/toxcore/logger.h
+++ b/protocols/Tox/libtox/src/toxcore/logger.h
@@ -19,7 +19,7 @@ extern "C" {
#ifndef MIN_LOGGER_LEVEL
#define MIN_LOGGER_LEVEL LOGGER_LEVEL_INFO
-#endif
+#endif /* MIN_LOGGER_LEVEL */
// NOTE: Don't forget to update build system files after modifying the enum.
typedef enum Logger_Level {
@@ -67,6 +67,8 @@ 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 +87,7 @@ void logger_write(
#define LOGGER_FATAL(log, ...) \
do { \
LOGGER_ERROR(log, __VA_ARGS__); \
- abort(); \
+ logger_abort(); \
} while (0)
#define LOGGER_ASSERT(log, cond, ...) \
@@ -97,7 +99,7 @@ void logger_write(
} while (0)
#ifdef __cplusplus
-} // extern "C"
+} /* extern "C" */
#endif
-#endif // C_TOXCORE_TOXCORE_LOGGER_H
+#endif /* C_TOXCORE_TOXCORE_LOGGER_H */
diff --git a/protocols/Tox/libtox/src/toxcore/mem.c b/protocols/Tox/libtox/src/toxcore/mem.c
new file mode 100644
index 0000000000..bddc335b82
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/mem.c
@@ -0,0 +1,89 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2013 Tox project.
+ */
+
+#include "mem.h"
+
+#include <stdlib.h>
+
+#include "attributes.h"
+#include "ccompat.h"
+
+nullable(1)
+static void *sys_malloc(void *obj, uint32_t size)
+{
+ return malloc(size);
+}
+
+nullable(1)
+static void *sys_calloc(void *obj, uint32_t nmemb, uint32_t size)
+{
+ return calloc(nmemb, size);
+}
+
+nullable(1, 2)
+static void *sys_realloc(void *obj, void *ptr, uint32_t size)
+{
+ return realloc(ptr, size);
+}
+
+nullable(1, 2)
+static void sys_free(void *obj, void *ptr)
+{
+ free(ptr);
+}
+
+static const Memory_Funcs os_memory_funcs = {
+ sys_malloc,
+ sys_calloc,
+ sys_realloc,
+ sys_free,
+};
+static const Memory os_memory_obj = {&os_memory_funcs};
+
+const Memory *os_memory(void)
+{
+ return &os_memory_obj;
+}
+
+void *mem_balloc(const Memory *mem, uint32_t size)
+{
+ void *const ptr = mem->funcs->malloc(mem->obj, size);
+ return ptr;
+}
+
+void *mem_alloc(const Memory *mem, uint32_t size)
+{
+ void *const ptr = mem->funcs->calloc(mem->obj, 1, size);
+ return ptr;
+}
+
+void *mem_valloc(const Memory *mem, uint32_t nmemb, uint32_t size)
+{
+ const uint32_t bytes = nmemb * size;
+
+ if (size != 0 && bytes / size != nmemb) {
+ return nullptr;
+ }
+
+ void *const ptr = mem->funcs->calloc(mem->obj, nmemb, size);
+ return ptr;
+}
+
+void *mem_vrealloc(const Memory *mem, void *ptr, uint32_t nmemb, uint32_t size)
+{
+ const uint32_t bytes = nmemb * size;
+
+ if (size != 0 && bytes / size != nmemb) {
+ return nullptr;
+ }
+
+ void *const new_ptr = mem->funcs->realloc(mem->obj, ptr, bytes);
+ return new_ptr;
+}
+
+void mem_delete(const Memory *mem, void *ptr)
+{
+ mem->funcs->free(mem->obj, ptr);
+}
diff --git a/protocols/Tox/libtox/src/toxcore/mem.h b/protocols/Tox/libtox/src/toxcore/mem.h
new file mode 100644
index 0000000000..7a96b6d358
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/mem.h
@@ -0,0 +1,86 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2013 Tox project.
+ */
+
+/**
+ * Memory allocation and deallocation functions.
+ */
+#ifndef C_TOXCORE_TOXCORE_MEM_H
+#define C_TOXCORE_TOXCORE_MEM_H
+
+#include <stdint.h> // uint*_t
+
+#include "attributes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void *mem_malloc_cb(void *obj, uint32_t size);
+typedef void *mem_calloc_cb(void *obj, uint32_t nmemb, uint32_t size);
+typedef void *mem_realloc_cb(void *obj, void *ptr, uint32_t size);
+typedef void mem_free_cb(void *obj, void *ptr);
+
+/** @brief Functions wrapping standard C memory allocation functions. */
+typedef struct Memory_Funcs {
+ mem_malloc_cb *malloc;
+ mem_calloc_cb *calloc;
+ mem_realloc_cb *realloc;
+ mem_free_cb *free;
+} Memory_Funcs;
+
+typedef struct Memory {
+ const Memory_Funcs *funcs;
+ void *obj;
+} Memory;
+
+const Memory *os_memory(void);
+
+/**
+ * @brief Allocate an array of a given size for built-in types.
+ *
+ * The array will not be initialised. Supported built-in types are
+ * `uint8_t`, `int8_t`, and `int16_t`.
+ */
+non_null() void *mem_balloc(const Memory *mem, uint32_t size);
+
+/**
+ * @brief Allocate a single object.
+ *
+ * Always use as `(T *)mem_alloc(mem, sizeof(T))`.
+ */
+non_null() void *mem_alloc(const Memory *mem, uint32_t size);
+
+/**
+ * @brief Allocate a vector (array) of objects.
+ *
+ * Always use as `(T *)mem_valloc(mem, N, sizeof(T))`.
+ */
+non_null() void *mem_valloc(const Memory *mem, uint32_t nmemb, uint32_t size);
+
+/**
+ * @brief Resize an object vector.
+ *
+ * Changes the size of (and possibly moves) the memory block pointed to by
+ * @p ptr to be large enough for an array of @p nmemb elements, each of which
+ * is @p size bytes. It is similar to the call
+ *
+ * @code
+ * realloc(ptr, nmemb * size);
+ * @endcode
+ *
+ * However, unlike that `realloc()` call, `mem_vrealloc()` fails safely in the
+ * case where the multiplication would overflow. If such an overflow occurs,
+ * `mem_vrealloc()` returns `nullptr`.
+ */
+non_null(1) nullable(2) void *mem_vrealloc(const Memory *mem, void *ptr, uint32_t nmemb, uint32_t size);
+
+/** @brief Free an array, object, or object vector. */
+non_null(1) nullable(2) void mem_delete(const Memory *mem, void *ptr);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* C_TOXCORE_TOXCORE_MEM_H */
diff --git a/protocols/Tox/libtox/src/toxcore/mono_time.c b/protocols/Tox/libtox/src/toxcore/mono_time.c
index df64f2246c..124f94fc23 100644
--- a/protocols/Tox/libtox/src/toxcore/mono_time.c
+++ b/protocols/Tox/libtox/src/toxcore/mono_time.c
@@ -1,94 +1,83 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2020 The TokTok team.
+ * Copyright © 2016-2023 The TokTok team.
* Copyright © 2014 Tox project.
*/
#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE 600
-#endif
+#endif /* _XOPEN_SOURCE */
#if !defined(OS_WIN32) && (defined(_WIN32) || defined(__WIN32__) || defined(WIN32))
#define OS_WIN32
-#endif
+#endif /* WIN32 */
#include "mono_time.h"
#ifdef OS_WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
-#endif
+#endif /* OS_WIN32 */
#ifdef __APPLE__
#include <mach/clock.h>
#include <mach/mach.h>
-#endif
+#endif /* __APPLE__ */
#ifndef OS_WIN32
#include <sys/time.h>
-#endif
+#endif /* OS_WIN32 */
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
#include <assert.h>
+#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
#include <pthread.h>
-#include <stdlib.h>
#include <time.h>
+#include "attributes.h"
#include "ccompat.h"
+#include "mem.h"
+#include "util.h"
/** don't call into system billions of times for no reason */
struct Mono_Time {
uint64_t cur_time;
uint64_t base_time;
-#ifdef OS_WIN32
- /* protect `last_clock_update` and `last_clock_mono` from concurrent access */
- pthread_mutex_t last_clock_lock;
- uint32_t last_clock_mono;
- bool last_clock_update;
-#endif
#ifndef ESP_PLATFORM
/* protect `time` from concurrent access */
pthread_rwlock_t *time_update_lock;
-#endif
+#endif /* ESP_PLATFORM */
mono_time_current_time_cb *current_time_callback;
void *user_data;
};
+static uint64_t timespec_to_u64(struct timespec clock_mono)
+{
+ return UINT64_C(1000) * clock_mono.tv_sec + (clock_mono.tv_nsec / UINT64_C(1000000));
+}
+
#ifdef OS_WIN32
non_null()
static uint64_t current_time_monotonic_default(void *user_data)
{
- Mono_Time *const mono_time = (Mono_Time *)user_data;
-
- /* Must hold mono_time->last_clock_lock here */
-
- /* GetTickCount provides only a 32 bit counter, but we can't use
- * GetTickCount64 for backwards compatibility, so we handle wraparound
- * ourselves.
- */
- const uint32_t ticks = GetTickCount();
-
- /* the higher 32 bits count the number of wrap arounds */
- uint64_t old_ovf = mono_time->cur_time & ~((uint64_t)UINT32_MAX);
-
- /* Check if time has decreased because of 32 bit wrap from GetTickCount() */
- if (ticks < mono_time->last_clock_mono) {
- /* account for overflow */
- old_ovf += UINT32_MAX + UINT64_C(1);
+ LARGE_INTEGER freq;
+ LARGE_INTEGER count;
+ if (!QueryPerformanceFrequency(&freq)) {
+ return 0;
}
-
- if (mono_time->last_clock_update) {
- mono_time->last_clock_mono = ticks;
- mono_time->last_clock_update = false;
+ if (!QueryPerformanceCounter(&count)) {
+ return 0;
}
-
- /* splice the low and high bits back together */
- return old_ovf + ticks;
-}
-#else // !OS_WIN32
-static uint64_t timespec_to_u64(struct timespec clock_mono)
-{
- return 1000ULL * clock_mono.tv_sec + (clock_mono.tv_nsec / 1000000ULL);
+ struct timespec sp = {0};
+ sp.tv_sec = count.QuadPart / freq.QuadPart;
+ if (freq.QuadPart < 1000000000) {
+ sp.tv_nsec = (count.QuadPart % freq.QuadPart) * 1000000000 / freq.QuadPart;
+ } else {
+ sp.tv_nsec = (long)((count.QuadPart % freq.QuadPart) * (1000000000.0 / freq.QuadPart));
+ }
+ return timespec_to_u64(sp);
}
+#else
#ifdef __APPLE__
non_null()
static uint64_t current_time_monotonic_default(void *user_data)
@@ -113,119 +102,98 @@ static uint64_t current_time_monotonic_default(void *user_data)
// This assert should always fail. If it does, the fuzzing harness didn't
// override the mono time callback.
assert(user_data == nullptr);
-#endif
+#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
struct timespec clock_mono;
clock_gettime(CLOCK_MONOTONIC, &clock_mono);
return timespec_to_u64(clock_mono);
}
-#endif // !__APPLE__
-#endif // !OS_WIN32
-
+#endif /* !__APPLE__ */
+#endif /* !OS_WIN32 */
-Mono_Time *mono_time_new(mono_time_current_time_cb *current_time_callback, void *user_data)
+Mono_Time *mono_time_new(const Memory *mem, mono_time_current_time_cb *current_time_callback, void *user_data)
{
- Mono_Time *mono_time = (Mono_Time *)calloc(1, sizeof(Mono_Time));
+ Mono_Time *mono_time = (Mono_Time *)mem_alloc(mem, sizeof(Mono_Time));
if (mono_time == nullptr) {
return nullptr;
}
#ifndef ESP_PLATFORM
- mono_time->time_update_lock = (pthread_rwlock_t *)calloc(1, sizeof(pthread_rwlock_t));
+ pthread_rwlock_t *rwlock = (pthread_rwlock_t *)mem_alloc(mem, sizeof(pthread_rwlock_t));
- if (mono_time->time_update_lock == nullptr) {
- free(mono_time);
+ if (rwlock == nullptr) {
+ mem_delete(mem, mono_time);
return nullptr;
}
- if (pthread_rwlock_init(mono_time->time_update_lock, nullptr) < 0) {
- free(mono_time->time_update_lock);
- free(mono_time);
+ if (pthread_rwlock_init(rwlock, nullptr) != 0) {
+ mem_delete(mem, rwlock);
+ mem_delete(mem, mono_time);
return nullptr;
}
-#endif
-
- mono_time_set_current_time_callback(mono_time, current_time_callback, user_data);
-#ifdef OS_WIN32
-
- mono_time->last_clock_mono = 0;
- mono_time->last_clock_update = false;
-
- if (pthread_mutex_init(&mono_time->last_clock_lock, nullptr) < 0) {
- free(mono_time->time_update_lock);
- free(mono_time);
- return nullptr;
- }
+ mono_time->time_update_lock = rwlock;
+#endif /* ESP_PLATFORM */
-#endif
+ mono_time_set_current_time_callback(mono_time, current_time_callback, user_data);
mono_time->cur_time = 0;
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
// Maximum reproducibility. Never return time = 0.
- mono_time->base_time = 1;
+ mono_time->base_time = 1000000000;
#else
- mono_time->base_time = (uint64_t)time(nullptr) - (current_time_monotonic(mono_time) / 1000ULL);
-#endif
+ // 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)) * UINT64_C(1000) - current_time_monotonic(mono_time);
+#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
mono_time_update(mono_time);
return mono_time;
}
-void mono_time_free(Mono_Time *mono_time)
+void mono_time_free(const Memory *mem, Mono_Time *mono_time)
{
if (mono_time == nullptr) {
return;
}
-#ifdef OS_WIN32
- pthread_mutex_destroy(&mono_time->last_clock_lock);
-#endif
#ifndef ESP_PLATFORM
pthread_rwlock_destroy(mono_time->time_update_lock);
- free(mono_time->time_update_lock);
-#endif
- free(mono_time);
+ mem_delete(mem, mono_time->time_update_lock);
+#endif /* ESP_PLATFORM */
+ mem_delete(mem, mono_time);
}
void mono_time_update(Mono_Time *mono_time)
{
- uint64_t cur_time = 0;
-#ifdef OS_WIN32
- /* we actually want to update the overflow state of mono_time here */
- pthread_mutex_lock(&mono_time->last_clock_lock);
- mono_time->last_clock_update = true;
-#endif
- cur_time = mono_time->current_time_callback(mono_time->user_data) / 1000ULL;
- cur_time += mono_time->base_time;
-#ifdef OS_WIN32
- pthread_mutex_unlock(&mono_time->last_clock_lock);
-#endif
+ const uint64_t cur_time =
+ mono_time->base_time + mono_time->current_time_callback(mono_time->user_data);
#ifndef ESP_PLATFORM
pthread_rwlock_wrlock(mono_time->time_update_lock);
-#endif
+#endif /* ESP_PLATFORM */
mono_time->cur_time = cur_time;
#ifndef ESP_PLATFORM
pthread_rwlock_unlock(mono_time->time_update_lock);
-#endif
+#endif /* ESP_PLATFORM */
}
-uint64_t mono_time_get(const Mono_Time *mono_time)
+uint64_t mono_time_get_ms(const Mono_Time *mono_time)
{
-#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+#if !defined(ESP_PLATFORM) && !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
// Fuzzing is only single thread for now, no locking needed */
- return mono_time->cur_time;
-#else
-#ifndef ESP_PLATFORM
pthread_rwlock_rdlock(mono_time->time_update_lock);
-#endif
+#endif /* !ESP_PLATFORM */
const uint64_t cur_time = mono_time->cur_time;
-#ifndef ESP_PLATFORM
+#if !defined(ESP_PLATFORM) && !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
pthread_rwlock_unlock(mono_time->time_update_lock);
-#endif
+#endif /* !ESP_PLATFORM */
return cur_time;
-#endif
+}
+
+uint64_t mono_time_get(const Mono_Time *mono_time)
+{
+ return mono_time_get_ms(mono_time) / UINT64_C(1000);
}
bool mono_time_is_timeout(const Mono_Time *mono_time, uint64_t timestamp, uint64_t timeout)
@@ -245,21 +213,12 @@ void mono_time_set_current_time_callback(Mono_Time *mono_time,
}
}
-/**
- * Return current monotonic time in milliseconds (ms). The starting point is
- * unspecified.
+/** @brief Return current monotonic time in milliseconds (ms).
+ *
+ * The starting point is unspecified and in particular is likely not comparable
+ * to the return value of `mono_time_get_ms()`.
*/
uint64_t current_time_monotonic(Mono_Time *mono_time)
{
- /* For WIN32 we don't want to change overflow state of mono_time here */
-#ifdef OS_WIN32
- /* We don't want to update the overflow state of mono_time here,
- * but must protect against other threads */
- pthread_mutex_lock(&mono_time->last_clock_lock);
-#endif
- const uint64_t cur_time = mono_time->current_time_callback(mono_time->user_data);
-#ifdef OS_WIN32
- pthread_mutex_unlock(&mono_time->last_clock_lock);
-#endif
- return cur_time;
+ return mono_time->current_time_callback(mono_time->user_data);
}
diff --git a/protocols/Tox/libtox/src/toxcore/mono_time.h b/protocols/Tox/libtox/src/toxcore/mono_time.h
index 5a36724715..d0f2b7a6d3 100644
--- a/protocols/Tox/libtox/src/toxcore/mono_time.h
+++ b/protocols/Tox/libtox/src/toxcore/mono_time.h
@@ -9,6 +9,7 @@
#include <stdint.h>
#include "attributes.h"
+#include "mem.h"
#ifdef __cplusplus
extern "C" {
@@ -47,11 +48,11 @@ typedef struct Mono_Time Mono_Time;
typedef uint64_t mono_time_current_time_cb(void *user_data);
-nullable(1, 2)
-Mono_Time *mono_time_new(mono_time_current_time_cb *current_time_callback, void *user_data);
+non_null(1) nullable(2, 3)
+Mono_Time *mono_time_new(const Memory *mem, mono_time_current_time_cb *current_time_callback, void *user_data);
-nullable(1)
-void mono_time_free(Mono_Time *mono_time);
+non_null(1) nullable(2)
+void mono_time_free(const Memory *mem, Mono_Time *mono_time);
/**
* Update mono_time; subsequent calls to mono_time_get or mono_time_is_timeout
@@ -60,8 +61,16 @@ void mono_time_free(Mono_Time *mono_time);
non_null()
void mono_time_update(Mono_Time *mono_time);
-/**
- * Return unix time since epoch in seconds.
+/** @brief Return current monotonic time in milliseconds (ms).
+ *
+ * The starting point is UNIX epoch as measured by `time()` in `mono_time_new()`.
+ */
+non_null()
+uint64_t mono_time_get_ms(const Mono_Time *mono_time);
+
+/** @brief Return a monotonically increasing time in seconds.
+ *
+ * The starting point is UNIX epoch as measured by `time()` in `mono_time_new()`.
*/
non_null()
uint64_t mono_time_get(const Mono_Time *mono_time);
@@ -72,9 +81,10 @@ uint64_t mono_time_get(const Mono_Time *mono_time);
non_null()
bool mono_time_is_timeout(const Mono_Time *mono_time, uint64_t timestamp, uint64_t timeout);
-/**
- * Return current monotonic time in milliseconds (ms). The starting point is
- * unspecified.
+/** @brief Return current monotonic time in milliseconds (ms).
+ *
+ * The starting point is unspecified and in particular is likely not comparable
+ * to the return value of `mono_time_get_ms()`.
*/
non_null()
uint64_t current_time_monotonic(Mono_Time *mono_time);
@@ -90,7 +100,7 @@ void mono_time_set_current_time_callback(Mono_Time *mono_time,
mono_time_current_time_cb *current_time_callback, void *user_data);
#ifdef __cplusplus
-}
+} /* extern "C" */
#endif
-#endif // C_TOXCORE_TOXCORE_MONO_TIME_H
+#endif /* C_TOXCORE_TOXCORE_MONO_TIME_H */
diff --git a/protocols/Tox/libtox/src/toxcore/net_crypto.c b/protocols/Tox/libtox/src/toxcore/net_crypto.c
index 71f6e39e64..1680b078b7 100644
--- a/protocols/Tox/libtox/src/toxcore/net_crypto.c
+++ b/protocols/Tox/libtox/src/toxcore/net_crypto.c
@@ -10,13 +10,20 @@
*/
#include "net_crypto.h"
-#include <math.h>
-#include <stdlib.h>
#include <string.h>
+#include "DHT.h"
+#include "LAN_discovery.h"
+#include "TCP_client.h"
+#include "TCP_connection.h"
+#include "attributes.h"
#include "ccompat.h"
+#include "crypto_core.h"
#include "list.h"
+#include "logger.h"
+#include "mem.h"
#include "mono_time.h"
+#include "network.h"
#include "util.h"
typedef struct Packet_Data {
@@ -127,6 +134,7 @@ static const Crypto_Connection empty_crypto_connection = {{0}};
struct Net_Crypto {
const Logger *log;
+ const Memory *mem;
const Random *rng;
Mono_Time *mono_time;
const Network *ns;
@@ -218,10 +226,9 @@ static int create_cookie_request(const Net_Crypto *c, uint8_t *packet, const uin
uint64_t number, uint8_t *shared_key)
{
uint8_t plain[COOKIE_REQUEST_PLAIN_LENGTH];
- uint8_t padding[CRYPTO_PUBLIC_KEY_SIZE] = {0};
memcpy(plain, c->self_public_key, CRYPTO_PUBLIC_KEY_SIZE);
- memcpy(plain + CRYPTO_PUBLIC_KEY_SIZE, padding, CRYPTO_PUBLIC_KEY_SIZE);
+ memzero(plain + CRYPTO_PUBLIC_KEY_SIZE, CRYPTO_PUBLIC_KEY_SIZE);
memcpy(plain + (CRYPTO_PUBLIC_KEY_SIZE * 2), &number, sizeof(uint64_t));
const uint8_t *tmp_shared_key = dht_get_shared_key_sent(c->dht, dht_public_key);
memcpy(shared_key, tmp_shared_key, CRYPTO_SHARED_KEY_SIZE);
@@ -292,7 +299,6 @@ static int open_cookie(const Mono_Time *mono_time, uint8_t *bytes, const uint8_t
return 0;
}
-
/** @brief Create a cookie response packet and put it in packet.
* @param request_plain must be COOKIE_REQUEST_PLAIN_LENGTH bytes.
* @param packet must be of size COOKIE_RESPONSE_LENGTH or bigger.
@@ -561,7 +567,6 @@ static bool handle_crypto_handshake(const Net_Crypto *c, uint8_t *nonce, uint8_t
return true;
}
-
non_null()
static Crypto_Connection *get_crypto_connection(const Net_Crypto *c, int crypt_connection_id)
{
@@ -572,7 +577,6 @@ static Crypto_Connection *get_crypto_connection(const Net_Crypto *c, int crypt_c
return &c->crypto_connections[crypt_connection_id];
}
-
/** @brief Associate an ip_port to a connection.
*
* @retval -1 on failure.
@@ -688,7 +692,7 @@ static int send_packet_to(Net_Crypto *c, int crypt_connection_id, const uint8_t
bool direct_send_attempt = false;
pthread_mutex_lock(conn->mutex);
- IP_Port ip_port = return_ip_port_connection(c, crypt_connection_id);
+ const IP_Port ip_port = return_ip_port_connection(c, crypt_connection_id);
// TODO(irungentoo): on bad networks, direct connections might not last indefinitely.
if (!net_family_is_unspec(ip_port.ip.family)) {
@@ -742,7 +746,6 @@ static int send_packet_to(Net_Crypto *c, int crypt_connection_id, const uint8_t
/*** START: Array Related functions */
-
/** @brief Return number of packets in array
* Note that holes are counted too.
*/
@@ -758,7 +761,7 @@ static uint32_t num_packets_array(const Packets_Array *array)
* @retval 0 on success.
*/
non_null()
-static int add_data_to_buffer(Packets_Array *array, uint32_t number, const Packet_Data *data)
+static int add_data_to_buffer(const Memory *mem, Packets_Array *array, uint32_t number, const Packet_Data *data)
{
if (number - array->buffer_start >= CRYPTO_PACKET_BUFFER_SIZE) {
return -1;
@@ -770,7 +773,7 @@ static int add_data_to_buffer(Packets_Array *array, uint32_t number, const Packe
return -1;
}
- Packet_Data *new_d = (Packet_Data *)calloc(1, sizeof(Packet_Data));
+ Packet_Data *new_d = (Packet_Data *)mem_alloc(mem, sizeof(Packet_Data));
if (new_d == nullptr) {
return -1;
@@ -817,7 +820,7 @@ static int get_data_pointer(const Packets_Array *array, Packet_Data **data, uint
* @return packet number on success.
*/
non_null()
-static int64_t add_data_end_of_buffer(const Logger *logger, Packets_Array *array, const Packet_Data *data)
+static int64_t add_data_end_of_buffer(const Logger *logger, const Memory *mem, Packets_Array *array, const Packet_Data *data)
{
const uint32_t num_spots = num_packets_array(array);
@@ -826,7 +829,7 @@ static int64_t add_data_end_of_buffer(const Logger *logger, Packets_Array *array
return -1;
}
- Packet_Data *new_d = (Packet_Data *)calloc(1, sizeof(Packet_Data));
+ Packet_Data *new_d = (Packet_Data *)mem_alloc(mem, sizeof(Packet_Data));
if (new_d == nullptr) {
LOGGER_ERROR(logger, "packet data allocation failed");
@@ -846,7 +849,7 @@ static int64_t add_data_end_of_buffer(const Logger *logger, Packets_Array *array
* @return packet number on success.
*/
non_null()
-static int64_t read_data_beg_buffer(Packets_Array *array, Packet_Data *data)
+static int64_t read_data_beg_buffer(const Memory *mem, Packets_Array *array, Packet_Data *data)
{
if (array->buffer_end == array->buffer_start) {
return -1;
@@ -861,7 +864,7 @@ static int64_t read_data_beg_buffer(Packets_Array *array, Packet_Data *data)
*data = *array->buffer[num];
const uint32_t id = array->buffer_start;
++array->buffer_start;
- free(array->buffer[num]);
+ mem_delete(mem, array->buffer[num]);
array->buffer[num] = nullptr;
return id;
}
@@ -872,7 +875,7 @@ static int64_t read_data_beg_buffer(Packets_Array *array, Packet_Data *data)
* @retval 0 on success
*/
non_null()
-static int clear_buffer_until(Packets_Array *array, uint32_t number)
+static int clear_buffer_until(const Memory *mem, Packets_Array *array, uint32_t number)
{
const uint32_t num_spots = num_packets_array(array);
@@ -886,7 +889,7 @@ static int clear_buffer_until(Packets_Array *array, uint32_t number)
const uint32_t num = i % CRYPTO_PACKET_BUFFER_SIZE;
if (array->buffer[num] != nullptr) {
- free(array->buffer[num]);
+ mem_delete(mem, array->buffer[num]);
array->buffer[num] = nullptr;
}
}
@@ -896,7 +899,7 @@ static int clear_buffer_until(Packets_Array *array, uint32_t number)
}
non_null()
-static int clear_buffer(Packets_Array *array)
+static int clear_buffer(const Memory *mem, Packets_Array *array)
{
uint32_t i;
@@ -904,7 +907,7 @@ static int clear_buffer(Packets_Array *array)
const uint32_t num = i % CRYPTO_PACKET_BUFFER_SIZE;
if (array->buffer[num] != nullptr) {
- free(array->buffer[num]);
+ mem_delete(mem, array->buffer[num]);
array->buffer[num] = nullptr;
}
}
@@ -995,7 +998,7 @@ static int generate_request_packet(uint8_t *data, uint16_t length, const Packets
* @return number of requested packets on success.
*/
non_null()
-static int handle_request_packet(Mono_Time *mono_time, Packets_Array *send_array,
+static int handle_request_packet(const Memory *mem, Mono_Time *mono_time, Packets_Array *send_array,
const uint8_t *data, uint16_t length,
uint64_t *latest_send_time, uint64_t rtt_time)
{
@@ -1044,7 +1047,7 @@ static int handle_request_packet(Mono_Time *mono_time, Packets_Array *send_array
if (send_array->buffer[num] != nullptr) {
l_sent_time = max_u64(l_sent_time, send_array->buffer[num]->sent_time);
- free(send_array->buffer[num]);
+ mem_delete(mem, send_array->buffer[num]);
send_array->buffer[num] = nullptr;
}
}
@@ -1110,7 +1113,7 @@ static int send_data_packet(Net_Crypto *c, int crypt_connection_id, const uint8_
increment_nonce(conn->sent_nonce);
pthread_mutex_unlock(conn->mutex);
- return send_packet_to(c, crypt_connection_id, packet, SIZEOF_VLA(packet));
+ return send_packet_to(c, crypt_connection_id, packet, packet_size);
}
/** @brief Creates and sends a data packet with buffer_start and num to the peer using the fastest route.
@@ -1130,13 +1133,14 @@ static int send_data_packet_helper(Net_Crypto *c, int crypt_connection_id, uint3
num = net_htonl(num);
buffer_start = net_htonl(buffer_start);
const uint16_t padding_length = (MAX_CRYPTO_DATA_SIZE - length) % CRYPTO_MAX_PADDING;
- VLA(uint8_t, packet, sizeof(uint32_t) + sizeof(uint32_t) + padding_length + length);
+ const uint16_t packet_size = sizeof(uint32_t) + sizeof(uint32_t) + padding_length + length;
+ VLA(uint8_t, packet, packet_size);
memcpy(packet, &buffer_start, sizeof(uint32_t));
memcpy(packet + sizeof(uint32_t), &num, sizeof(uint32_t));
- memset(packet + (sizeof(uint32_t) * 2), PACKET_ID_PADDING, padding_length);
+ memzero(packet + (sizeof(uint32_t) * 2), padding_length);
memcpy(packet + (sizeof(uint32_t) * 2) + padding_length, data, length);
- return send_data_packet(c, crypt_connection_id, packet, SIZEOF_VLA(packet));
+ return send_data_packet(c, crypt_connection_id, packet, packet_size);
}
non_null()
@@ -1204,7 +1208,7 @@ static int64_t send_lossless_packet(Net_Crypto *c, int crypt_connection_id, cons
dt.length = length;
memcpy(dt.data, data, length);
pthread_mutex_lock(conn->mutex);
- const int64_t packet_num = add_data_end_of_buffer(c->log, &conn->send_array, &dt);
+ const int64_t packet_num = add_data_end_of_buffer(c->log, c->mem, &conn->send_array, &dt);
pthread_mutex_unlock(conn->mutex);
if (packet_num == -1) {
@@ -1365,7 +1369,6 @@ static int send_requested_packets(Net_Crypto *c, int crypt_connection_id, uint32
return num_sent;
}
-
/** @brief Add a new temp packet to send repeatedly.
*
* @retval -1 on failure.
@@ -1384,14 +1387,14 @@ static int new_temp_packet(const Net_Crypto *c, int crypt_connection_id, const u
return -1;
}
- uint8_t *temp_packet = (uint8_t *)malloc(length);
+ uint8_t *temp_packet = (uint8_t *)mem_balloc(c->mem, length);
if (temp_packet == nullptr) {
return -1;
}
if (conn->temp_packet != nullptr) {
- free(conn->temp_packet);
+ mem_delete(c->mem, conn->temp_packet);
}
memcpy(temp_packet, packet, length);
@@ -1417,7 +1420,7 @@ static int clear_temp_packet(const Net_Crypto *c, int crypt_connection_id)
}
if (conn->temp_packet != nullptr) {
- free(conn->temp_packet);
+ mem_delete(c->mem, conn->temp_packet);
}
conn->temp_packet = nullptr;
@@ -1427,7 +1430,6 @@ static int clear_temp_packet(const Net_Crypto *c, int crypt_connection_id)
return 0;
}
-
/** @brief Send the temp packet.
*
* @retval -1 on failure.
@@ -1500,9 +1502,9 @@ static int send_kill_packet(Net_Crypto *c, int crypt_connection_id)
return -1;
}
- uint8_t kill_packet = PACKET_ID_KILL;
+ const uint8_t kill_packet[1] = {PACKET_ID_KILL};
return send_data_packet_helper(c, crypt_connection_id, conn->recv_array.buffer_start, conn->send_array.buffer_end,
- &kill_packet, sizeof(kill_packet));
+ kill_packet, sizeof(kill_packet));
}
non_null(1) nullable(3)
@@ -1575,7 +1577,7 @@ static int handle_data_packet_core(Net_Crypto *c, int crypt_connection_id, const
rtt_calc_time = packet_time->sent_time;
}
- if (clear_buffer_until(&conn->send_array, buffer_start) != 0) {
+ if (clear_buffer_until(c->mem, &conn->send_array, buffer_start) != 0) {
return -1;
}
}
@@ -1583,7 +1585,7 @@ static int handle_data_packet_core(Net_Crypto *c, int crypt_connection_id, const
const uint8_t *real_data = data + (sizeof(uint32_t) * 2);
uint16_t real_length = len - (sizeof(uint32_t) * 2);
- while (real_data[0] == PACKET_ID_PADDING) { /* Remove Padding */
+ while (real_data[0] == 0) { /* Remove Padding */
++real_data;
--real_length;
@@ -1616,9 +1618,7 @@ static int handle_data_packet_core(Net_Crypto *c, int crypt_connection_id, const
rtt_time = DEFAULT_TCP_PING_CONNECTION;
}
- const int requested = handle_request_packet(c->mono_time, &conn->send_array,
- real_data, real_length,
- &rtt_calc_time, rtt_time);
+ const int requested = handle_request_packet(c->mem, c->mono_time, &conn->send_array, real_data, real_length, &rtt_calc_time, rtt_time);
if (requested == -1) {
return -1;
@@ -1630,13 +1630,13 @@ static int handle_data_packet_core(Net_Crypto *c, int crypt_connection_id, const
dt.length = real_length;
memcpy(dt.data, real_data, real_length);
- if (add_data_to_buffer(&conn->recv_array, num, &dt) != 0) {
+ if (add_data_to_buffer(c->mem, &conn->recv_array, num, &dt) != 0) {
return -1;
}
while (true) {
pthread_mutex_lock(conn->mutex);
- const int ret = read_data_beg_buffer(&conn->recv_array, &dt);
+ const int ret = read_data_beg_buffer(c->mem, &conn->recv_array, &dt);
pthread_mutex_unlock(conn->mutex);
if (ret == -1) {
@@ -1671,7 +1671,7 @@ static int handle_data_packet_core(Net_Crypto *c, int crypt_connection_id, const
}
if (rtt_calc_time != 0) {
- uint64_t rtt_time = current_time_monotonic(c->mono_time) - rtt_calc_time;
+ const uint64_t rtt_time = current_time_monotonic(c->mono_time) - rtt_calc_time;
if (rtt_time < conn->rtt_time) {
conn->rtt_time = rtt_time;
@@ -1804,20 +1804,20 @@ static int handle_packet_connection(Net_Crypto *c, int crypt_connection_id, cons
/** @brief Set the size of the friend list to numfriends.
*
- * @retval -1 if realloc fails.
+ * @retval -1 if mem_vrealloc fails.
* @retval 0 if it succeeds.
*/
non_null()
static int realloc_cryptoconnection(Net_Crypto *c, uint32_t num)
{
if (num == 0) {
- free(c->crypto_connections);
+ mem_delete(c->mem, c->crypto_connections);
c->crypto_connections = nullptr;
return 0;
}
- Crypto_Connection *newcrypto_connections = (Crypto_Connection *)realloc(c->crypto_connections,
- num * sizeof(Crypto_Connection));
+ Crypto_Connection *newcrypto_connections = (Crypto_Connection *)mem_vrealloc(
+ c->mem, c->crypto_connections, num, sizeof(Crypto_Connection));
if (newcrypto_connections == nullptr) {
return -1;
@@ -1827,7 +1827,6 @@ static int realloc_cryptoconnection(Net_Crypto *c, uint32_t num)
return 0;
}
-
/** @brief Create a new empty crypto connection.
*
* @retval -1 on failure.
@@ -1864,25 +1863,26 @@ static int create_crypto_connection(Net_Crypto *c)
}
if (id != -1) {
- // Memsetting float/double to 0 is non-portable, so we explicitly set them to 0
- c->crypto_connections[id].packet_recv_rate = 0;
- c->crypto_connections[id].packet_send_rate = 0;
- c->crypto_connections[id].last_packets_left_rem = 0;
- c->crypto_connections[id].packet_send_rate_requested = 0;
- c->crypto_connections[id].last_packets_left_requested_rem = 0;
- c->crypto_connections[id].mutex = (pthread_mutex_t *)calloc(1, sizeof(pthread_mutex_t));
-
- if (c->crypto_connections[id].mutex == nullptr) {
+ pthread_mutex_t *mutex = (pthread_mutex_t *)mem_alloc(c->mem, sizeof(pthread_mutex_t));
+
+ if (mutex == nullptr) {
pthread_mutex_unlock(&c->connections_mutex);
return -1;
}
- if (pthread_mutex_init(c->crypto_connections[id].mutex, nullptr) != 0) {
- free(c->crypto_connections[id].mutex);
+ if (pthread_mutex_init(mutex, nullptr) != 0) {
+ mem_delete(c->mem, mutex);
pthread_mutex_unlock(&c->connections_mutex);
return -1;
}
+ // Memsetting float/double to 0 is non-portable, so we explicitly set them to 0
+ c->crypto_connections[id].packet_recv_rate = 0.0;
+ c->crypto_connections[id].packet_send_rate = 0.0;
+ c->crypto_connections[id].last_packets_left_rem = 0.0;
+ c->crypto_connections[id].packet_send_rate_requested = 0.0;
+ c->crypto_connections[id].last_packets_left_requested_rem = 0.0;
+ c->crypto_connections[id].mutex = mutex;
c->crypto_connections[id].status = CRYPTO_CONN_NO_CONNECTION;
}
@@ -1915,7 +1915,7 @@ static int wipe_crypto_connection(Net_Crypto *c, int crypt_connection_id)
uint32_t i;
pthread_mutex_destroy(c->crypto_connections[crypt_connection_id].mutex);
- free(c->crypto_connections[crypt_connection_id].mutex);
+ mem_delete(c->mem, c->crypto_connections[crypt_connection_id].mutex);
crypto_memzero(&c->crypto_connections[crypt_connection_id], sizeof(Crypto_Connection));
/* check if we can resize the connections array */
@@ -1995,7 +1995,6 @@ static int crypto_connection_add_source(Net_Crypto *c, int crypt_connection_id,
return -1;
}
-
/** @brief Set function to be called when someone requests a new connection to us.
*
* The set function should return -1 on failure and 0 on success.
@@ -2018,19 +2017,20 @@ non_null(1, 2, 3) nullable(5)
static int handle_new_connection_handshake(Net_Crypto *c, const IP_Port *source, const uint8_t *data, uint16_t length,
void *userdata)
{
- New_Connection n_c;
- n_c.cookie = (uint8_t *)malloc(COOKIE_LENGTH);
+ uint8_t *cookie = (uint8_t *)mem_balloc(c->mem, COOKIE_LENGTH);
- if (n_c.cookie == nullptr) {
+ if (cookie == nullptr) {
return -1;
}
+ New_Connection n_c = {{{{0}}}};
+ n_c.cookie = cookie;
n_c.source = *source;
n_c.cookie_length = COOKIE_LENGTH;
if (!handle_crypto_handshake(c, n_c.recv_nonce, n_c.peersessionpublic_key, n_c.public_key, n_c.dht_public_key,
n_c.cookie, data, length, nullptr)) {
- free(n_c.cookie);
+ mem_delete(c->mem, n_c.cookie);
return -1;
}
@@ -2047,7 +2047,7 @@ static int handle_new_connection_handshake(Net_Crypto *c, const IP_Port *source,
connection_kill(c, crypt_connection_id, userdata);
} else {
if (conn->status != CRYPTO_CONN_COOKIE_REQUESTING && conn->status != CRYPTO_CONN_HANDSHAKE_SENT) {
- free(n_c.cookie);
+ mem_delete(c->mem, n_c.cookie);
return -1;
}
@@ -2058,18 +2058,18 @@ static int handle_new_connection_handshake(Net_Crypto *c, const IP_Port *source,
crypto_connection_add_source(c, crypt_connection_id, source);
if (create_send_handshake(c, crypt_connection_id, n_c.cookie, n_c.dht_public_key) != 0) {
- free(n_c.cookie);
+ mem_delete(c->mem, n_c.cookie);
return -1;
}
conn->status = CRYPTO_CONN_NOT_CONFIRMED;
- free(n_c.cookie);
+ mem_delete(c->mem, n_c.cookie);
return 0;
}
}
const int ret = c->new_connection_callback(c->new_connection_callback_object, &n_c);
- free(n_c.cookie);
+ mem_delete(c->mem, n_c.cookie);
return ret;
}
@@ -2221,9 +2221,8 @@ int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, const IP_Port *ip
return 0;
}
-
non_null(1, 3) nullable(5)
-static int tcp_data_callback(void *object, int crypt_connection_id, const uint8_t *data, uint16_t length,
+static int tcp_data_callback(void *object, int crypt_connection_id, const uint8_t *packet, uint16_t length,
void *userdata)
{
Net_Crypto *c = (Net_Crypto *)object;
@@ -2238,14 +2237,14 @@ static int tcp_data_callback(void *object, int crypt_connection_id, const uint8_
return -1;
}
- if (data[0] == NET_PACKET_COOKIE_REQUEST) {
- return tcp_handle_cookie_request(c, conn->connection_number_tcp, data, length);
+ if (packet[0] == NET_PACKET_COOKIE_REQUEST) {
+ return tcp_handle_cookie_request(c, conn->connection_number_tcp, packet, length);
}
// This unlocks the mutex that at this point is locked by do_tcp before
// calling do_tcp_connections.
pthread_mutex_unlock(&c->tcp_mutex);
- const int ret = handle_packet_connection(c, crypt_connection_id, data, length, false, userdata);
+ const int ret = handle_packet_connection(c, crypt_connection_id, packet, length, false, userdata);
pthread_mutex_lock(&c->tcp_mutex);
if (ret != 0) {
@@ -2258,7 +2257,7 @@ static int tcp_data_callback(void *object, int crypt_connection_id, const uint8_
non_null(1, 2, 4) nullable(6)
static int tcp_oob_callback(void *object, const uint8_t *public_key, unsigned int tcp_connections_number,
- const uint8_t *data, uint16_t length, void *userdata)
+ const uint8_t *packet, uint16_t length, void *userdata)
{
Net_Crypto *c = (Net_Crypto *)object;
@@ -2266,14 +2265,14 @@ static int tcp_oob_callback(void *object, const uint8_t *public_key, unsigned in
return -1;
}
- if (data[0] == NET_PACKET_COOKIE_REQUEST) {
- return tcp_oob_handle_cookie_request(c, tcp_connections_number, public_key, data, length);
+ if (packet[0] == NET_PACKET_COOKIE_REQUEST) {
+ return tcp_oob_handle_cookie_request(c, tcp_connections_number, public_key, packet, length);
}
- if (data[0] == NET_PACKET_CRYPTO_HS) {
- IP_Port source = tcp_connections_number_to_ip_port(tcp_connections_number);
+ if (packet[0] == NET_PACKET_CRYPTO_HS) {
+ const IP_Port source = tcp_connections_number_to_ip_port(tcp_connections_number);
- if (handle_new_connection_handshake(c, &source, data, length, userdata) != 0) {
+ if (handle_new_connection_handshake(c, &source, packet, length, userdata) != 0) {
return -1;
}
@@ -2374,7 +2373,7 @@ int send_tcp_forward_request(const Logger *logger, Net_Crypto *c, const IP_Port
{
pthread_mutex_lock(&c->tcp_mutex);
const int ret = tcp_send_forward_request(logger, c->tcp_c, tcp_forwarder, dht_node,
- chain_keys, chain_length, data, data_length);
+ chain_keys, chain_length, data, data_length);
pthread_mutex_unlock(&c->tcp_mutex);
return ret;
@@ -2515,7 +2514,6 @@ int connection_lossy_data_handler(const Net_Crypto *c, int crypt_connection_id,
return 0;
}
-
/** @brief Set the function for this friend that will be callbacked with object and number if
* the friend sends us a different dht public key than we have associated to him.
*
@@ -2809,8 +2807,8 @@ static void send_crypto_packets(Net_Crypto *c)
1000.0);
n_packets += conn->last_packets_left_requested_rem;
- uint32_t num_packets = n_packets;
- double rem = n_packets - (double)num_packets;
+ const uint32_t num_packets = n_packets;
+ const double rem = n_packets - (double)num_packets;
conn->packets_left_requested = num_packets;
conn->last_packets_left_requested_set = temp_time;
@@ -3045,8 +3043,8 @@ int crypto_kill(Net_Crypto *c, int crypt_connection_id)
bs_list_remove(&c->ip_port_list, (uint8_t *)&conn->ip_portv4, crypt_connection_id);
bs_list_remove(&c->ip_port_list, (uint8_t *)&conn->ip_portv6, crypt_connection_id);
clear_temp_packet(c, crypt_connection_id);
- clear_buffer(&conn->send_array);
- clear_buffer(&conn->recv_array);
+ clear_buffer(c->mem, &conn->send_array);
+ clear_buffer(c->mem, &conn->recv_array);
ret = wipe_crypto_connection(c, crypt_connection_id);
}
@@ -3067,9 +3065,8 @@ bool crypto_connection_status(const Net_Crypto *c, int crypt_connection_id, bool
const uint64_t current_time = mono_time_get(c->mono_time);
- if ((UDP_DIRECT_TIMEOUT + conn->direct_lastrecv_timev4) > current_time) {
- *direct_connected = true;
- } else if ((UDP_DIRECT_TIMEOUT + conn->direct_lastrecv_timev6) > current_time) {
+ if ((UDP_DIRECT_TIMEOUT + conn->direct_lastrecv_timev4) > current_time ||
+ (UDP_DIRECT_TIMEOUT + conn->direct_lastrecv_timev6) > current_time) {
*direct_connected = true;
}
}
@@ -3109,27 +3106,29 @@ void load_secret_key(Net_Crypto *c, const uint8_t *sk)
/** @brief Create new instance of Net_Crypto.
* Sets all the global connection variables to their default values.
*/
-Net_Crypto *new_net_crypto(const Logger *log, const Random *rng, const Network *ns, Mono_Time *mono_time, DHT *dht, const TCP_Proxy_Info *proxy_info)
+Net_Crypto *new_net_crypto(const Logger *log, const Memory *mem, const Random *rng, const Network *ns,
+ Mono_Time *mono_time, DHT *dht, const TCP_Proxy_Info *proxy_info)
{
if (dht == nullptr) {
return nullptr;
}
- Net_Crypto *temp = (Net_Crypto *)calloc(1, sizeof(Net_Crypto));
+ Net_Crypto *temp = (Net_Crypto *)mem_alloc(mem, sizeof(Net_Crypto));
if (temp == nullptr) {
return nullptr;
}
temp->log = log;
+ temp->mem = mem;
temp->rng = rng;
temp->mono_time = mono_time;
temp->ns = ns;
- temp->tcp_c = new_tcp_connections(log, rng, ns, mono_time, dht_get_self_secret_key(dht), proxy_info);
+ temp->tcp_c = new_tcp_connections(log, mem, rng, ns, mono_time, dht_get_self_secret_key(dht), proxy_info);
if (temp->tcp_c == nullptr) {
- free(temp);
+ mem_delete(mem, temp);
return nullptr;
}
@@ -3139,7 +3138,7 @@ Net_Crypto *new_net_crypto(const Logger *log, const Random *rng, const Network *
if (create_recursive_mutex(&temp->tcp_mutex) != 0 ||
pthread_mutex_init(&temp->connections_mutex, nullptr) != 0) {
kill_tcp_connections(temp->tcp_c);
- free(temp);
+ mem_delete(mem, temp);
return nullptr;
}
@@ -3155,7 +3154,7 @@ Net_Crypto *new_net_crypto(const Logger *log, const Random *rng, const Network *
networking_registerhandler(dht_get_net(dht), NET_PACKET_CRYPTO_HS, &udp_handle_packet, temp);
networking_registerhandler(dht_get_net(dht), NET_PACKET_CRYPTO_DATA, &udp_handle_packet, temp);
- bs_list_init(&temp->ip_port_list, sizeof(IP_Port), 8);
+ bs_list_init(&temp->ip_port_list, sizeof(IP_Port), 8, ipport_cmp_handler);
return temp;
}
@@ -3186,7 +3185,7 @@ static void kill_timedout(Net_Crypto *c, void *userdata)
/* do_timeout_here(); */
}
-#endif
+#endif /* 0 */
}
}
@@ -3210,6 +3209,8 @@ void kill_net_crypto(Net_Crypto *c)
return;
}
+ const Memory *mem = c->mem;
+
for (uint32_t i = 0; i < c->crypto_connections_length; ++i) {
crypto_kill(c, i);
}
@@ -3224,5 +3225,5 @@ void kill_net_crypto(Net_Crypto *c)
networking_registerhandler(dht_get_net(c->dht), NET_PACKET_CRYPTO_HS, nullptr, nullptr);
networking_registerhandler(dht_get_net(c->dht), NET_PACKET_CRYPTO_DATA, nullptr, nullptr);
crypto_memzero(c, sizeof(Net_Crypto));
- free(c);
+ mem_delete(mem, c);
}
diff --git a/protocols/Tox/libtox/src/toxcore/net_crypto.h b/protocols/Tox/libtox/src/toxcore/net_crypto.h
index 0c3dfd0d45..0d817e4315 100644
--- a/protocols/Tox/libtox/src/toxcore/net_crypto.h
+++ b/protocols/Tox/libtox/src/toxcore/net_crypto.h
@@ -13,8 +13,14 @@
#include "DHT.h"
#include "LAN_discovery.h"
+#include "TCP_client.h"
#include "TCP_connection.h"
+#include "attributes.h"
+#include "crypto_core.h"
#include "logger.h"
+#include "mem.h"
+#include "mono_time.h"
+#include "network.h"
/*** Crypto payloads. */
@@ -43,29 +49,30 @@
/*** Messages. */
-#define PACKET_ID_PADDING 0 // Denotes padding
-#define PACKET_ID_REQUEST 1 // Used to request unreceived packets
-#define PACKET_ID_KILL 2 // Used to kill connection
-
-#define PACKET_ID_ONLINE 24
-#define PACKET_ID_OFFLINE 25
-#define PACKET_ID_NICKNAME 48
-#define PACKET_ID_STATUSMESSAGE 49
-#define PACKET_ID_USERSTATUS 50
-#define PACKET_ID_TYPING 51
-#define PACKET_ID_MESSAGE 64
-#define PACKET_ID_ACTION 65 // PACKET_ID_MESSAGE + MESSAGE_ACTION
-#define PACKET_ID_MSI 69 // Used by AV to setup calls and etc
-#define PACKET_ID_FILE_SENDREQUEST 80
-#define PACKET_ID_FILE_CONTROL 81
-#define PACKET_ID_FILE_DATA 82
-#define PACKET_ID_INVITE_GROUPCHAT 95
-#define PACKET_ID_INVITE_CONFERENCE 96
-#define PACKET_ID_ONLINE_PACKET 97
-#define PACKET_ID_DIRECT_CONFERENCE 98
-#define PACKET_ID_MESSAGE_CONFERENCE 99
-#define PACKET_ID_REJOIN_CONFERENCE 100
-#define PACKET_ID_LOSSY_CONFERENCE 199
+typedef enum Packet_Id {
+ PACKET_ID_REQUEST = 1, // Used to request unreceived packets
+ PACKET_ID_KILL = 2, // Used to kill connection
+
+ PACKET_ID_ONLINE = 24,
+ PACKET_ID_OFFLINE = 25,
+ PACKET_ID_NICKNAME = 48,
+ PACKET_ID_STATUSMESSAGE = 49,
+ PACKET_ID_USERSTATUS = 50,
+ PACKET_ID_TYPING = 51,
+ PACKET_ID_MESSAGE = 64,
+ PACKET_ID_ACTION = 65, // PACKET_ID_MESSAGE + MESSAGE_ACTION
+ PACKET_ID_MSI = 69, // Used by AV to setup calls and etc
+ PACKET_ID_FILE_SENDREQUEST = 80,
+ PACKET_ID_FILE_CONTROL = 81,
+ PACKET_ID_FILE_DATA = 82,
+ PACKET_ID_INVITE_GROUPCHAT = 95,
+ PACKET_ID_INVITE_CONFERENCE = 96,
+ PACKET_ID_ONLINE_PACKET = 97,
+ PACKET_ID_DIRECT_CONFERENCE = 98,
+ PACKET_ID_MESSAGE_CONFERENCE = 99,
+ PACKET_ID_REJOIN_CONFERENCE = 100,
+ PACKET_ID_LOSSY_CONFERENCE = 199,
+} Packet_Id;
/** Maximum size of receiving and sending packet buffers. */
#define CRYPTO_PACKET_BUFFER_SIZE 32768 // Must be a power of 2
@@ -133,7 +140,7 @@ typedef struct New_Connection {
typedef int connection_status_cb(void *object, int id, bool status, void *userdata);
typedef int connection_data_cb(void *object, int id, const uint8_t *data, uint16_t length, void *userdata);
typedef int connection_lossy_data_cb(void *object, int id, const uint8_t *data, uint16_t length, void *userdata);
-typedef void dht_pk_cb(void *data, int32_t number, const uint8_t *dht_public_key, void *userdata);
+typedef void dht_pk_cb(void *object, int32_t number, const uint8_t *dht_public_key, void *userdata);
typedef int new_connection_cb(void *object, const New_Connection *n_c);
/** @brief Set function to be called when someone requests a new connection to us.
@@ -198,7 +205,6 @@ non_null()
int connection_data_handler(const Net_Crypto *c, int crypt_connection_id,
connection_data_cb *connection_data_callback, void *object, int id);
-
/** @brief Set function to be called when connection with crypt_connection_id receives a lossy data packet of length.
*
* The set function should return -1 on failure and 0 on success.
@@ -398,7 +404,8 @@ void load_secret_key(Net_Crypto *c, const uint8_t *sk);
* Sets all the global connection variables to their default values.
*/
non_null()
-Net_Crypto *new_net_crypto(const Logger *log, const Random *rng, const Network *ns, Mono_Time *mono_time, DHT *dht, const TCP_Proxy_Info *proxy_info);
+Net_Crypto *new_net_crypto(const Logger *log, const Memory *mem, const Random *rng, const Network *ns,
+ Mono_Time *mono_time, DHT *dht, const TCP_Proxy_Info *proxy_info);
/** return the optimal interval in ms for running do_net_crypto. */
non_null()
@@ -411,4 +418,4 @@ void do_net_crypto(Net_Crypto *c, void *userdata);
nullable(1)
void kill_net_crypto(Net_Crypto *c);
-#endif
+#endif /* C_TOXCORE_TOXCORE_NET_CRYPTO_H */
diff --git a/protocols/Tox/libtox/src/toxcore/network.c b/protocols/Tox/libtox/src/toxcore/network.c
index 8544496c1c..55aa4e2818 100644
--- a/protocols/Tox/libtox/src/toxcore/network.c
+++ b/protocols/Tox/libtox/src/toxcore/network.c
@@ -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.
*/
@@ -9,40 +9,34 @@
#ifdef __APPLE__
#define _DARWIN_C_SOURCE
-#endif
+#endif /* __APPLE__ */
// For Solaris.
#ifdef __sun
#define __EXTENSIONS__ 1
-#endif
+#endif /* __sun */
// For Linux (and some BSDs).
#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE 700
-#endif
+#endif /* _XOPEN_SOURCE */
-#if defined(_WIN32) && _WIN32_WINNT >= _WIN32_WINNT_WINXP
+#if defined(_WIN32) && defined(_WIN32_WINNT) && defined(_WIN32_WINNT_WINXP) && _WIN32_WINNT >= _WIN32_WINNT_WINXP
#undef _WIN32_WINNT
#define _WIN32_WINNT 0x501
-#endif
+#endif /* defined(_WIN32) && defined(_WIN32_WINNT) && defined(_WIN32_WINNT_WINXP) && _WIN32_WINNT >= _WIN32_WINNT_WINXP */
#if !defined(OS_WIN32) && (defined(_WIN32) || defined(__WIN32__) || defined(WIN32))
#define OS_WIN32
-#endif
+#endif /* !defined(OS_WIN32) && (defined(_WIN32) || defined(__WIN32__) || defined(WIN32)) */
#if defined(OS_WIN32) && !defined(WINVER)
// Windows XP
#define WINVER 0x0501
-#endif
+#endif /* defined(OS_WIN32) && !defined(WINVER) */
#include "network.h"
-#ifdef PLAN9
-#include <u.h> // Plan 9 requires this is imported first
-// Comment line here to avoid reordering by source code formatters.
-#include <libc.h>
-#endif
-
#ifdef OS_WIN32 // Put win32 includes here
// The mingw32/64 Windows library warns about including winsock2.h after
// windows.h even though with the above it's a valid thing to do. So, to make
@@ -51,12 +45,12 @@
// Comment line here to avoid reordering by source code formatters.
#include <windows.h>
#include <ws2tcpip.h>
-#endif
+#endif /* OS_WIN32 */
#ifdef __APPLE__
#include <mach/clock.h>
#include <mach/mach.h>
-#endif
+#endif /* __APPLE__ */
#if !defined(OS_WIN32)
#include <arpa/inet.h>
@@ -73,13 +67,13 @@
#ifdef __sun
#include <stropts.h>
#include <sys/filio.h>
-#endif
+#endif /* __sun */
#else
#ifndef IPV6_V6ONLY
#define IPV6_V6ONLY 27
-#endif
-#endif
+#endif /* IPV6_V6ONLY */
+#endif /* !defined(OS_WIN32) */
#include <assert.h>
#include <limits.h>
@@ -87,26 +81,23 @@
#include <stdlib.h>
#include <string.h>
-#ifndef VANILLA_NACL
-// Used for sodium_init()
-#include <sodium.h>
-#endif
-
+#include "attributes.h"
+#include "bin_pack.h"
#include "ccompat.h"
#include "logger.h"
-#include "mono_time.h"
+#include "mem.h"
#include "util.h"
// Disable MSG_NOSIGNAL on systems not supporting it, e.g. Windows, FreeBSD
#if !defined(MSG_NOSIGNAL)
#define MSG_NOSIGNAL 0
-#endif
+#endif /* !defined(MSG_NOSIGNAL) */
#ifndef IPV6_ADD_MEMBERSHIP
#ifdef IPV6_JOIN_GROUP
#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
-#endif
-#endif
+#endif /* IPV6_JOIN_GROUP */
+#endif /* IPV6_ADD_MEMBERSHIP */
static_assert(sizeof(IP4) == SIZE_IP4, "IP4 size must be 4");
@@ -139,21 +130,21 @@ static const char *inet_ntop6(const struct in6_addr *addr, char *buf, size_t buf
}
non_null()
-static int inet_pton4(const char *addrString, struct in_addr *addrbuf)
+static int inet_pton4(const char *addr_string, struct in_addr *addrbuf)
{
- return inet_pton(AF_INET, addrString, addrbuf);
+ return inet_pton(AF_INET, addr_string, addrbuf);
}
non_null()
-static int inet_pton6(const char *addrString, struct in6_addr *addrbuf)
+static int inet_pton6(const char *addr_string, struct in6_addr *addrbuf)
{
- return inet_pton(AF_INET6, addrString, addrbuf);
+ return inet_pton(AF_INET6, addr_string, addrbuf);
}
#else
#ifndef IPV6_V6ONLY
#define IPV6_V6ONLY 27
-#endif
+#endif /* IPV6_V6ONLY */
static bool should_ignore_recv_error(int err)
{
@@ -233,7 +224,7 @@ static int inet_pton6(const char *addrString, struct in6_addr *addrbuf)
return 1;
}
-#endif
+#endif /* !defined(OS_WIN32) */
static_assert(TOX_INET6_ADDRSTRLEN >= INET6_ADDRSTRLEN,
"TOX_INET6_ADDRSTRLEN should be greater or equal to INET6_ADDRSTRLEN (#INET6_ADDRSTRLEN)");
@@ -342,15 +333,21 @@ static void fill_addr6(const IP6 *ip, struct in6_addr *addr)
#if !defined(INADDR_LOOPBACK)
#define INADDR_LOOPBACK 0x7f000001
-#endif
+#endif /* !defined(INADDR_LOOPBACK) */
-static const IP empty_ip = {{0}};
-const IP_Port empty_ip_port = {{{0}}};
+IP4 get_ip4_broadcast(void)
+{
+ const IP4 ip4_broadcast = { INADDR_BROADCAST };
+ return ip4_broadcast;
+}
-const IP4 ip4_broadcast = { INADDR_BROADCAST };
-const IP6 ip6_broadcast = {
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }
-};
+IP6 get_ip6_broadcast(void)
+{
+ const IP6 ip6_broadcast = {
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }
+ };
+ return ip6_broadcast;
+}
IP4 get_ip4_loopback(void)
{
@@ -361,63 +358,73 @@ IP4 get_ip4_loopback(void)
IP6 get_ip6_loopback(void)
{
- IP6 loopback;
-#ifdef ESP_PLATFORM
- loopback = empty_ip_port.ip.ip.v6;
+ /* in6addr_loopback isn't available everywhere, so we do it ourselves. */
+ IP6 loopback = {{0}};
loopback.uint8[15] = 1;
-#else
- get_ip6(&loopback, &in6addr_loopback);
-#endif
return loopback;
}
#ifndef OS_WIN32
#define INVALID_SOCKET (-1)
-#endif
+#endif /* OS_WIN32 */
-const Socket net_invalid_socket = { (int)INVALID_SOCKET };
+int net_socket_to_native(Socket sock)
+{
+ return (force int)sock.value;
+}
-Family net_family_unspec()
+Socket net_socket_from_native(int sock)
+{
+ const Socket res = {(force Socket_Value)sock};
+ return res;
+}
+
+Socket net_invalid_socket(void)
+{
+ return net_socket_from_native(INVALID_SOCKET);
+}
+
+Family net_family_unspec(void)
{
return family_unspec;
}
-Family net_family_ipv4()
+Family net_family_ipv4(void)
{
return family_ipv4;
}
-Family net_family_ipv6()
+Family net_family_ipv6(void)
{
return family_ipv6;
}
-Family net_family_tcp_server()
+Family net_family_tcp_server(void)
{
return family_tcp_server;
}
-Family net_family_tcp_client()
+Family net_family_tcp_client(void)
{
return family_tcp_client;
}
-Family net_family_tcp_ipv4()
+Family net_family_tcp_ipv4(void)
{
return family_tcp_ipv4;
}
-Family net_family_tcp_ipv6()
+Family net_family_tcp_ipv6(void)
{
return family_tcp_ipv6;
}
-Family net_family_tox_tcp_ipv4()
+Family net_family_tox_tcp_ipv4(void)
{
return family_tox_tcp_ipv4;
}
-Family net_family_tox_tcp_ipv6()
+Family net_family_tox_tcp_ipv6(void)
{
return family_tox_tcp_ipv6;
}
@@ -469,7 +476,8 @@ bool net_family_is_tox_tcp_ipv6(Family family)
bool sock_valid(Socket sock)
{
- return sock.sock != net_invalid_socket.sock;
+ const Socket invalid_socket = net_invalid_socket();
+ return sock.value != invalid_socket.value;
}
struct Network_Addr {
@@ -478,105 +486,107 @@ struct Network_Addr {
};
non_null()
-static int sys_close(void *obj, int sock)
+static int sys_close(void *obj, Socket sock)
{
#if defined(OS_WIN32)
- return closesocket(sock);
+ return closesocket(net_socket_to_native(sock));
#else // !OS_WIN32
- return close(sock);
-#endif
+ return close(net_socket_to_native(sock));
+#endif /* OS_WIN32 */
}
non_null()
-static int sys_accept(void *obj, int sock)
+static Socket sys_accept(void *obj, Socket sock)
{
- return accept(sock, nullptr, nullptr);
+ return net_socket_from_native(accept(net_socket_to_native(sock), nullptr, nullptr));
}
non_null()
-static int sys_bind(void *obj, int sock, const Network_Addr *addr)
+static int sys_bind(void *obj, Socket sock, const Network_Addr *addr)
{
- return bind(sock, (const struct sockaddr *)&addr->addr, addr->size);
+ return bind(net_socket_to_native(sock), (const struct sockaddr *)&addr->addr, addr->size);
}
non_null()
-static int sys_listen(void *obj, int sock, int backlog)
+static int sys_listen(void *obj, Socket sock, int backlog)
{
- return listen(sock, backlog);
+ return listen(net_socket_to_native(sock), backlog);
}
non_null()
-static int sys_recvbuf(void *obj, int sock)
+static int sys_recvbuf(void *obj, Socket sock)
{
#ifdef OS_WIN32
u_long count = 0;
- ioctlsocket(sock, FIONREAD, &count);
+ ioctlsocket(net_socket_to_native(sock), FIONREAD, &count);
#else
int count = 0;
- ioctl(sock, FIONREAD, &count);
-#endif
+ ioctl(net_socket_to_native(sock), FIONREAD, &count);
+#endif /* OS_WIN32 */
return count;
}
non_null()
-static int sys_recv(void *obj, int sock, uint8_t *buf, size_t len)
+static int sys_recv(void *obj, Socket sock, uint8_t *buf, size_t len)
{
- return recv(sock, (char *)buf, len, MSG_NOSIGNAL);
+ return recv(net_socket_to_native(sock), (char *)buf, len, MSG_NOSIGNAL);
}
non_null()
-static int sys_send(void *obj, int sock, const uint8_t *buf, size_t len)
+static int sys_send(void *obj, Socket sock, const uint8_t *buf, size_t len)
{
- return send(sock, (const char *)buf, len, MSG_NOSIGNAL);
+ return send(net_socket_to_native(sock), (const char *)buf, len, MSG_NOSIGNAL);
}
non_null()
-static int sys_sendto(void *obj, int sock, const uint8_t *buf, size_t len, const Network_Addr *addr) {
- return sendto(sock, (const char *)buf, len, 0, (const struct sockaddr *)&addr->addr, addr->size);
+static int sys_sendto(void *obj, Socket sock, const uint8_t *buf, size_t len, const Network_Addr *addr)
+{
+ return sendto(net_socket_to_native(sock), (const char *)buf, len, 0, (const struct sockaddr *)&addr->addr, addr->size);
}
non_null()
-static int sys_recvfrom(void *obj, int sock, uint8_t *buf, size_t len, Network_Addr *addr) {
+static int sys_recvfrom(void *obj, Socket sock, uint8_t *buf, size_t len, Network_Addr *addr)
+{
socklen_t size = addr->size;
- const int ret = recvfrom(sock, (char *)buf, len, 0, (struct sockaddr *)&addr->addr, &size);
+ const int ret = recvfrom(net_socket_to_native(sock), (char *)buf, len, 0, (struct sockaddr *)&addr->addr, &size);
addr->size = size;
return ret;
}
non_null()
-static int sys_socket(void *obj, int domain, int type, int proto)
+static Socket sys_socket(void *obj, int domain, int type, int proto)
{
- return (int)socket(domain, type, proto);
+ return net_socket_from_native(socket(domain, type, proto));
}
non_null()
-static int sys_socket_nonblock(void *obj, int sock, bool nonblock)
+static int sys_socket_nonblock(void *obj, Socket sock, bool nonblock)
{
#ifdef OS_WIN32
u_long mode = nonblock ? 1 : 0;
- return ioctlsocket(sock, FIONBIO, &mode);
+ return ioctlsocket(net_socket_to_native(sock), FIONBIO, &mode);
#else
- return fcntl(sock, F_SETFL, O_NONBLOCK, nonblock ? 1 : 0);
+ return fcntl(net_socket_to_native(sock), F_SETFL, O_NONBLOCK, nonblock ? 1 : 0);
#endif /* OS_WIN32 */
}
non_null()
-static int sys_getsockopt(void *obj, int sock, int level, int optname, void *optval, size_t *optlen)
+static int sys_getsockopt(void *obj, Socket sock, int level, int optname, void *optval, size_t *optlen)
{
socklen_t len = *optlen;
- const int ret = getsockopt(sock, level, optname, optval, &len);
+ const int ret = getsockopt(net_socket_to_native(sock), level, optname, (char *)optval, &len);
*optlen = len;
return ret;
}
non_null()
-static int sys_setsockopt(void *obj, int sock, int level, int optname, const void *optval, size_t optlen)
+static int sys_setsockopt(void *obj, Socket sock, int level, int optname, const void *optval, size_t optlen)
{
- return setsockopt(sock, level, optname, optval, optlen);
+ return setsockopt(net_socket_to_native(sock), level, optname, (const char *)optval, optlen);
}
-static const Network_Funcs system_network_funcs = {
+static const Network_Funcs os_network_funcs = {
sys_close,
sys_accept,
sys_bind,
@@ -591,45 +601,45 @@ static const Network_Funcs system_network_funcs = {
sys_getsockopt,
sys_setsockopt,
};
-static const Network system_network_obj = {&system_network_funcs};
+static const Network os_network_obj = {&os_network_funcs};
-const Network *system_network(void)
+const Network *os_network(void)
{
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
if ((true)) {
return nullptr;
}
-#endif
+#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
#ifdef OS_WIN32
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != NO_ERROR) {
return nullptr;
}
-#endif
- return &system_network_obj;
+#endif /* OS_WIN32 */
+ return &os_network_obj;
}
#if 0
-/* TODO(iphydf): Call this from functions that use `system_network()`. */
-void system_network_deinit(const Network *ns)
+/* TODO(iphydf): Call this from functions that use `os_network()`. */
+void os_network_deinit(const Network *ns)
{
#ifdef OS_WIN32
WSACleanup();
-#endif
+#endif /* OS_WIN32 */
}
-#endif
+#endif /* 0 */
non_null()
static int net_setsockopt(const Network *ns, Socket sock, int level, int optname, const void *optval, size_t optlen)
{
- return ns->funcs->setsockopt(ns->obj, sock.sock, level, optname, optval, optlen);
+ return ns->funcs->setsockopt(ns->obj, sock, level, optname, optval, optlen);
}
non_null()
static int net_getsockopt(const Network *ns, Socket sock, int level, int optname, void *optval, size_t *optlen)
{
- return ns->funcs->getsockopt(ns->obj, sock.sock, level, optname, optval, optlen);
+ return ns->funcs->getsockopt(ns->obj, sock, level, optname, optval, optlen);
}
non_null()
@@ -778,7 +788,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 +796,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",
@@ -804,23 +814,23 @@ static void loglogdata(const Logger *log, const char *message, const uint8_t *bu
int net_send(const Network *ns, const Logger *log,
Socket sock, const uint8_t *buf, size_t len, const IP_Port *ip_port)
{
- const int res = ns->funcs->send(ns->obj, sock.sock, buf, len);
+ const int res = ns->funcs->send(ns->obj, sock, buf, len);
loglogdata(log, "T=>", buf, len, ip_port, res);
return res;
}
non_null()
static int net_sendto(
- const Network *ns,
- Socket sock, const uint8_t *buf, size_t len, const Network_Addr *addr, const IP_Port *ip_port)
+ const Network *ns,
+ Socket sock, const uint8_t *buf, size_t len, const Network_Addr *addr, const IP_Port *ip_port)
{
- return ns->funcs->sendto(ns->obj, sock.sock, buf, len, addr);
+ return ns->funcs->sendto(ns->obj, sock, buf, len, addr);
}
int net_recv(const Network *ns, const Logger *log,
Socket sock, uint8_t *buf, size_t len, const IP_Port *ip_port)
{
- const int res = ns->funcs->recv(ns->obj, sock.sock, buf, len);
+ const int res = ns->funcs->recv(ns->obj, sock, buf, len);
loglogdata(log, "=>T", buf, len, ip_port, res);
return res;
}
@@ -829,35 +839,34 @@ non_null()
static int net_recvfrom(const Network *ns,
Socket sock, uint8_t *buf, size_t len, Network_Addr *addr)
{
- return ns->funcs->recvfrom(ns->obj, sock.sock, buf, len, addr);
+ return ns->funcs->recvfrom(ns->obj, sock, buf, len, addr);
}
int net_listen(const Network *ns, Socket sock, int backlog)
{
- return ns->funcs->listen(ns->obj, sock.sock, backlog);
+ return ns->funcs->listen(ns->obj, sock, backlog);
}
non_null()
static int net_bind(const Network *ns, Socket sock, const Network_Addr *addr)
{
- return ns->funcs->bind(ns->obj, sock.sock, addr);
+ return ns->funcs->bind(ns->obj, sock, addr);
}
Socket net_accept(const Network *ns, Socket sock)
{
- const Socket newsock = {ns->funcs->accept(ns->obj, sock.sock)};
- return newsock;
+ return ns->funcs->accept(ns->obj, sock);
}
/** Close the socket. */
void kill_sock(const Network *ns, Socket sock)
{
- ns->funcs->close(ns->obj, sock.sock);
+ ns->funcs->close(ns->obj, sock);
}
bool set_socket_nonblock(const Network *ns, Socket sock)
{
- return ns->funcs->socket_nonblock(ns->obj, sock.sock, true) == 0;
+ return ns->funcs->socket_nonblock(ns->obj, sock, true) == 0;
}
bool set_socket_nosigpipe(const Network *ns, Socket sock)
@@ -867,7 +876,7 @@ bool set_socket_nosigpipe(const Network *ns, Socket sock)
return net_setsockopt(ns, sock, SOL_SOCKET, SO_NOSIGPIPE, &set, sizeof(int)) == 0;
#else
return true;
-#endif
+#endif /* __APPLE__ */
}
bool set_socket_reuseaddr(const Network *ns, Socket sock)
@@ -890,7 +899,6 @@ bool set_socket_dualstack(const Network *ns, Socket sock)
return net_setsockopt(ns, sock, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6only, sizeof(ipv6only)) == 0;
}
-
typedef struct Packet_Handler {
packet_handler_cb *function;
void *object;
@@ -898,6 +906,7 @@ typedef struct Packet_Handler {
struct Networking_Core {
const Logger *log;
+ const Memory *mem;
Packet_Handler packethandlers[256];
const Network *ns;
@@ -941,8 +950,9 @@ int send_packet(const Networking_Core *net, const IP_Port *ip_port, Packet packe
if (net_family_is_ipv4(net->family) && !net_family_is_ipv4(ipp_copy.ip.family)) {
// TODO(iphydf): Make this an error. Occasionally we try to send to an
// all-zero ip_port.
- LOGGER_WARNING(net->log, "attempted to send message with network family %d (probably IPv6) on IPv4 socket",
- ipp_copy.ip.family.value);
+ Ip_Ntoa ip_str;
+ LOGGER_WARNING(net->log, "attempted to send message with network family %d (probably IPv6) on IPv4 socket (%s)",
+ ipp_copy.ip.family.value, net_ip_ntoa(&ipp_copy.ip, &ip_str));
return -1;
}
@@ -1009,7 +1019,7 @@ int sendpacket(const Networking_Core *net, const IP_Port *ip_port, const uint8_t
* Packet length is put into length.
*/
non_null()
-static int receivepacket(const Network *ns, const Logger *log, Socket sock, IP_Port *ip_port, uint8_t *data, uint32_t *length)
+static int receivepacket(const Network *ns, const Memory *mem, const Logger *log, Socket sock, IP_Port *ip_port, uint8_t *data, uint32_t *length)
{
memset(ip_port, 0, sizeof(IP_Port));
Network_Addr addr = {{0}};
@@ -1085,10 +1095,10 @@ void networking_poll(const Networking_Core *net, void *userdata)
}
IP_Port ip_port;
- uint8_t data[MAX_UDP_PACKET_SIZE];
+ uint8_t data[MAX_UDP_PACKET_SIZE] = {0};
uint32_t length;
- while (receivepacket(net->ns, net->log, net->sock, &ip_port, data, &length) != -1) {
+ while (receivepacket(net->ns, net->mem, net->log, net->sock, &ip_port, data, &length) != -1) {
if (length < 1) {
continue;
}
@@ -1117,8 +1127,8 @@ void networking_poll(const Networking_Core *net, void *userdata)
* If error is non NULL it is set to 0 if no issues, 1 if socket related error, 2 if other.
*/
Networking_Core *new_networking_ex(
- const Logger *log, const Network *ns, const IP *ip,
- uint16_t port_from, uint16_t port_to, unsigned int *error)
+ const Logger *log, const Memory *mem, const Network *ns, const IP *ip,
+ uint16_t port_from, uint16_t port_to, unsigned int *error)
{
/* If both from and to are 0, use default port range
* If one is 0 and the other is non-0, use the non-0 value as only port
@@ -1147,7 +1157,7 @@ Networking_Core *new_networking_ex(
return nullptr;
}
- Networking_Core *temp = (Networking_Core *)calloc(1, sizeof(Networking_Core));
+ Networking_Core *temp = (Networking_Core *)mem_alloc(mem, sizeof(Networking_Core));
if (temp == nullptr) {
return nullptr;
@@ -1155,6 +1165,7 @@ Networking_Core *new_networking_ex(
temp->ns = ns;
temp->log = log;
+ temp->mem = mem;
temp->family = ip->family;
temp->port = 0;
@@ -1168,7 +1179,7 @@ Networking_Core *new_networking_ex(
char *strerror = net_new_strerror(neterror);
LOGGER_ERROR(log, "failed to get a socket?! %d, %s", neterror, strerror);
net_kill_strerror(strerror);
- free(temp);
+ mem_delete(mem, temp);
if (error != nullptr) {
*error = 1;
@@ -1182,11 +1193,11 @@ Networking_Core *new_networking_ex(
int n = 1024 * 1024 * 2;
if (net_setsockopt(ns, temp->sock, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n)) != 0) {
- LOGGER_ERROR(log, "failed to set socket option %d", SO_RCVBUF);
+ LOGGER_WARNING(log, "failed to set socket option %d", SO_RCVBUF);
}
if (net_setsockopt(ns, temp->sock, SOL_SOCKET, SO_SNDBUF, &n, sizeof(n)) != 0) {
- LOGGER_ERROR(log, "failed to set socket option %d", SO_SNDBUF);
+ LOGGER_WARNING(log, "failed to set socket option %d", SO_SNDBUF);
}
/* Enable broadcast on socket */
@@ -1220,9 +1231,7 @@ Networking_Core *new_networking_ex(
/* Bind our socket to port PORT and the given IP address (usually 0.0.0.0 or ::) */
uint16_t *portptr = nullptr;
- Network_Addr addr;
-
- memset(&addr.addr, 0, sizeof(struct sockaddr_storage));
+ Network_Addr addr = {{0}};
if (net_family_is_ipv4(temp->family)) {
struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr.addr;
@@ -1246,7 +1255,7 @@ Networking_Core *new_networking_ex(
portptr = &addr6->sin6_port;
} else {
- free(temp);
+ mem_delete(mem, temp);
return nullptr;
}
@@ -1261,16 +1270,15 @@ Networking_Core *new_networking_ex(
#ifndef ESP_PLATFORM
/* multicast local nodes */
- struct ipv6_mreq mreq;
- memset(&mreq, 0, sizeof(mreq));
- mreq.ipv6mr_multiaddr.s6_addr[ 0] = 0xFF;
- mreq.ipv6mr_multiaddr.s6_addr[ 1] = 0x02;
+ struct ipv6_mreq mreq = {{{{0}}}};
+ mreq.ipv6mr_multiaddr.s6_addr[0] = 0xFF;
+ mreq.ipv6mr_multiaddr.s6_addr[1] = 0x02;
mreq.ipv6mr_multiaddr.s6_addr[15] = 0x01;
mreq.ipv6mr_interface = 0;
const int res = net_setsockopt(ns, temp->sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
- int neterror = net_error();
+ const int neterror = net_error();
char *strerror = net_new_strerror(neterror);
if (res < 0) {
@@ -1280,7 +1288,7 @@ Networking_Core *new_networking_ex(
}
net_kill_strerror(strerror);
-#endif
+#endif /* ESP_PLATFORM */
}
/* A hanging program or a different user might block the standard port.
@@ -1336,10 +1344,10 @@ Networking_Core *new_networking_ex(
}
Ip_Ntoa ip_str;
- int neterror = net_error();
+ const int neterror = net_error();
char *strerror = net_new_strerror(neterror);
- LOGGER_ERROR(log, "failed to bind socket: %d, %s IP: %s port_from: %u port_to: %u", neterror, strerror,
- net_ip_ntoa(ip, &ip_str), port_from, port_to);
+ LOGGER_ERROR(log, "failed to bind socket: %d, %s IP: %s port_from: %u port_to: %u",
+ neterror, strerror, net_ip_ntoa(ip, &ip_str), port_from, port_to);
net_kill_strerror(strerror);
kill_networking(temp);
@@ -1350,10 +1358,10 @@ Networking_Core *new_networking_ex(
return nullptr;
}
-Networking_Core *new_networking_no_udp(const Logger *log, const Network *ns)
+Networking_Core *new_networking_no_udp(const Logger *log, const Memory *mem, const Network *ns)
{
/* this is the easiest way to completely disable UDP without changing too much code. */
- Networking_Core *net = (Networking_Core *)calloc(1, sizeof(Networking_Core));
+ Networking_Core *net = (Networking_Core *)mem_alloc(mem, sizeof(Networking_Core));
if (net == nullptr) {
return nullptr;
@@ -1361,6 +1369,7 @@ Networking_Core *new_networking_no_udp(const Logger *log, const Network *ns)
net->ns = ns;
net->log = log;
+ net->mem = mem;
return net;
}
@@ -1377,10 +1386,9 @@ void kill_networking(Networking_Core *net)
kill_sock(net->ns, net->sock);
}
- free(net);
+ mem_delete(net->mem, net);
}
-
bool ip_equal(const IP *a, const IP *b)
{
if (a == nullptr || b == nullptr) {
@@ -1436,6 +1444,63 @@ bool ipport_equal(const IP_Port *a, const IP_Port *b)
return ip_equal(&a->ip, &b->ip);
}
+non_null()
+static int ip4_cmp(const IP4 *a, const IP4 *b)
+{
+ return cmp_uint(a->uint32, b->uint32);
+}
+
+non_null()
+static int ip6_cmp(const IP6 *a, const IP6 *b)
+{
+ const int res = cmp_uint(a->uint64[0], b->uint64[0]);
+ if (res != 0) {
+ return res;
+ }
+ return cmp_uint(a->uint64[1], b->uint64[1]);
+}
+
+non_null()
+static int ip_cmp(const IP *a, const IP *b)
+{
+ const int res = cmp_uint(a->family.value, b->family.value);
+ if (res != 0) {
+ return res;
+ }
+ switch (a->family.value) {
+ case TOX_AF_UNSPEC:
+ return 0;
+ case TOX_AF_INET:
+ case TCP_INET:
+ case TOX_TCP_INET:
+ return ip4_cmp(&a->ip.v4, &b->ip.v4);
+ case TOX_AF_INET6:
+ case TCP_INET6:
+ case TOX_TCP_INET6:
+ case TCP_SERVER_FAMILY: // these happen to be ipv6 according to TCP_server.c.
+ case TCP_CLIENT_FAMILY:
+ return ip6_cmp(&a->ip.v6, &b->ip.v6);
+ }
+ // Invalid, we don't compare any further and consider them equal.
+ return 0;
+}
+
+int ipport_cmp_handler(const void *a, const void *b, size_t size)
+{
+ const IP_Port *ipp_a = (const IP_Port *)a;
+ const IP_Port *ipp_b = (const IP_Port *)b;
+ assert(size == sizeof(IP_Port));
+
+ const int ip_res = ip_cmp(&ipp_a->ip, &ipp_b->ip);
+ if (ip_res != 0) {
+ return ip_res;
+ }
+
+ return cmp_uint(ipp_a->port, ipp_b->port);
+}
+
+static const IP empty_ip = {{0}};
+
/** nulls out ip */
void ip_reset(IP *ip)
{
@@ -1446,6 +1511,8 @@ void ip_reset(IP *ip)
*ip = empty_ip;
}
+static const IP_Port empty_ip_port = {{{0}}};
+
/** nulls out ip_port */
void ipport_reset(IP_Port *ipport)
{
@@ -1463,7 +1530,7 @@ void ip_init(IP *ip, bool ipv6enabled)
return;
}
- *ip = empty_ip;
+ ip_reset(ip);
ip->family = ipv6enabled ? net_family_ipv6() : net_family_ipv4();
}
@@ -1508,33 +1575,176 @@ void ipport_copy(IP_Port *target, const IP_Port *source)
return;
}
- *target = *source;
+ // Write to a temporary object first, so that padding bytes are
+ // uninitialised and msan can catch mistakes in downstream code.
+ IP_Port tmp;
+ tmp.ip.family = source->ip.family;
+ tmp.ip.ip = source->ip.ip;
+ tmp.port = source->port;
+
+ *target = tmp;
}
-/** @brief Converts IP into a string.
+/** @brief Packs an IP structure.
+ *
+ * It's the caller's responsibility to make sure `is_ipv4` tells the truth. This
+ * function is an implementation detail of @ref bin_pack_ip_port.
*
- * Writes error message into the buffer on error.
+ * @param is_ipv4 whether this IP is an IP4 or IP6.
*
- * @param ip_str contains a buffer of the required size.
+ * @retval true on success.
+ */
+non_null()
+static bool bin_pack_ip(Bin_Pack *bp, const IP *ip, bool is_ipv4)
+{
+ if (is_ipv4) {
+ return bin_pack_bin_b(bp, ip->ip.v4.uint8, SIZE_IP4);
+ } else {
+ return bin_pack_bin_b(bp, ip->ip.v6.uint8, SIZE_IP6);
+ }
+}
+
+/** @brief Packs an IP_Port structure.
*
- * @return Pointer to the buffer inside `ip_str` containing the IP string.
+ * @retval true on success.
*/
+bool bin_pack_ip_port(Bin_Pack *bp, const Logger *logger, const IP_Port *ip_port)
+{
+ bool is_ipv4;
+ uint8_t family;
+
+ if (net_family_is_ipv4(ip_port->ip.family)) {
+ // TODO(irungentoo): use functions to convert endianness
+ is_ipv4 = true;
+ family = TOX_AF_INET;
+ } else if (net_family_is_tcp_ipv4(ip_port->ip.family)) {
+ is_ipv4 = true;
+ family = TOX_TCP_INET;
+ } else if (net_family_is_ipv6(ip_port->ip.family)) {
+ is_ipv4 = false;
+ family = TOX_AF_INET6;
+ } else if (net_family_is_tcp_ipv6(ip_port->ip.family)) {
+ is_ipv4 = false;
+ family = TOX_TCP_INET6;
+ } else {
+ Ip_Ntoa ip_str;
+ // TODO(iphydf): Find out why we're trying to pack invalid IPs, stop
+ // doing that, and turn this into an error.
+ LOGGER_TRACE(logger, "cannot pack invalid IP: %s", net_ip_ntoa(&ip_port->ip, &ip_str));
+ return false;
+ }
+
+ return bin_pack_u08_b(bp, family)
+ && bin_pack_ip(bp, &ip_port->ip, is_ipv4)
+ && bin_pack_u16_b(bp, net_ntohs(ip_port->port));
+}
+
+non_null()
+static bool bin_pack_ip_port_handler(const void *obj, const Logger *logger, Bin_Pack *bp)
+{
+ const IP_Port *ip_port = (const IP_Port *)obj;
+ return bin_pack_ip_port(bp, logger, ip_port);
+}
+
+int pack_ip_port(const Logger *logger, uint8_t *data, uint16_t length, const IP_Port *ip_port)
+{
+ const uint32_t size = bin_pack_obj_size(bin_pack_ip_port_handler, ip_port, logger);
+
+ if (size > length) {
+ return -1;
+ }
+
+ if (!bin_pack_obj(bin_pack_ip_port_handler, ip_port, logger, data, length)) {
+ return -1;
+ }
+
+ assert(size < INT_MAX);
+ return (int)size;
+}
+
+int unpack_ip_port(IP_Port *ip_port, const uint8_t *data, uint16_t length, bool tcp_enabled)
+{
+ if (data == nullptr) {
+ return -1;
+ }
+
+ bool is_ipv4;
+ Family host_family;
+
+ if (data[0] == TOX_AF_INET) {
+ is_ipv4 = true;
+ host_family = net_family_ipv4();
+ } else if (data[0] == TOX_TCP_INET) {
+ if (!tcp_enabled) {
+ return -1;
+ }
+
+ is_ipv4 = true;
+ host_family = net_family_tcp_ipv4();
+ } else if (data[0] == TOX_AF_INET6) {
+ is_ipv4 = false;
+ host_family = net_family_ipv6();
+ } else if (data[0] == TOX_TCP_INET6) {
+ if (!tcp_enabled) {
+ return -1;
+ }
+
+ is_ipv4 = false;
+ host_family = net_family_tcp_ipv6();
+ } else {
+ return -1;
+ }
+
+ ipport_reset(ip_port);
+
+ if (is_ipv4) {
+ const uint32_t size = 1 + SIZE_IP4 + sizeof(uint16_t);
+
+ if (size > length) {
+ return -1;
+ }
+
+ ip_port->ip.family = host_family;
+ memcpy(ip_port->ip.ip.v4.uint8, data + 1, SIZE_IP4);
+ memcpy(&ip_port->port, data + 1 + SIZE_IP4, sizeof(uint16_t));
+ return size;
+ } else {
+ const uint32_t size = 1 + SIZE_IP6 + sizeof(uint16_t);
+
+ if (size > length) {
+ return -1;
+ }
+
+ ip_port->ip.family = host_family;
+ memcpy(ip_port->ip.ip.v6.uint8, data + 1, SIZE_IP6);
+ memcpy(&ip_port->port, data + 1 + SIZE_IP6, sizeof(uint16_t));
+ return size;
+ }
+}
+
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;
}
@@ -1614,7 +1824,7 @@ static int addr_resolve(const Network *ns, const char *address, IP *to, IP *extr
if ((true)) {
return 0;
}
-#endif
+#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
if (address == nullptr || to == nullptr) {
return 0;
@@ -1623,8 +1833,7 @@ static int addr_resolve(const Network *ns, const char *address, IP *to, IP *extr
const Family tox_family = to->family;
const int family = make_family(tox_family);
- struct addrinfo hints;
- memset(&hints, 0, sizeof(hints));
+ struct addrinfo hints = {0};
hints.ai_family = family;
hints.ai_socktype = SOCK_DGRAM; // type of socket Tox uses.
@@ -1712,7 +1921,7 @@ bool addr_resolve_or_parse_ip(const Network *ns, const char *address, IP *to, IP
return true;
}
-bool net_connect(const Logger *log, Socket sock, const IP_Port *ip_port)
+bool net_connect(const Memory *mem, const Logger *log, Socket sock, const IP_Port *ip_port)
{
struct sockaddr_storage addr = {0};
size_t addrsize;
@@ -1742,21 +1951,21 @@ bool net_connect(const Logger *log, Socket sock, const IP_Port *ip_port)
if ((true)) {
return true;
}
-#endif
+#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
Ip_Ntoa ip_str;
LOGGER_DEBUG(log, "connecting socket %d to %s:%d",
- (int)sock.sock, net_ip_ntoa(&ip_port->ip, &ip_str), net_ntohs(ip_port->port));
+ net_socket_to_native(sock), net_ip_ntoa(&ip_port->ip, &ip_str), net_ntohs(ip_port->port));
errno = 0;
- if (connect(sock.sock, (struct sockaddr *)&addr, addrsize) == -1) {
+ if (connect(net_socket_to_native(sock), (struct sockaddr *)&addr, addrsize) == -1) {
const int error = net_error();
// Non-blocking socket: "Operation in progress" means it's connecting.
if (!should_ignore_connect_error(error)) {
char *net_strerror = net_new_strerror(error);
- LOGGER_ERROR(log, "failed to connect to %s:%d: %d (%s)",
- net_ip_ntoa(&ip_port->ip, &ip_str), net_ntohs(ip_port->port), error, net_strerror);
+ LOGGER_WARNING(log, "failed to connect to %s:%d: %d (%s)",
+ net_ip_ntoa(&ip_port->ip, &ip_str), net_ntohs(ip_port->port), error, net_strerror);
net_kill_strerror(net_strerror);
return false;
}
@@ -1765,13 +1974,18 @@ bool net_connect(const Logger *log, Socket sock, const IP_Port *ip_port)
return true;
}
-int32_t net_getipport(const char *node, IP_Port **res, int tox_type)
+int32_t net_getipport(const Memory *mem, const char *node, IP_Port **res, int tox_type)
{
+ assert(node != nullptr);
+
// Try parsing as IP address first.
IP_Port parsed = {{{0}}};
+ // Initialise to nullptr. In error paths, at least we initialise the out
+ // parameter.
+ *res = nullptr;
if (addr_parse_ip(node, &parsed.ip)) {
- IP_Port *tmp = (IP_Port *)calloc(1, sizeof(IP_Port));
+ IP_Port *tmp = (IP_Port *)mem_alloc(mem, sizeof(IP_Port));
if (tmp == nullptr) {
return -1;
@@ -1784,20 +1998,21 @@ int32_t net_getipport(const char *node, IP_Port **res, int tox_type)
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
if ((true)) {
- *res = (IP_Port *)calloc(1, sizeof(IP_Port));
- assert(*res != nullptr);
- IP_Port *ip_port = *res;
+ IP_Port *ip_port = (IP_Port *)mem_alloc(mem, sizeof(IP_Port));
+ if (ip_port == nullptr) {
+ abort();
+ }
ip_port->ip.ip.v4.uint32 = net_htonl(0x7F000003); // 127.0.0.3
ip_port->ip.family = *make_tox_family(AF_INET);
+ *res = ip_port;
return 1;
}
-#endif
+#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
// It's not an IP address, so now we try doing a DNS lookup.
struct addrinfo *infos;
const int ret = getaddrinfo(node, nullptr, nullptr, &infos);
- *res = nullptr;
if (ret != 0) {
return -1;
@@ -1809,7 +2024,7 @@ int32_t net_getipport(const char *node, IP_Port **res, int tox_type)
size_t count = 0;
for (struct addrinfo *cur = infos; count < max_count && cur != nullptr; cur = cur->ai_next) {
- if (cur->ai_socktype && type > 0 && cur->ai_socktype != type) {
+ if (cur->ai_socktype != 0 && type > 0 && cur->ai_socktype != type) {
continue;
}
@@ -1827,26 +2042,27 @@ int32_t net_getipport(const char *node, IP_Port **res, int tox_type)
return 0;
}
- *res = (IP_Port *)calloc(count, sizeof(IP_Port));
+ IP_Port *ip_port = (IP_Port *)mem_valloc(mem, count, sizeof(IP_Port));
- if (*res == nullptr) {
+ if (ip_port == nullptr) {
freeaddrinfo(infos);
+ *res = nullptr;
return -1;
}
- IP_Port *ip_port = *res;
+ *res = ip_port;
for (struct addrinfo *cur = infos; cur != nullptr; cur = cur->ai_next) {
- if (cur->ai_socktype && type > 0 && cur->ai_socktype != type) {
+ if (cur->ai_socktype != 0 && type > 0 && cur->ai_socktype != type) {
continue;
}
if (cur->ai_family == AF_INET) {
const struct sockaddr_in *addr = (const struct sockaddr_in *)(const void *)cur->ai_addr;
- memcpy(&ip_port->ip.ip.v4, &addr->sin_addr, sizeof(IP4));
+ ip_port->ip.ip.v4.uint32 = addr->sin_addr.s_addr;
} else if (cur->ai_family == AF_INET6) {
const struct sockaddr_in6 *addr = (const struct sockaddr_in6 *)(const void *)cur->ai_addr;
- memcpy(&ip_port->ip.ip.v6, &addr->sin6_addr, sizeof(IP6));
+ memcpy(ip_port->ip.ip.v6.uint8, addr->sin6_addr.s6_addr, sizeof(IP6));
} else {
continue;
}
@@ -1869,9 +2085,9 @@ int32_t net_getipport(const char *node, IP_Port **res, int tox_type)
return count;
}
-void net_freeipport(IP_Port *ip_ports)
+void net_freeipport(const Memory *mem, IP_Port *ip_ports)
{
- free(ip_ports);
+ mem_delete(mem, ip_ports);
}
bool bind_to_port(const Network *ns, Socket sock, Family family, uint16_t port)
@@ -1902,13 +2118,12 @@ Socket net_socket(const Network *ns, Family domain, int type, int protocol)
const int platform_domain = make_family(domain);
const int platform_type = make_socktype(type);
const int platform_prot = make_proto(protocol);
- const Socket sock = {ns->funcs->socket(ns->obj, platform_domain, platform_type, platform_prot)};
- return sock;
+ return ns->funcs->socket(ns->obj, platform_domain, platform_type, platform_prot);
}
uint16_t net_socket_data_recv_buffer(const Network *ns, Socket sock)
{
- const int count = ns->funcs->recvbuf(ns->obj, sock.sock);
+ const int count = ns->funcs->recvbuf(ns->obj, sock);
return (uint16_t)max_s32(0, min_s32(count, UINT16_MAX));
}
@@ -2004,14 +2219,14 @@ bool ipv6_ipv4_in_v6(const IP6 *a)
int net_error(void)
{
-#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
+#ifdef OS_WIN32
return WSAGetLastError();
#else
return errno;
-#endif
+#endif /* OS_WIN32 */
}
-#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
+#ifdef OS_WIN32
char *net_new_strerror(int error)
{
char *str = nullptr;
@@ -2027,7 +2242,7 @@ char *net_new_strerror(int error)
return str;
}
#else
-#ifdef _GNU_SOURCE
+#if defined(_GNU_SOURCE) && defined(__GLIBC__)
non_null()
static const char *net_strerror_r(int error, char *tmp, size_t tmp_size)
{
@@ -2051,7 +2266,7 @@ static const char *net_strerror_r(int error, char *tmp, size_t tmp_size)
return tmp;
}
-#endif
+#endif /* GNU */
char *net_new_strerror(int error)
{
char tmp[256];
@@ -2071,13 +2286,13 @@ char *net_new_strerror(int error)
return str;
}
-#endif
+#endif /* OS_WIN32 */
void net_kill_strerror(char *strerror)
{
-#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
+#ifdef OS_WIN32
LocalFree((char *)strerror);
#else
free(strerror);
-#endif
+#endif /* OS_WIN32 */
}
diff --git a/protocols/Tox/libtox/src/toxcore/network.h b/protocols/Tox/libtox/src/toxcore/network.h
index ffc04ed6e4..06857b8917 100644
--- a/protocols/Tox/libtox/src/toxcore/network.h
+++ b/protocols/Tox/libtox/src/toxcore/network.h
@@ -13,7 +13,10 @@
#include <stddef.h> // size_t
#include <stdint.h> // uint*_t
+#include "attributes.h"
+#include "bin_pack.h"
#include "logger.h"
+#include "mem.h"
#ifdef __cplusplus
extern "C" {
@@ -24,19 +27,27 @@ extern "C" {
*/
typedef struct Network_Addr Network_Addr;
-typedef int net_close_cb(void *obj, int sock);
-typedef int net_accept_cb(void *obj, int sock);
-typedef int net_bind_cb(void *obj, int sock, const Network_Addr *addr);
-typedef int net_listen_cb(void *obj, int sock, int backlog);
-typedef int net_recvbuf_cb(void *obj, int sock);
-typedef int net_recv_cb(void *obj, int sock, uint8_t *buf, size_t len);
-typedef int net_recvfrom_cb(void *obj, int sock, uint8_t *buf, size_t len, Network_Addr *addr);
-typedef int net_send_cb(void *obj, int sock, const uint8_t *buf, size_t len);
-typedef int net_sendto_cb(void *obj, int sock, const uint8_t *buf, size_t len, const Network_Addr *addr);
-typedef int net_socket_cb(void *obj, int domain, int type, int proto);
-typedef int net_socket_nonblock_cb(void *obj, int sock, bool nonblock);
-typedef int net_getsockopt_cb(void *obj, int sock, int level, int optname, void *optval, size_t *optlen);
-typedef int net_setsockopt_cb(void *obj, int sock, int level, int optname, const void *optval, size_t optlen);
+typedef bitwise int Socket_Value;
+typedef struct Socket {
+ Socket_Value value;
+} Socket;
+
+int net_socket_to_native(Socket sock);
+Socket net_socket_from_native(int sock);
+
+typedef int net_close_cb(void *obj, Socket sock);
+typedef Socket net_accept_cb(void *obj, Socket sock);
+typedef int net_bind_cb(void *obj, Socket sock, const Network_Addr *addr);
+typedef int net_listen_cb(void *obj, Socket sock, int backlog);
+typedef int net_recvbuf_cb(void *obj, Socket sock);
+typedef int net_recv_cb(void *obj, Socket sock, uint8_t *buf, size_t len);
+typedef int net_recvfrom_cb(void *obj, Socket sock, uint8_t *buf, size_t len, Network_Addr *addr);
+typedef int net_send_cb(void *obj, Socket sock, const uint8_t *buf, size_t len);
+typedef int net_sendto_cb(void *obj, Socket sock, const uint8_t *buf, size_t len, const Network_Addr *addr);
+typedef Socket net_socket_cb(void *obj, int domain, int type, int proto);
+typedef int net_socket_nonblock_cb(void *obj, Socket sock, bool nonblock);
+typedef int net_getsockopt_cb(void *obj, Socket sock, int level, int optname, void *optval, size_t *optlen);
+typedef int net_setsockopt_cb(void *obj, Socket sock, int level, int optname, const void *optval, size_t optlen);
typedef int net_getaddrinfo_cb(void *obj, int family, Network_Addr **addrs);
typedef int net_freeaddrinfo_cb(void *obj, Network_Addr *addrs);
@@ -68,7 +79,7 @@ typedef struct Network {
void *obj;
} Network;
-const Network *system_network(void);
+const Network *os_network(void);
typedef struct Family {
uint8_t value;
@@ -96,56 +107,6 @@ Family net_family_tox_tcp_ipv6(void);
#define MAX_UDP_PACKET_SIZE 2048
-#ifdef USE_TEST_NETWORK
-typedef enum Net_Packet_Type {
- NET_PACKET_PING_REQUEST = 0x05, /* Ping request packet ID. */
- NET_PACKET_PING_RESPONSE = 0x06, /* Ping response packet ID. */
- NET_PACKET_GET_NODES = 0x07, /* Get nodes request packet ID. */
- NET_PACKET_SEND_NODES_IPV6 = 0x08, /* Send nodes response packet ID for other addresses. */
- NET_PACKET_COOKIE_REQUEST = 0x1c, /* Cookie request packet */
- NET_PACKET_COOKIE_RESPONSE = 0x1d, /* Cookie response packet */
- NET_PACKET_CRYPTO_HS = 0x1e, /* Crypto handshake packet */
- NET_PACKET_CRYPTO_DATA = 0x1f, /* Crypto data packet */
- NET_PACKET_CRYPTO = 0x24, /* Encrypted data packet ID. */
- NET_PACKET_LAN_DISCOVERY = 0x25, /* LAN discovery packet ID. */
-
- NET_PACKET_GC_HANDSHAKE = 0x62, /* Group chat handshake packet ID */
- NET_PACKET_GC_LOSSLESS = 0x63, /* Group chat lossless packet ID */
- NET_PACKET_GC_LOSSY = 0x64, /* Group chat lossy packet ID */
-
- /* See: `docs/Prevent_Tracking.txt` and `onion.{c,h}` */
- NET_PACKET_ONION_SEND_INITIAL = 0x8f,
- NET_PACKET_ONION_SEND_1 = 0x90,
- NET_PACKET_ONION_SEND_2 = 0x91,
-
- NET_PACKET_ANNOUNCE_REQUEST = 0x92,
- NET_PACKET_ANNOUNCE_RESPONSE = 0x93,
- NET_PACKET_ONION_DATA_REQUEST = 0x94,
- NET_PACKET_ONION_DATA_RESPONSE = 0x95,
-
- NET_PACKET_ANNOUNCE_REQUEST_OLD = 0x96, /* TODO: DEPRECATE */
- NET_PACKET_ANNOUNCE_RESPONSE_OLD = 0x97, /* TODO: DEPRECATE */
-
- NET_PACKET_ONION_RECV_3 = 0x9b,
- NET_PACKET_ONION_RECV_2 = 0x9c,
- NET_PACKET_ONION_RECV_1 = 0x9d,
-
- NET_PACKET_FORWARD_REQUEST = 0x9e,
- NET_PACKET_FORWARDING = 0x9f,
- NET_PACKET_FORWARD_REPLY = 0xa0,
-
- NET_PACKET_DATA_SEARCH_REQUEST = 0xa1,
- NET_PACKET_DATA_SEARCH_RESPONSE = 0xa2,
- NET_PACKET_DATA_RETRIEVE_REQUEST = 0xa3,
- NET_PACKET_DATA_RETRIEVE_RESPONSE = 0xa4,
- NET_PACKET_STORE_ANNOUNCE_REQUEST = 0xa5,
- NET_PACKET_STORE_ANNOUNCE_RESPONSE = 0xa6,
-
- BOOTSTRAP_INFO_PACKET_ID = 0xf1, /* Only used for bootstrap nodes */
-
- NET_PACKET_MAX = 0xff, /* This type must remain within a single uint8. */
-} Net_Packet_Type;
-#else
typedef enum Net_Packet_Type {
NET_PACKET_PING_REQUEST = 0x00, /* Ping request packet ID. */
NET_PACKET_PING_RESPONSE = 0x01, /* Ping response packet ID. */
@@ -194,8 +155,6 @@ typedef enum Net_Packet_Type {
NET_PACKET_MAX = 0xff, /* This type must remain within a single uint8. */
} Net_Packet_Type;
-#endif // test network
-
#define TOX_PORTRANGE_FROM 33445
#define TOX_PORTRANGE_TO 33545
@@ -233,7 +192,7 @@ typedef union IP4 {
} IP4;
IP4 get_ip4_loopback(void);
-extern const IP4 ip4_broadcast;
+IP4 get_ip4_broadcast(void);
typedef union IP6 {
uint8_t uint8[16];
@@ -243,7 +202,7 @@ typedef union IP6 {
} IP6;
IP6 get_ip6_loopback(void);
-extern const IP6 ip6_broadcast;
+IP6 get_ip6_broadcast(void);
typedef union IP_Union {
IP4 v4;
@@ -260,12 +219,6 @@ typedef struct IP_Port {
uint16_t port;
} IP_Port;
-extern const IP_Port empty_ip_port;
-
-typedef struct Socket {
- int sock;
-} Socket;
-
non_null()
Socket net_socket(const Network *ns, Family domain, int type, int protocol);
@@ -276,7 +229,7 @@ Socket net_socket(const Network *ns, Family domain, int type, int protocol);
*/
bool sock_valid(Socket sock);
-extern const Socket net_invalid_socket;
+Socket net_invalid_socket(void);
/**
* Calls send(sockfd, buf, len, MSG_NOSIGNAL).
@@ -342,11 +295,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.
*
@@ -386,7 +342,7 @@ non_null()
bool addr_parse_ip(const char *address, IP *to);
/**
- * Compares two IPAny structures.
+ * Compares two IP structures.
*
* Unset means unequal.
*
@@ -396,7 +352,7 @@ nullable(1, 2)
bool ip_equal(const IP *a, const IP *b);
/**
- * Compares two IPAny_Port structures.
+ * Compares two IP_Port structures.
*
* Unset means unequal.
*
@@ -405,6 +361,18 @@ bool ip_equal(const IP *a, const IP *b);
nullable(1, 2)
bool ipport_equal(const IP_Port *a, const IP_Port *b);
+/**
+ * @brief IP_Port comparison function with `memcmp` signature.
+ *
+ * Casts the void pointers to `IP_Port *` for comparison.
+ *
+ * @retval -1 if `a < b`
+ * @retval 0 if `a == b`
+ * @retval 1 if `a > b`
+ */
+non_null()
+int ipport_cmp_handler(const void *a, const void *b, size_t size);
+
/** nulls out ip */
non_null()
void ip_reset(IP *ip);
@@ -448,7 +416,7 @@ bool addr_resolve_or_parse_ip(const Network *ns, const char *address, IP *to, IP
* Packet data is put into data.
* Packet length is put into length.
*/
-typedef int packet_handler_cb(void *object, const IP_Port *ip_port, const uint8_t *data, uint16_t len, void *userdata);
+typedef int packet_handler_cb(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, void *userdata);
typedef struct Networking_Core Networking_Core;
@@ -533,7 +501,7 @@ void networking_poll(const Networking_Core *net, void *userdata);
* Return false on failure.
*/
non_null()
-bool net_connect(const Logger *log, Socket sock, const IP_Port *ip_port);
+bool net_connect(const Memory *mem, const Logger *log, Socket sock, const IP_Port *ip_port);
/** @brief High-level getaddrinfo implementation.
*
@@ -549,11 +517,34 @@ bool net_connect(const Logger *log, Socket sock, const IP_Port *ip_port);
* @retval -1 on error.
*/
non_null()
-int32_t net_getipport(const char *node, IP_Port **res, int tox_type);
+int32_t net_getipport(const Memory *mem, const char *node, IP_Port **res, int tox_type);
/** Deallocates memory allocated by net_getipport */
-nullable(1)
-void net_freeipport(IP_Port *ip_ports);
+non_null(1) nullable(2)
+void net_freeipport(const Memory *mem, IP_Port *ip_ports);
+
+non_null()
+bool bin_pack_ip_port(Bin_Pack *bp, const Logger *logger, const IP_Port *ip_port);
+
+/** @brief Pack an IP_Port structure into data of max size length.
+ *
+ * Packed_length is the offset of data currently packed.
+ *
+ * @return size of packed IP_Port data on success.
+ * @retval -1 on failure.
+ */
+non_null()
+int pack_ip_port(const Logger *logger, uint8_t *data, uint16_t length, const IP_Port *ip_port);
+
+/** @brief Unpack IP_Port structure from data of max size length into ip_port.
+ *
+ * len_processed is the offset of data currently unpacked.
+ *
+ * @return size of unpacked ip_port on success.
+ * @retval -1 on failure.
+ */
+non_null()
+int unpack_ip_port(IP_Port *ip_port, const uint8_t *data, uint16_t length, bool tcp_enabled);
/**
* @return true on success, false on failure.
@@ -587,7 +578,7 @@ char *net_new_strerror(int error);
* It's valid to pass NULL as the argument, the function does nothing in this
* case.
*/
-non_null()
+nullable(1)
void net_kill_strerror(char *strerror);
/** @brief Initialize networking.
@@ -600,20 +591,20 @@ void net_kill_strerror(char *strerror);
*
* If error is non NULL it is set to 0 if no issues, 1 if socket related error, 2 if other.
*/
-non_null(1, 2, 3) nullable(6)
+non_null(1, 2, 3, 4) nullable(7)
Networking_Core *new_networking_ex(
- const Logger *log, const Network *ns, const IP *ip,
- uint16_t port_from, uint16_t port_to, unsigned int *error);
+ const Logger *log, const Memory *mem, const Network *ns, const IP *ip,
+ uint16_t port_from, uint16_t port_to, unsigned int *error);
non_null()
-Networking_Core *new_networking_no_udp(const Logger *log, const Network *ns);
+Networking_Core *new_networking_no_udp(const Logger *log, const Memory *mem, const Network *ns);
/** Function to cleanup networking stuff (doesn't do much right now). */
nullable(1)
void kill_networking(Networking_Core *net);
#ifdef __cplusplus
-} // extern "C"
+} /* extern "C" */
#endif
-#endif
+#endif /* C_TOXCORE_TOXCORE_NETWORK_H */
diff --git a/protocols/Tox/libtox/src/toxcore/onion.c b/protocols/Tox/libtox/src/toxcore/onion.c
index 63ff6d8520..9fab57af90 100644
--- a/protocols/Tox/libtox/src/toxcore/onion.c
+++ b/protocols/Tox/libtox/src/toxcore/onion.c
@@ -9,11 +9,17 @@
#include "onion.h"
#include <assert.h>
-#include <stdlib.h>
#include <string.h>
+#include "DHT.h"
+#include "attributes.h"
#include "ccompat.h"
+#include "crypto_core.h"
+#include "logger.h"
+#include "mem.h"
#include "mono_time.h"
+#include "network.h"
+#include "shared_key_cache.h"
#include "util.h"
#define RETURN_1 ONION_RETURN_1
@@ -27,7 +33,6 @@
#define KEY_REFRESH_INTERVAL (2 * 60 * 60)
-
// Settings for the shared key cache
#define MAX_KEYS_PER_SLOT 4
#define KEYS_TIMEOUT 600
@@ -44,12 +49,12 @@ static void change_symmetric_key(Onion *onion)
/** packing and unpacking functions */
non_null()
-static void ip_pack(uint8_t *data, const IP *source)
+static void ip_pack_to_bytes(uint8_t *data, const IP *source)
{
data[0] = source->family.value;
if (net_family_is_ipv4(source->family) || net_family_is_tox_tcp_ipv4(source->family)) {
- memset(data + 1, 0, SIZE_IP6);
+ memzero(data + 1, SIZE_IP6);
memcpy(data + 1, source->ip.v4.uint8, SIZE_IP4);
} else {
memcpy(data + 1, source->ip.v6.uint8, SIZE_IP6);
@@ -58,7 +63,7 @@ static void ip_pack(uint8_t *data, const IP *source)
/** return 0 on success, -1 on failure. */
non_null()
-static int ip_unpack(IP *target, const uint8_t *data, unsigned int data_size, bool disable_family_check)
+static int ip_unpack_from_bytes(IP *target, const uint8_t *data, unsigned int data_size, bool disable_family_check)
{
if (data_size < (1 + SIZE_IP6)) {
return -1;
@@ -74,8 +79,8 @@ static int ip_unpack(IP *target, const uint8_t *data, unsigned int data_size, bo
}
const bool valid = disable_family_check ||
- net_family_is_ipv4(target->family) ||
- net_family_is_ipv6(target->family);
+ net_family_is_ipv4(target->family) ||
+ net_family_is_ipv6(target->family);
return valid ? 0 : -1;
}
@@ -83,7 +88,7 @@ static int ip_unpack(IP *target, const uint8_t *data, unsigned int data_size, bo
non_null()
static void ipport_pack(uint8_t *data, const IP_Port *source)
{
- ip_pack(data, &source->ip);
+ ip_pack_to_bytes(data, &source->ip);
memcpy(data + SIZE_IP, &source->port, SIZE_PORT);
}
@@ -95,7 +100,7 @@ static int ipport_unpack(IP_Port *target, const uint8_t *data, unsigned int data
return -1;
}
- if (ip_unpack(&target->ip, data, data_size, disable_family_check) == -1) {
+ if (ip_unpack_from_bytes(&target->ip, data, data_size, disable_family_check) == -1) {
return -1;
}
@@ -103,7 +108,6 @@ static int ipport_unpack(IP_Port *target, const uint8_t *data, unsigned int data
return 0;
}
-
/** @brief Create a new onion path.
*
* Create a new onion path out of nodes (nodes is a list of ONION_PATH_LENGTH nodes)
@@ -184,7 +188,8 @@ int create_onion_packet(const Random *rng, uint8_t *packet, uint16_t max_packet_
return -1;
}
- VLA(uint8_t, step1, SIZE_IPPORT + length);
+ const uint16_t step1_size = SIZE_IPPORT + length;
+ VLA(uint8_t, step1, step1_size);
ipport_pack(step1, dest);
memcpy(step1 + SIZE_IPPORT, data, length);
@@ -192,21 +197,23 @@ int create_onion_packet(const Random *rng, uint8_t *packet, uint16_t max_packet_
uint8_t nonce[CRYPTO_NONCE_SIZE];
random_nonce(rng, nonce);
- VLA(uint8_t, step2, SIZE_IPPORT + SEND_BASE + length);
+ const uint16_t step2_size = SIZE_IPPORT + SEND_BASE + length;
+ VLA(uint8_t, step2, step2_size);
ipport_pack(step2, &path->ip_port3);
memcpy(step2 + SIZE_IPPORT, path->public_key3, CRYPTO_PUBLIC_KEY_SIZE);
- int len = encrypt_data_symmetric(path->shared_key3, nonce, step1, SIZEOF_VLA(step1),
+ int len = encrypt_data_symmetric(path->shared_key3, nonce, step1, step1_size,
step2 + SIZE_IPPORT + CRYPTO_PUBLIC_KEY_SIZE);
if (len != SIZE_IPPORT + length + CRYPTO_MAC_SIZE) {
return -1;
}
- VLA(uint8_t, step3, SIZE_IPPORT + SEND_BASE * 2 + length);
+ const uint16_t step3_size = SIZE_IPPORT + SEND_BASE * 2 + length;
+ VLA(uint8_t, step3, step3_size);
ipport_pack(step3, &path->ip_port2);
memcpy(step3 + SIZE_IPPORT, path->public_key2, CRYPTO_PUBLIC_KEY_SIZE);
- len = encrypt_data_symmetric(path->shared_key2, nonce, step2, SIZEOF_VLA(step2),
+ len = encrypt_data_symmetric(path->shared_key2, nonce, step2, step2_size,
step3 + SIZE_IPPORT + CRYPTO_PUBLIC_KEY_SIZE);
if (len != SIZE_IPPORT + SEND_BASE + length + CRYPTO_MAC_SIZE) {
@@ -217,7 +224,7 @@ int create_onion_packet(const Random *rng, uint8_t *packet, uint16_t max_packet_
memcpy(packet + 1, nonce, CRYPTO_NONCE_SIZE);
memcpy(packet + 1 + CRYPTO_NONCE_SIZE, path->public_key1, CRYPTO_PUBLIC_KEY_SIZE);
- len = encrypt_data_symmetric(path->shared_key1, nonce, step3, SIZEOF_VLA(step3),
+ len = encrypt_data_symmetric(path->shared_key1, nonce, step3, step3_size,
packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE);
if (len != SIZE_IPPORT + SEND_BASE * 2 + length + CRYPTO_MAC_SIZE) {
@@ -244,7 +251,8 @@ int create_onion_packet_tcp(const Random *rng, uint8_t *packet, uint16_t max_pac
return -1;
}
- VLA(uint8_t, step1, SIZE_IPPORT + length);
+ const uint16_t step1_size = SIZE_IPPORT + length;
+ VLA(uint8_t, step1, step1_size);
ipport_pack(step1, dest);
memcpy(step1 + SIZE_IPPORT, data, length);
@@ -252,11 +260,12 @@ int create_onion_packet_tcp(const Random *rng, uint8_t *packet, uint16_t max_pac
uint8_t nonce[CRYPTO_NONCE_SIZE];
random_nonce(rng, nonce);
- VLA(uint8_t, step2, SIZE_IPPORT + SEND_BASE + length);
+ const uint16_t step2_size = SIZE_IPPORT + SEND_BASE + length;
+ VLA(uint8_t, step2, step2_size);
ipport_pack(step2, &path->ip_port3);
memcpy(step2 + SIZE_IPPORT, path->public_key3, CRYPTO_PUBLIC_KEY_SIZE);
- int len = encrypt_data_symmetric(path->shared_key3, nonce, step1, SIZEOF_VLA(step1),
+ int len = encrypt_data_symmetric(path->shared_key3, nonce, step1, step1_size,
step2 + SIZE_IPPORT + CRYPTO_PUBLIC_KEY_SIZE);
if (len != SIZE_IPPORT + length + CRYPTO_MAC_SIZE) {
@@ -265,7 +274,7 @@ int create_onion_packet_tcp(const Random *rng, uint8_t *packet, uint16_t max_pac
ipport_pack(packet + CRYPTO_NONCE_SIZE, &path->ip_port2);
memcpy(packet + CRYPTO_NONCE_SIZE + SIZE_IPPORT, path->public_key2, CRYPTO_PUBLIC_KEY_SIZE);
- len = encrypt_data_symmetric(path->shared_key2, nonce, step2, SIZEOF_VLA(step2),
+ len = encrypt_data_symmetric(path->shared_key2, nonce, step2, step2_size,
packet + CRYPTO_NONCE_SIZE + SIZE_IPPORT + CRYPTO_PUBLIC_KEY_SIZE);
if (len != SIZE_IPPORT + SEND_BASE + length + CRYPTO_MAC_SIZE) {
@@ -283,22 +292,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 +323,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 +367,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 +406,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 +472,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,10 +545,12 @@ 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;
}
-
non_null()
static int handle_recv_3(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, void *userdata)
{
@@ -537,7 +575,7 @@ static int handle_recv_3(void *object, const IP_Port *source, const uint8_t *pac
uint8_t plain[SIZE_IPPORT + RETURN_2];
const int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE,
- SIZE_IPPORT + RETURN_2 + CRYPTO_MAC_SIZE, plain);
+ SIZE_IPPORT + RETURN_2 + CRYPTO_MAC_SIZE, plain);
if ((uint32_t)len != sizeof(plain)) {
return 1;
@@ -546,6 +584,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 +598,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;
}
@@ -586,7 +628,7 @@ static int handle_recv_2(void *object, const IP_Port *source, const uint8_t *pac
uint8_t plain[SIZE_IPPORT + RETURN_1];
const int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE,
- SIZE_IPPORT + RETURN_1 + CRYPTO_MAC_SIZE, plain);
+ SIZE_IPPORT + RETURN_1 + CRYPTO_MAC_SIZE, plain);
if ((uint32_t)len != sizeof(plain)) {
return 1;
@@ -608,6 +650,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;
}
@@ -635,7 +680,7 @@ static int handle_recv_1(void *object, const IP_Port *source, const uint8_t *pac
uint8_t plain[SIZE_IPPORT];
const int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE,
- SIZE_IPPORT + CRYPTO_MAC_SIZE, plain);
+ SIZE_IPPORT + CRYPTO_MAC_SIZE, plain);
if ((uint32_t)len != SIZE_IPPORT) {
return 1;
@@ -644,6 +689,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;
}
@@ -668,13 +714,13 @@ void set_callback_handle_recv_1(Onion *onion, onion_recv_1_cb *function, void *o
onion->callback_object = object;
}
-Onion *new_onion(const Logger *log, const Mono_Time *mono_time, const Random *rng, DHT *dht)
+Onion *new_onion(const Logger *log, const Memory *mem, const Mono_Time *mono_time, const Random *rng, DHT *dht)
{
if (dht == nullptr) {
return nullptr;
}
- Onion *onion = (Onion *)calloc(1, sizeof(Onion));
+ Onion *onion = (Onion *)mem_alloc(mem, sizeof(Onion));
if (onion == nullptr) {
return nullptr;
@@ -685,22 +731,23 @@ Onion *new_onion(const Logger *log, const Mono_Time *mono_time, const Random *rn
onion->net = dht_get_net(dht);
onion->mono_time = mono_time;
onion->rng = rng;
+ onion->mem = mem;
new_symmetric_key(rng, onion->secret_symmetric_key);
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, secret_key, KEYS_TIMEOUT, MAX_KEYS_PER_SLOT);
- onion->shared_keys_2 = shared_key_cache_new(mono_time, secret_key, KEYS_TIMEOUT, MAX_KEYS_PER_SLOT);
- onion->shared_keys_3 = shared_key_cache_new(mono_time, 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 ||
- onion->shared_keys_3 == nullptr) {
+ onion->shared_keys_2 == nullptr ||
+ onion->shared_keys_3 == nullptr) {
+ // cppcheck-suppress mismatchAllocDealloc
kill_onion(onion);
return nullptr;
}
-
networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_INITIAL, &handle_send_initial, onion);
networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_1, &handle_send_1, onion);
networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_2, &handle_send_2, onion);
@@ -732,5 +779,5 @@ void kill_onion(Onion *onion)
shared_key_cache_free(onion->shared_keys_2);
shared_key_cache_free(onion->shared_keys_3);
- free(onion);
+ mem_delete(onion->mem, onion);
}
diff --git a/protocols/Tox/libtox/src/toxcore/onion.h b/protocols/Tox/libtox/src/toxcore/onion.h
index 5c8f920b44..a5d3554e7b 100644
--- a/protocols/Tox/libtox/src/toxcore/onion.h
+++ b/protocols/Tox/libtox/src/toxcore/onion.h
@@ -10,8 +10,12 @@
#define C_TOXCORE_TOXCORE_ONION_H
#include "DHT.h"
+#include "attributes.h"
+#include "crypto_core.h"
#include "logger.h"
+#include "mem.h"
#include "mono_time.h"
+#include "network.h"
#include "shared_key_cache.h"
typedef int onion_recv_1_cb(void *object, const IP_Port *dest, const uint8_t *data, uint16_t length);
@@ -20,6 +24,7 @@ typedef struct Onion {
const Logger *log;
const Mono_Time *mono_time;
const Random *rng;
+ const Memory *mem;
DHT *dht;
Networking_Core *net;
uint8_t secret_symmetric_key[CRYPTO_SYMMETRIC_KEY_SIZE];
@@ -104,7 +109,6 @@ int create_onion_packet(const Random *rng, uint8_t *packet, uint16_t max_packet_
const Onion_Path *path, const IP_Port *dest,
const uint8_t *data, uint16_t length);
-
/** @brief Create a onion packet to be sent over tcp.
*
* Use Onion_Path path to create packet for data of length to dest.
@@ -126,7 +130,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.
@@ -147,10 +152,9 @@ non_null(1) nullable(2, 3)
void set_callback_handle_recv_1(Onion *onion, onion_recv_1_cb *function, void *object);
non_null()
-Onion *new_onion(const Logger *log, const Mono_Time *mono_time, const Random *rng, DHT *dht);
+Onion *new_onion(const Logger *log, const Memory *mem, const Mono_Time *mono_time, const Random *rng, DHT *dht);
nullable(1)
void kill_onion(Onion *onion);
-
-#endif
+#endif /* C_TOXCORE_TOXCORE_ONION_H */
diff --git a/protocols/Tox/libtox/src/toxcore/onion_announce.c b/protocols/Tox/libtox/src/toxcore/onion_announce.c
index fb04d21f56..593d81aa2c 100644
--- a/protocols/Tox/libtox/src/toxcore/onion_announce.c
+++ b/protocols/Tox/libtox/src/toxcore/onion_announce.c
@@ -14,10 +14,16 @@
#include "DHT.h"
#include "LAN_discovery.h"
+#include "attributes.h"
#include "ccompat.h"
+#include "crypto_core.h"
+#include "logger.h"
+#include "mem.h"
#include "mono_time.h"
+#include "network.h"
+#include "onion.h"
#include "shared_key_cache.h"
-#include "util.h"
+#include "timed_auth.h"
#define PING_ID_TIMEOUT ONION_ANNOUNCE_TIMEOUT
@@ -51,6 +57,7 @@ struct Onion_Announce {
const Logger *log;
const Mono_Time *mono_time;
const Random *rng;
+ const Memory *mem;
DHT *dht;
Networking_Core *net;
Onion_Announce_Entry entries[ONION_ANNOUNCE_MAX_ENTRIES];
@@ -185,11 +192,12 @@ 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,
- 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,
- const uint8_t *data_public_key, uint64_t sendback_data)
+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,
+ const uint8_t *data_public_key, uint64_t sendback_data)
{
uint8_t request[ONION_ANNOUNCE_REQUEST_MIN_SIZE];
int len = create_announce_request(rng, request, sizeof(request), dest->public_key, public_key, secret_key, ping_id,
@@ -229,9 +237,10 @@ 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,
- const uint8_t *public_key, const uint8_t *encrypt_public_key, const uint8_t *nonce,
- const uint8_t *data, uint16_t length)
+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)
{
uint8_t request[ONION_MAX_DATA_SIZE];
int len = create_data_request(rng, request, sizeof(request), public_key, encrypt_public_key, nonce, data, length);
@@ -316,12 +325,13 @@ static int cmp_entry(const void *a, const void *b)
}
non_null()
-static void sort_onion_announce_list(Onion_Announce_Entry *list, unsigned int length, const Mono_Time *mono_time,
+static void sort_onion_announce_list(const Memory *mem, const Mono_Time *mono_time,
+ Onion_Announce_Entry *list, unsigned int length,
const uint8_t *comp_public_key)
{
// Pass comp_public_key to qsort with each Client_data entry, so the
// comparison function can use it as the base of comparison.
- Cmp_Data *cmp_list = (Cmp_Data *)calloc(length, sizeof(Cmp_Data));
+ Cmp_Data *cmp_list = (Cmp_Data *)mem_valloc(mem, length, sizeof(Cmp_Data));
if (cmp_list == nullptr) {
return;
@@ -339,7 +349,7 @@ static void sort_onion_announce_list(Onion_Announce_Entry *list, unsigned int le
list[i] = cmp_list[i].entry;
}
- free(cmp_list);
+ mem_delete(mem, cmp_list);
}
/** @brief add entry to entries list
@@ -377,7 +387,8 @@ static int add_to_entries(Onion_Announce *onion_a, const IP_Port *ret_ip_port, c
memcpy(onion_a->entries[pos].data_public_key, data_public_key, CRYPTO_PUBLIC_KEY_SIZE);
onion_a->entries[pos].announce_time = mono_time_get(onion_a->mono_time);
- sort_onion_announce_list(onion_a->entries, ONION_ANNOUNCE_MAX_ENTRIES, onion_a->mono_time,
+ sort_onion_announce_list(onion_a->mem, onion_a->mono_time,
+ onion_a->entries, ONION_ANNOUNCE_MAX_ENTRIES,
dht_get_self_public_key(onion_a->dht));
return in_entries(onion_a, public_key);
}
@@ -438,7 +449,7 @@ static int handle_announce_request_common(
return 1;
}
- uint8_t *plain = (uint8_t *)malloc(plain_size);
+ uint8_t *plain = (uint8_t *)mem_balloc(onion_a->mem, plain_size);
if (plain == nullptr) {
return 1;
@@ -448,7 +459,7 @@ static int handle_announce_request_common(
packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE, plain_size + CRYPTO_MAC_SIZE, plain);
if ((uint32_t)decrypted_len != plain_size) {
- free(plain);
+ mem_delete(onion_a->mem, plain);
return 1;
}
@@ -483,10 +494,10 @@ static int handle_announce_request_common(
const uint16_t response_size = nodes_offset
+ MAX_SENT_NODES * PACKED_NODE_SIZE_IP6
+ max_extra_size;
- uint8_t *response = (uint8_t *)malloc(response_size);
+ uint8_t *response = (uint8_t *)mem_balloc(onion_a->mem, response_size);
if (response == nullptr) {
- free(plain);
+ mem_delete(onion_a->mem, plain);
return 1;
}
@@ -504,8 +515,8 @@ static int handle_announce_request_common(
if (nodes_length <= 0) {
LOGGER_WARNING(onion_a->log, "Failed to pack nodes");
- free(response);
- free(plain);
+ mem_delete(onion_a->mem, response);
+ mem_delete(onion_a->mem, plain);
return 1;
}
}
@@ -523,8 +534,8 @@ static int handle_announce_request_common(
response, response_size, offset);
if (extra_size == -1) {
- free(response);
- free(plain);
+ mem_delete(onion_a->mem, response);
+ mem_delete(onion_a->mem, plain);
return 1;
}
@@ -536,8 +547,8 @@ static int handle_announce_request_common(
if (len != offset + CRYPTO_MAC_SIZE) {
LOGGER_ERROR(onion_a->log, "Failed to encrypt announce response");
- free(response);
- free(plain);
+ mem_delete(onion_a->mem, response);
+ mem_delete(onion_a->mem, plain);
return 1;
}
@@ -546,16 +557,16 @@ 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) {
- free(response);
- free(plain);
+ mem_delete(onion_a->mem, response);
+ mem_delete(onion_a->mem, plain);
return 1;
}
- free(response);
- free(plain);
+ mem_delete(onion_a->mem, response);
+ mem_delete(onion_a->mem, plain);
return 0;
}
@@ -627,11 +638,12 @@ static int handle_data_request(void *object, const IP_Port *source, const uint8_
return 1;
}
- VLA(uint8_t, data, length - (CRYPTO_PUBLIC_KEY_SIZE + ONION_RETURN_3));
+ const uint16_t data_size = length - (CRYPTO_PUBLIC_KEY_SIZE + ONION_RETURN_3);
+ VLA(uint8_t, data, data_size);
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, data_size,
onion_a->entries[index].ret) == -1) {
return 1;
}
@@ -639,13 +651,13 @@ static int handle_data_request(void *object, const IP_Port *source, const uint8_
return 0;
}
-Onion_Announce *new_onion_announce(const Logger *log, const Random *rng, const Mono_Time *mono_time, DHT *dht)
+Onion_Announce *new_onion_announce(const Logger *log, const Memory *mem, const Random *rng, const Mono_Time *mono_time, DHT *dht)
{
if (dht == nullptr) {
return nullptr;
}
- Onion_Announce *onion_a = (Onion_Announce *)calloc(1, sizeof(Onion_Announce));
+ Onion_Announce *onion_a = (Onion_Announce *)mem_alloc(mem, sizeof(Onion_Announce));
if (onion_a == nullptr) {
return nullptr;
@@ -653,6 +665,7 @@ Onion_Announce *new_onion_announce(const Logger *log, const Random *rng, const M
onion_a->log = log;
onion_a->rng = rng;
+ onion_a->mem = mem;
onion_a->mono_time = mono_time;
onion_a->dht = dht;
onion_a->net = dht_get_net(dht);
@@ -661,8 +674,9 @@ Onion_Announce *new_onion_announce(const Logger *log, const Random *rng, const M
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, 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) {
+ // cppcheck-suppress mismatchAllocDealloc
kill_onion_announce(onion_a);
return nullptr;
}
@@ -687,5 +701,5 @@ void kill_onion_announce(Onion_Announce *onion_a)
crypto_memzero(onion_a->hmac_key, CRYPTO_HMAC_KEY_SIZE);
shared_key_cache_free(onion_a->shared_keys_recv);
- free(onion_a);
+ mem_delete(onion_a->mem, onion_a);
}
diff --git a/protocols/Tox/libtox/src/toxcore/onion_announce.h b/protocols/Tox/libtox/src/toxcore/onion_announce.h
index 24303abccb..1158093170 100644
--- a/protocols/Tox/libtox/src/toxcore/onion_announce.h
+++ b/protocols/Tox/libtox/src/toxcore/onion_announce.h
@@ -9,7 +9,13 @@
#ifndef C_TOXCORE_TOXCORE_ONION_ANNOUNCE_H
#define C_TOXCORE_TOXCORE_ONION_ANNOUNCE_H
+#include "DHT.h"
+#include "attributes.h"
+#include "crypto_core.h"
#include "logger.h"
+#include "mem.h"
+#include "mono_time.h"
+#include "network.h"
#include "onion.h"
#include "timed_auth.h"
@@ -94,11 +100,12 @@ 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,
- 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,
- const uint8_t *data_public_key, uint64_t sendback_data);
+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,
+ const uint8_t *data_public_key, uint64_t sendback_data);
/** @brief Create and send an onion data request packet.
*
@@ -117,10 +124,10 @@ 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,
- const uint8_t *public_key, const uint8_t *encrypt_public_key, const uint8_t *nonce,
- const uint8_t *data, uint16_t length);
-
+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);
typedef int pack_extra_data_cb(void *object, const Logger *logger, const Mono_Time *mono_time,
uint8_t num_nodes, uint8_t *plain, uint16_t plain_size,
@@ -131,9 +138,9 @@ void onion_announce_extra_data_callback(Onion_Announce *onion_a, uint16_t extra_
pack_extra_data_cb *extra_data_callback, void *extra_data_object);
non_null()
-Onion_Announce *new_onion_announce(const Logger *log, const Random *rng, const Mono_Time *mono_time, DHT *dht);
+Onion_Announce *new_onion_announce(const Logger *log, const Memory *mem, const Random *rng, const Mono_Time *mono_time, DHT *dht);
nullable(1)
void kill_onion_announce(Onion_Announce *onion_a);
-#endif
+#endif /* C_TOXCORE_TOXCORE_ONION_ANNOUNCE_H */
diff --git a/protocols/Tox/libtox/src/toxcore/onion_client.c b/protocols/Tox/libtox/src/toxcore/onion_client.c
index ff63473e10..9b0ac96102 100644
--- a/protocols/Tox/libtox/src/toxcore/onion_client.c
+++ b/protocols/Tox/libtox/src/toxcore/onion_client.c
@@ -13,10 +13,23 @@
#include <stdlib.h>
#include <string.h>
+#include "DHT.h"
#include "LAN_discovery.h"
+#include "TCP_connection.h"
+#include "attributes.h"
#include "ccompat.h"
+#include "crypto_core.h"
+#include "group_announce.h"
#include "group_onion_announce.h"
+#include "logger.h"
+#include "mem.h"
#include "mono_time.h"
+#include "net_crypto.h"
+#include "network.h"
+#include "onion.h"
+#include "onion_announce.h"
+#include "ping_array.h"
+#include "timed_auth.h"
#include "util.h"
/** @brief defines for the array size and timeout for onion announce packets. */
@@ -106,6 +119,7 @@ struct Onion_Client {
const Mono_Time *mono_time;
const Logger *logger;
const Random *rng;
+ const Memory *mem;
DHT *dht;
Net_Crypto *c;
@@ -469,17 +483,6 @@ static int random_path(const Onion_Client *onion_c, Onion_Client_Paths *onion_pa
return 0;
}
-/** Does path with path_num exist. */
-non_null()
-static bool path_exists(const Mono_Time *mono_time, const Onion_Client_Paths *onion_paths, uint32_t path_num)
-{
- if (path_timed_out(mono_time, onion_paths, path_num)) {
- return false;
- }
-
- return onion_paths->paths[path_num % NUMBER_ONION_PATHS].path_num == path_num;
-}
-
/** Set path timeouts, return the path number. */
non_null()
static uint32_t set_path_timeouts(Onion_Client *onion_c, uint32_t num, uint32_t path_num)
@@ -581,6 +584,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;
}
@@ -623,6 +627,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;
}
@@ -631,10 +636,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;
}
}
@@ -666,7 +673,6 @@ static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, con
onion_friend->temp_secret_key, ping_id, onion_friend->real_public_key,
zero_ping_id, sendback);
} else { // contact is a gc
-#ifndef VANILLA_NACL
onion_friend->is_groupchat = true;
len = create_gca_announce_request(
@@ -674,16 +680,17 @@ static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, con
onion_friend->temp_secret_key, ping_id, onion_friend->real_public_key,
zero_ping_id, sendback, onion_friend->gc_data,
onion_friend->gc_data_length);
-#else
- return -1;
-#endif // VANILLA_NACL
}
}
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);
}
@@ -731,12 +738,12 @@ static int onion_client_cmp_entry(const void *a, const void *b)
}
non_null()
-static void sort_onion_node_list(Onion_Node *list, unsigned int length, const Mono_Time *mono_time,
- const uint8_t *comp_public_key)
+static void sort_onion_node_list(const Memory *mem, const Mono_Time *mono_time,
+ Onion_Node *list, unsigned int length, const uint8_t *comp_public_key)
{
// Pass comp_public_key to qsort with each Client_data entry, so the
// comparison function can use it as the base of comparison.
- Onion_Client_Cmp_Data *cmp_list = (Onion_Client_Cmp_Data *)calloc(length, sizeof(Onion_Client_Cmp_Data));
+ Onion_Client_Cmp_Data *cmp_list = (Onion_Client_Cmp_Data *)mem_valloc(mem, length, sizeof(Onion_Client_Cmp_Data));
if (cmp_list == nullptr) {
return;
@@ -754,7 +761,7 @@ static void sort_onion_node_list(Onion_Node *list, unsigned int length, const Mo
list[i] = cmp_list[i].entry;
}
- free(cmp_list);
+ mem_delete(mem, cmp_list);
}
non_null()
@@ -787,7 +794,7 @@ static int client_add_to_list(Onion_Client *onion_c, uint32_t num, const uint8_t
list_length = MAX_ONION_CLIENTS;
}
- sort_onion_node_list(node_list, list_length, onion_c->mono_time, reference_id);
+ sort_onion_node_list(onion_c->mem, onion_c->mono_time, node_list, list_length, reference_id);
int index = -1;
bool stored = false;
@@ -933,6 +940,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;
}
@@ -948,30 +957,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;
}
@@ -988,10 +1004,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;
}
}
@@ -1010,6 +1028,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;
}
@@ -1022,6 +1042,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;
}
@@ -1036,32 +1058,40 @@ static int handle_announce_response_old(void *object, const IP_Port *source, con
return 1;
}
- VLA(uint8_t, plain, 1 + ONION_PING_ID_SIZE + len_nodes);
+ const uint16_t plain_size = 1 + ONION_PING_ID_SIZE + len_nodes;
+ VLA(uint8_t, plain, plain_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 ((uint32_t)len != SIZEOF_VLA(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 (%u)", (unsigned long)len, 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;
}
@@ -1070,16 +1100,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;
}
@@ -1099,21 +1134,23 @@ static int handle_data_response(void *object, const IP_Port *source, const uint8
return 1;
}
- VLA(uint8_t, temp_plain, length - ONION_DATA_RESPONSE_MIN_SIZE);
+ const uint16_t temp_plain_size = length - ONION_DATA_RESPONSE_MIN_SIZE;
+ VLA(uint8_t, temp_plain, temp_plain_size);
int len = decrypt_data(packet + 1 + CRYPTO_NONCE_SIZE, onion_c->temp_secret_key, packet + 1,
packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE,
length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE), temp_plain);
- if ((uint32_t)len != SIZEOF_VLA(temp_plain)) {
+ if ((uint32_t)len != temp_plain_size) {
return 1;
}
- VLA(uint8_t, plain, SIZEOF_VLA(temp_plain) - DATA_IN_RESPONSE_MIN_SIZE);
+ const uint16_t plain_size = temp_plain_size - DATA_IN_RESPONSE_MIN_SIZE;
+ VLA(uint8_t, plain, plain_size);
len = decrypt_data(temp_plain, nc_get_self_secret_key(onion_c->c),
packet + 1, temp_plain + CRYPTO_PUBLIC_KEY_SIZE,
- SIZEOF_VLA(temp_plain) - CRYPTO_PUBLIC_KEY_SIZE, plain);
+ temp_plain_size - CRYPTO_PUBLIC_KEY_SIZE, plain);
- if ((uint32_t)len != SIZEOF_VLA(plain)) {
+ if ((uint32_t)len != plain_size) {
return 1;
}
@@ -1122,7 +1159,7 @@ static int handle_data_response(void *object, const IP_Port *source, const uint8
}
return onion_c->onion_data_handlers[plain[0]].function(onion_c->onion_data_handlers[plain[0]].object, temp_plain, plain,
- SIZEOF_VLA(plain), userdata);
+ plain_size, userdata);
}
#define DHTPK_DATA_MIN_LENGTH (1 + sizeof(uint64_t) + CRYPTO_PUBLIC_KEY_SIZE)
@@ -1161,7 +1198,7 @@ static int handle_dhtpk_announce(void *object, const uint8_t *source_pubkey, con
onion_c->friends_list[friend_num].dht_pk_callback_number, data + 1 + sizeof(uint64_t), userdata);
}
- onion_set_friend_DHT_pubkey(onion_c, friend_num, data + 1 + sizeof(uint64_t));
+ onion_set_friend_dht_pubkey(onion_c, friend_num, data + 1 + sizeof(uint64_t));
const uint16_t len_nodes = length - DHTPK_DATA_MIN_LENGTH;
@@ -1265,13 +1302,14 @@ int send_onion_data(Onion_Client *onion_c, int friend_num, const uint8_t *data,
uint8_t nonce[CRYPTO_NONCE_SIZE];
random_nonce(onion_c->rng, nonce);
- VLA(uint8_t, packet, DATA_IN_RESPONSE_MIN_SIZE + length);
+ const uint16_t packet_size = DATA_IN_RESPONSE_MIN_SIZE + length;
+ VLA(uint8_t, packet, packet_size);
memcpy(packet, nc_get_self_public_key(onion_c->c), CRYPTO_PUBLIC_KEY_SIZE);
int len = encrypt_data(onion_c->friends_list[friend_num].real_public_key,
nc_get_self_secret_key(onion_c->c), nonce, data,
length, packet + CRYPTO_PUBLIC_KEY_SIZE);
- if ((uint32_t)len + CRYPTO_PUBLIC_KEY_SIZE != SIZEOF_VLA(packet)) {
+ if ((uint32_t)len + CRYPTO_PUBLIC_KEY_SIZE != packet_size) {
return -1;
}
@@ -1287,7 +1325,7 @@ int send_onion_data(Onion_Client *onion_c, int friend_num, const uint8_t *data,
uint8_t o_packet[ONION_MAX_PACKET_SIZE];
len = create_data_request(
onion_c->rng, o_packet, sizeof(o_packet), onion_c->friends_list[friend_num].real_public_key,
- node_list[good_nodes[i]].data_public_key, nonce, packet, SIZEOF_VLA(packet));
+ node_list[good_nodes[i]].data_public_key, nonce, packet, packet_size);
if (len == -1) {
continue;
@@ -1322,21 +1360,22 @@ static int send_dht_dhtpk(const Onion_Client *onion_c, int friend_num, const uin
uint8_t nonce[CRYPTO_NONCE_SIZE];
random_nonce(onion_c->rng, nonce);
- VLA(uint8_t, temp, DATA_IN_RESPONSE_MIN_SIZE + CRYPTO_NONCE_SIZE + length);
+ const uint16_t temp_size = DATA_IN_RESPONSE_MIN_SIZE + CRYPTO_NONCE_SIZE + length;
+ VLA(uint8_t, temp, temp_size);
memcpy(temp, nc_get_self_public_key(onion_c->c), CRYPTO_PUBLIC_KEY_SIZE);
memcpy(temp + CRYPTO_PUBLIC_KEY_SIZE, nonce, CRYPTO_NONCE_SIZE);
int len = encrypt_data(onion_c->friends_list[friend_num].real_public_key,
nc_get_self_secret_key(onion_c->c), nonce, data,
length, temp + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE);
- if ((uint32_t)len + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE != SIZEOF_VLA(temp)) {
+ if ((uint32_t)len + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE != temp_size) {
return -1;
}
uint8_t packet_data[MAX_CRYPTO_REQUEST_SIZE];
len = create_request(
onion_c->rng, dht_get_self_public_key(onion_c->dht), dht_get_self_secret_key(onion_c->dht), packet_data,
- onion_c->friends_list[friend_num].dht_public_key, temp, SIZEOF_VLA(temp), CRYPTO_PACKET_DHTPK);
+ onion_c->friends_list[friend_num].dht_public_key, temp, temp_size, CRYPTO_PACKET_DHTPK);
assert(len <= UINT16_MAX);
const Packet packet = {packet_data, (uint16_t)len};
@@ -1377,6 +1416,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.
@@ -1457,19 +1497,19 @@ int onion_friend_num(const Onion_Client *onion_c, const uint8_t *public_key)
/** @brief Set the size of the friend list to num.
*
- * @retval -1 if realloc fails.
+ * @retval -1 if mem_vrealloc fails.
* @retval 0 if it succeeds.
*/
non_null()
static int realloc_onion_friends(Onion_Client *onion_c, uint32_t num)
{
if (num == 0) {
- free(onion_c->friends_list);
+ mem_delete(onion_c->mem, onion_c->friends_list);
onion_c->friends_list = nullptr;
return 0;
}
- Onion_Friend *newonion_friends = (Onion_Friend *)realloc(onion_c->friends_list, num * sizeof(Onion_Friend));
+ Onion_Friend *newonion_friends = (Onion_Friend *)mem_vrealloc(onion_c->mem, onion_c->friends_list, num, sizeof(Onion_Friend));
if (newonion_friends == nullptr) {
return -1;
@@ -1535,7 +1575,7 @@ int onion_delfriend(Onion_Client *onion_c, int friend_num)
dht_delfriend(onion_c->dht, onion_c->friends_list[friend_num].dht_public_key, 0);
}
-#endif
+#endif /* 0 */
crypto_memzero(&onion_c->friends_list[friend_num], sizeof(Onion_Friend));
unsigned int i;
@@ -1601,7 +1641,7 @@ int onion_dht_pk_callback(Onion_Client *onion_c, int friend_num,
* return -1 on failure.
* return 0 on success.
*/
-int onion_set_friend_DHT_pubkey(Onion_Client *onion_c, int friend_num, const uint8_t *dht_key)
+int onion_set_friend_dht_pubkey(Onion_Client *onion_c, int friend_num, const uint8_t *dht_key)
{
if ((uint32_t)friend_num >= onion_c->num_friends) {
return -1;
@@ -1628,7 +1668,7 @@ int onion_set_friend_DHT_pubkey(Onion_Client *onion_c, int friend_num, const uin
* return 0 on failure (no key copied).
* return 1 on success (key copied).
*/
-unsigned int onion_getfriend_DHT_pubkey(const Onion_Client *onion_c, int friend_num, uint8_t *dht_key)
+unsigned int onion_getfriend_dht_pubkey(const Onion_Client *onion_c, int friend_num, uint8_t *dht_key)
{
if ((uint32_t)friend_num >= onion_c->num_friends) {
return 0;
@@ -1656,14 +1696,13 @@ int onion_getfriendip(const Onion_Client *onion_c, int friend_num, IP_Port *ip_p
{
uint8_t dht_public_key[CRYPTO_PUBLIC_KEY_SIZE];
- if (onion_getfriend_DHT_pubkey(onion_c, friend_num, dht_public_key) == 0) {
+ if (onion_getfriend_dht_pubkey(onion_c, friend_num, dht_public_key) == 0) {
return -1;
}
return dht_getfriendip(onion_c->dht, dht_public_key, ip_port);
}
-
/** @brief Set if friend is online or not.
*
* NOTE: This function is there and should be used so that we don't send
@@ -1836,7 +1875,6 @@ static void do_friend(Onion_Client *onion_c, uint16_t friendnum)
}
}
-
/** Function to call when onion data packet with contents beginning with byte is received. */
void oniondata_registerhandler(Onion_Client *onion_c, uint8_t byte, oniondata_handler_cb *cb, void *object)
{
@@ -1857,6 +1895,45 @@ void onion_group_announce_register(Onion_Client *onion_c, onion_group_announce_c
#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;
+}
+
+/** Does path with path_num exist. */
+non_null()
+static bool path_exists(const Mono_Time *mono_time, const Onion_Client_Paths *onion_paths, uint32_t path_num)
+{
+ if (path_timed_out(mono_time, onion_paths, path_num)) {
+ return false;
+ }
+
+ return onion_paths->paths[path_num % NUMBER_ONION_PATHS].path_num == path_num;
+}
+
+/**
+ * A node/path is considered "stable" if it has survived for at least TIME_TO_STABLE
+ * and the latest packets sent to it are not timing out.
+ */
+non_null()
+static bool path_is_stable(const Mono_Time *mono_time, const Onion_Client_Paths *paths,
+ uint32_t pathnum, const Onion_Node *node)
+{
+ return mono_time_is_timeout(mono_time, node->added_time, TIME_TO_STABLE)
+ && !(node->pings_since_last_response > 0
+ && mono_time_is_timeout(mono_time, node->last_pinged, ONION_NODE_TIMEOUT))
+ && mono_time_is_timeout(mono_time, paths->path_creation_time[pathnum], TIME_TO_STABLE)
+ && !(paths->last_path_used_times[pathnum] > 0
+ && mono_time_is_timeout(mono_time, paths->last_path_used[pathnum], ONION_PATH_TIMEOUT));
+}
+
+non_null()
static void do_announce(Onion_Client *onion_c)
{
unsigned int count = 0;
@@ -1879,7 +1956,6 @@ static void do_announce(Onion_Client *onion_c)
continue;
}
-
unsigned int interval = ANNOUNCE_INTERVAL_NOT_ANNOUNCED;
if (node_list[i].is_stored != 0
@@ -1888,16 +1964,8 @@ static void do_announce(Onion_Client *onion_c)
const uint32_t pathnum = node_list[i].path_used % NUMBER_ONION_PATHS;
- /* A node/path is considered "stable", and can be pinged less
- * aggressively, if it has survived for at least TIME_TO_STABLE
- * and the latest packets sent to it are not timing out.
- */
- if (mono_time_is_timeout(onion_c->mono_time, node_list[i].added_time, TIME_TO_STABLE)
- && !(node_list[i].pings_since_last_response > 0
- && mono_time_is_timeout(onion_c->mono_time, node_list[i].last_pinged, ONION_NODE_TIMEOUT))
- && mono_time_is_timeout(onion_c->mono_time, onion_c->onion_paths_self.path_creation_time[pathnum], TIME_TO_STABLE)
- && !(onion_c->onion_paths_self.last_path_used_times[pathnum] > 0
- && mono_time_is_timeout(onion_c->mono_time, onion_c->onion_paths_self.last_path_used[pathnum], ONION_PATH_TIMEOUT))) {
+ /* If a node/path is considered "stable", it can be pinged less aggressively. */
+ if (path_is_stable(onion_c->mono_time, &onion_c->onion_paths_self, pathnum, &node_list[i])) {
interval = ANNOUNCE_INTERVAL_STABLE;
}
}
@@ -1944,9 +2012,30 @@ 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.
+ //
+ // TODO(iphydf): Figure out why on esp32, this is necessary for the onion
+ // connection to succeed. This is an optimisation and shouldn't be necessary.
+ 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));
+ }
}
}
}
@@ -1958,22 +2047,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;
@@ -1989,14 +2081,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;
}
@@ -2074,28 +2170,29 @@ void do_onion_client(Onion_Client *onion_c)
onion_c->last_run = mono_time_get(onion_c->mono_time);
}
-Onion_Client *new_onion_client(const Logger *logger, const Random *rng, const Mono_Time *mono_time, Net_Crypto *c)
+Onion_Client *new_onion_client(const Logger *logger, const Memory *mem, const Random *rng, const Mono_Time *mono_time, Net_Crypto *c)
{
if (c == nullptr) {
return nullptr;
}
- Onion_Client *onion_c = (Onion_Client *)calloc(1, sizeof(Onion_Client));
+ Onion_Client *onion_c = (Onion_Client *)mem_alloc(mem, sizeof(Onion_Client));
if (onion_c == nullptr) {
return nullptr;
}
- onion_c->announce_ping_array = ping_array_new(ANNOUNCE_ARRAY_SIZE, ANNOUNCE_TIMEOUT);
+ onion_c->announce_ping_array = ping_array_new(mem, ANNOUNCE_ARRAY_SIZE, ANNOUNCE_TIMEOUT);
if (onion_c->announce_ping_array == nullptr) {
- free(onion_c);
+ mem_delete(mem, onion_c);
return nullptr;
}
onion_c->mono_time = mono_time;
onion_c->logger = logger;
onion_c->rng = rng;
+ onion_c->mem = mem;
onion_c->dht = nc_get_dht(c);
onion_c->net = dht_get_net(onion_c->dht);
onion_c->c = c;
@@ -2117,6 +2214,8 @@ void kill_onion_client(Onion_Client *onion_c)
return;
}
+ const Memory *mem = onion_c->mem;
+
ping_array_kill(onion_c->announce_ping_array);
realloc_onion_friends(onion_c, 0);
networking_registerhandler(onion_c->net, NET_PACKET_ANNOUNCE_RESPONSE, nullptr, nullptr);
@@ -2126,5 +2225,5 @@ void kill_onion_client(Onion_Client *onion_c)
cryptopacket_registerhandler(onion_c->dht, CRYPTO_PACKET_DHTPK, nullptr, nullptr);
set_onion_packet_tcp_connection_callback(nc_get_tcp_c(onion_c->c), nullptr, nullptr);
crypto_memzero(onion_c, sizeof(Onion_Client));
- free(onion_c);
+ mem_delete(mem, onion_c);
}
diff --git a/protocols/Tox/libtox/src/toxcore/onion_client.h b/protocols/Tox/libtox/src/toxcore/onion_client.h
index 23a48ef5e6..61e4e6fd1c 100644
--- a/protocols/Tox/libtox/src/toxcore/onion_client.h
+++ b/protocols/Tox/libtox/src/toxcore/onion_client.h
@@ -12,7 +12,14 @@
#include <stdbool.h>
+#include "DHT.h"
+#include "attributes.h"
+#include "crypto_core.h"
+#include "logger.h"
+#include "mem.h"
+#include "mono_time.h"
#include "net_crypto.h"
+#include "network.h"
#include "onion_announce.h"
#include "ping_array.h"
@@ -145,7 +152,7 @@ non_null()
int recv_tcp_relay_handler(Onion_Client *onion_c, int friend_num,
recv_tcp_relay_cb *callback, void *object, uint32_t number);
-typedef void onion_dht_pk_cb(void *data, int32_t number, const uint8_t *dht_public_key, void *userdata);
+typedef void onion_dht_pk_cb(void *object, int32_t number, const uint8_t *dht_public_key, void *userdata);
/** @brief Set the function for this friend that will be callbacked with object and number
* when that friend gives us their DHT temporary public key.
@@ -165,7 +172,7 @@ int onion_dht_pk_callback(Onion_Client *onion_c, int friend_num, onion_dht_pk_cb
* return 0 on success.
*/
non_null()
-int onion_set_friend_DHT_pubkey(Onion_Client *onion_c, int friend_num, const uint8_t *dht_key);
+int onion_set_friend_dht_pubkey(Onion_Client *onion_c, int friend_num, const uint8_t *dht_key);
/** @brief Copy friends DHT public key into dht_key.
*
@@ -173,7 +180,7 @@ int onion_set_friend_DHT_pubkey(Onion_Client *onion_c, int friend_num, const uin
* return 1 on success (key copied).
*/
non_null()
-unsigned int onion_getfriend_DHT_pubkey(const Onion_Client *onion_c, int friend_num, uint8_t *dht_key);
+unsigned int onion_getfriend_dht_pubkey(const Onion_Client *onion_c, int friend_num, uint8_t *dht_key);
#define ONION_DATA_IN_RESPONSE_MIN_SIZE (CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_MAC_SIZE)
#define ONION_CLIENT_MAX_DATA_SIZE (MAX_DATA_REQUEST_SIZE - ONION_DATA_IN_RESPONSE_MIN_SIZE)
@@ -191,7 +198,7 @@ non_null()
int send_onion_data(Onion_Client *onion_c, int friend_num, const uint8_t *data, uint16_t length);
typedef int oniondata_handler_cb(void *object, const uint8_t *source_pubkey, const uint8_t *data,
- uint16_t len, void *userdata);
+ uint16_t length, void *userdata);
/** Function to call when onion data packet with contents beginning with byte is received. */
non_null(1) nullable(3, 4)
@@ -208,12 +215,11 @@ non_null()
void do_onion_client(Onion_Client *onion_c);
non_null()
-Onion_Client *new_onion_client(const Logger *logger, const Random *rng, const Mono_Time *mono_time, Net_Crypto *c);
+Onion_Client *new_onion_client(const Logger *logger, const Memory *mem, const Random *rng, const Mono_Time *mono_time, Net_Crypto *c);
nullable(1)
void kill_onion_client(Onion_Client *onion_c);
-
typedef enum Onion_Connection_Status {
/** We are not connected to the network. */
ONION_CONNECTION_STATUS_NONE = 0,
@@ -228,13 +234,13 @@ Onion_Connection_Status onion_connection_status(const Onion_Client *onion_c);
typedef struct Onion_Friend Onion_Friend;
-non_null() uint16_t onion_get_friend_count(const Onion_Client *const onion_c);
-non_null() Onion_Friend *onion_get_friend(const Onion_Client *const onion_c, uint16_t friend_num);
-non_null() const uint8_t *onion_friend_get_gc_public_key(const Onion_Friend *const onion_friend);
-non_null() const uint8_t *onion_friend_get_gc_public_key_num(const Onion_Client *const onion_c, uint32_t num);
-non_null() void onion_friend_set_gc_public_key(Onion_Friend *const onion_friend, const uint8_t *public_key);
+non_null() uint16_t onion_get_friend_count(const Onion_Client *onion_c);
+non_null() Onion_Friend *onion_get_friend(const Onion_Client *onion_c, uint16_t friend_num);
+non_null() const uint8_t *onion_friend_get_gc_public_key(const Onion_Friend *onion_friend);
+non_null() const uint8_t *onion_friend_get_gc_public_key_num(const Onion_Client *onion_c, uint32_t num);
+non_null() void onion_friend_set_gc_public_key(Onion_Friend *onion_friend, const uint8_t *public_key);
non_null(1) nullable(2)
-void onion_friend_set_gc_data(Onion_Friend *const onion_friend, const uint8_t *gc_data, uint16_t gc_data_length);
-non_null() bool onion_friend_is_groupchat(const Onion_Friend *const onion_friend);
+void onion_friend_set_gc_data(Onion_Friend *onion_friend, const uint8_t *gc_data, uint16_t gc_data_length);
+non_null() bool onion_friend_is_groupchat(const Onion_Friend *onion_friend);
-#endif
+#endif /* C_TOXCORE_TOXCORE_ONION_CLIENT_H */
diff --git a/protocols/Tox/libtox/src/toxcore/ping.c b/protocols/Tox/libtox/src/toxcore/ping.c
index f44777b8ee..303c418cea 100644
--- a/protocols/Tox/libtox/src/toxcore/ping.c
+++ b/protocols/Tox/libtox/src/toxcore/ping.c
@@ -9,15 +9,16 @@
*/
#include "ping.h"
-#include <stdlib.h>
#include <string.h>
#include "DHT.h"
+#include "attributes.h"
#include "ccompat.h"
+#include "crypto_core.h"
+#include "mem.h"
#include "mono_time.h"
#include "network.h"
#include "ping_array.h"
-#include "util.h"
#define PING_NUM_MAX 512
@@ -27,7 +28,6 @@
/** Ping newly announced nodes to ping per TIME_TO_PING seconds*/
#define TIME_TO_PING 2
-
struct Ping {
const Mono_Time *mono_time;
const Random *rng;
@@ -38,7 +38,6 @@ struct Ping {
uint64_t last_to_ping;
};
-
#define PING_PLAIN_SIZE (1 + sizeof(uint64_t))
#define DHT_PING_SIZE (1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + PING_PLAIN_SIZE + CRYPTO_MAC_SIZE)
#define PING_DATA_SIZE (CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port))
@@ -53,7 +52,6 @@ void ping_send_request(Ping *ping, const IP_Port *ipp, const uint8_t *public_key
return;
}
-
// generate key to encrypt ping_id with recipient privkey
const uint8_t *shared_key = dht_get_shared_key_sent(ping->dht, public_key);
// Generate random ping_id.
@@ -74,7 +72,6 @@ void ping_send_request(Ping *ping, const IP_Port *ipp, const uint8_t *public_key
pk_copy(pk + 1, dht_get_self_public_key(ping->dht)); // Our pubkey
random_nonce(ping->rng, pk + 1 + CRYPTO_PUBLIC_KEY_SIZE); // Generate new nonce
-
rc = encrypt_data_symmetric(shared_key,
pk + 1 + CRYPTO_PUBLIC_KEY_SIZE,
ping_plain, sizeof(ping_plain),
@@ -301,7 +298,6 @@ int32_t ping_add(Ping *ping, const uint8_t *public_key, const IP_Port *ip_port)
return -1;
}
-
/** @brief Ping all the valid nodes in the to_ping list every TIME_TO_PING seconds.
* This function must be run at least once every TIME_TO_PING seconds.
*/
@@ -335,19 +331,18 @@ void ping_iterate(Ping *ping)
}
}
-
-Ping *ping_new(const Mono_Time *mono_time, const Random *rng, DHT *dht)
+Ping *ping_new(const Memory *mem, const Mono_Time *mono_time, const Random *rng, DHT *dht)
{
- Ping *ping = (Ping *)calloc(1, sizeof(Ping));
+ Ping *ping = (Ping *)mem_alloc(mem, sizeof(Ping));
if (ping == nullptr) {
return nullptr;
}
- ping->ping_array = ping_array_new(PING_NUM_MAX, PING_TIMEOUT);
+ ping->ping_array = ping_array_new(mem, PING_NUM_MAX, PING_TIMEOUT);
if (ping->ping_array == nullptr) {
- free(ping);
+ mem_delete(mem, ping);
return nullptr;
}
@@ -360,7 +355,7 @@ Ping *ping_new(const Mono_Time *mono_time, const Random *rng, DHT *dht)
return ping;
}
-void ping_kill(Ping *ping)
+void ping_kill(const Memory *mem, Ping *ping)
{
if (ping == nullptr) {
return;
@@ -370,5 +365,5 @@ void ping_kill(Ping *ping)
networking_registerhandler(dht_get_net(ping->dht), NET_PACKET_PING_RESPONSE, nullptr, nullptr);
ping_array_kill(ping->ping_array);
- free(ping);
+ mem_delete(mem, ping);
}
diff --git a/protocols/Tox/libtox/src/toxcore/ping.h b/protocols/Tox/libtox/src/toxcore/ping.h
index da8d7f003e..b0339ec75d 100644
--- a/protocols/Tox/libtox/src/toxcore/ping.h
+++ b/protocols/Tox/libtox/src/toxcore/ping.h
@@ -13,15 +13,19 @@
#include <stdint.h>
#include "DHT.h"
+#include "attributes.h"
+#include "crypto_core.h"
+#include "mem.h"
+#include "mono_time.h"
#include "network.h"
typedef struct Ping Ping;
non_null()
-Ping *ping_new(const Mono_Time *mono_time, const Random *rng, DHT *dht);
+Ping *ping_new(const Memory *mem, const Mono_Time *mono_time, const Random *rng, DHT *dht);
-nullable(1)
-void ping_kill(Ping *ping);
+non_null(1) nullable(2)
+void ping_kill(const Memory *mem, Ping *ping);
/** @brief Add nodes to the to_ping list.
* All nodes in this list are pinged every TIME_TO_PING seconds
@@ -45,4 +49,4 @@ void ping_iterate(Ping *ping);
non_null()
void ping_send_request(Ping *ping, const IP_Port *ipp, const uint8_t *public_key);
-#endif // C_TOXCORE_TOXCORE_PING_H
+#endif /* C_TOXCORE_TOXCORE_PING_H */
diff --git a/protocols/Tox/libtox/src/toxcore/ping_array.c b/protocols/Tox/libtox/src/toxcore/ping_array.c
index e22a2e6c1c..c40215ea47 100644
--- a/protocols/Tox/libtox/src/toxcore/ping_array.c
+++ b/protocols/Tox/libtox/src/toxcore/ping_array.c
@@ -8,13 +8,13 @@
*/
#include "ping_array.h"
-#include <stdlib.h>
#include <string.h>
+#include "attributes.h"
#include "ccompat.h"
#include "crypto_core.h"
+#include "mem.h"
#include "mono_time.h"
-#include "util.h"
typedef struct Ping_Array_Entry {
uint8_t *data;
@@ -24,6 +24,7 @@ typedef struct Ping_Array_Entry {
} Ping_Array_Entry;
struct Ping_Array {
+ const Memory *mem;
Ping_Array_Entry *entries;
uint32_t last_deleted; /* number representing the next entry to be deleted. */
@@ -32,7 +33,7 @@ struct Ping_Array {
uint32_t timeout; /* The timeout after which entries are cleared. */
};
-Ping_Array *ping_array_new(uint32_t size, uint32_t timeout)
+Ping_Array *ping_array_new(const Memory *mem, uint32_t size, uint32_t timeout)
{
if (size == 0 || timeout == 0) {
return nullptr;
@@ -43,19 +44,21 @@ Ping_Array *ping_array_new(uint32_t size, uint32_t timeout)
return nullptr;
}
- Ping_Array *const empty_array = (Ping_Array *)calloc(1, sizeof(Ping_Array));
+ Ping_Array *const empty_array = (Ping_Array *)mem_alloc(mem, sizeof(Ping_Array));
if (empty_array == nullptr) {
return nullptr;
}
- empty_array->entries = (Ping_Array_Entry *)calloc(size, sizeof(Ping_Array_Entry));
+ Ping_Array_Entry *entries = (Ping_Array_Entry *)mem_valloc(mem, size, sizeof(Ping_Array_Entry));
- if (empty_array->entries == nullptr) {
- free(empty_array);
+ if (entries == nullptr) {
+ mem_delete(mem, empty_array);
return nullptr;
}
+ empty_array->mem = mem;
+ empty_array->entries = entries;
empty_array->last_deleted = 0;
empty_array->last_added = 0;
empty_array->total_size = size;
@@ -67,7 +70,7 @@ non_null()
static void clear_entry(Ping_Array *array, uint32_t index)
{
const Ping_Array_Entry empty = {nullptr};
- free(array->entries[index].data);
+ mem_delete(array->mem, array->entries[index].data);
array->entries[index] = empty;
}
@@ -83,8 +86,8 @@ void ping_array_kill(Ping_Array *array)
++array->last_deleted;
}
- free(array->entries);
- free(array);
+ mem_delete(array->mem, array->entries);
+ mem_delete(array->mem, array);
}
/** Clear timed out entries. */
@@ -114,13 +117,16 @@ uint64_t ping_array_add(Ping_Array *array, const Mono_Time *mono_time, const Ran
clear_entry(array, index);
}
- array->entries[index].data = (uint8_t *)malloc(length);
+ uint8_t *entry_data = (uint8_t *)mem_balloc(array->mem, length);
- if (array->entries[index].data == nullptr) {
+ if (entry_data == nullptr) {
+ array->entries[index].data = nullptr;
return 0;
}
- memcpy(array->entries[index].data, data, length);
+ memcpy(entry_data, data, length);
+
+ array->entries[index].data = entry_data;
array->entries[index].length = length;
array->entries[index].ping_time = mono_time_get(mono_time);
++array->last_added;
diff --git a/protocols/Tox/libtox/src/toxcore/ping_array.h b/protocols/Tox/libtox/src/toxcore/ping_array.h
index fda84cb110..3e50e66876 100644
--- a/protocols/Tox/libtox/src/toxcore/ping_array.h
+++ b/protocols/Tox/libtox/src/toxcore/ping_array.h
@@ -12,7 +12,9 @@
#include <stddef.h>
#include <stdint.h>
+#include "attributes.h"
#include "crypto_core.h"
+#include "mem.h"
#include "mono_time.h"
#ifdef __cplusplus
@@ -29,7 +31,8 @@ typedef struct Ping_Array Ping_Array;
*
* @return pointer to allocated Ping_Array on success, nullptr on failure.
*/
-struct Ping_Array *ping_array_new(uint32_t size, uint32_t timeout);
+non_null()
+struct Ping_Array *ping_array_new(const Memory *mem, uint32_t size, uint32_t timeout);
/**
* @brief Free all the allocated memory in a @ref Ping_Array.
@@ -58,7 +61,7 @@ int32_t ping_array_check(Ping_Array *array, const Mono_Time *mono_time, uint8_t
uint64_t ping_id);
#ifdef __cplusplus
-} // extern "C"
+} /* extern "C" */
#endif
-#endif // C_TOXCORE_TOXCORE_PING_ARRAY_H
+#endif /* C_TOXCORE_TOXCORE_PING_ARRAY_H */
diff --git a/protocols/Tox/libtox/src/toxcore/shared_key_cache.c b/protocols/Tox/libtox/src/toxcore/shared_key_cache.c
index 7846ae4f69..80d74aecb4 100644
--- a/protocols/Tox/libtox/src/toxcore/shared_key_cache.c
+++ b/protocols/Tox/libtox/src/toxcore/shared_key_cache.c
@@ -4,13 +4,14 @@
#include "shared_key_cache.h"
-#include <assert.h>
#include <stdint.h>
-#include <stdlib.h> // calloc(...)
#include <string.h> // memcpy(...)
+#include "attributes.h"
#include "ccompat.h"
#include "crypto_core.h"
+#include "logger.h"
+#include "mem.h"
#include "mono_time.h"
typedef struct Shared_Key {
@@ -21,15 +22,18 @@ typedef struct Shared_Key {
struct Shared_Key_Cache {
Shared_Key *keys;
- const uint8_t* self_secret_key;
+ const uint8_t *self_secret_key;
uint64_t timeout; /** After this time (in seconds), a key is erased on the next housekeeping cycle */
- const Mono_Time *time;
+ 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,42 +42,48 @@ static bool shared_key_is_empty(const Shared_Key *k) {
}
non_null()
-static void shared_key_set_empty(Shared_Key *k) {
- crypto_memzero(k, sizeof (Shared_Key));
- assert(shared_key_is_empty(k));
+static void shared_key_set_empty(const Logger *log, Shared_Key *k)
+{
+ crypto_memzero(k, sizeof(Shared_Key));
+ 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 *time, 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 (time == nullptr || self_secret_key == nullptr || timeout == 0 || keys_per_slot == 0) {
+ if (mono_time == nullptr || self_secret_key == nullptr || timeout == 0 || keys_per_slot == 0) {
return nullptr;
}
// Time must not be zero, since we use that as special value for empty slots
- if (mono_time_get(time) == 0) {
+ 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;
}
- Shared_Key_Cache *res = (Shared_Key_Cache *)calloc(1, sizeof (Shared_Key_Cache));
+ Shared_Key_Cache *res = (Shared_Key_Cache *)mem_alloc(mem, sizeof(Shared_Key_Cache));
if (res == nullptr) {
return nullptr;
}
res->self_secret_key = self_secret_key;
- res->time = time;
+ 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;
- res->keys = (Shared_Key *)calloc(cache_size, sizeof (Shared_Key));
+ Shared_Key *keys = (Shared_Key *)mem_valloc(mem, cache_size, sizeof(Shared_Key));
- if (res->keys == nullptr) {
- free(res);
+ if (keys == nullptr) {
+ mem_delete(mem, res);
return nullptr;
}
- crypto_memlock(res->keys, cache_size * sizeof (Shared_Key));
+ crypto_memlock(keys, cache_size * sizeof(Shared_Key));
+
+ res->keys = keys;
return res;
}
@@ -86,26 +96,26 @@ void shared_key_cache_free(Shared_Key_Cache *cache)
const size_t cache_size = 256 * cache->keys_per_slot;
// Don't leave key material in memory
- crypto_memzero(cache->keys, cache_size * sizeof (Shared_Key));
- crypto_memunlock(cache->keys, cache_size * sizeof (Shared_Key));
- free(cache->keys);
- free(cache);
+ crypto_memzero(cache->keys, cache_size * sizeof(Shared_Key));
+ crypto_memunlock(cache->keys, cache_size * sizeof(Shared_Key));
+ mem_delete(cache->mem, cache->keys);
+ mem_delete(cache->mem, cache);
}
/* NOTE: On each lookup housekeeping is performed to evict keys that did timeout. */
const uint8_t *shared_key_cache_lookup(Shared_Key_Cache *cache, const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE])
{
// caching the time is not necessary, but calls to mono_time_get(...) are not free
- const uint64_t cur_time = mono_time_get(cache->time);
+ const uint64_t cur_time = mono_time_get(cache->mono_time);
// We can't use the first and last bytes because they are masked in curve25519. Selected 8 for good alignment.
const uint8_t bucket_idx = public_key[8];
- Shared_Key* bucket_start = &cache->keys[bucket_idx*cache->keys_per_slot];
+ Shared_Key *bucket_start = &cache->keys[bucket_idx * cache->keys_per_slot];
- const uint8_t* found = nullptr;
+ const uint8_t *found = nullptr;
// Perform lookup
- for(size_t i = 0; i < cache->keys_per_slot; ++i) {
- if (shared_key_is_empty(&bucket_start[i])) {
+ for (size_t i = 0; i < cache->keys_per_slot; ++i) {
+ if (shared_key_is_empty(cache->log, &bucket_start[i])) {
continue;
}
@@ -118,13 +128,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]);
}
}
diff --git a/protocols/Tox/libtox/src/toxcore/shared_key_cache.h b/protocols/Tox/libtox/src/toxcore/shared_key_cache.h
index 97d8b7a4a8..f6e84c3130 100644
--- a/protocols/Tox/libtox/src/toxcore/shared_key_cache.h
+++ b/protocols/Tox/libtox/src/toxcore/shared_key_cache.h
@@ -7,7 +7,10 @@
#include <stdint.h> // uint*_t
+#include "attributes.h"
#include "crypto_core.h"
+#include "logger.h"
+#include "mem.h"
#include "mono_time.h"
/**
@@ -18,7 +21,7 @@ typedef struct Shared_Key_Cache Shared_Key_Cache;
/**
* @brief Initializes a new shared key cache.
- * @param time Time object for retrieving current time.
+ * @param mono_time Time object for retrieving current time.
* @param self_secret_key Our own secret key of length CRYPTO_SECRET_KEY_SIZE,
* it must not change during the lifetime of the cache.
* @param timeout Number of milliseconds, after which a key should be evicted.
@@ -26,9 +29,10 @@ typedef struct Shared_Key_Cache Shared_Key_Cache;
* @return nullptr on error.
*/
non_null()
-Shared_Key_Cache *shared_key_cache_new(const Mono_Time *time,
- 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);
/**
* @brief Deletes the cache and frees all resources.
@@ -46,6 +50,6 @@ void shared_key_cache_free(Shared_Key_Cache *cache);
* @return nullptr on error.
*/
non_null()
-const uint8_t* shared_key_cache_lookup(Shared_Key_Cache *cache, const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE]);
+const uint8_t *shared_key_cache_lookup(Shared_Key_Cache *cache, const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE]);
-#endif // C_TOXCORE_TOXCORE_SHARED_KEY_CACHE_H
+#endif /* C_TOXCORE_TOXCORE_SHARED_KEY_CACHE_H */
diff --git a/protocols/Tox/libtox/src/toxcore/state.c b/protocols/Tox/libtox/src/toxcore/state.c
index 701cf4426b..6835ca0007 100644
--- a/protocols/Tox/libtox/src/toxcore/state.c
+++ b/protocols/Tox/libtox/src/toxcore/state.c
@@ -7,6 +7,7 @@
#include <string.h>
#include "ccompat.h"
+#include "logger.h"
/** state load/save */
int state_load(const Logger *log, state_load_cb *state_load_callback, void *outer,
@@ -17,7 +18,6 @@ int state_load(const Logger *log, state_load_cb *state_load_callback, void *oute
return -1;
}
-
const uint32_t size_head = sizeof(uint32_t) * 2;
while (length >= size_head) {
@@ -52,7 +52,7 @@ int state_load(const Logger *log, state_load_cb *state_load_callback, void *oute
}
case STATE_LOAD_STATUS_ERROR: {
- LOGGER_ERROR(log, "Error occcured in state file (type: %u).", type);
+ LOGGER_ERROR(log, "Error occcured in state file (type: 0x%02x).", type);
return -1;
}
@@ -85,7 +85,7 @@ uint16_t lendian_to_host16(uint16_t lendian)
return (lendian << 8) | (lendian >> 8);
#else
return lendian;
-#endif
+#endif /* WORDS_BIGENDIAN */
}
uint16_t host_to_lendian16(uint16_t host)
@@ -99,7 +99,7 @@ void host_to_lendian_bytes64(uint8_t *dest, uint64_t num)
num = ((num << 8) & 0xFF00FF00FF00FF00) | ((num >> 8) & 0xFF00FF00FF00FF);
num = ((num << 16) & 0xFFFF0000FFFF0000) | ((num >> 16) & 0xFFFF0000FFFF);
num = (num << 32) | (num >> 32);
-#endif
+#endif /* WORDS_BIGENDIAN */
memcpy(dest, &num, sizeof(uint64_t));
}
@@ -111,7 +111,7 @@ void lendian_bytes_to_host64(uint64_t *dest, const uint8_t *lendian)
d = ((d << 8) & 0xFF00FF00FF00FF00) | ((d >> 8) & 0xFF00FF00FF00FF);
d = ((d << 16) & 0xFFFF0000FFFF0000) | ((d >> 16) & 0xFFFF0000FFFF);
d = (d << 32) | (d >> 32);
-#endif
+#endif /* WORDS_BIGENDIAN */
*dest = d;
}
@@ -120,7 +120,7 @@ void host_to_lendian_bytes32(uint8_t *dest, uint32_t num)
#ifdef WORDS_BIGENDIAN
num = ((num << 8) & 0xFF00FF00) | ((num >> 8) & 0xFF00FF);
num = (num << 16) | (num >> 16);
-#endif
+#endif /* WORDS_BIGENDIAN */
memcpy(dest, &num, sizeof(uint32_t));
}
@@ -131,7 +131,7 @@ void lendian_bytes_to_host32(uint32_t *dest, const uint8_t *lendian)
#ifdef WORDS_BIGENDIAN
d = ((d << 8) & 0xFF00FF00) | ((d >> 8) & 0xFF00FF);
d = (d << 16) | (d >> 16);
-#endif
+#endif /* WORDS_BIGENDIAN */
*dest = d;
}
@@ -139,7 +139,7 @@ void host_to_lendian_bytes16(uint8_t *dest, uint16_t num)
{
#ifdef WORDS_BIGENDIAN
num = (num << 8) | (num >> 8);
-#endif
+#endif /* WORDS_BIGENDIAN */
memcpy(dest, &num, sizeof(uint16_t));
}
@@ -149,6 +149,6 @@ void lendian_bytes_to_host16(uint16_t *dest, const uint8_t *lendian)
memcpy(&d, lendian, sizeof(uint16_t));
#ifdef WORDS_BIGENDIAN
d = (d << 8) | (d >> 8);
-#endif
+#endif /* WORDS_BIGENDIAN */
*dest = d;
}
diff --git a/protocols/Tox/libtox/src/toxcore/state.h b/protocols/Tox/libtox/src/toxcore/state.h
index 0cc188d50d..ebe0c37221 100644
--- a/protocols/Tox/libtox/src/toxcore/state.h
+++ b/protocols/Tox/libtox/src/toxcore/state.h
@@ -17,6 +17,7 @@
#ifndef C_TOXCORE_TOXCORE_STATE_H
#define C_TOXCORE_TOXCORE_STATE_H
+#include "attributes.h"
#include "logger.h"
#ifdef __cplusplus
@@ -51,7 +52,7 @@ typedef enum State_Load_Status {
STATE_LOAD_STATUS_END,
} State_Load_Status;
-typedef State_Load_Status state_load_cb(void *outer, const uint8_t *data, uint32_t len, uint16_t type);
+typedef State_Load_Status state_load_cb(void *outer, const uint8_t *data, uint32_t length, uint16_t type);
/** state load/save */
non_null()
@@ -82,7 +83,7 @@ non_null()
void lendian_bytes_to_host16(uint16_t *dest, const uint8_t *lendian);
#ifdef __cplusplus
-} // extern "C"
+} /* extern "C" */
#endif
-#endif // C_TOXCORE_TOXCORE_STATE_H
+#endif /* C_TOXCORE_TOXCORE_STATE_H */
diff --git a/protocols/Tox/libtox/src/toxcore/timed_auth.c b/protocols/Tox/libtox/src/toxcore/timed_auth.c
index ebd5100286..875003257b 100644
--- a/protocols/Tox/libtox/src/toxcore/timed_auth.c
+++ b/protocols/Tox/libtox/src/toxcore/timed_auth.c
@@ -5,9 +5,12 @@
#include <string.h>
+#include "attributes.h"
#include "ccompat.h"
+#include "crypto_core.h"
+#include "mono_time.h"
-non_null(1,6) nullable(4)
+non_null(1, 6) nullable(4)
static void create_timed_auth_to_hash(const Mono_Time *mono_time, uint16_t timeout, bool previous, const uint8_t *data,
uint16_t length, uint8_t *to_hash)
{
@@ -22,20 +25,22 @@ static void create_timed_auth_to_hash(const Mono_Time *mono_time, uint16_t timeo
void generate_timed_auth(const Mono_Time *mono_time, uint16_t timeout, const uint8_t *key,
const uint8_t *data, uint16_t length, uint8_t *timed_auth)
{
- VLA(uint8_t, to_hash, sizeof(uint64_t) + length);
+ const uint16_t to_hash_size = sizeof(uint64_t) + length;
+ VLA(uint8_t, to_hash, to_hash_size);
create_timed_auth_to_hash(mono_time, timeout, false, data, length, to_hash);
- crypto_hmac(timed_auth, key, to_hash, SIZEOF_VLA(to_hash));
+ crypto_hmac(timed_auth, key, to_hash, to_hash_size);
}
bool check_timed_auth(const Mono_Time *mono_time, uint16_t timeout, const uint8_t *key, const uint8_t *data,
uint16_t length, const uint8_t *timed_auth)
{
- VLA(uint8_t, to_hash, sizeof(uint64_t) + length);
+ const uint16_t to_hash_size = sizeof(uint64_t) + length;
+ VLA(uint8_t, to_hash, to_hash_size);
for (uint8_t i = 0; i < 2; ++i) {
create_timed_auth_to_hash(mono_time, timeout, i != 0, data, length, to_hash);
- if (crypto_hmac_verify(timed_auth, key, to_hash, SIZEOF_VLA(to_hash))) {
+ if (crypto_hmac_verify(timed_auth, key, to_hash, to_hash_size)) {
return true;
}
}
diff --git a/protocols/Tox/libtox/src/toxcore/timed_auth.h b/protocols/Tox/libtox/src/toxcore/timed_auth.h
index 691b04d0df..bb19570872 100644
--- a/protocols/Tox/libtox/src/toxcore/timed_auth.h
+++ b/protocols/Tox/libtox/src/toxcore/timed_auth.h
@@ -4,6 +4,7 @@
#ifndef C_TOXCORE_TOXCORE_TIMED_AUTH_H
#define C_TOXCORE_TOXCORE_TIMED_AUTH_H
+#include "attributes.h"
#include "crypto_core.h"
#include "mono_time.h"
@@ -32,4 +33,4 @@ void generate_timed_auth(const Mono_Time *mono_time, uint16_t timeout, const uin
non_null(1, 3, 6) nullable(4)
bool check_timed_auth(const Mono_Time *mono_time, uint16_t timeout, const uint8_t *key,
const uint8_t *data, uint16_t length, const uint8_t *timed_auth);
-#endif
+#endif /* C_TOXCORE_TOXCORE_TIMED_AUTH_H */
diff --git a/protocols/Tox/libtox/src/toxcore/tox.c b/protocols/Tox/libtox/src/toxcore/tox.c
index 3f7dcc439d..085fab2ec1 100644
--- a/protocols/Tox/libtox/src/toxcore/tox.c
+++ b/protocols/Tox/libtox/src/toxcore/tox.c
@@ -8,24 +8,33 @@
*/
#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE 600
-#endif
+#endif /* _XOPEN_SOURCE */
#include "tox.h"
#include <assert.h>
-#include <stdlib.h>
#include <string.h>
+#include "DHT.h"
#include "Messenger.h"
+#include "TCP_client.h"
+#include "attributes.h"
#include "ccompat.h"
+#include "crypto_core.h"
+#include "friend_requests.h"
#include "group.h"
#include "group_chats.h"
-#include "group_moderation.h"
+#include "group_common.h"
#include "logger.h"
+#include "mem.h"
#include "mono_time.h"
+#include "net_crypto.h"
#include "network.h"
+#include "onion_client.h"
+#include "state.h"
#include "tox_private.h"
#include "tox_struct.h"
+#include "util.h"
#include "../toxencryptsave/defines.h"
@@ -42,6 +51,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,
@@ -86,7 +97,9 @@ static void tox_self_connection_status_handler(Messenger *m, Onion_Connection_St
struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
if (tox_data->tox->self_connection_status_callback != nullptr) {
+ tox_unlock(tox_data->tox);
tox_data->tox->self_connection_status_callback(tox_data->tox, (Tox_Connection)connection_status, tox_data->user_data);
+ tox_lock(tox_data->tox);
}
}
@@ -98,7 +111,9 @@ static void tox_friend_name_handler(Messenger *m, uint32_t friend_number, const
struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
if (tox_data->tox->friend_name_callback != nullptr) {
+ tox_unlock(tox_data->tox);
tox_data->tox->friend_name_callback(tox_data->tox, friend_number, name, length, tox_data->user_data);
+ tox_lock(tox_data->tox);
}
}
@@ -110,7 +125,9 @@ static void tox_friend_status_message_handler(Messenger *m, uint32_t friend_numb
struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
if (tox_data->tox->friend_status_message_callback != nullptr) {
+ tox_unlock(tox_data->tox);
tox_data->tox->friend_status_message_callback(tox_data->tox, friend_number, message, length, tox_data->user_data);
+ tox_lock(tox_data->tox);
}
}
@@ -121,7 +138,9 @@ static void tox_friend_status_handler(Messenger *m, uint32_t friend_number, unsi
struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
if (tox_data->tox->friend_status_callback != nullptr) {
+ tox_unlock(tox_data->tox);
tox_data->tox->friend_status_callback(tox_data->tox, friend_number, (Tox_User_Status)status, tox_data->user_data);
+ tox_lock(tox_data->tox);
}
}
@@ -133,8 +152,10 @@ static void tox_friend_connection_status_handler(Messenger *m, uint32_t friend_n
struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
if (tox_data->tox->friend_connection_status_callback != nullptr) {
+ tox_unlock(tox_data->tox);
tox_data->tox->friend_connection_status_callback(tox_data->tox, friend_number, (Tox_Connection)connection_status,
tox_data->user_data);
+ tox_lock(tox_data->tox);
}
}
@@ -145,7 +166,9 @@ static void tox_friend_typing_handler(Messenger *m, uint32_t friend_number, bool
struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
if (tox_data->tox->friend_typing_callback != nullptr) {
+ tox_unlock(tox_data->tox);
tox_data->tox->friend_typing_callback(tox_data->tox, friend_number, is_typing, tox_data->user_data);
+ tox_lock(tox_data->tox);
}
}
@@ -156,19 +179,23 @@ static void tox_friend_read_receipt_handler(Messenger *m, uint32_t friend_number
struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
if (tox_data->tox->friend_read_receipt_callback != nullptr) {
+ tox_unlock(tox_data->tox);
tox_data->tox->friend_read_receipt_callback(tox_data->tox, friend_number, message_id, tox_data->user_data);
+ tox_lock(tox_data->tox);
}
}
static m_friend_request_cb tox_friend_request_handler;
non_null(1, 2, 3) nullable(5)
-static void tox_friend_request_handler(Messenger *m, const uint8_t *public_key, const uint8_t *message, size_t length,
+static void tox_friend_request_handler(Messenger *m, const uint8_t public_key[TOX_PUBLIC_KEY_SIZE], const uint8_t *message, size_t length,
void *user_data)
{
struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
if (tox_data->tox->friend_request_callback != nullptr) {
+ tox_unlock(tox_data->tox);
tox_data->tox->friend_request_callback(tox_data->tox, public_key, message, length, tox_data->user_data);
+ tox_lock(tox_data->tox);
}
}
@@ -180,8 +207,10 @@ static void tox_friend_message_handler(Messenger *m, uint32_t friend_number, uns
struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
if (tox_data->tox->friend_message_callback != nullptr) {
+ tox_unlock(tox_data->tox);
tox_data->tox->friend_message_callback(tox_data->tox, friend_number, (Tox_Message_Type)message_type, message, length,
tox_data->user_data);
+ tox_lock(tox_data->tox);
}
}
@@ -193,8 +222,10 @@ static void tox_file_recv_control_handler(Messenger *m, uint32_t friend_number,
struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
if (tox_data->tox->file_recv_control_callback != nullptr) {
+ tox_unlock(tox_data->tox);
tox_data->tox->file_recv_control_callback(tox_data->tox, friend_number, file_number, (Tox_File_Control)control,
tox_data->user_data);
+ tox_lock(tox_data->tox);
}
}
@@ -206,8 +237,10 @@ static void tox_file_chunk_request_handler(Messenger *m, uint32_t friend_number,
struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
if (tox_data->tox->file_chunk_request_callback != nullptr) {
+ tox_unlock(tox_data->tox);
tox_data->tox->file_chunk_request_callback(tox_data->tox, friend_number, file_number, position, length,
tox_data->user_data);
+ tox_lock(tox_data->tox);
}
}
@@ -219,8 +252,10 @@ static void tox_file_recv_handler(Messenger *m, uint32_t friend_number, uint32_t
struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
if (tox_data->tox->file_recv_callback != nullptr) {
+ tox_unlock(tox_data->tox);
tox_data->tox->file_recv_callback(tox_data->tox, friend_number, file_number, kind, file_size, filename, filename_length,
tox_data->user_data);
+ tox_lock(tox_data->tox);
}
}
@@ -232,8 +267,10 @@ static void tox_file_recv_chunk_handler(Messenger *m, uint32_t friend_number, ui
struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
if (tox_data->tox->file_recv_chunk_callback != nullptr) {
+ tox_unlock(tox_data->tox);
tox_data->tox->file_recv_chunk_callback(tox_data->tox, friend_number, file_number, position, data, length,
tox_data->user_data);
+ tox_lock(tox_data->tox);
}
}
@@ -245,8 +282,10 @@ static void tox_conference_invite_handler(Messenger *m, uint32_t friend_number,
struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
if (tox_data->tox->conference_invite_callback != nullptr) {
+ tox_unlock(tox_data->tox);
tox_data->tox->conference_invite_callback(tox_data->tox, friend_number, (Tox_Conference_Type)type, cookie, length,
tox_data->user_data);
+ tox_lock(tox_data->tox);
}
}
@@ -257,7 +296,9 @@ static void tox_conference_connected_handler(Messenger *m, uint32_t conference_n
struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
if (tox_data->tox->conference_connected_callback != nullptr) {
+ tox_unlock(tox_data->tox);
tox_data->tox->conference_connected_callback(tox_data->tox, conference_number, tox_data->user_data);
+ tox_lock(tox_data->tox);
}
}
@@ -269,8 +310,10 @@ static void tox_conference_message_handler(Messenger *m, uint32_t conference_num
struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
if (tox_data->tox->conference_message_callback != nullptr) {
+ tox_unlock(tox_data->tox);
tox_data->tox->conference_message_callback(tox_data->tox, conference_number, peer_number, (Tox_Message_Type)type,
message, length, tox_data->user_data);
+ tox_lock(tox_data->tox);
}
}
@@ -282,8 +325,10 @@ static void tox_conference_title_handler(Messenger *m, uint32_t conference_numbe
struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
if (tox_data->tox->conference_title_callback != nullptr) {
+ tox_unlock(tox_data->tox);
tox_data->tox->conference_title_callback(tox_data->tox, conference_number, peer_number, title, length,
tox_data->user_data);
+ tox_lock(tox_data->tox);
}
}
@@ -295,8 +340,10 @@ static void tox_conference_peer_name_handler(Messenger *m, uint32_t conference_n
struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
if (tox_data->tox->conference_peer_name_callback != nullptr) {
+ tox_unlock(tox_data->tox);
tox_data->tox->conference_peer_name_callback(tox_data->tox, conference_number, peer_number, name, length,
tox_data->user_data);
+ tox_lock(tox_data->tox);
}
}
@@ -307,7 +354,9 @@ static void tox_conference_peer_list_changed_handler(Messenger *m, uint32_t conf
struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
if (tox_data->tox->conference_peer_list_changed_callback != nullptr) {
+ tox_unlock(tox_data->tox);
tox_data->tox->conference_peer_list_changed_callback(tox_data->tox, conference_number, tox_data->user_data);
+ tox_lock(tox_data->tox);
}
}
@@ -322,9 +371,11 @@ static void tox_dht_get_nodes_response_handler(const DHT *dht, const Node_format
}
Ip_Ntoa ip_str;
+ tox_unlock(tox_data->tox);
tox_data->tox->dht_get_nodes_response_callback(
tox_data->tox, node->public_key, net_ip_ntoa(&node->ip_port.ip, &ip_str), net_ntohs(node->ip_port.port),
tox_data->user_data);
+ tox_lock(tox_data->tox);
}
static m_friend_lossy_packet_cb tox_friend_lossy_packet_handler;
@@ -332,14 +383,16 @@ non_null(1, 4) nullable(6)
static void tox_friend_lossy_packet_handler(Messenger *m, uint32_t friend_number, uint8_t packet_id,
const uint8_t *data, size_t length, void *user_data)
{
+ struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
+
assert(data != nullptr);
assert(length > 0);
- struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
-
if (tox_data->tox->friend_lossy_packet_callback_per_pktid[packet_id] != nullptr) {
+ tox_unlock(tox_data->tox);
tox_data->tox->friend_lossy_packet_callback_per_pktid[packet_id](tox_data->tox, friend_number, data, length,
tox_data->user_data);
+ tox_lock(tox_data->tox);
}
}
@@ -348,49 +401,56 @@ non_null(1, 4) nullable(6)
static void tox_friend_lossless_packet_handler(Messenger *m, uint32_t friend_number, uint8_t packet_id,
const uint8_t *data, size_t length, void *user_data)
{
+ struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
+
assert(data != nullptr);
assert(length > 0);
- struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
-
if (tox_data->tox->friend_lossless_packet_callback_per_pktid[packet_id] != nullptr) {
+ tox_unlock(tox_data->tox);
tox_data->tox->friend_lossless_packet_callback_per_pktid[packet_id](tox_data->tox, friend_number, data, length,
tox_data->user_data);
+ tox_lock(tox_data->tox);
}
}
-#ifndef VANILLA_NACL
non_null(1, 4) nullable(6)
-static void tox_group_peer_name_handler(const Messenger *m, uint32_t group_number, uint32_t peer_id,
+static void tox_group_peer_name_handler(const Messenger *m, uint32_t group_number, GC_Peer_Id peer_id,
const uint8_t *name, size_t length, void *user_data)
{
struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
if (tox_data->tox->group_peer_name_callback != nullptr) {
- tox_data->tox->group_peer_name_callback(tox_data->tox, group_number, peer_id, name, length, tox_data->user_data);
+ tox_unlock(tox_data->tox);
+ tox_data->tox->group_peer_name_callback(tox_data->tox, group_number, gc_peer_id_to_int(peer_id), name, length, tox_data->user_data);
+ tox_lock(tox_data->tox);
}
}
non_null(1) nullable(5)
-static void tox_group_peer_status_handler(const Messenger *m, uint32_t group_number, uint32_t peer_id,
+static void tox_group_peer_status_handler(const Messenger *m, uint32_t group_number, GC_Peer_Id peer_id,
unsigned int status, void *user_data)
{
struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
if (tox_data->tox->group_peer_status_callback != nullptr) {
- tox_data->tox->group_peer_status_callback(tox_data->tox, group_number, peer_id, (Tox_User_Status)status,
+ tox_unlock(tox_data->tox);
+ tox_data->tox->group_peer_status_callback(tox_data->tox, group_number, gc_peer_id_to_int(peer_id), (Tox_User_Status)status,
tox_data->user_data);
+ tox_lock(tox_data->tox);
}
}
non_null(1, 4) nullable(6)
-static void tox_group_topic_handler(const Messenger *m, uint32_t group_number, uint32_t peer_id, const uint8_t *topic,
+static void tox_group_topic_handler(const Messenger *m, uint32_t group_number, GC_Peer_Id peer_id, const uint8_t *topic,
size_t length, void *user_data)
{
struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
if (tox_data->tox->group_topic_callback != nullptr) {
- tox_data->tox->group_topic_callback(tox_data->tox, group_number, peer_id, topic, length, tox_data->user_data);
+ tox_unlock(tox_data->tox);
+ tox_data->tox->group_topic_callback(tox_data->tox, group_number, gc_peer_id_to_int(peer_id), topic, length, tox_data->user_data);
+ tox_lock(tox_data->tox);
}
}
@@ -401,8 +461,10 @@ static void tox_group_topic_lock_handler(const Messenger *m, uint32_t group_numb
struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
if (tox_data->tox->group_topic_lock_callback != nullptr) {
+ tox_unlock(tox_data->tox);
tox_data->tox->group_topic_lock_callback(tox_data->tox, group_number, (Tox_Group_Topic_Lock)topic_lock,
tox_data->user_data);
+ tox_lock(tox_data->tox);
}
}
@@ -413,8 +475,10 @@ static void tox_group_voice_state_handler(const Messenger *m, uint32_t group_num
struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
if (tox_data->tox->group_voice_state_callback != nullptr) {
+ tox_unlock(tox_data->tox);
tox_data->tox->group_voice_state_callback(tox_data->tox, group_number, (Tox_Group_Voice_State)voice_state,
tox_data->user_data);
+ tox_lock(tox_data->tox);
}
}
@@ -425,7 +489,9 @@ static void tox_group_peer_limit_handler(const Messenger *m, uint32_t group_numb
struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
if (tox_data->tox->group_peer_limit_callback != nullptr) {
+ tox_unlock(tox_data->tox);
tox_data->tox->group_peer_limit_callback(tox_data->tox, group_number, peer_limit, tox_data->user_data);
+ tox_lock(tox_data->tox);
}
}
@@ -436,8 +502,10 @@ static void tox_group_privacy_state_handler(const Messenger *m, uint32_t group_n
struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
if (tox_data->tox->group_privacy_state_callback != nullptr) {
+ tox_unlock(tox_data->tox);
tox_data->tox->group_privacy_state_callback(tox_data->tox, group_number, (Tox_Group_Privacy_State)privacy_state,
tox_data->user_data);
+ tox_lock(tox_data->tox);
}
}
@@ -448,55 +516,64 @@ static void tox_group_password_handler(const Messenger *m, uint32_t group_number
struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
if (tox_data->tox->group_password_callback != nullptr) {
+ tox_unlock(tox_data->tox);
tox_data->tox->group_password_callback(tox_data->tox, group_number, password, length, tox_data->user_data);
+ tox_lock(tox_data->tox);
}
}
non_null(1, 5) nullable(8)
-static void tox_group_message_handler(const Messenger *m, uint32_t group_number, uint32_t peer_id, unsigned int type,
+static void tox_group_message_handler(const Messenger *m, uint32_t group_number, GC_Peer_Id peer_id, unsigned int type,
const uint8_t *message, size_t length, uint32_t message_id, void *user_data)
{
struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
if (tox_data->tox->group_message_callback != nullptr) {
- tox_data->tox->group_message_callback(tox_data->tox, group_number, peer_id, (Tox_Message_Type)type, message, length,
+ tox_unlock(tox_data->tox);
+ tox_data->tox->group_message_callback(tox_data->tox, group_number, gc_peer_id_to_int(peer_id), (Tox_Message_Type)type, message, length,
message_id, tox_data->user_data);
+ tox_lock(tox_data->tox);
}
}
non_null(1, 5) nullable(7)
-static void tox_group_private_message_handler(const Messenger *m, uint32_t group_number, uint32_t peer_id,
+static void tox_group_private_message_handler(const Messenger *m, uint32_t group_number, GC_Peer_Id peer_id,
unsigned int type, const uint8_t *message, size_t length, void *user_data)
{
struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
if (tox_data->tox->group_private_message_callback != nullptr) {
- tox_data->tox->group_private_message_callback(tox_data->tox, group_number, peer_id, (Tox_Message_Type)type, message,
- length,
- tox_data->user_data);
+ tox_unlock(tox_data->tox);
+ tox_data->tox->group_private_message_callback(tox_data->tox, group_number, gc_peer_id_to_int(peer_id), (Tox_Message_Type)type, message,
+ length, tox_data->user_data);
+ tox_lock(tox_data->tox);
}
}
non_null(1, 4) nullable(6)
-static void tox_group_custom_packet_handler(const Messenger *m, uint32_t group_number, uint32_t peer_id,
+static void tox_group_custom_packet_handler(const Messenger *m, uint32_t group_number, GC_Peer_Id peer_id,
const uint8_t *data, size_t length, void *user_data)
{
struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
if (tox_data->tox->group_custom_packet_callback != nullptr) {
- tox_data->tox->group_custom_packet_callback(tox_data->tox, group_number, peer_id, data, length, tox_data->user_data);
+ tox_unlock(tox_data->tox);
+ tox_data->tox->group_custom_packet_callback(tox_data->tox, group_number, gc_peer_id_to_int(peer_id), data, length, tox_data->user_data);
+ tox_lock(tox_data->tox);
}
}
non_null(1, 4) nullable(6)
-static void tox_group_custom_private_packet_handler(const Messenger *m, uint32_t group_number, uint32_t peer_id,
+static void tox_group_custom_private_packet_handler(const Messenger *m, uint32_t group_number, GC_Peer_Id peer_id,
const uint8_t *data, size_t length, void *user_data)
{
struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
if (tox_data->tox->group_custom_private_packet_callback != nullptr) {
- tox_data->tox->group_custom_private_packet_callback(tox_data->tox, group_number, peer_id, data, length,
+ tox_unlock(tox_data->tox);
+ tox_data->tox->group_custom_private_packet_callback(tox_data->tox, group_number, gc_peer_id_to_int(peer_id), data, length,
tox_data->user_data);
+ tox_lock(tox_data->tox);
}
}
@@ -507,32 +584,38 @@ static void tox_group_invite_handler(const Messenger *m, uint32_t friend_number,
struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
if (tox_data->tox->group_invite_callback != nullptr) {
+ tox_unlock(tox_data->tox);
tox_data->tox->group_invite_callback(tox_data->tox, friend_number, invite_data, length, group_name, group_name_length,
tox_data->user_data);
+ tox_lock(tox_data->tox);
}
}
non_null(1) nullable(4)
-static void tox_group_peer_join_handler(const Messenger *m, uint32_t group_number, uint32_t peer_id, void *user_data)
+static void tox_group_peer_join_handler(const Messenger *m, uint32_t group_number, GC_Peer_Id peer_id, void *user_data)
{
struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
if (tox_data->tox->group_peer_join_callback != nullptr) {
- tox_data->tox->group_peer_join_callback(tox_data->tox, group_number, peer_id, tox_data->user_data);
+ tox_unlock(tox_data->tox);
+ tox_data->tox->group_peer_join_callback(tox_data->tox, group_number, gc_peer_id_to_int(peer_id), tox_data->user_data);
+ tox_lock(tox_data->tox);
}
}
non_null(1, 5) nullable(7, 9)
-static void tox_group_peer_exit_handler(const Messenger *m, uint32_t group_number, uint32_t peer_id,
+static void tox_group_peer_exit_handler(const Messenger *m, uint32_t group_number, GC_Peer_Id peer_id,
unsigned int exit_type, const uint8_t *name, size_t name_length,
const uint8_t *part_message, size_t length, void *user_data)
{
struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
if (tox_data->tox->group_peer_exit_callback != nullptr) {
- tox_data->tox->group_peer_exit_callback(tox_data->tox, group_number, peer_id, (Tox_Group_Exit_Type) exit_type, name,
- name_length,
+ tox_unlock(tox_data->tox);
+ tox_data->tox->group_peer_exit_callback(tox_data->tox, group_number, gc_peer_id_to_int(peer_id),
+ (Tox_Group_Exit_Type)exit_type, name, name_length,
part_message, length, tox_data->user_data);
+ tox_lock(tox_data->tox);
}
}
@@ -542,7 +625,9 @@ static void tox_group_self_join_handler(const Messenger *m, uint32_t group_numbe
struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
if (tox_data->tox->group_self_join_callback != nullptr) {
+ tox_unlock(tox_data->tox);
tox_data->tox->group_self_join_callback(tox_data->tox, group_number, tox_data->user_data);
+ tox_lock(tox_data->tox);
}
}
@@ -553,24 +638,27 @@ static void tox_group_join_fail_handler(const Messenger *m, uint32_t group_numbe
struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
if (tox_data->tox->group_join_fail_callback != nullptr) {
+ tox_unlock(tox_data->tox);
tox_data->tox->group_join_fail_callback(tox_data->tox, group_number, (Tox_Group_Join_Fail)fail_type,
tox_data->user_data);
+ tox_lock(tox_data->tox);
}
}
non_null(1) nullable(6)
-static void tox_group_moderation_handler(const Messenger *m, uint32_t group_number, uint32_t source_peer_number,
- uint32_t target_peer_number, unsigned int mod_type, void *user_data)
+static void tox_group_moderation_handler(const Messenger *m, uint32_t group_number, GC_Peer_Id source_peer_number,
+ GC_Peer_Id target_peer_number, unsigned int mod_type, void *user_data)
{
struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
if (tox_data->tox->group_moderation_callback != nullptr) {
- tox_data->tox->group_moderation_callback(tox_data->tox, group_number, source_peer_number, target_peer_number,
- (Tox_Group_Mod_Event)mod_type,
- tox_data->user_data);
+ tox_unlock(tox_data->tox);
+ tox_data->tox->group_moderation_callback(tox_data->tox, group_number,
+ gc_peer_id_to_int(source_peer_number), gc_peer_id_to_int(target_peer_number),
+ (Tox_Group_Mod_Event)mod_type, tox_data->user_data);
+ tox_lock(tox_data->tox);
}
}
-#endif
bool tox_version_is_compatible(uint32_t major, uint32_t minor, uint32_t patch)
{
@@ -626,18 +714,6 @@ static int tox_load(Tox *tox, const uint8_t *data, uint32_t length)
Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)
{
- Tox *tox = (Tox *)calloc(1, sizeof(Tox));
-
- if (tox == nullptr) {
- SET_ERROR_PARAMETER(error, TOX_ERR_NEW_MALLOC);
- return nullptr;
- }
-
- Messenger_Options m_options = {0};
-
- bool load_savedata_sk = false;
- bool load_savedata_tox = false;
-
struct Tox_Options *default_options = nullptr;
if (options == nullptr) {
@@ -646,12 +722,12 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)
switch (err) {
case TOX_ERR_OPTIONS_NEW_OK: {
+ assert(default_options != nullptr);
break;
}
case TOX_ERR_OPTIONS_NEW_MALLOC: {
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_MALLOC);
- free(tox);
return nullptr;
}
}
@@ -660,11 +736,29 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)
const struct Tox_Options *const opts = options != nullptr ? options : default_options;
assert(opts != nullptr);
+ const Tox_System *sys = tox_options_get_operating_system(opts);
+ const Tox_System default_system = tox_default_system();
+
+ if (sys == nullptr) {
+ sys = &default_system;
+ }
+
+ if (sys->rng == nullptr || sys->ns == nullptr || sys->mem == nullptr) {
+ // TODO(iphydf): Not quite right, but similar.
+ SET_ERROR_PARAMETER(error, TOX_ERR_NEW_MALLOC);
+ tox_options_free(default_options);
+ return nullptr;
+ }
+
+ Messenger_Options m_options = {false};
+
+ bool load_savedata_sk = false;
+ bool load_savedata_tox = false;
+
if (tox_options_get_savedata_type(opts) != TOX_SAVEDATA_TYPE_NONE) {
if (tox_options_get_savedata_data(opts) == nullptr || tox_options_get_savedata_length(opts) == 0) {
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_BAD_FORMAT);
tox_options_free(default_options);
- free(tox);
return nullptr;
}
}
@@ -673,7 +767,6 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)
if (tox_options_get_savedata_length(opts) != TOX_SECRET_KEY_SIZE) {
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_BAD_FORMAT);
tox_options_free(default_options);
- free(tox);
return nullptr;
}
@@ -682,14 +775,12 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)
if (tox_options_get_savedata_length(opts) < TOX_ENC_SAVE_MAGIC_LENGTH) {
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_BAD_FORMAT);
tox_options_free(default_options);
- free(tox);
return nullptr;
}
if (memcmp(tox_options_get_savedata_data(opts), TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) == 0) {
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_ENCRYPTED);
tox_options_free(default_options);
- free(tox);
return nullptr;
}
@@ -704,11 +795,20 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)
m_options.hole_punching_enabled = tox_options_get_hole_punching_enabled(opts);
m_options.local_discovery_enabled = tox_options_get_local_discovery_enabled(opts);
m_options.dht_announcements_enabled = tox_options_get_dht_announcements_enabled(opts);
+ m_options.groups_persistence_enabled = tox_options_get_experimental_groups_persistence(opts);
if (m_options.udp_disabled) {
m_options.local_discovery_enabled = false;
}
+ Tox *tox = (Tox *)mem_alloc(sys->mem, sizeof(Tox));
+
+ if (tox == nullptr) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_NEW_MALLOC);
+ tox_options_free(default_options);
+ return nullptr;
+ }
+
tox->log_callback = tox_options_get_log_callback(opts);
m_options.log_callback = tox_log_handler;
m_options.log_context = tox;
@@ -732,35 +832,19 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)
default: {
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PROXY_BAD_TYPE);
+ mem_delete(sys->mem, tox);
tox_options_free(default_options);
- free(tox);
return nullptr;
}
}
- const Tox_System *sys = tox_options_get_operating_system(opts);
- const Tox_System default_system = tox_default_system();
-
- if (sys == nullptr) {
- sys = &default_system;
- }
-
- if (sys->rng == nullptr || sys->ns == nullptr) {
- // TODO(iphydf): Not quite right, but similar.
- SET_ERROR_PARAMETER(error, TOX_ERR_NEW_MALLOC);
- tox_options_free(default_options);
- free(tox);
- return nullptr;
- }
-
- tox->rng = *sys->rng;
- tox->ns = *sys->ns;
+ tox->sys = *sys;
if (m_options.proxy_info.proxy_type != TCP_PROXY_NONE) {
if (tox_options_get_proxy_port(opts) == 0) {
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PROXY_BAD_PORT);
+ mem_delete(sys->mem, tox);
tox_options_free(default_options);
- free(tox);
return nullptr;
}
@@ -773,42 +857,39 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)
const char *const proxy_host = tox_options_get_proxy_host(opts);
if (proxy_host == nullptr
- || !addr_resolve_or_parse_ip(&tox->ns, proxy_host, &m_options.proxy_info.ip_port.ip, nullptr)) {
+ || !addr_resolve_or_parse_ip(tox->sys.ns, proxy_host, &m_options.proxy_info.ip_port.ip, nullptr)) {
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PROXY_BAD_HOST);
// TODO(irungentoo): TOX_ERR_NEW_PROXY_NOT_FOUND if domain.
+ mem_delete(sys->mem, tox);
tox_options_free(default_options);
- free(tox);
return nullptr;
}
m_options.proxy_info.ip_port.port = net_htons(tox_options_get_proxy_port(opts));
}
- tox->mono_time = mono_time_new(sys->mono_time_callback, sys->mono_time_user_data);
+ tox->mono_time = mono_time_new(tox->sys.mem, sys->mono_time_callback, sys->mono_time_user_data);
if (tox->mono_time == nullptr) {
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_MALLOC);
+ mem_delete(sys->mem, tox);
tox_options_free(default_options);
- free(tox);
return nullptr;
}
if (tox_options_get_experimental_thread_safety(opts)) {
- tox->mutex = (pthread_mutex_t *)calloc(1, sizeof(pthread_mutex_t));
+ pthread_mutex_t *mutex = (pthread_mutex_t *)mem_alloc(sys->mem, sizeof(pthread_mutex_t));
- if (tox->mutex == nullptr) {
+ if (mutex == nullptr) {
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_MALLOC);
+ mem_delete(sys->mem, tox);
tox_options_free(default_options);
- free(tox);
return nullptr;
}
+ pthread_mutex_init(mutex, nullptr);
- pthread_mutexattr_t attr;
-
- pthread_mutexattr_init(&attr);
- pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
- pthread_mutex_init(tox->mutex, &attr);
+ tox->mutex = mutex;
} else {
tox->mutex = nullptr;
}
@@ -816,56 +897,77 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)
tox_lock(tox);
Messenger_Error m_error;
- tox->m = new_messenger(tox->mono_time, &tox->rng, &tox->ns, &m_options, &m_error);
+ tox->m = new_messenger(tox->mono_time, tox->sys.mem, tox->sys.rng, tox->sys.ns, &m_options, &m_error);
if (tox->m == nullptr) {
- if (m_error == MESSENGER_ERROR_PORT) {
- SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PORT_ALLOC);
- } else if (m_error == MESSENGER_ERROR_TCP_SERVER) {
- SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PORT_ALLOC);
- } else {
- SET_ERROR_PARAMETER(error, TOX_ERR_NEW_MALLOC);
+ switch (m_error) {
+ case MESSENGER_ERROR_PORT:
+ case MESSENGER_ERROR_TCP_SERVER: {
+ SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PORT_ALLOC);
+ break;
+ }
+ case MESSENGER_ERROR_OTHER:
+ case MESSENGER_ERROR_NONE: {
+ SET_ERROR_PARAMETER(error, TOX_ERR_NEW_MALLOC);
+ break;
+ }
}
- mono_time_free(tox->mono_time);
- tox_options_free(default_options);
+ mono_time_free(tox->sys.mem, tox->mono_time);
tox_unlock(tox);
if (tox->mutex != nullptr) {
pthread_mutex_destroy(tox->mutex);
}
- free(tox->mutex);
- free(tox);
+ mem_delete(sys->mem, tox->mutex);
+ mem_delete(sys->mem, tox);
+ tox_options_free(default_options);
return nullptr;
}
- if (new_groupchats(tox->mono_time, tox->m) == nullptr) {
+ tox->m->conferences_object = new_groupchats(tox->mono_time, tox->m);
+
+ if (tox->m->conferences_object == nullptr) {
kill_messenger(tox->m);
- mono_time_free(tox->mono_time);
- tox_options_free(default_options);
+ mono_time_free(tox->sys.mem, tox->mono_time);
tox_unlock(tox);
if (tox->mutex != nullptr) {
pthread_mutex_destroy(tox->mutex);
}
- free(tox->mutex);
- free(tox);
+ mem_delete(sys->mem, tox->mutex);
+ mem_delete(sys->mem, tox);
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_MALLOC);
+ tox_options_free(default_options);
return nullptr;
}
if (load_savedata_tox
&& tox_load(tox, tox_options_get_savedata_data(opts), tox_options_get_savedata_length(opts)) == -1) {
+ kill_groupchats(tox->m->conferences_object);
+ kill_messenger(tox->m);
+
+ mono_time_free(tox->sys.mem, tox->mono_time);
+ tox_unlock(tox);
+
+ if (tox->mutex != nullptr) {
+ pthread_mutex_destroy(tox->mutex);
+ }
+
+ mem_delete(sys->mem, tox->mutex);
+ mem_delete(sys->mem, tox);
+
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_BAD_FORMAT);
- } else if (load_savedata_sk) {
+ tox_options_free(default_options);
+ return nullptr;
+ }
+
+ if (load_savedata_sk) {
load_secret_key(tox->m->net_crypto, tox_options_get_savedata_data(opts));
- SET_ERROR_PARAMETER(error, TOX_ERR_NEW_OK);
- } else {
- SET_ERROR_PARAMETER(error, TOX_ERR_NEW_OK);
}
m_callback_namechange(tox->m, tox_friend_name_handler);
@@ -891,7 +993,6 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)
custom_lossy_packet_registerhandler(tox->m, tox_friend_lossy_packet_handler);
custom_lossless_packet_registerhandler(tox->m, tox_friend_lossless_packet_handler);
-#ifndef VANILLA_NACL
m_callback_group_invite(tox->m, tox_group_invite_handler);
gc_callback_message(tox->m, tox_group_message_handler);
gc_callback_private_message(tox->m, tox_group_private_message_handler);
@@ -910,11 +1011,12 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)
gc_callback_self_join(tox->m, tox_group_self_join_handler);
gc_callback_rejected(tox->m, tox_group_join_fail_handler);
gc_callback_voice_state(tox->m, tox_group_voice_state_handler);
-#endif
-
- tox_options_free(default_options);
tox_unlock(tox);
+
+ SET_ERROR_PARAMETER(error, TOX_ERR_NEW_OK);
+
+ tox_options_free(default_options);
return tox;
}
@@ -928,15 +1030,15 @@ void tox_kill(Tox *tox)
LOGGER_ASSERT(tox->m->log, tox->m->msi_packet == nullptr, "Attempted to kill tox while toxav is still alive");
kill_groupchats(tox->m->conferences_object);
kill_messenger(tox->m);
- mono_time_free(tox->mono_time);
+ mono_time_free(tox->sys.mem, tox->mono_time);
tox_unlock(tox);
if (tox->mutex != nullptr) {
pthread_mutex_destroy(tox->mutex);
- free(tox->mutex);
+ mem_delete(tox->sys.mem, tox->mutex);
}
- free(tox);
+ mem_delete(tox->sys.mem, tox);
}
static uint32_t end_size(void)
@@ -970,14 +1072,14 @@ void tox_get_savedata(const Tox *tox, uint8_t *savedata)
return;
}
- memset(savedata, 0, tox_get_savedata_size(tox));
+ memzero(savedata, tox_get_savedata_size(tox));
tox_lock(tox);
const uint32_t size32 = sizeof(uint32_t);
// write cookie
- memset(savedata, 0, size32);
+ memzero(savedata, size32);
savedata += size32;
host_to_lendian_bytes32(savedata, STATE_COOKIE_GLOBAL);
savedata += size32;
@@ -990,7 +1092,7 @@ void tox_get_savedata(const Tox *tox, uint8_t *savedata)
}
non_null(5) nullable(1, 2, 4, 6)
-static int32_t resolve_bootstrap_node(Tox *tox, const char *host, uint16_t port, const uint8_t *public_key,
+static int32_t resolve_bootstrap_node(Tox *tox, const char *host, uint16_t port, const uint8_t public_key[TOX_PUBLIC_KEY_SIZE],
IP_Port **root, Tox_Err_Bootstrap *error)
{
assert(tox != nullptr);
@@ -1006,11 +1108,11 @@ static int32_t resolve_bootstrap_node(Tox *tox, const char *host, uint16_t port,
return -1;
}
- const int32_t count = net_getipport(host, root, TOX_SOCK_DGRAM);
+ const int32_t count = net_getipport(tox->sys.mem, host, root, TOX_SOCK_DGRAM);
if (count < 1) {
LOGGER_DEBUG(tox->m->log, "could not resolve bootstrap node '%s'", host);
- net_freeipport(*root);
+ net_freeipport(tox->sys.mem, *root);
SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_HOST);
return -1;
}
@@ -1019,7 +1121,7 @@ static int32_t resolve_bootstrap_node(Tox *tox, const char *host, uint16_t port,
return count;
}
-bool tox_bootstrap(Tox *tox, const char *host, uint16_t port, const uint8_t *public_key, Tox_Err_Bootstrap *error)
+bool tox_bootstrap(Tox *tox, const char *host, uint16_t port, const uint8_t public_key[TOX_PUBLIC_KEY_SIZE], Tox_Err_Bootstrap *error)
{
IP_Port *root;
const int32_t count = resolve_bootstrap_node(tox, host, port, public_key, &root, error);
@@ -1035,6 +1137,11 @@ bool tox_bootstrap(Tox *tox, const char *host, uint16_t port, const uint8_t *pub
bool udp_success = tox->m->options.udp_disabled;
for (int32_t i = 0; i < count; ++i) {
+ if (!tox->m->options.ipv6enabled && net_family_is_ipv6(root[i].ip.family)) {
+ // We can't use ipv6 when it's disabled.
+ continue;
+ }
+
root[i].port = net_htons(port);
if (onion_add_bs_path_node(tox->m->onion_c, &root[i], public_key)) {
@@ -1054,7 +1161,7 @@ bool tox_bootstrap(Tox *tox, const char *host, uint16_t port, const uint8_t *pub
tox_unlock(tox);
- net_freeipport(root);
+ net_freeipport(tox->sys.mem, root);
if (count == 0 || !onion_success || !udp_success) {
LOGGER_DEBUG(tox->m->log, "bootstrap node '%s' resolved to %d IP_Ports%s (onion: %s, UDP: %s)",
@@ -1070,7 +1177,7 @@ bool tox_bootstrap(Tox *tox, const char *host, uint16_t port, const uint8_t *pub
return true;
}
-bool tox_add_tcp_relay(Tox *tox, const char *host, uint16_t port, const uint8_t *public_key,
+bool tox_add_tcp_relay(Tox *tox, const char *host, uint16_t port, const uint8_t public_key[TOX_PUBLIC_KEY_SIZE],
Tox_Err_Bootstrap *error)
{
IP_Port *root;
@@ -1091,7 +1198,7 @@ bool tox_add_tcp_relay(Tox *tox, const char *host, uint16_t port, const uint8_t
tox_unlock(tox);
- net_freeipport(root);
+ net_freeipport(tox->sys.mem, root);
if (count == 0) {
SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_HOST);
@@ -1124,7 +1231,6 @@ Tox_Connection tox_self_get_connection_status(const Tox *tox)
return TOX_CONNECTION_NONE;
}
-
void tox_callback_self_connection_status(Tox *tox, tox_self_connection_status_cb *callback)
{
assert(tox != nullptr);
@@ -1159,7 +1265,7 @@ void tox_iterate(Tox *tox, void *user_data)
tox_unlock(tox);
}
-void tox_self_get_address(const Tox *tox, uint8_t *address)
+void tox_self_get_address(const Tox *tox, uint8_t address[TOX_ADDRESS_SIZE])
{
assert(tox != nullptr);
@@ -1187,7 +1293,7 @@ uint32_t tox_self_get_nospam(const Tox *tox)
return ret;
}
-void tox_self_get_public_key(const Tox *tox, uint8_t *public_key)
+void tox_self_get_public_key(const Tox *tox, uint8_t public_key[TOX_PUBLIC_KEY_SIZE])
{
assert(tox != nullptr);
@@ -1198,7 +1304,7 @@ void tox_self_get_public_key(const Tox *tox, uint8_t *public_key)
}
}
-void tox_self_get_secret_key(const Tox *tox, uint8_t *secret_key)
+void tox_self_get_secret_key(const Tox *tox, uint8_t secret_key[TOX_SECRET_KEY_SIZE])
{
assert(tox != nullptr);
@@ -1359,7 +1465,7 @@ static void set_friend_error(const Logger *log, int32_t ret, Tox_Err_Friend_Add
}
}
-uint32_t tox_friend_add(Tox *tox, const uint8_t *address, const uint8_t *message, size_t length,
+uint32_t tox_friend_add(Tox *tox, const uint8_t address[TOX_ADDRESS_SIZE], const uint8_t *message, size_t length,
Tox_Err_Friend_Add *error)
{
assert(tox != nullptr);
@@ -1383,7 +1489,7 @@ uint32_t tox_friend_add(Tox *tox, const uint8_t *address, const uint8_t *message
return UINT32_MAX;
}
-uint32_t tox_friend_add_norequest(Tox *tox, const uint8_t *public_key, Tox_Err_Friend_Add *error)
+uint32_t tox_friend_add_norequest(Tox *tox, const uint8_t public_key[TOX_PUBLIC_KEY_SIZE], Tox_Err_Friend_Add *error)
{
assert(tox != nullptr);
@@ -1423,7 +1529,7 @@ bool tox_friend_delete(Tox *tox, uint32_t friend_number, Tox_Err_Friend_Delete *
return true;
}
-uint32_t tox_friend_by_public_key(const Tox *tox, const uint8_t *public_key, Tox_Err_Friend_By_Public_Key *error)
+uint32_t tox_friend_by_public_key(const Tox *tox, const uint8_t public_key[TOX_PUBLIC_KEY_SIZE], Tox_Err_Friend_By_Public_Key *error)
{
assert(tox != nullptr);
@@ -1446,7 +1552,7 @@ uint32_t tox_friend_by_public_key(const Tox *tox, const uint8_t *public_key, Tox
return (uint32_t)ret;
}
-bool tox_friend_get_public_key(const Tox *tox, uint32_t friend_number, uint8_t *public_key,
+bool tox_friend_get_public_key(const Tox *tox, uint32_t friend_number, uint8_t public_key[TOX_PUBLIC_KEY_SIZE],
Tox_Err_Friend_Get_Public_Key *error)
{
assert(tox != nullptr);
@@ -1772,7 +1878,7 @@ void tox_callback_friend_message(Tox *tox, tox_friend_message_cb *callback)
tox->friend_message_callback = callback;
}
-bool tox_hash(uint8_t *hash, const uint8_t *data, size_t length)
+bool tox_hash(uint8_t hash[TOX_HASH_LENGTH], const uint8_t *data, size_t length)
{
if (hash == nullptr || (data == nullptr && length != 0)) {
return false;
@@ -1902,7 +2008,7 @@ void tox_callback_file_recv_control(Tox *tox, tox_file_recv_control_cb *callback
tox->file_recv_control_callback = callback;
}
-bool tox_file_get_file_id(const Tox *tox, uint32_t friend_number, uint32_t file_number, uint8_t *file_id,
+bool tox_file_get_file_id(const Tox *tox, uint32_t friend_number, uint32_t file_number, uint8_t file_id[TOX_FILE_ID_LENGTH],
Tox_Err_File_Get *error)
{
assert(tox != nullptr);
@@ -1930,7 +2036,7 @@ bool tox_file_get_file_id(const Tox *tox, uint32_t friend_number, uint32_t file_
return false;
}
-uint32_t tox_file_send(Tox *tox, uint32_t friend_number, uint32_t kind, uint64_t file_size, const uint8_t *file_id,
+uint32_t tox_file_send(Tox *tox, uint32_t friend_number, uint32_t kind, uint64_t file_size, const uint8_t file_id[TOX_FILE_ID_LENGTH],
const uint8_t *filename, size_t filename_length, Tox_Err_File_Send *error)
{
assert(tox != nullptr);
@@ -1944,7 +2050,7 @@ uint32_t tox_file_send(Tox *tox, uint32_t friend_number, uint32_t kind, uint64_t
if (file_id == nullptr) {
/* Tox keys are 32 bytes like FILE_ID_LENGTH. */
- new_symmetric_key(&tox->rng, f_id);
+ new_symmetric_key(tox->sys.rng, f_id);
file_id = f_id;
}
@@ -2099,7 +2205,7 @@ uint32_t tox_conference_new(Tox *tox, Tox_Err_Conference_New *error)
{
assert(tox != nullptr);
tox_lock(tox);
- const int ret = add_groupchat(tox->m->conferences_object, &tox->rng, GROUPCHAT_TYPE_TEXT);
+ const int ret = add_groupchat(tox->m->conferences_object, tox->sys.rng, GROUPCHAT_TYPE_TEXT);
tox_unlock(tox);
if (ret == -1) {
@@ -2192,7 +2298,7 @@ bool tox_conference_peer_get_name(const Tox *tox, uint32_t conference_number, ui
}
bool tox_conference_peer_get_public_key(const Tox *tox, uint32_t conference_number, uint32_t peer_number,
- uint8_t *public_key, Tox_Err_Conference_Peer_Query *error)
+ uint8_t public_key[TOX_PUBLIC_KEY_SIZE], Tox_Err_Conference_Peer_Query *error)
{
assert(tox != nullptr);
tox_lock(tox);
@@ -2313,7 +2419,7 @@ bool tox_conference_offline_peer_get_name(const Tox *tox, uint32_t conference_nu
bool tox_conference_offline_peer_get_public_key(const Tox *tox, uint32_t conference_number,
uint32_t offline_peer_number,
- uint8_t *public_key, Tox_Err_Conference_Peer_Query *error)
+ uint8_t public_key[TOX_PUBLIC_KEY_SIZE], Tox_Err_Conference_Peer_Query *error)
{
assert(tox != nullptr);
tox_lock(tox);
@@ -2364,12 +2470,12 @@ uint64_t tox_conference_offline_peer_get_last_active(const Tox *tox, uint32_t co
}
bool tox_conference_set_max_offline(Tox *tox, uint32_t conference_number,
- uint32_t max_offline_peers,
+ uint32_t max_offline,
Tox_Err_Conference_Set_Max_Offline *error)
{
assert(tox != nullptr);
tox_lock(tox);
- const int ret = group_set_max_frozen(tox->m->conferences_object, conference_number, max_offline_peers);
+ const int ret = group_set_max_frozen(tox->m->conferences_object, conference_number, max_offline);
tox_unlock(tox);
if (ret == -1) {
@@ -2606,7 +2712,7 @@ Tox_Conference_Type tox_conference_get_type(const Tox *tox, uint32_t conference_
return (Tox_Conference_Type)ret;
}
-bool tox_conference_get_id(const Tox *tox, uint32_t conference_number, uint8_t *id)
+bool tox_conference_get_id(const Tox *tox, uint32_t conference_number, uint8_t id[TOX_CONFERENCE_ID_SIZE])
{
assert(tox != nullptr);
tox_lock(tox);
@@ -2616,13 +2722,13 @@ bool tox_conference_get_id(const Tox *tox, uint32_t conference_number, uint8_t *
}
// TODO(iphydf): Delete in 0.3.0.
-bool tox_conference_get_uid(const Tox *tox, uint32_t conference_number, uint8_t *uid)
+bool tox_conference_get_uid(const Tox *tox, uint32_t conference_number, uint8_t uid[TOX_CONFERENCE_UID_SIZE])
{
assert(tox != nullptr);
return tox_conference_get_id(tox, conference_number, uid);
}
-uint32_t tox_conference_by_id(const Tox *tox, const uint8_t *id, Tox_Err_Conference_By_Id *error)
+uint32_t tox_conference_by_id(const Tox *tox, const uint8_t id[TOX_CONFERENCE_ID_SIZE], Tox_Err_Conference_By_Id *error)
{
assert(tox != nullptr);
@@ -2646,7 +2752,7 @@ uint32_t tox_conference_by_id(const Tox *tox, const uint8_t *id, Tox_Err_Confere
}
// TODO(iphydf): Delete in 0.3.0.
-uint32_t tox_conference_by_uid(const Tox *tox, const uint8_t *uid, Tox_Err_Conference_By_Uid *error)
+uint32_t tox_conference_by_uid(const Tox *tox, const uint8_t uid[TOX_CONFERENCE_UID_SIZE], Tox_Err_Conference_By_Uid *error)
{
assert(tox != nullptr);
Tox_Err_Conference_By_Id id_error;
@@ -2708,6 +2814,7 @@ static void set_custom_packet_error(int ret, Tox_Err_Friend_Custom_Packet *error
}
}
+// cppcheck-suppress constParameterPointer
bool tox_friend_send_lossy_packet(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length,
Tox_Err_Friend_Custom_Packet *error)
{
@@ -2747,6 +2854,7 @@ void tox_callback_friend_lossy_packet(Tox *tox, tox_friend_lossy_packet_cb *call
}
}
+// cppcheck-suppress constParameterPointer
bool tox_friend_send_lossless_packet(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length,
Tox_Err_Friend_Custom_Packet *error)
{
@@ -2780,7 +2888,7 @@ void tox_callback_friend_lossless_packet(Tox *tox, tox_friend_lossless_packet_cb
}
}
-void tox_self_get_dht_id(const Tox *tox, uint8_t *dht_id)
+void tox_self_get_dht_id(const Tox *tox, uint8_t dht_id[TOX_PUBLIC_KEY_SIZE])
{
assert(tox != nullptr);
@@ -2795,7 +2903,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) {
@@ -2812,7 +2920,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);
@@ -2826,7 +2934,6 @@ uint16_t tox_self_get_tcp_port(const Tox *tox, Tox_Err_Get_Port *error)
/* GROUPCHAT FUNCTIONS */
-#ifndef VANILLA_NACL
void tox_callback_group_invite(Tox *tox, tox_group_invite_cb *callback)
{
assert(tox != nullptr);
@@ -2983,7 +3090,7 @@ uint32_t tox_group_new(Tox *tox, Tox_Group_Privacy_State privacy_state, const ui
return UINT32_MAX;
}
-uint32_t tox_group_join(Tox *tox, const uint8_t *chat_id, const uint8_t *name, size_t name_length,
+uint32_t tox_group_join(Tox *tox, const uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE], const uint8_t *name, size_t name_length,
const uint8_t *password, size_t password_length, Tox_Err_Group_Join *error)
{
assert(tox != nullptr);
@@ -3075,7 +3182,6 @@ bool tox_group_disconnect(const Tox *tox, uint32_t group_number, Tox_Err_Group_D
return false;
}
-
const bool ret = gc_disconnect_from_group(tox->m->group_handler, chat);
tox_unlock(tox);
@@ -3169,7 +3275,7 @@ bool tox_group_leave(Tox *tox, uint32_t group_number, const uint8_t *part_messag
return false;
}
-bool tox_group_self_set_name(const Tox *tox, uint32_t group_number, const uint8_t *name, size_t length,
+bool tox_group_self_set_name(Tox *tox, uint32_t group_number, const uint8_t *name, size_t length,
Tox_Err_Group_Self_Name_Set *error)
{
assert(tox != nullptr);
@@ -3253,7 +3359,7 @@ bool tox_group_self_get_name(const Tox *tox, uint32_t group_number, uint8_t *nam
return true;
}
-bool tox_group_self_set_status(const Tox *tox, uint32_t group_number, Tox_User_Status status,
+bool tox_group_self_set_status(Tox *tox, uint32_t group_number, Tox_User_Status status,
Tox_Err_Group_Self_Status_Set *error)
{
assert(tox != nullptr);
@@ -3342,13 +3448,13 @@ uint32_t tox_group_self_get_peer_id(const Tox *tox, uint32_t group_number, Tox_E
SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SELF_QUERY_OK);
- const uint32_t ret = gc_get_self_peer_id(chat);
+ const GC_Peer_Id ret = gc_get_self_peer_id(chat);
tox_unlock(tox);
- return ret;
+ return gc_peer_id_to_int(ret);
}
-bool tox_group_self_get_public_key(const Tox *tox, uint32_t group_number, uint8_t *public_key,
+bool tox_group_self_get_public_key(const Tox *tox, uint32_t group_number, uint8_t public_key[TOX_PUBLIC_KEY_SIZE],
Tox_Err_Group_Self_Query *error)
{
assert(tox != nullptr);
@@ -3384,7 +3490,7 @@ size_t tox_group_peer_get_name_size(const Tox *tox, uint32_t group_number, uint3
return -1;
}
- const int ret = gc_get_peer_nick_size(chat, peer_id);
+ const int ret = gc_get_peer_nick_size(chat, gc_peer_id_from_int(peer_id));
tox_unlock(tox);
if (ret == -1) {
@@ -3410,7 +3516,7 @@ bool tox_group_peer_get_name(const Tox *tox, uint32_t group_number, uint32_t pee
return false;
}
- const bool ret = gc_get_peer_nick(chat, peer_id, name);
+ const bool ret = gc_get_peer_nick(chat, gc_peer_id_from_int(peer_id), name);
tox_unlock(tox);
if (!ret) {
@@ -3436,7 +3542,7 @@ Tox_User_Status tox_group_peer_get_status(const Tox *tox, uint32_t group_number,
return (Tox_User_Status) - 1;
}
- const uint8_t ret = gc_get_status(chat, peer_id);
+ const uint8_t ret = gc_get_status(chat, gc_peer_id_from_int(peer_id));
tox_unlock(tox);
if (ret == UINT8_MAX) {
@@ -3462,7 +3568,7 @@ Tox_Group_Role tox_group_peer_get_role(const Tox *tox, uint32_t group_number, ui
return (Tox_Group_Role) - 1;
}
- const uint8_t ret = gc_get_role(chat, peer_id);
+ const uint8_t ret = gc_get_role(chat, gc_peer_id_from_int(peer_id));
tox_unlock(tox);
if (ret == (uint8_t) -1) {
@@ -3474,7 +3580,7 @@ Tox_Group_Role tox_group_peer_get_role(const Tox *tox, uint32_t group_number, ui
return (Tox_Group_Role)ret;
}
-bool tox_group_peer_get_public_key(const Tox *tox, uint32_t group_number, uint32_t peer_id, uint8_t *public_key,
+bool tox_group_peer_get_public_key(const Tox *tox, uint32_t group_number, uint32_t peer_id, uint8_t public_key[TOX_PUBLIC_KEY_SIZE],
Tox_Err_Group_Peer_Query *error)
{
assert(tox != nullptr);
@@ -3488,7 +3594,7 @@ bool tox_group_peer_get_public_key(const Tox *tox, uint32_t group_number, uint32
return false;
}
- const int ret = gc_get_peer_public_key_by_peer_id(chat, peer_id, public_key);
+ const int ret = gc_get_peer_public_key_by_peer_id(chat, gc_peer_id_from_int(peer_id), public_key);
tox_unlock(tox);
if (ret == -1) {
@@ -3514,7 +3620,7 @@ Tox_Connection tox_group_peer_get_connection_status(const Tox *tox, uint32_t gro
return TOX_CONNECTION_NONE;
}
- const unsigned int ret = gc_get_peer_connection_status(chat, peer_id);
+ const unsigned int ret = gc_get_peer_connection_status(chat, gc_peer_id_from_int(peer_id));
tox_unlock(tox);
if (ret == 0) {
@@ -3526,7 +3632,7 @@ Tox_Connection tox_group_peer_get_connection_status(const Tox *tox, uint32_t gro
return (Tox_Connection)ret;
}
-bool tox_group_set_topic(const Tox *tox, uint32_t group_number, const uint8_t *topic, size_t length,
+bool tox_group_set_topic(Tox *tox, uint32_t group_number, const uint8_t *topic, size_t length,
Tox_Err_Group_Topic_Set *error)
{
assert(tox != nullptr);
@@ -3644,7 +3750,7 @@ size_t tox_group_get_name_size(const Tox *tox, uint32_t group_number, Tox_Err_Gr
return ret;
}
-bool tox_group_get_name(const Tox *tox, uint32_t group_number, uint8_t *group_name, Tox_Err_Group_State_Queries *error)
+bool tox_group_get_name(const Tox *tox, uint32_t group_number, uint8_t *name, Tox_Err_Group_State_Queries *error)
{
assert(tox != nullptr);
@@ -3657,7 +3763,7 @@ bool tox_group_get_name(const Tox *tox, uint32_t group_number, uint8_t *group_na
return false;
}
- gc_get_group_name(chat, group_name);
+ gc_get_group_name(chat, name);
tox_unlock(tox);
SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_OK);
@@ -3665,7 +3771,7 @@ bool tox_group_get_name(const Tox *tox, uint32_t group_number, uint8_t *group_na
return true;
}
-bool tox_group_get_chat_id(const Tox *tox, uint32_t group_number, uint8_t *chat_id, Tox_Err_Group_State_Queries *error)
+bool tox_group_get_chat_id(const Tox *tox, uint32_t group_number, uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE], Tox_Err_Group_State_Queries *error)
{
assert(tox != nullptr);
@@ -3825,8 +3931,9 @@ bool tox_group_get_password(const Tox *tox, uint32_t group_number, uint8_t *pass
return true;
}
-bool tox_group_send_message(const Tox *tox, uint32_t group_number, Tox_Message_Type type, const uint8_t *message,
- size_t length, uint32_t *message_id, Tox_Err_Group_Send_Message *error)
+Tox_Group_Message_Id tox_group_send_message(
+ const Tox *tox, uint32_t group_number, Tox_Message_Type type, const uint8_t *message,
+ size_t length, Tox_Err_Group_Send_Message *error)
{
assert(tox != nullptr);
@@ -3836,54 +3943,55 @@ bool tox_group_send_message(const Tox *tox, uint32_t group_number, Tox_Message_T
if (chat == nullptr) {
SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_MESSAGE_GROUP_NOT_FOUND);
tox_unlock(tox);
- return false;
+ return -1;
}
if (chat->connection_state == CS_DISCONNECTED) {
SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_MESSAGE_DISCONNECTED);
tox_unlock(tox);
- return false;
+ return -1;
}
- const int ret = gc_send_message(chat, message, length, type, message_id);
+ uint32_t message_id = 0;
+ const int ret = gc_send_message(chat, message, length, type, &message_id);
tox_unlock(tox);
switch (ret) {
case 0: {
SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_MESSAGE_OK);
- return true;
+ return message_id;
}
case -1: {
SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_MESSAGE_TOO_LONG);
- return false;
+ return -1;
}
case -2: {
SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_MESSAGE_EMPTY);
- return false;
+ return -1;
}
case -3: {
SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_MESSAGE_BAD_TYPE);
- return false;
+ return -1;
}
case -4: {
SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_MESSAGE_PERMISSIONS);
- return false;
+ return -1;
}
case -5: {
SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_MESSAGE_FAIL_SEND);
- return false;
+ return -1;
}
}
/* can't happen */
LOGGER_FATAL(tox->m->log, "impossible return value: %d", ret);
- return false;
+ return -1;
}
bool tox_group_send_private_message(const Tox *tox, uint32_t group_number, uint32_t peer_id, Tox_Message_Type type,
@@ -3906,7 +4014,7 @@ bool tox_group_send_private_message(const Tox *tox, uint32_t group_number, uint3
return false;
}
- const int ret = gc_send_private_message(chat, peer_id, type, message, length);
+ const int ret = gc_send_private_message(chat, gc_peer_id_from_int(peer_id), type, message, length);
tox_unlock(tox);
switch (ret) {
@@ -3995,6 +4103,11 @@ bool tox_group_send_custom_packet(const Tox *tox, uint32_t group_number, bool lo
SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_CUSTOM_PACKET_PERMISSIONS);
return false;
}
+
+ case -4: {
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_CUSTOM_PACKET_FAIL_SEND);
+ return false;
+ }
}
/* can't happen */
@@ -4024,7 +4137,7 @@ bool tox_group_send_custom_private_packet(const Tox *tox, uint32_t group_number,
return false;
}
- const int ret = gc_send_custom_private_packet(chat, lossless, peer_id, data, length);
+ const int ret = gc_send_custom_private_packet(chat, lossless, gc_peer_id_from_int(peer_id), data, length);
tox_unlock(tox);
switch (ret) {
@@ -4181,7 +4294,7 @@ uint32_t tox_group_invite_accept(Tox *tox, uint32_t friend_number, const uint8_t
return UINT32_MAX;
}
-bool tox_group_founder_set_password(const Tox *tox, uint32_t group_number, const uint8_t *password, size_t length,
+bool tox_group_founder_set_password(Tox *tox, uint32_t group_number, const uint8_t *password, size_t length,
Tox_Err_Group_Founder_Set_Password *error)
{
assert(tox != nullptr);
@@ -4237,7 +4350,7 @@ bool tox_group_founder_set_password(const Tox *tox, uint32_t group_number, const
return false;
}
-bool tox_group_founder_set_privacy_state(const Tox *tox, uint32_t group_number, Tox_Group_Privacy_State privacy_state,
+bool tox_group_founder_set_privacy_state(Tox *tox, uint32_t group_number, Tox_Group_Privacy_State privacy_state,
Tox_Err_Group_Founder_Set_Privacy_State *error)
{
assert(tox != nullptr);
@@ -4284,7 +4397,7 @@ bool tox_group_founder_set_privacy_state(const Tox *tox, uint32_t group_number,
return false;
}
-bool tox_group_founder_set_topic_lock(const Tox *tox, uint32_t group_number, Tox_Group_Topic_Lock topic_lock,
+bool tox_group_founder_set_topic_lock(Tox *tox, uint32_t group_number, Tox_Group_Topic_Lock topic_lock,
Tox_Err_Group_Founder_Set_Topic_Lock *error)
{
assert(tox != nullptr);
@@ -4336,7 +4449,7 @@ bool tox_group_founder_set_topic_lock(const Tox *tox, uint32_t group_number, Tox
return false;
}
-bool tox_group_founder_set_voice_state(const Tox *tox, uint32_t group_number, Tox_Group_Voice_State voice_state,
+bool tox_group_founder_set_voice_state(Tox *tox, uint32_t group_number, Tox_Group_Voice_State voice_state,
Tox_Err_Group_Founder_Set_Voice_State *error)
{
assert(tox != nullptr);
@@ -4383,7 +4496,7 @@ bool tox_group_founder_set_voice_state(const Tox *tox, uint32_t group_number, To
return false;
}
-bool tox_group_founder_set_peer_limit(const Tox *tox, uint32_t group_number, uint16_t max_peers,
+bool tox_group_founder_set_peer_limit(Tox *tox, uint32_t group_number, uint16_t peer_limit,
Tox_Err_Group_Founder_Set_Peer_Limit *error)
{
assert(tox != nullptr);
@@ -4403,7 +4516,7 @@ bool tox_group_founder_set_peer_limit(const Tox *tox, uint32_t group_number, uin
return false;
}
- const int ret = gc_founder_set_max_peers(chat, max_peers);
+ const int ret = gc_founder_set_max_peers(chat, peer_limit);
tox_unlock(tox);
switch (ret) {
@@ -4434,7 +4547,7 @@ bool tox_group_founder_set_peer_limit(const Tox *tox, uint32_t group_number, uin
return false;
}
-bool tox_group_set_ignore(const Tox *tox, uint32_t group_number, uint32_t peer_id, bool ignore,
+bool tox_group_set_ignore(Tox *tox, uint32_t group_number, uint32_t peer_id, bool ignore,
Tox_Err_Group_Set_Ignore *error)
{
assert(tox != nullptr);
@@ -4448,7 +4561,7 @@ bool tox_group_set_ignore(const Tox *tox, uint32_t group_number, uint32_t peer_i
return false;
}
- const int ret = gc_set_ignore(chat, peer_id, ignore);
+ const int ret = gc_set_ignore(chat, gc_peer_id_from_int(peer_id), ignore);
tox_unlock(tox);
switch (ret) {
@@ -4474,13 +4587,13 @@ bool tox_group_set_ignore(const Tox *tox, uint32_t group_number, uint32_t peer_i
return false;
}
-bool tox_group_mod_set_role(const Tox *tox, uint32_t group_number, uint32_t peer_id, Tox_Group_Role role,
+bool tox_group_mod_set_role(Tox *tox, uint32_t group_number, uint32_t peer_id, Tox_Group_Role role,
Tox_Err_Group_Mod_Set_Role *error)
{
assert(tox != nullptr);
tox_lock(tox);
- const int ret = gc_set_peer_role(tox->m, group_number, peer_id, (Group_Role) role);
+ const int ret = gc_set_peer_role(tox->m, group_number, gc_peer_id_from_int(peer_id), (Group_Role) role);
tox_unlock(tox);
switch (ret) {
@@ -4532,7 +4645,7 @@ bool tox_group_mod_kick_peer(const Tox *tox, uint32_t group_number, uint32_t pee
assert(tox != nullptr);
tox_lock(tox);
- const int ret = gc_kick_peer(tox->m, group_number, peer_id);
+ const int ret = gc_kick_peer(tox->m, group_number, gc_peer_id_from_int(peer_id));
tox_unlock(tox);
switch (ret) {
@@ -4578,5 +4691,8 @@ bool tox_group_mod_kick_peer(const Tox *tox, uint32_t group_number, uint32_t pee
return false;
}
-#endif /* VANILLA_NACL */
-
+const Tox_System *tox_get_system(Tox *tox)
+{
+ assert(tox != nullptr);
+ return &tox->sys;
+}
diff --git a/protocols/Tox/libtox/src/toxcore/tox.h b/protocols/Tox/libtox/src/toxcore/tox.h
index fd1901f69c..fa887fc779 100644
--- a/protocols/Tox/libtox/src/toxcore/tox.h
+++ b/protocols/Tox/libtox/src/toxcore/tox.h
@@ -124,7 +124,6 @@ extern "C" {
typedef struct Tox Tox;
#endif /* TOX_DEFINED */
-
/** @{
* @name API version
*/
@@ -202,7 +201,6 @@ bool tox_version_is_compatible(uint32_t major, uint32_t minor, uint32_t patch);
/** @} */
-
/** @{
* @name Numeric constants
*
@@ -344,7 +342,6 @@ uint32_t tox_max_hostname_length(void);
/** @} */
-
/** @{
* @name Global enumerations
*/
@@ -373,6 +370,7 @@ 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,8 +391,9 @@ typedef enum Tox_Message_Type {
} Tox_Message_Type;
-/** @} */
+const char *tox_message_type_to_string(Tox_Message_Type value);
+/** @} */
/** @{
* @name Startup options
@@ -422,6 +421,7 @@ 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 +445,7 @@ 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 +479,7 @@ 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.
@@ -490,6 +492,9 @@ typedef enum Tox_Log_Level {
* any time. Thus, user code must make sure it is equipped to handle concurrent
* execution, e.g. by employing appropriate mutex locking.
*
+ * When using the experimental_thread_safety option, no Tox API functions can
+ * be called from within the log callback.
+ *
* @param level The severity of the log message.
* @param file The source file from which the message originated.
* @param line The source line from which the message originated.
@@ -500,7 +505,6 @@ typedef enum Tox_Log_Level {
typedef void tox_log_cb(Tox *tox, Tox_Log_Level level, const char *file, uint32_t line, const char *func,
const char *message, void *user_data);
-
/**
* @brief Operating system functions used by Tox.
*
@@ -510,7 +514,6 @@ typedef void tox_log_cb(Tox *tox, Tox_Log_Level level, const char *file, uint32_
*/
typedef struct Tox_System Tox_System;
-
/**
* @brief This struct contains all the startup options for Tox.
*
@@ -526,6 +529,7 @@ typedef struct Tox_System Tox_System;
* members. The struct will become opaque (i.e. the definition will become
* private) in v0.3.0.
*/
+typedef struct Tox_Options Tox_Options;
struct Tox_Options {
/**
@@ -538,7 +542,6 @@ struct Tox_Options {
*/
bool ipv6_enabled;
-
/**
* Enable the use of UDP communication when available.
*
@@ -550,7 +553,6 @@ struct Tox_Options {
*/
bool udp_enabled;
-
/**
* Enable local network peer discovery.
*
@@ -558,7 +560,6 @@ struct Tox_Options {
*/
bool local_discovery_enabled;
-
/**
* Enable storing DHT announcements and forwarding corresponding requests.
*
@@ -571,7 +572,6 @@ struct Tox_Options {
*/
Tox_Proxy_Type proxy_type;
-
/**
* The IP address or DNS name of the proxy to be used.
*
@@ -586,7 +586,6 @@ struct Tox_Options {
*/
const char *proxy_host;
-
/**
* The port to use to connect to the proxy server.
*
@@ -595,7 +594,6 @@ struct Tox_Options {
*/
uint16_t proxy_port;
-
/**
* The start port of the inclusive port range to attempt to use.
*
@@ -610,13 +608,11 @@ struct Tox_Options {
*/
uint16_t start_port;
-
/**
* The end port of the inclusive port range to attempt to use.
*/
uint16_t end_port;
-
/**
* The port to use for the TCP server (relay). If 0, the TCP server is
* disabled.
@@ -630,19 +626,16 @@ struct Tox_Options {
*/
uint16_t tcp_port;
-
/**
* Enables or disables UDP hole-punching in toxcore. (Default: enabled).
*/
bool hole_punching_enabled;
-
/**
* The type of savedata to load from.
*/
Tox_Savedata_Type savedata_type;
-
/**
* The savedata.
*
@@ -651,25 +644,21 @@ struct Tox_Options {
*/
const uint8_t *savedata_data;
-
/**
* The length of the savedata.
*/
size_t savedata_length;
-
/**
* Logging callback for the new tox instance.
*/
tox_log_cb *log_callback;
-
/**
* User data pointer passed to the logging callback.
*/
void *log_user_data;
-
/**
* These options are experimental, so avoid writing code that depends on
* them. Options marked "experimental" may change their behaviour or go away
@@ -684,85 +673,99 @@ struct Tox_Options {
bool experimental_thread_safety;
/**
- * Low level operating system functionality such as send/recv and random
- * number generation.
+ * Low level operating system functionality such as send/recv, random
+ * number generation, and memory allocation.
*/
const Tox_System *operating_system;
+ /**
+ * Enable saving DHT-based group chats to Tox save data (via `tox_get_savedata`).
+ * This format will change in the future, so don't rely on it.
+ *
+ * As an alternative, clients can save the group chat ID in client-owned
+ * savedata. Then, when the client starts, it can use `tox_group_join`
+ * with the saved chat ID to recreate the group chat.
+ *
+ * Default: false.
+ */
+ bool experimental_groups_persistence;
};
+bool tox_options_get_ipv6_enabled(const Tox_Options *options);
-bool tox_options_get_ipv6_enabled(const struct Tox_Options *options);
+void tox_options_set_ipv6_enabled(Tox_Options *options, bool ipv6_enabled);
-void tox_options_set_ipv6_enabled(struct Tox_Options *options, bool ipv6_enabled);
+bool tox_options_get_udp_enabled(const Tox_Options *options);
-bool tox_options_get_udp_enabled(const struct Tox_Options *options);
+void tox_options_set_udp_enabled(Tox_Options *options, bool udp_enabled);
-void tox_options_set_udp_enabled(struct Tox_Options *options, bool udp_enabled);
+bool tox_options_get_local_discovery_enabled(const Tox_Options *options);
-bool tox_options_get_local_discovery_enabled(const struct Tox_Options *options);
+void tox_options_set_local_discovery_enabled(Tox_Options *options, bool local_discovery_enabled);
-void tox_options_set_local_discovery_enabled(struct Tox_Options *options, bool local_discovery_enabled);
+bool tox_options_get_dht_announcements_enabled(const Tox_Options *options);
-bool tox_options_get_dht_announcements_enabled(const struct Tox_Options *options);
+void tox_options_set_dht_announcements_enabled(Tox_Options *options, bool dht_announcements_enabled);
-void tox_options_set_dht_announcements_enabled(struct Tox_Options *options, bool dht_announcements_enabled);
+Tox_Proxy_Type tox_options_get_proxy_type(const Tox_Options *options);
-Tox_Proxy_Type tox_options_get_proxy_type(const struct Tox_Options *options);
+void tox_options_set_proxy_type(Tox_Options *options, Tox_Proxy_Type proxy_type);
-void tox_options_set_proxy_type(struct Tox_Options *options, Tox_Proxy_Type type);
+const char *tox_options_get_proxy_host(const Tox_Options *options);
-const char *tox_options_get_proxy_host(const struct Tox_Options *options);
+void tox_options_set_proxy_host(Tox_Options *options, const char *proxy_host);
-void tox_options_set_proxy_host(struct Tox_Options *options, const char *host);
+uint16_t tox_options_get_proxy_port(const Tox_Options *options);
-uint16_t tox_options_get_proxy_port(const struct Tox_Options *options);
+void tox_options_set_proxy_port(Tox_Options *options, uint16_t proxy_port);
-void tox_options_set_proxy_port(struct Tox_Options *options, uint16_t port);
+uint16_t tox_options_get_start_port(const Tox_Options *options);
-uint16_t tox_options_get_start_port(const struct Tox_Options *options);
+void tox_options_set_start_port(Tox_Options *options, uint16_t start_port);
-void tox_options_set_start_port(struct Tox_Options *options, uint16_t start_port);
+uint16_t tox_options_get_end_port(const Tox_Options *options);
-uint16_t tox_options_get_end_port(const struct Tox_Options *options);
+void tox_options_set_end_port(Tox_Options *options, uint16_t end_port);
-void tox_options_set_end_port(struct Tox_Options *options, uint16_t end_port);
+uint16_t tox_options_get_tcp_port(const Tox_Options *options);
-uint16_t tox_options_get_tcp_port(const struct Tox_Options *options);
+void tox_options_set_tcp_port(Tox_Options *options, uint16_t tcp_port);
-void tox_options_set_tcp_port(struct Tox_Options *options, uint16_t tcp_port);
+bool tox_options_get_hole_punching_enabled(const Tox_Options *options);
-bool tox_options_get_hole_punching_enabled(const struct Tox_Options *options);
+void tox_options_set_hole_punching_enabled(Tox_Options *options, bool hole_punching_enabled);
-void tox_options_set_hole_punching_enabled(struct Tox_Options *options, bool hole_punching_enabled);
+Tox_Savedata_Type tox_options_get_savedata_type(const Tox_Options *options);
-Tox_Savedata_Type tox_options_get_savedata_type(const struct Tox_Options *options);
+void tox_options_set_savedata_type(Tox_Options *options, Tox_Savedata_Type savedata_type);
-void tox_options_set_savedata_type(struct Tox_Options *options, Tox_Savedata_Type type);
+const uint8_t *tox_options_get_savedata_data(const Tox_Options *options);
-const uint8_t *tox_options_get_savedata_data(const struct Tox_Options *options);
+void tox_options_set_savedata_data(Tox_Options *options, const uint8_t savedata_data[], size_t length);
-void tox_options_set_savedata_data(struct Tox_Options *options, const uint8_t *data, size_t length);
+size_t tox_options_get_savedata_length(const Tox_Options *options);
-size_t tox_options_get_savedata_length(const struct Tox_Options *options);
+void tox_options_set_savedata_length(Tox_Options *options, size_t savedata_length);
-void tox_options_set_savedata_length(struct Tox_Options *options, size_t length);
+tox_log_cb *tox_options_get_log_callback(const Tox_Options *options);
-tox_log_cb *tox_options_get_log_callback(const struct Tox_Options *options);
+void tox_options_set_log_callback(Tox_Options *options, tox_log_cb *log_callback);
-void tox_options_set_log_callback(struct Tox_Options *options, tox_log_cb *callback);
+void *tox_options_get_log_user_data(const Tox_Options *options);
-void *tox_options_get_log_user_data(const struct Tox_Options *options);
+void tox_options_set_log_user_data(Tox_Options *options, void *log_user_data);
-void tox_options_set_log_user_data(struct Tox_Options *options, void *user_data);
+bool tox_options_get_experimental_thread_safety(const Tox_Options *options);
-bool tox_options_get_experimental_thread_safety(const struct Tox_Options *options);
+void tox_options_set_experimental_thread_safety(Tox_Options *options, bool experimental_thread_safety);
-void tox_options_set_experimental_thread_safety(struct Tox_Options *options, bool experimental_thread_safety);
+const Tox_System *tox_options_get_operating_system(const Tox_Options *options);
-const Tox_System *tox_options_get_operating_system(const struct Tox_Options *options);
+void tox_options_set_operating_system(Tox_Options *options, const Tox_System *operating_system);
-void tox_options_set_operating_system(struct Tox_Options *options, const Tox_System *operating_system);
+bool tox_options_get_experimental_groups_persistence(const Tox_Options *options);
+
+void tox_options_set_experimental_groups_persistence(Tox_Options *options, bool experimental_groups_persistence);
/**
* @brief Initialises a Tox_Options object with the default options.
@@ -775,7 +778,7 @@ void tox_options_set_operating_system(struct Tox_Options *options, const Tox_Sys
*
* @param options An options object to be filled with default options.
*/
-void tox_options_default(struct Tox_Options *options);
+void tox_options_default(Tox_Options *options);
typedef enum Tox_Err_Options_New {
@@ -791,6 +794,7 @@ 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
@@ -804,7 +808,7 @@ typedef enum Tox_Err_Options_New {
*
* @return A new Tox_Options object with default options or NULL on failure.
*/
-struct Tox_Options *tox_options_new(Tox_Err_Options_New *error);
+Tox_Options *tox_options_new(Tox_Err_Options_New *error);
/**
* @brief Releases all resources associated with an options objects.
@@ -812,11 +816,10 @@ struct Tox_Options *tox_options_new(Tox_Err_Options_New *error);
* Passing a pointer that was not returned by tox_options_new results in
* undefined behaviour.
*/
-void tox_options_free(struct Tox_Options *options);
+void tox_options_free(Tox_Options *options);
/** @} */
-
/** @{
* @name Creation and destruction
*/
@@ -883,6 +886,7 @@ 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.
@@ -890,9 +894,6 @@ typedef enum Tox_Err_New {
* This function will bring the instance into a valid state. Running the event
* loop with a new instance will operate correctly.
*
- * If loading failed or succeeded only partially, the new or partially loaded
- * instance is returned and an error code is set.
- *
* @param options An options object as described above. If this parameter is
* NULL, the default options are used.
*
@@ -900,7 +901,7 @@ typedef enum Tox_Err_New {
*
* @return A new Tox instance pointer on success or NULL on failure.
*/
-Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error);
+Tox *tox_new(const Tox_Options *options, Tox_Err_New *error);
/**
* @brief Releases all resources associated with the Tox instance and
@@ -928,11 +929,10 @@ size_t tox_get_savedata_size(const Tox *tox);
* data. Call tox_get_savedata_size to find the number of bytes required. If this parameter
* is NULL, this function has no effect.
*/
-void tox_get_savedata(const Tox *tox, uint8_t *savedata);
+void tox_get_savedata(const Tox *tox, uint8_t savedata[]);
/** @} */
-
/** @{
* @name Connection lifecycle and event loop
*/
@@ -963,6 +963,7 @@ 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,
@@ -979,7 +980,7 @@ typedef enum Tox_Err_Bootstrap {
* (TOX_PUBLIC_KEY_SIZE bytes).
* @return true on success.
*/
-bool tox_bootstrap(Tox *tox, const char *host, uint16_t port, const uint8_t *public_key, Tox_Err_Bootstrap *error);
+bool tox_bootstrap(Tox *tox, const char *host, uint16_t port, const uint8_t public_key[TOX_PUBLIC_KEY_SIZE], Tox_Err_Bootstrap *error);
/**
* @brief Adds additional host:port pair as TCP relay.
@@ -995,7 +996,7 @@ bool tox_bootstrap(Tox *tox, const char *host, uint16_t port, const uint8_t *pub
* (TOX_PUBLIC_KEY_SIZE bytes).
* @return true on success.
*/
-bool tox_add_tcp_relay(Tox *tox, const char *host, uint16_t port, const uint8_t *public_key, Tox_Err_Bootstrap *error);
+bool tox_add_tcp_relay(Tox *tox, const char *host, uint16_t port, const uint8_t public_key[TOX_PUBLIC_KEY_SIZE], Tox_Err_Bootstrap *error);
/**
* @brief Protocols that can be used to connect to the network or friends.
@@ -1030,6 +1031,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.
*
@@ -1046,7 +1049,6 @@ Tox_Connection tox_self_get_connection_status(const Tox *tox);
*/
typedef void tox_self_connection_status_cb(Tox *tox, Tox_Connection connection_status, void *user_data);
-
/**
* @brief Set the callback for the `self_connection_status` event.
*
@@ -1076,7 +1078,6 @@ void tox_iterate(Tox *tox, void *user_data);
/** @} */
-
/** @{
* @name Internal client information (Tox address/id)
*/
@@ -1091,7 +1092,7 @@ void tox_iterate(Tox *tox, void *user_data);
* parameter is NULL, this function has no effect.
* @see TOX_ADDRESS_SIZE for the address format.
*/
-void tox_self_get_address(const Tox *tox, uint8_t *address);
+void tox_self_get_address(const Tox *tox, uint8_t address[TOX_ADDRESS_SIZE]);
/**
* @brief Set the 4-byte nospam part of the address.
@@ -1116,7 +1117,7 @@ uint32_t tox_self_get_nospam(const Tox *tox);
* @param public_key A memory region of at least TOX_PUBLIC_KEY_SIZE bytes. If
* this parameter is NULL, this function has no effect.
*/
-void tox_self_get_public_key(const Tox *tox, uint8_t *public_key);
+void tox_self_get_public_key(const Tox *tox, uint8_t public_key[TOX_PUBLIC_KEY_SIZE]);
/**
* @brief Copy the Tox Secret Key from the Tox object.
@@ -1124,11 +1125,10 @@ void tox_self_get_public_key(const Tox *tox, uint8_t *public_key);
* @param secret_key A memory region of at least TOX_SECRET_KEY_SIZE bytes. If
* this parameter is NULL, this function has no effect.
*/
-void tox_self_get_secret_key(const Tox *tox, uint8_t *secret_key);
+void tox_self_get_secret_key(const Tox *tox, uint8_t secret_key[TOX_SECRET_KEY_SIZE]);
/** @} */
-
/** @{
* @name User-visible client information (nickname/status)
*/
@@ -1156,6 +1156,7 @@ 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.
@@ -1168,7 +1169,7 @@ typedef enum Tox_Err_Set_Info {
*
* @return true on success.
*/
-bool tox_self_set_name(Tox *tox, const uint8_t *name, size_t length, Tox_Err_Set_Info *error);
+bool tox_self_set_name(Tox *tox, const uint8_t name[], size_t length, Tox_Err_Set_Info *error);
/**
* @brief Return the length of the current nickname as passed to tox_self_set_name.
@@ -1192,7 +1193,7 @@ size_t tox_self_get_name_size(const Tox *tox);
* @param name A valid memory location large enough to hold the nickname.
* If this parameter is NULL, the function has no effect.
*/
-void tox_self_get_name(const Tox *tox, uint8_t *name);
+void tox_self_get_name(const Tox *tox, uint8_t name[]);
/**
* @brief Set the client's status message.
@@ -1201,7 +1202,8 @@ void tox_self_get_name(const Tox *tox, uint8_t *name);
* length is 0, the status parameter is ignored (it can be NULL), and the
* user status is set back to empty.
*/
-bool tox_self_set_status_message(Tox *tox, const uint8_t *status_message, size_t length, Tox_Err_Set_Info *error);
+bool tox_self_set_status_message(
+ Tox *tox, const uint8_t status_message[], size_t length, Tox_Err_Set_Info *error);
/**
* @brief Return the length of the current status message as passed to tox_self_set_status_message.
@@ -1225,7 +1227,7 @@ size_t tox_self_get_status_message_size(const Tox *tox);
* @param status_message A valid memory location large enough to hold the
* status message. If this parameter is NULL, the function has no effect.
*/
-void tox_self_get_status_message(const Tox *tox, uint8_t *status_message);
+void tox_self_get_status_message(const Tox *tox, uint8_t status_message[]);
/**
* @brief Set the client's user status.
@@ -1241,11 +1243,12 @@ Tox_User_Status tox_self_get_status(const Tox *tox);
/** @} */
-
/** @{
* @name Friend list management
*/
+typedef uint32_t Tox_Friend_Number;
+
typedef enum Tox_Err_Friend_Add {
/**
@@ -1298,6 +1301,7 @@ 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.
@@ -1322,8 +1326,10 @@ typedef enum Tox_Err_Friend_Add {
*
* @return the friend number on success, an unspecified value on failure.
*/
-uint32_t tox_friend_add(Tox *tox, const uint8_t *address, const uint8_t *message, size_t length,
- Tox_Err_Friend_Add *error);
+Tox_Friend_Number tox_friend_add(
+ Tox *tox, const uint8_t address[TOX_ADDRESS_SIZE],
+ const uint8_t message[], size_t length,
+ Tox_Err_Friend_Add *error);
/**
* @brief Add a friend without sending a friend request.
@@ -1343,7 +1349,8 @@ uint32_t tox_friend_add(Tox *tox, const uint8_t *address, const uint8_t *message
* @return the friend number on success, an unspecified value on failure.
* @see tox_friend_add for a more detailed description of friend numbers.
*/
-uint32_t tox_friend_add_norequest(Tox *tox, const uint8_t *public_key, Tox_Err_Friend_Add *error);
+Tox_Friend_Number tox_friend_add_norequest(
+ Tox *tox, const uint8_t public_key[TOX_PUBLIC_KEY_SIZE], Tox_Err_Friend_Add *error);
typedef enum Tox_Err_Friend_Delete {
@@ -1359,6 +1366,7 @@ 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.
@@ -1371,11 +1379,10 @@ typedef enum Tox_Err_Friend_Delete {
*
* @return true on success.
*/
-bool tox_friend_delete(Tox *tox, uint32_t friend_number, Tox_Err_Friend_Delete *error);
+bool tox_friend_delete(Tox *tox, Tox_Friend_Number friend_number, Tox_Err_Friend_Delete *error);
/** @} */
-
/** @{
* @name Friend list queries
*/
@@ -1399,6 +1406,7 @@ 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.
@@ -1406,13 +1414,13 @@ typedef enum Tox_Err_Friend_By_Public_Key {
* @return the friend number on success, an unspecified value on failure.
* @param public_key A byte array containing the Public Key.
*/
-uint32_t tox_friend_by_public_key(const Tox *tox, const uint8_t *public_key, Tox_Err_Friend_By_Public_Key *error);
+Tox_Friend_Number tox_friend_by_public_key(const Tox *tox, const uint8_t public_key[TOX_PUBLIC_KEY_SIZE], Tox_Err_Friend_By_Public_Key *error);
/**
* @brief Checks if a friend with the given friend number exists and returns true if
* it does.
*/
-bool tox_friend_exists(const Tox *tox, uint32_t friend_number);
+bool tox_friend_exists(const Tox *tox, Tox_Friend_Number friend_number);
/**
* @brief Return the number of friends on the friend list.
@@ -1430,7 +1438,7 @@ size_t tox_self_get_friend_list_size(const Tox *tox);
* @param friend_list A memory region with enough space to hold the friend
* list. If this parameter is NULL, this function has no effect.
*/
-void tox_self_get_friend_list(const Tox *tox, uint32_t *friend_list);
+void tox_self_get_friend_list(const Tox *tox, Tox_Friend_Number friend_list[]);
typedef enum Tox_Err_Friend_Get_Public_Key {
@@ -1446,6 +1454,7 @@ 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.
@@ -1456,8 +1465,9 @@ typedef enum Tox_Err_Friend_Get_Public_Key {
*
* @return true on success.
*/
-bool tox_friend_get_public_key(const Tox *tox, uint32_t friend_number, uint8_t *public_key,
- Tox_Err_Friend_Get_Public_Key *error);
+bool tox_friend_get_public_key(
+ const Tox *tox, Tox_Friend_Number friend_number, uint8_t public_key[TOX_PUBLIC_KEY_SIZE],
+ Tox_Err_Friend_Get_Public_Key *error);
typedef enum Tox_Err_Friend_Get_Last_Online {
@@ -1473,6 +1483,7 @@ 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
@@ -1482,11 +1493,11 @@ typedef enum Tox_Err_Friend_Get_Last_Online {
*
* @param friend_number The friend number you want to query.
*/
-uint64_t tox_friend_get_last_online(const Tox *tox, uint32_t friend_number, Tox_Err_Friend_Get_Last_Online *error);
+uint64_t tox_friend_get_last_online(
+ const Tox *tox, Tox_Friend_Number friend_number, Tox_Err_Friend_Get_Last_Online *error);
/** @} */
-
/** @{
* @name Friend-specific state queries (can also be received through callbacks)
*/
@@ -1515,6 +1526,7 @@ 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.
@@ -1524,7 +1536,8 @@ typedef enum Tox_Err_Friend_Query {
* The return value is equal to the `length` argument received by the last
* `friend_name` callback.
*/
-size_t tox_friend_get_name_size(const Tox *tox, uint32_t friend_number, Tox_Err_Friend_Query *error);
+size_t tox_friend_get_name_size(
+ const Tox *tox, Tox_Friend_Number friend_number, Tox_Err_Friend_Query *error);
/**
* @brief Write the name of the friend designated by the given friend number to a byte
@@ -1540,7 +1553,8 @@ size_t tox_friend_get_name_size(const Tox *tox, uint32_t friend_number, Tox_Err_
*
* @return true on success.
*/
-bool tox_friend_get_name(const Tox *tox, uint32_t friend_number, uint8_t *name, Tox_Err_Friend_Query *error);
+bool tox_friend_get_name(
+ const Tox *tox, Tox_Friend_Number friend_number, uint8_t name[], Tox_Err_Friend_Query *error);
/**
* @param friend_number The friend number of the friend whose name changed.
@@ -1549,8 +1563,9 @@ bool tox_friend_get_name(const Tox *tox, uint32_t friend_number, uint8_t *name,
* @param length A value equal to the return value of
* tox_friend_get_name_size.
*/
-typedef void tox_friend_name_cb(Tox *tox, uint32_t friend_number, const uint8_t *name, size_t length, void *user_data);
-
+typedef void tox_friend_name_cb(
+ Tox *tox, Tox_Friend_Number friend_number,
+ const uint8_t name[], size_t length, void *user_data);
/**
* @brief Set the callback for the `friend_name` event.
@@ -1566,7 +1581,8 @@ void tox_callback_friend_name(Tox *tox, tox_friend_name_cb *callback);
*
* If the friend number isinvalid, the return value is SIZE_MAX.
*/
-size_t tox_friend_get_status_message_size(const Tox *tox, uint32_t friend_number, Tox_Err_Friend_Query *error);
+size_t tox_friend_get_status_message_size(
+ const Tox *tox, Tox_Friend_Number friend_number, Tox_Err_Friend_Query *error);
/**
* @brief Write the status message of the friend designated by the given friend number to a byte
@@ -1580,8 +1596,9 @@ size_t tox_friend_get_status_message_size(const Tox *tox, uint32_t friend_number
*
* @param status_message A valid memory region large enough to store the friend's status message.
*/
-bool tox_friend_get_status_message(const Tox *tox, uint32_t friend_number, uint8_t *status_message,
- Tox_Err_Friend_Query *error);
+bool tox_friend_get_status_message(
+ const Tox *tox, Tox_Friend_Number friend_number, uint8_t status_message[],
+ Tox_Err_Friend_Query *error);
/**
* @param friend_number The friend number of the friend whose status message
@@ -1591,9 +1608,9 @@ bool tox_friend_get_status_message(const Tox *tox, uint32_t friend_number, uint8
* @param length A value equal to the return value of
* tox_friend_get_status_message_size.
*/
-typedef void tox_friend_status_message_cb(Tox *tox, uint32_t friend_number, const uint8_t *message, size_t length,
- void *user_data);
-
+typedef void tox_friend_status_message_cb(
+ Tox *tox, Tox_Friend_Number friend_number,
+ const uint8_t message[], size_t length, void *user_data);
/**
* @brief Set the callback for the `friend_status_message` event.
@@ -1615,15 +1632,16 @@ void tox_callback_friend_status_message(Tox *tox, tox_friend_status_message_cb *
* @deprecated This getter is deprecated. Use the event and store the status
* in the client state.
*/
-Tox_User_Status tox_friend_get_status(const Tox *tox, uint32_t friend_number, Tox_Err_Friend_Query *error);
+Tox_User_Status tox_friend_get_status(
+ const Tox *tox, Tox_Friend_Number friend_number, Tox_Err_Friend_Query *error);
/**
* @param friend_number The friend number of the friend whose user status
* changed.
* @param status The new user status.
*/
-typedef void tox_friend_status_cb(Tox *tox, uint32_t friend_number, Tox_User_Status status, void *user_data);
-
+typedef void tox_friend_status_cb(
+ Tox *tox, Tox_Friend_Number friend_number, Tox_User_Status status, void *user_data);
/**
* @brief Set the callback for the `friend_status` event.
@@ -1649,7 +1667,8 @@ void tox_callback_friend_status(Tox *tox, tox_friend_status_cb *callback);
* @deprecated This getter is deprecated. Use the event and store the status
* in the client state.
*/
-Tox_Connection tox_friend_get_connection_status(const Tox *tox, uint32_t friend_number, Tox_Err_Friend_Query *error);
+Tox_Connection tox_friend_get_connection_status(
+ const Tox *tox, Tox_Friend_Number friend_number, Tox_Err_Friend_Query *error);
/**
* @param friend_number The friend number of the friend whose connection status
@@ -1657,9 +1676,8 @@ Tox_Connection tox_friend_get_connection_status(const Tox *tox, uint32_t friend_
* @param connection_status The result of calling
* tox_friend_get_connection_status on the passed friend_number.
*/
-typedef void tox_friend_connection_status_cb(Tox *tox, uint32_t friend_number, Tox_Connection connection_status,
- void *user_data);
-
+typedef void tox_friend_connection_status_cb(
+ Tox *tox, Tox_Friend_Number friend_number, Tox_Connection connection_status, void *user_data);
/**
* @brief Set the callback for the `friend_connection_status` event.
@@ -1686,7 +1704,8 @@ void tox_callback_friend_connection_status(Tox *tox, tox_friend_connection_statu
* @deprecated This getter is deprecated. Use the event and store the status
* in the client state.
*/
-bool tox_friend_get_typing(const Tox *tox, uint32_t friend_number, Tox_Err_Friend_Query *error);
+bool tox_friend_get_typing(
+ const Tox *tox, Tox_Friend_Number friend_number, Tox_Err_Friend_Query *error);
/**
* @param friend_number The friend number of the friend who started or stopped
@@ -1694,8 +1713,8 @@ bool tox_friend_get_typing(const Tox *tox, uint32_t friend_number, Tox_Err_Frien
* @param typing The result of calling tox_friend_get_typing on the passed
* friend_number.
*/
-typedef void tox_friend_typing_cb(Tox *tox, uint32_t friend_number, bool typing, void *user_data);
-
+typedef void tox_friend_typing_cb(
+ Tox *tox, Tox_Friend_Number friend_number, bool typing, void *user_data);
/**
* @brief Set the callback for the `friend_typing` event.
@@ -1708,7 +1727,6 @@ void tox_callback_friend_typing(Tox *tox, tox_friend_typing_cb *callback);
/** @} */
-
/** @{
* @name Sending private messages
*/
@@ -1727,6 +1745,7 @@ 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.
@@ -1738,7 +1757,8 @@ typedef enum Tox_Err_Set_Typing {
*
* @return true on success.
*/
-bool tox_self_set_typing(Tox *tox, uint32_t friend_number, bool typing, Tox_Err_Set_Typing *error);
+bool tox_self_set_typing(
+ Tox *tox, Tox_Friend_Number friend_number, bool typing, Tox_Err_Set_Typing *error);
typedef enum Tox_Err_Friend_Send_Message {
@@ -1779,6 +1799,9 @@ 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);
+
+typedef uint32_t Tox_Friend_Message_Id;
/**
* @brief Send a text chat message to an online friend.
@@ -1803,16 +1826,17 @@ typedef enum Tox_Err_Friend_Send_Message {
* containing the message text.
* @param length Length of the message to be sent.
*/
-uint32_t tox_friend_send_message(Tox *tox, uint32_t friend_number, Tox_Message_Type type, const uint8_t *message,
- size_t length, Tox_Err_Friend_Send_Message *error);
+Tox_Friend_Message_Id tox_friend_send_message(
+ Tox *tox, Tox_Friend_Number friend_number, Tox_Message_Type type,
+ const uint8_t message[], size_t length, Tox_Err_Friend_Send_Message *error);
/**
* @param friend_number The friend number of the friend who received the message.
* @param message_id The message ID as returned from tox_friend_send_message
* corresponding to the message sent.
*/
-typedef void tox_friend_read_receipt_cb(Tox *tox, uint32_t friend_number, uint32_t message_id, void *user_data);
-
+typedef void tox_friend_read_receipt_cb(
+ Tox *tox, Tox_Friend_Number friend_number, Tox_Friend_Message_Id message_id, void *user_data);
/**
* @brief Set the callback for the `friend_read_receipt` event.
@@ -1826,7 +1850,6 @@ void tox_callback_friend_read_receipt(Tox *tox, tox_friend_read_receipt_cb *call
/** @} */
-
/** @{
* @name Receiving private messages and friend requests
*/
@@ -1836,9 +1859,10 @@ void tox_callback_friend_read_receipt(Tox *tox, tox_friend_read_receipt_cb *call
* @param message The message they sent along with the request.
* @param length The size of the message byte array.
*/
-typedef void tox_friend_request_cb(Tox *tox, const uint8_t *public_key, const uint8_t *message, size_t length,
- void *user_data);
-
+typedef void tox_friend_request_cb(
+ Tox *tox, const uint8_t public_key[TOX_PUBLIC_KEY_SIZE],
+ const uint8_t message[], size_t length,
+ void *user_data);
/**
* @brief Set the callback for the `friend_request` event.
@@ -1854,9 +1878,9 @@ void tox_callback_friend_request(Tox *tox, tox_friend_request_cb *callback);
* @param message The message data they sent.
* @param length The size of the message byte array.
*/
-typedef void tox_friend_message_cb(Tox *tox, uint32_t friend_number, Tox_Message_Type type, const uint8_t *message,
- size_t length, void *user_data);
-
+typedef void tox_friend_message_cb(
+ Tox *tox, Tox_Friend_Number friend_number, Tox_Message_Type type,
+ const uint8_t message[], size_t length, void *user_data);
/**
* @brief Set the callback for the `friend_message` event.
@@ -1869,11 +1893,12 @@ void tox_callback_friend_message(Tox *tox, tox_friend_message_cb *callback);
/** @} */
-
/** @{
* @name File transmission: common between sending and receiving
*/
+typedef uint32_t Tox_File_Number;
+
/**
* @brief Generates a cryptographic hash of the given data.
*
@@ -1893,7 +1918,7 @@ void tox_callback_friend_message(Tox *tox, tox_friend_message_cb *callback);
*
* @return true if hash was not NULL.
*/
-bool tox_hash(uint8_t *hash, const uint8_t *data, size_t length);
+bool tox_hash(uint8_t hash[TOX_HASH_LENGTH], const uint8_t data[], size_t length);
/**
* @brief A list of pre-defined file kinds.
@@ -1936,7 +1961,6 @@ enum Tox_File_Kind {
};
-
typedef enum Tox_File_Control {
/**
@@ -1961,6 +1985,7 @@ 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 {
@@ -2007,6 +2032,7 @@ 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.
@@ -2018,8 +2044,9 @@ typedef enum Tox_Err_File_Control {
*
* @return true on success.
*/
-bool tox_file_control(Tox *tox, uint32_t friend_number, uint32_t file_number, Tox_File_Control control,
- Tox_Err_File_Control *error);
+bool tox_file_control(
+ Tox *tox, Tox_Friend_Number friend_number, Tox_File_Number file_number, Tox_File_Control control,
+ Tox_Err_File_Control *error);
/**
* @brief When receiving TOX_FILE_CONTROL_CANCEL, the client should release the
@@ -2030,9 +2057,9 @@ bool tox_file_control(Tox *tox, uint32_t friend_number, uint32_t file_number, To
* associated with.
* @param control The file control command received.
*/
-typedef void tox_file_recv_control_cb(Tox *tox, uint32_t friend_number, uint32_t file_number, Tox_File_Control control,
- void *user_data);
-
+typedef void tox_file_recv_control_cb(
+ Tox *tox, Tox_Friend_Number friend_number, Tox_File_Number file_number, Tox_File_Control control,
+ void *user_data);
/**
* @brief Set the callback for the `file_recv_control` event.
@@ -2083,6 +2110,7 @@ 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.
@@ -2095,7 +2123,8 @@ typedef enum Tox_Err_File_Seek {
* @param file_number The friend-specific identifier for the file transfer.
* @param position The position that the file should be seeked to.
*/
-bool tox_file_seek(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position, Tox_Err_File_Seek *error);
+bool tox_file_seek(
+ Tox *tox, Tox_Friend_Number friend_number, Tox_File_Number file_number, uint64_t position, Tox_Err_File_Seek *error);
typedef enum Tox_Err_File_Get {
@@ -2121,6 +2150,7 @@ 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.
@@ -2133,12 +2163,13 @@ typedef enum Tox_Err_File_Get {
*
* @return true on success.
*/
-bool tox_file_get_file_id(const Tox *tox, uint32_t friend_number, uint32_t file_number, uint8_t *file_id,
- Tox_Err_File_Get *error);
+bool tox_file_get_file_id(
+ const Tox *tox, Tox_Friend_Number friend_number, Tox_File_Number file_number,
+ uint8_t file_id[TOX_FILE_ID_LENGTH],
+ Tox_Err_File_Get *error);
/** @} */
-
/** @{
* @name File transmission: sending
*/
@@ -2178,6 +2209,7 @@ 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.
@@ -2237,8 +2269,10 @@ typedef enum Tox_Err_File_Send {
* On failure, this function returns an unspecified value. Any pattern in file numbers
* should not be relied on.
*/
-uint32_t tox_file_send(Tox *tox, uint32_t friend_number, uint32_t kind, uint64_t file_size, const uint8_t *file_id,
- const uint8_t *filename, size_t filename_length, Tox_Err_File_Send *error);
+Tox_File_Number tox_file_send(
+ Tox *tox, Tox_Friend_Number friend_number, uint32_t kind, uint64_t file_size,
+ const uint8_t file_id[TOX_FILE_ID_LENGTH], const uint8_t filename[], size_t filename_length,
+ Tox_Err_File_Send *error);
typedef enum Tox_Err_File_Send_Chunk {
@@ -2292,6 +2326,7 @@ 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.
@@ -2309,8 +2344,9 @@ typedef enum Tox_Err_File_Send_Chunk {
* @param position The file or stream position from which to continue reading.
* @return true on success.
*/
-bool tox_file_send_chunk(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position, const uint8_t *data,
- size_t length, Tox_Err_File_Send_Chunk *error);
+bool tox_file_send_chunk(
+ Tox *tox, Tox_Friend_Number friend_number, Tox_File_Number file_number, uint64_t position,
+ const uint8_t data[], size_t length, Tox_Err_File_Send_Chunk *error);
/**
* If the length parameter is 0, the file transfer is finished, and the client's
@@ -2334,9 +2370,9 @@ bool tox_file_send_chunk(Tox *tox, uint32_t friend_number, uint32_t file_number,
* @param position The file or stream position from which to continue reading.
* @param length The number of bytes requested for the current chunk.
*/
-typedef void tox_file_chunk_request_cb(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position,
- size_t length, void *user_data);
-
+typedef void tox_file_chunk_request_cb(
+ Tox *tox, Tox_Friend_Number friend_number, Tox_File_Number file_number, uint64_t position,
+ size_t length, void *user_data);
/**
* @brief Set the callback for the `file_chunk_request` event.
@@ -2349,7 +2385,6 @@ void tox_callback_file_chunk_request(Tox *tox, tox_file_chunk_request_cb *callba
/** @} */
-
/** @{
* @name File transmission: receiving
*/
@@ -2372,9 +2407,9 @@ void tox_callback_file_chunk_request(Tox *tox, tox_file_chunk_request_cb *callba
* name will be sent along with the file send request.
* @param filename_length Size in bytes of the filename.
*/
-typedef void tox_file_recv_cb(Tox *tox, uint32_t friend_number, uint32_t file_number, uint32_t kind, uint64_t file_size,
- const uint8_t *filename, size_t filename_length, void *user_data);
-
+typedef void tox_file_recv_cb(
+ Tox *tox, Tox_Friend_Number friend_number, Tox_File_Number file_number, uint32_t kind, uint64_t file_size,
+ const uint8_t filename[], size_t filename_length, void *user_data);
/**
* @brief Set the callback for the `file_recv` event.
@@ -2401,9 +2436,9 @@ void tox_callback_file_recv(Tox *tox, tox_file_recv_cb *callback);
* @param data A byte array containing the received chunk.
* @param length The length of the received chunk.
*/
-typedef void tox_file_recv_chunk_cb(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position,
- const uint8_t *data, size_t length, void *user_data);
-
+typedef void tox_file_recv_chunk_cb(
+ Tox *tox, Tox_Friend_Number friend_number, Tox_File_Number file_number, uint64_t position,
+ const uint8_t data[], size_t length, void *user_data);
/**
* @brief Set the callback for the `file_recv_chunk` event.
@@ -2417,11 +2452,13 @@ void tox_callback_file_recv_chunk(Tox *tox, tox_file_recv_chunk_cb *callback);
/** @} */
-
/** @{
* @name Conference management
*/
+typedef uint32_t Tox_Conference_Number;
+typedef uint32_t Tox_Conference_Peer_Number;
+
/**
* @brief Conference types for the conference_invite event.
*/
@@ -2439,6 +2476,7 @@ 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
@@ -2450,9 +2488,9 @@ typedef enum Tox_Conference_Type {
* conference.
* @param length The length of the cookie.
*/
-typedef void tox_conference_invite_cb(Tox *tox, uint32_t friend_number, Tox_Conference_Type type, const uint8_t *cookie,
- size_t length, void *user_data);
-
+typedef void tox_conference_invite_cb(
+ Tox *tox, Tox_Friend_Number friend_number, Tox_Conference_Type type,
+ const uint8_t cookie[], size_t length, void *user_data);
/**
* @brief Set the callback for the `conference_invite` event.
@@ -2466,8 +2504,7 @@ void tox_callback_conference_invite(Tox *tox, tox_conference_invite_cb *callback
/**
* @param conference_number The conference number of the conference to which we have connected.
*/
-typedef void tox_conference_connected_cb(Tox *tox, uint32_t conference_number, void *user_data);
-
+typedef void tox_conference_connected_cb(Tox *tox, Tox_Conference_Number conference_number, void *user_data);
/**
* @brief Set the callback for the `conference_connected` event.
@@ -2487,9 +2524,9 @@ void tox_callback_conference_connected(Tox *tox, tox_conference_connected_cb *ca
* @param message The message data.
* @param length The length of the message.
*/
-typedef void tox_conference_message_cb(Tox *tox, uint32_t conference_number, uint32_t peer_number,
- Tox_Message_Type type, const uint8_t *message, size_t length, void *user_data);
-
+typedef void tox_conference_message_cb(
+ Tox *tox, Tox_Conference_Number conference_number, Tox_Conference_Peer_Number peer_number,
+ Tox_Message_Type type, const uint8_t message[], size_t length, void *user_data);
/**
* @brief Set the callback for the `conference_message` event.
@@ -2507,9 +2544,9 @@ void tox_callback_conference_message(Tox *tox, tox_conference_message_cb *callba
* @param title The title data.
* @param length The title length.
*/
-typedef void tox_conference_title_cb(Tox *tox, uint32_t conference_number, uint32_t peer_number, const uint8_t *title,
- size_t length, void *user_data);
-
+typedef void tox_conference_title_cb(
+ Tox *tox, Tox_Conference_Number conference_number, Tox_Conference_Peer_Number peer_number,
+ const uint8_t title[], size_t length, void *user_data);
/**
* @brief Set the callback for the `conference_title` event.
@@ -2529,9 +2566,9 @@ void tox_callback_conference_title(Tox *tox, tox_conference_title_cb *callback);
* @param name A byte array containing the new nickname.
* @param length The size of the name byte array.
*/
-typedef void tox_conference_peer_name_cb(Tox *tox, uint32_t conference_number, uint32_t peer_number,
- const uint8_t *name, size_t length, void *user_data);
-
+typedef void tox_conference_peer_name_cb(
+ Tox *tox, Tox_Conference_Number conference_number, Tox_Conference_Peer_Number peer_number,
+ const uint8_t name[], size_t length, void *user_data);
/**
* @brief Set the callback for the `conference_peer_name` event.
@@ -2546,8 +2583,7 @@ void tox_callback_conference_peer_name(Tox *tox, tox_conference_peer_name_cb *ca
* @param conference_number The conference number of the conference the
* peer is in.
*/
-typedef void tox_conference_peer_list_changed_cb(Tox *tox, uint32_t conference_number, void *user_data);
-
+typedef void tox_conference_peer_list_changed_cb(Tox *tox, Tox_Conference_Number conference_number, void *user_data);
/**
* @brief Set the callback for the `conference_peer_list_changed` event.
@@ -2572,6 +2608,7 @@ 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.
@@ -2582,7 +2619,7 @@ typedef enum Tox_Err_Conference_New {
* - conference number on success
* - an unspecified value on failure
*/
-uint32_t tox_conference_new(Tox *tox, Tox_Err_Conference_New *error);
+Tox_Conference_Number tox_conference_new(Tox *tox, Tox_Err_Conference_New *error);
typedef enum Tox_Err_Conference_Delete {
@@ -2598,6 +2635,7 @@ 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.
@@ -2606,7 +2644,7 @@ typedef enum Tox_Err_Conference_Delete {
*
* @return true on success.
*/
-bool tox_conference_delete(Tox *tox, uint32_t conference_number, Tox_Err_Conference_Delete *error);
+bool tox_conference_delete(Tox *tox, Tox_Conference_Number conference_number, Tox_Err_Conference_Delete *error);
/**
* @brief Error codes for peer info queries.
@@ -2635,6 +2673,7 @@ 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.
@@ -2643,15 +2682,17 @@ typedef enum Tox_Err_Conference_Peer_Query {
* peer_number for the functions querying these peers. Return value is
* unspecified on failure.
*/
-uint32_t tox_conference_peer_count(const Tox *tox, uint32_t conference_number, Tox_Err_Conference_Peer_Query *error);
+Tox_Conference_Peer_Number tox_conference_peer_count(
+ const Tox *tox, Tox_Conference_Number conference_number, Tox_Err_Conference_Peer_Query *error);
/**
* @brief Return the length of the peer's name.
*
* Return value is unspecified on failure.
*/
-size_t tox_conference_peer_get_name_size(const Tox *tox, uint32_t conference_number, uint32_t peer_number,
- Tox_Err_Conference_Peer_Query *error);
+size_t tox_conference_peer_get_name_size(
+ const Tox *tox, Tox_Conference_Number conference_number, Tox_Conference_Peer_Number peer_number,
+ Tox_Err_Conference_Peer_Query *error);
/**
* @brief Copy the name of peer_number who is in conference_number to name.
@@ -2662,8 +2703,9 @@ size_t tox_conference_peer_get_name_size(const Tox *tox, uint32_t conference_num
*
* @return true on success.
*/
-bool tox_conference_peer_get_name(const Tox *tox, uint32_t conference_number, uint32_t peer_number, uint8_t *name,
- Tox_Err_Conference_Peer_Query *error);
+bool tox_conference_peer_get_name(
+ const Tox *tox, Tox_Conference_Number conference_number, Tox_Conference_Peer_Number peer_number,
+ uint8_t name[], Tox_Err_Conference_Peer_Query *error);
/**
* @brief Copy the public key of peer_number who is in conference_number to public_key.
@@ -2672,14 +2714,16 @@ bool tox_conference_peer_get_name(const Tox *tox, uint32_t conference_number, ui
*
* @return true on success.
*/
-bool tox_conference_peer_get_public_key(const Tox *tox, uint32_t conference_number, uint32_t peer_number,
- uint8_t *public_key, Tox_Err_Conference_Peer_Query *error);
+bool tox_conference_peer_get_public_key(
+ const Tox *tox, Tox_Conference_Number conference_number, Tox_Conference_Peer_Number peer_number,
+ uint8_t public_key[TOX_PUBLIC_KEY_SIZE], Tox_Err_Conference_Peer_Query *error);
/**
* @brief Return true if passed peer_number corresponds to our own.
*/
-bool tox_conference_peer_number_is_ours(const Tox *tox, uint32_t conference_number, uint32_t peer_number,
- Tox_Err_Conference_Peer_Query *error);
+bool tox_conference_peer_number_is_ours(
+ const Tox *tox, Tox_Conference_Number conference_number, Tox_Conference_Peer_Number peer_number,
+ Tox_Err_Conference_Peer_Query *error);
/**
* @brief Return the number of offline peers in the conference.
@@ -2689,16 +2733,18 @@ bool tox_conference_peer_number_is_ours(const Tox *tox, uint32_t conference_numb
*
* Return value is unspecified on failure.
*/
-uint32_t tox_conference_offline_peer_count(const Tox *tox, uint32_t conference_number,
- Tox_Err_Conference_Peer_Query *error);
+uint32_t tox_conference_offline_peer_count(
+ const Tox *tox, Tox_Conference_Number conference_number,
+ Tox_Err_Conference_Peer_Query *error);
/**
* @brief Return the length of the offline peer's name.
*
* Return value is unspecified on failure.
*/
-size_t tox_conference_offline_peer_get_name_size(const Tox *tox, uint32_t conference_number,
- uint32_t offline_peer_number, Tox_Err_Conference_Peer_Query *error);
+size_t tox_conference_offline_peer_get_name_size(
+ const Tox *tox, Tox_Conference_Number conference_number,
+ Tox_Conference_Peer_Number offline_peer_number, Tox_Err_Conference_Peer_Query *error);
/**
* @brief Copy the name of offline_peer_number who is in conference_number to name.
@@ -2710,8 +2756,9 @@ size_t tox_conference_offline_peer_get_name_size(const Tox *tox, uint32_t confer
*
* @return true on success.
*/
-bool tox_conference_offline_peer_get_name(const Tox *tox, uint32_t conference_number, uint32_t offline_peer_number,
- uint8_t *name, Tox_Err_Conference_Peer_Query *error);
+bool tox_conference_offline_peer_get_name(
+ const Tox *tox, Tox_Conference_Number conference_number, Tox_Conference_Peer_Number offline_peer_number,
+ uint8_t name[], Tox_Err_Conference_Peer_Query *error);
/**
* @brief Copy the public key of offline_peer_number who is in conference_number to public_key.
@@ -2720,14 +2767,16 @@ bool tox_conference_offline_peer_get_name(const Tox *tox, uint32_t conference_nu
*
* @return true on success.
*/
-bool tox_conference_offline_peer_get_public_key(const Tox *tox, uint32_t conference_number,
- uint32_t offline_peer_number, uint8_t *public_key, Tox_Err_Conference_Peer_Query *error);
+bool tox_conference_offline_peer_get_public_key(
+ const Tox *tox, Tox_Conference_Number conference_number,
+ Tox_Conference_Peer_Number offline_peer_number, uint8_t public_key[TOX_PUBLIC_KEY_SIZE], Tox_Err_Conference_Peer_Query *error);
/**
* @brief Return a unix-time timestamp of the last time offline_peer_number was seen to be active.
*/
-uint64_t tox_conference_offline_peer_get_last_active(const Tox *tox, uint32_t conference_number,
- uint32_t offline_peer_number, Tox_Err_Conference_Peer_Query *error);
+uint64_t tox_conference_offline_peer_get_last_active(
+ const Tox *tox, Tox_Conference_Number conference_number,
+ Tox_Conference_Peer_Number offline_peer_number, Tox_Err_Conference_Peer_Query *error);
typedef enum Tox_Err_Conference_Set_Max_Offline {
@@ -2743,12 +2792,14 @@ 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.
*/
-bool tox_conference_set_max_offline(Tox *tox, uint32_t conference_number, uint32_t max_offline_peers,
- Tox_Err_Conference_Set_Max_Offline *error);
+bool tox_conference_set_max_offline(
+ Tox *tox, Tox_Conference_Number conference_number, uint32_t max_offline,
+ Tox_Err_Conference_Set_Max_Offline *error);
typedef enum Tox_Err_Conference_Invite {
@@ -2774,6 +2825,7 @@ 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.
@@ -2783,8 +2835,9 @@ typedef enum Tox_Err_Conference_Invite {
*
* @return true on success.
*/
-bool tox_conference_invite(Tox *tox, uint32_t friend_number, uint32_t conference_number,
- Tox_Err_Conference_Invite *error);
+bool tox_conference_invite(
+ Tox *tox, Tox_Friend_Number friend_number, Tox_Conference_Number conference_number,
+ Tox_Err_Conference_Invite *error);
typedef enum Tox_Err_Conference_Join {
@@ -2825,6 +2878,7 @@ 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.
@@ -2843,8 +2897,10 @@ typedef enum Tox_Err_Conference_Join {
*
* @return conference number on success, an unspecified value on failure.
*/
-uint32_t tox_conference_join(Tox *tox, uint32_t friend_number, const uint8_t *cookie, size_t length,
- Tox_Err_Conference_Join *error);
+Tox_Conference_Number tox_conference_join(
+ Tox *tox, Tox_Friend_Number friend_number,
+ const uint8_t cookie[], size_t length,
+ Tox_Err_Conference_Join *error);
typedef enum Tox_Err_Conference_Send_Message {
@@ -2875,6 +2931,7 @@ 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.
@@ -2895,8 +2952,10 @@ typedef enum Tox_Err_Conference_Send_Message {
*
* @return true on success.
*/
-bool tox_conference_send_message(Tox *tox, uint32_t conference_number, Tox_Message_Type type, const uint8_t *message,
- size_t length, Tox_Err_Conference_Send_Message *error);
+bool tox_conference_send_message(
+ Tox *tox, Tox_Conference_Number conference_number, Tox_Message_Type type,
+ const uint8_t message[], size_t length,
+ Tox_Err_Conference_Send_Message *error);
typedef enum Tox_Err_Conference_Title {
@@ -2922,6 +2981,7 @@ 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.
@@ -2931,7 +2991,8 @@ typedef enum Tox_Err_Conference_Title {
* The return value is equal to the `length` argument received by the last
* `conference_title` callback.
*/
-size_t tox_conference_get_title_size(const Tox *tox, uint32_t conference_number, Tox_Err_Conference_Title *error);
+size_t tox_conference_get_title_size(
+ const Tox *tox, Tox_Conference_Number conference_number, Tox_Err_Conference_Title *error);
/**
* @brief Write the title designated by the given conference number to a byte array.
@@ -2946,8 +3007,10 @@ size_t tox_conference_get_title_size(const Tox *tox, uint32_t conference_number,
*
* @return true on success.
*/
-bool tox_conference_get_title(const Tox *tox, uint32_t conference_number, uint8_t *title,
- Tox_Err_Conference_Title *error);
+bool tox_conference_get_title(
+ const Tox *tox, Tox_Conference_Number conference_number,
+ uint8_t title[],
+ Tox_Err_Conference_Title *error);
/**
* @brief Set the conference title and broadcast it to the rest of the conference.
@@ -2956,8 +3019,10 @@ bool tox_conference_get_title(const Tox *tox, uint32_t conference_number, uint8_
*
* @return true on success.
*/
-bool tox_conference_set_title(Tox *tox, uint32_t conference_number, const uint8_t *title, size_t length,
- Tox_Err_Conference_Title *error);
+bool tox_conference_set_title(
+ Tox *tox, Tox_Conference_Number conference_number,
+ const uint8_t title[], size_t length,
+ Tox_Err_Conference_Title *error);
/**
* @brief Return the number of conferences in the Tox instance.
@@ -2980,7 +3045,7 @@ size_t tox_conference_get_chatlist_size(const Tox *tox);
* The conference number of a loaded conference may differ from the conference
* number it had when it was saved.
*/
-void tox_conference_get_chatlist(const Tox *tox, uint32_t *chatlist);
+void tox_conference_get_chatlist(const Tox *tox, Tox_Conference_Number chatlist[]);
/**
* @brief Returns the type of conference (Tox_Conference_Type) that conference_number is.
@@ -3001,12 +3066,14 @@ 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.
*/
-Tox_Conference_Type tox_conference_get_type(const Tox *tox, uint32_t conference_number,
- Tox_Err_Conference_Get_Type *error);
+Tox_Conference_Type tox_conference_get_type(
+ const Tox *tox, Tox_Conference_Number conference_number,
+ Tox_Err_Conference_Get_Type *error);
/**
* @brief Get the conference unique ID.
@@ -3017,7 +3084,8 @@ Tox_Conference_Type tox_conference_get_type(const Tox *tox, uint32_t conference_
*
* @return true on success.
*/
-bool tox_conference_get_id(const Tox *tox, uint32_t conference_number, uint8_t *id);
+bool tox_conference_get_id(
+ const Tox *tox, Tox_Conference_Number conference_number, uint8_t id[TOX_CONFERENCE_ID_SIZE]);
typedef enum Tox_Err_Conference_By_Id {
@@ -3038,6 +3106,7 @@ 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.
@@ -3046,7 +3115,8 @@ typedef enum Tox_Err_Conference_By_Id {
*
* @return the conference number on success, an unspecified value on failure.
*/
-uint32_t tox_conference_by_id(const Tox *tox, const uint8_t *id, Tox_Err_Conference_By_Id *error);
+Tox_Conference_Number tox_conference_by_id(
+ const Tox *tox, const uint8_t id[TOX_CONFERENCE_ID_SIZE], Tox_Err_Conference_By_Id *error);
/**
* @brief Get the conference unique ID.
@@ -3058,7 +3128,8 @@ uint32_t tox_conference_by_id(const Tox *tox, const uint8_t *id, Tox_Err_Confere
* @return true on success.
* @deprecated use tox_conference_get_id instead (exactly the same function, just renamed).
*/
-bool tox_conference_get_uid(const Tox *tox, uint32_t conference_number, uint8_t *uid);
+bool tox_conference_get_uid(
+ const Tox *tox, Tox_Conference_Number conference_number, uint8_t uid[TOX_CONFERENCE_UID_SIZE]);
typedef enum Tox_Err_Conference_By_Uid {
@@ -3079,6 +3150,7 @@ 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.
@@ -3088,11 +3160,11 @@ typedef enum Tox_Err_Conference_By_Uid {
* @return the conference number on success, an unspecified value on failure.
* @deprecated use tox_conference_by_id instead (exactly the same function, just renamed).
*/
-uint32_t tox_conference_by_uid(const Tox *tox, const uint8_t *uid, Tox_Err_Conference_By_Uid *error);
+Tox_Conference_Number tox_conference_by_uid(
+ const Tox *tox, const uint8_t uid[TOX_CONFERENCE_UID_SIZE], Tox_Err_Conference_By_Uid *error);
/** @} */
-
/** @{
* @name Low-level custom packet sending and receiving
*/
@@ -3142,6 +3214,7 @@ 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.
@@ -3163,8 +3236,10 @@ typedef enum Tox_Err_Friend_Custom_Packet {
*
* @return true on success.
*/
-bool tox_friend_send_lossy_packet(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length,
- Tox_Err_Friend_Custom_Packet *error);
+bool tox_friend_send_lossy_packet(
+ Tox *tox, Tox_Friend_Number friend_number,
+ const uint8_t data[], size_t length,
+ Tox_Err_Friend_Custom_Packet *error);
/**
* @brief Send a custom lossless packet to a friend.
@@ -3182,17 +3257,20 @@ bool tox_friend_send_lossy_packet(Tox *tox, uint32_t friend_number, const uint8_
*
* @return true on success.
*/
-bool tox_friend_send_lossless_packet(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length,
- Tox_Err_Friend_Custom_Packet *error);
+bool tox_friend_send_lossless_packet(
+ Tox *tox, Tox_Friend_Number friend_number,
+ const uint8_t data[], size_t length,
+ Tox_Err_Friend_Custom_Packet *error);
/**
* @param friend_number The friend number of the friend who sent a lossy packet.
* @param data A byte array containing the received packet data.
* @param length The length of the packet data byte array.
*/
-typedef void tox_friend_lossy_packet_cb(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length,
- void *user_data);
-
+typedef void tox_friend_lossy_packet_cb(
+ Tox *tox, Tox_Friend_Number friend_number,
+ const uint8_t data[], size_t length,
+ void *user_data);
/**
* @brief Set the callback for the `friend_lossy_packet` event.
@@ -3206,9 +3284,10 @@ void tox_callback_friend_lossy_packet(Tox *tox, tox_friend_lossy_packet_cb *call
* @param data A byte array containing the received packet data.
* @param length The length of the packet data byte array.
*/
-typedef void tox_friend_lossless_packet_cb(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length,
- void *user_data);
-
+typedef void tox_friend_lossless_packet_cb(
+ Tox *tox, Tox_Friend_Number friend_number,
+ const uint8_t data[], size_t length,
+ void *user_data);
/**
* @brief Set the callback for the `friend_lossless_packet` event.
@@ -3219,7 +3298,6 @@ void tox_callback_friend_lossless_packet(Tox *tox, tox_friend_lossless_packet_cb
/** @} */
-
/** @{
* @name Low-level network information
*/
@@ -3238,6 +3316,7 @@ 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.
@@ -3251,7 +3330,7 @@ typedef enum Tox_Err_Get_Port {
* @param dht_id A memory region of at least TOX_PUBLIC_KEY_SIZE bytes. If this
* parameter is NULL, this function has no effect.
*/
-void tox_self_get_dht_id(const Tox *tox, uint8_t *dht_id);
+void tox_self_get_dht_id(const Tox *tox, uint8_t dht_id[TOX_PUBLIC_KEY_SIZE]);
/**
* @brief Return the UDP port this Tox instance is bound to.
@@ -3267,14 +3346,13 @@ uint16_t tox_self_get_tcp_port(const Tox *tox, Tox_Err_Get_Port *error);
/** @} */
-/*******************************************************************************
- *
- * :: Group chats
- *
- ******************************************************************************/
-
-
+/** @{
+ * @name Group chats
+ */
+typedef uint32_t Tox_Group_Number;
+typedef uint32_t Tox_Group_Peer_Number;
+typedef uint32_t Tox_Group_Message_Id;
/*******************************************************************************
*
@@ -3282,9 +3360,7 @@ uint16_t tox_self_get_tcp_port(const Tox *tox, Tox_Err_Get_Port *error);
*
******************************************************************************/
-
-
-/** @{
+/**
* Maximum length of a group topic.
*/
#define TOX_GROUP_MAX_TOPIC_LENGTH 512
@@ -3308,7 +3384,7 @@ uint32_t tox_group_max_message_length(void);
/**
* Maximum length of a group custom lossy packet.
*/
-#define TOX_GROUP_MAX_CUSTOM_LOSSY_PACKET_LENGTH 500
+#define TOX_GROUP_MAX_CUSTOM_LOSSY_PACKET_LENGTH 1373
uint32_t tox_group_max_custom_lossy_packet_length(void);
@@ -3347,15 +3423,12 @@ uint32_t tox_group_chat_id_size(void);
uint32_t tox_group_peer_public_key_size(void);
-
/*******************************************************************************
*
* :: Group chat state enumerators
*
******************************************************************************/
-
-
/**
* Represents the group privacy state.
*/
@@ -3383,6 +3456,7 @@ 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.
@@ -3401,6 +3475,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.
@@ -3422,6 +3498,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.
*
@@ -3454,7 +3532,7 @@ typedef enum Tox_Group_Role {
} Tox_Group_Role;
-
+const char *tox_group_role_to_string(Tox_Group_Role value);
/*******************************************************************************
*
@@ -3462,8 +3540,6 @@ typedef enum Tox_Group_Role {
*
******************************************************************************/
-
-
typedef enum Tox_Err_Group_New {
/**
@@ -3499,6 +3575,7 @@ 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.
@@ -3522,8 +3599,10 @@ typedef enum Tox_Err_Group_New {
*
* @return group_number on success, UINT32_MAX on failure.
*/
-uint32_t tox_group_new(Tox *tox, Tox_Group_Privacy_State privacy_state, const uint8_t *group_name,
- size_t group_name_length, const uint8_t *name, size_t name_length, Tox_Err_Group_New *error);
+Tox_Group_Number tox_group_new(
+ Tox *tox, Tox_Group_Privacy_State privacy_state,
+ const uint8_t group_name[], size_t group_name_length,
+ const uint8_t name[], size_t name_length, Tox_Err_Group_New *error);
typedef enum Tox_Err_Group_Join {
@@ -3565,6 +3644,7 @@ 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.
@@ -3583,8 +3663,11 @@ typedef enum Tox_Err_Group_Join {
*
* @return group_number on success, UINT32_MAX on failure.
*/
-uint32_t tox_group_join(Tox *tox, const uint8_t *chat_id, const uint8_t *name, size_t name_length,
- const uint8_t *password, size_t password_length, Tox_Err_Group_Join *error);
+Tox_Group_Number tox_group_join(
+ Tox *tox, const uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE],
+ const uint8_t name[], size_t name_length,
+ const uint8_t password[], size_t password_length,
+ Tox_Err_Group_Join *error);
typedef enum Tox_Err_Group_Is_Connected {
@@ -3600,6 +3683,7 @@ 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
@@ -3607,7 +3691,7 @@ typedef enum Tox_Err_Group_Is_Connected {
*
* @param group_number The group number of the designated group.
*/
-bool tox_group_is_connected(const Tox *tox, uint32_t group_number, Tox_Err_Group_Is_Connected *error);
+bool tox_group_is_connected(const Tox *tox, Tox_Group_Number group_number, Tox_Err_Group_Is_Connected *error);
typedef enum Tox_Err_Group_Disconnect {
@@ -3627,6 +3711,7 @@ 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.
@@ -3635,7 +3720,7 @@ typedef enum Tox_Err_Group_Disconnect {
*
* @param group_number The group number of the designated group.
*/
-bool tox_group_disconnect(const Tox *tox, uint32_t group_number, Tox_Err_Group_Disconnect *error);
+bool tox_group_disconnect(const Tox *tox, Tox_Group_Number group_number, Tox_Err_Group_Disconnect *error);
typedef enum Tox_Err_Group_Reconnect {
@@ -3656,6 +3741,7 @@ 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.
@@ -3667,7 +3753,7 @@ typedef enum Tox_Err_Group_Reconnect {
*
* @return true on success.
*/
-bool tox_group_reconnect(Tox *tox, uint32_t group_number, Tox_Err_Group_Reconnect *error);
+bool tox_group_reconnect(Tox *tox, Tox_Group_Number group_number, Tox_Err_Group_Reconnect *error);
typedef enum Tox_Err_Group_Leave {
@@ -3692,6 +3778,7 @@ 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.
@@ -3707,9 +3794,10 @@ typedef enum Tox_Err_Group_Leave {
*
* @return true if the group chat instance is successfully deleted.
*/
-bool tox_group_leave(Tox *tox, uint32_t group_number, const uint8_t *part_message, size_t length,
- Tox_Err_Group_Leave *error);
-
+bool tox_group_leave(
+ Tox *tox, Tox_Group_Number group_number,
+ const uint8_t part_message[], size_t length,
+ Tox_Err_Group_Leave *error);
/*******************************************************************************
*
@@ -3717,8 +3805,6 @@ bool tox_group_leave(Tox *tox, uint32_t group_number, const uint8_t *part_messag
*
******************************************************************************/
-
-
/**
* General error codes for self state get and size functions.
*/
@@ -3736,6 +3822,7 @@ 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.
@@ -3769,6 +3856,7 @@ 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.
@@ -3781,8 +3869,10 @@ typedef enum Tox_Err_Group_Self_Name_Set {
*
* @return true on success.
*/
-bool tox_group_self_set_name(const Tox *tox, uint32_t group_number, const uint8_t *name, size_t length,
- Tox_Err_Group_Self_Name_Set *error);
+bool tox_group_self_set_name(
+ Tox *tox, Tox_Group_Number group_number,
+ const uint8_t name[], size_t length,
+ Tox_Err_Group_Self_Name_Set *error);
/**
* Return the length of the client's current nickname for the group instance designated
@@ -3793,7 +3883,7 @@ bool tox_group_self_set_name(const Tox *tox, uint32_t group_number, const uint8_
*
* @see threading for concurrency implications.
*/
-size_t tox_group_self_get_name_size(const Tox *tox, uint32_t group_number, Tox_Err_Group_Self_Query *error);
+size_t tox_group_self_get_name_size(const Tox *tox, Tox_Group_Number group_number, Tox_Err_Group_Self_Query *error);
/**
* Write the nickname set by tox_group_self_set_name to a byte array.
@@ -3808,7 +3898,9 @@ size_t tox_group_self_get_name_size(const Tox *tox, uint32_t group_number, Tox_E
*
* @return true on success.
*/
-bool tox_group_self_get_name(const Tox *tox, uint32_t group_number, uint8_t *name, Tox_Err_Group_Self_Query *error);
+bool tox_group_self_get_name(
+ const Tox *tox, Tox_Group_Number group_number,
+ uint8_t name[], Tox_Err_Group_Self_Query *error);
/**
* Error codes for self status setting.
@@ -3832,32 +3924,33 @@ 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.
*
* @return true on success.
*/
-bool tox_group_self_set_status(const Tox *tox, uint32_t group_number, Tox_User_Status status,
+bool tox_group_self_set_status(Tox *tox, Tox_Group_Number group_number, Tox_User_Status status,
Tox_Err_Group_Self_Status_Set *error);
/**
* returns the client's status for the group instance on success.
* return value is unspecified on failure.
*/
-Tox_User_Status tox_group_self_get_status(const Tox *tox, uint32_t group_number, Tox_Err_Group_Self_Query *error);
+Tox_User_Status tox_group_self_get_status(const Tox *tox, Tox_Group_Number group_number, Tox_Err_Group_Self_Query *error);
/**
* returns the client's role for the group instance on success.
* return value is unspecified on failure.
*/
-Tox_Group_Role tox_group_self_get_role(const Tox *tox, uint32_t group_number, Tox_Err_Group_Self_Query *error);
+Tox_Group_Role tox_group_self_get_role(const Tox *tox, Tox_Group_Number group_number, Tox_Err_Group_Self_Query *error);
/**
* returns the client's peer id for the group instance on success.
* return value is unspecified on failure.
*/
-uint32_t tox_group_self_get_peer_id(const Tox *tox, uint32_t group_number, Tox_Err_Group_Self_Query *error);
+Tox_Group_Peer_Number tox_group_self_get_peer_id(const Tox *tox, Tox_Group_Number group_number, Tox_Err_Group_Self_Query *error);
/**
* Write the client's group public key designated by the given group number to a byte array.
@@ -3873,18 +3966,15 @@ uint32_t tox_group_self_get_peer_id(const Tox *tox, uint32_t group_number, Tox_E
*
* @return true on success.
*/
-bool tox_group_self_get_public_key(const Tox *tox, uint32_t group_number, uint8_t *public_key,
+bool tox_group_self_get_public_key(const Tox *tox, Tox_Group_Number group_number, uint8_t public_key[TOX_PUBLIC_KEY_SIZE],
Tox_Err_Group_Self_Query *error);
-
/*******************************************************************************
*
* :: Peer-specific group state queries.
*
******************************************************************************/
-
-
/**
* Error codes for peer info queries.
*/
@@ -3907,6 +3997,7 @@ 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
@@ -3918,7 +4009,7 @@ typedef enum Tox_Err_Group_Peer_Query {
* The return value is equal to the `length` argument received by the last
* `group_peer_name` callback.
*/
-size_t tox_group_peer_get_name_size(const Tox *tox, uint32_t group_number, uint32_t peer_id,
+size_t tox_group_peer_get_name_size(const Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id,
Tox_Err_Group_Peer_Query *error);
/**
@@ -3936,8 +4027,9 @@ size_t tox_group_peer_get_name_size(const Tox *tox, uint32_t group_number, uint3
*
* @return true on success.
*/
-bool tox_group_peer_get_name(const Tox *tox, uint32_t group_number, uint32_t peer_id, uint8_t *name,
- Tox_Err_Group_Peer_Query *error);
+bool tox_group_peer_get_name(
+ const Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id,
+ uint8_t name[], Tox_Err_Group_Peer_Query *error);
/**
* Return the peer's user status (away/busy/...). If the ID or group number is
@@ -3949,7 +4041,7 @@ bool tox_group_peer_get_name(const Tox *tox, uint32_t group_number, uint32_t pee
* The status returned is equal to the last status received through the
* `group_peer_status` callback.
*/
-Tox_User_Status tox_group_peer_get_status(const Tox *tox, uint32_t group_number, uint32_t peer_id,
+Tox_User_Status tox_group_peer_get_status(const Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id,
Tox_Err_Group_Peer_Query *error);
/**
@@ -3962,18 +4054,19 @@ Tox_User_Status tox_group_peer_get_status(const Tox *tox, uint32_t group_number,
* The role returned is equal to the last role received through the
* `group_moderation` callback.
*/
-Tox_Group_Role tox_group_peer_get_role(const Tox *tox, uint32_t group_number, uint32_t peer_id,
+Tox_Group_Role tox_group_peer_get_role(const Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id,
Tox_Err_Group_Peer_Query *error);
/**
* Return the type of connection we have established with a peer.
*
- * This function will return an error if called on ourselves.
+ * If `peer_id` designates ourself, the return value indicates whether we're capable
+ * of making UDP connections with other peers, or are limited to TCP connections.
*
* @param group_number The group number of the group we wish to query.
* @param peer_id The ID of the peer whose connection status we wish to query.
*/
-Tox_Connection tox_group_peer_get_connection_status(const Tox *tox, uint32_t group_number, uint32_t peer_id,
+Tox_Connection tox_group_peer_get_connection_status(const Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id,
Tox_Err_Group_Peer_Query *error);
/**
@@ -3992,8 +4085,9 @@ Tox_Connection tox_group_peer_get_connection_status(const Tox *tox, uint32_t gro
*
* @return true on success.
*/
-bool tox_group_peer_get_public_key(const Tox *tox, uint32_t group_number, uint32_t peer_id, uint8_t *public_key,
- Tox_Err_Group_Peer_Query *error);
+bool tox_group_peer_get_public_key(
+ const Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id,
+ uint8_t public_key[TOX_PUBLIC_KEY_SIZE], Tox_Err_Group_Peer_Query *error);
/**
* @param group_number The group number of the group the name change is intended for.
@@ -4001,9 +4095,9 @@ bool tox_group_peer_get_public_key(const Tox *tox, uint32_t group_number, uint32
* @param name The name data.
* @param length The length of the name.
*/
-typedef void tox_group_peer_name_cb(Tox *tox, uint32_t group_number, uint32_t peer_id, const uint8_t *name,
- size_t length, void *user_data);
-
+typedef void tox_group_peer_name_cb(
+ Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id,
+ const uint8_t name[], size_t length, void *user_data);
/**
* Set the callback for the `group_peer_name` event. Pass NULL to unset.
@@ -4017,10 +4111,9 @@ void tox_callback_group_peer_name(Tox *tox, tox_group_peer_name_cb *callback);
* @param peer_id The ID of the peer who has changed their status.
* @param status The new status of the peer.
*/
-typedef void tox_group_peer_status_cb(Tox *tox, uint32_t group_number, uint32_t peer_id, Tox_User_Status status,
+typedef void tox_group_peer_status_cb(Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id, Tox_User_Status status,
void *user_data);
-
/**
* Set the callback for the `group_peer_status` event. Pass NULL to unset.
*
@@ -4028,15 +4121,12 @@ typedef void tox_group_peer_status_cb(Tox *tox, uint32_t group_number, uint32_t
*/
void tox_callback_group_peer_status(Tox *tox, tox_group_peer_status_cb *callback);
-
/*******************************************************************************
*
* :: Group chat state queries and events.
*
******************************************************************************/
-
-
/**
* General error codes for group state get and size functions.
*/
@@ -4054,6 +4144,7 @@ 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 +4188,7 @@ 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.
@@ -4106,8 +4198,10 @@ typedef enum Tox_Err_Group_Topic_Set {
*
* @return true on success.
*/
-bool tox_group_set_topic(const Tox *tox, uint32_t group_number, const uint8_t *topic, size_t length,
- Tox_Err_Group_Topic_Set *error);
+bool tox_group_set_topic(
+ Tox *tox, Tox_Group_Number group_number,
+ const uint8_t topic[], size_t length,
+ Tox_Err_Group_Topic_Set *error);
/**
* Return the length of the group topic. If the group number is invalid, the
@@ -4116,7 +4210,7 @@ bool tox_group_set_topic(const Tox *tox, uint32_t group_number, const uint8_t *t
* The return value is equal to the `length` argument received by the last
* `group_topic` callback.
*/
-size_t tox_group_get_topic_size(const Tox *tox, uint32_t group_number, Tox_Err_Group_State_Queries *error);
+size_t tox_group_get_topic_size(const Tox *tox, Tox_Group_Number group_number, Tox_Err_Group_State_Queries *error);
/**
* Write the topic designated by the given group number to a byte array.
@@ -4131,7 +4225,9 @@ size_t tox_group_get_topic_size(const Tox *tox, uint32_t group_number, Tox_Err_G
*
* @return true on success.
*/
-bool tox_group_get_topic(const Tox *tox, uint32_t group_number, uint8_t *topic, Tox_Err_Group_State_Queries *error);
+bool tox_group_get_topic(
+ const Tox *tox, Tox_Group_Number group_number,
+ uint8_t topic[], Tox_Err_Group_State_Queries *error);
/**
* @param group_number The group number of the group the topic change is intended for.
@@ -4140,9 +4236,10 @@ bool tox_group_get_topic(const Tox *tox, uint32_t group_number, uint8_t *topic,
* @param topic The topic data.
* @param length The topic length.
*/
-typedef void tox_group_topic_cb(Tox *tox, uint32_t group_number, uint32_t peer_id, const uint8_t *topic, size_t length,
- void *user_data);
-
+typedef void tox_group_topic_cb(
+ Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id,
+ const uint8_t topic[], size_t length,
+ void *user_data);
/**
* Set the callback for the `group_topic` event. Pass NULL to unset.
@@ -4155,19 +4252,21 @@ void tox_callback_group_topic(Tox *tox, tox_group_topic_cb *callback);
* Return the length of the group name. If the group number is invalid, the
* return value is unspecified.
*/
-size_t tox_group_get_name_size(const Tox *tox, uint32_t group_number, Tox_Err_Group_State_Queries *error);
+size_t tox_group_get_name_size(const Tox *tox, Tox_Group_Number group_number, Tox_Err_Group_State_Queries *error);
/**
* Write the name of the group designated by the given group number to a byte array.
*
* Call tox_group_get_name_size to determine the allocation size for the `name` parameter.
*
- * @param group_name A valid memory region large enough to store the group name.
+ * @param name A valid memory region large enough to store the group name.
* If this parameter is NULL, this function call has no effect.
*
* @return true on success.
*/
-bool tox_group_get_name(const Tox *tox, uint32_t group_number, uint8_t *group_name, Tox_Err_Group_State_Queries *error);
+bool tox_group_get_name(
+ const Tox *tox, Tox_Group_Number group_number,
+ uint8_t name[], Tox_Err_Group_State_Queries *error);
/**
* Write the Chat ID designated by the given group number to a byte array.
@@ -4179,7 +4278,9 @@ bool tox_group_get_name(const Tox *tox, uint32_t group_number, uint8_t *group_na
*
* @return true on success.
*/
-bool tox_group_get_chat_id(const Tox *tox, uint32_t group_number, uint8_t *chat_id, Tox_Err_Group_State_Queries *error);
+bool tox_group_get_chat_id(
+ const Tox *tox, Tox_Group_Number group_number, uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE],
+ Tox_Err_Group_State_Queries *error);
/**
* Return the number of groups in the Tox chats array.
@@ -4195,17 +4296,16 @@ uint32_t tox_group_get_number_groups(const Tox *tox);
*
* @see the `Group chat founder controls` section for the respective set function.
*/
-Tox_Group_Privacy_State tox_group_get_privacy_state(const Tox *tox, uint32_t group_number,
+Tox_Group_Privacy_State tox_group_get_privacy_state(const Tox *tox, Tox_Group_Number group_number,
Tox_Err_Group_State_Queries *error);
/**
* @param group_number The group number of the group the privacy state is intended for.
* @param privacy_state The new privacy state.
*/
-typedef void tox_group_privacy_state_cb(Tox *tox, uint32_t group_number, Tox_Group_Privacy_State privacy_state,
+typedef void tox_group_privacy_state_cb(Tox *tox, Tox_Group_Number group_number, Tox_Group_Privacy_State privacy_state,
void *user_data);
-
/**
* Set the callback for the `group_privacy_state` event. Pass NULL to unset.
*
@@ -4221,17 +4321,16 @@ void tox_callback_group_privacy_state(Tox *tox, tox_group_privacy_state_cb *call
*
* @see the `Group chat founder controls` section for the respective set function.
*/
-Tox_Group_Voice_State tox_group_get_voice_state(const Tox *tox, uint32_t group_number,
+Tox_Group_Voice_State tox_group_get_voice_state(const Tox *tox, Tox_Group_Number group_number,
Tox_Err_Group_State_Queries *error);
/**
* @param group_number The group number of the group the voice state change is intended for.
* @param voice_state The new voice state.
*/
-typedef void tox_group_voice_state_cb(Tox *tox, uint32_t group_number, Tox_Group_Voice_State voice_state,
+typedef void tox_group_voice_state_cb(Tox *tox, Tox_Group_Number group_number, Tox_Group_Voice_State voice_state,
void *user_data);
-
/**
* Set the callback for the `group_privacy_state` event. Pass NULL to unset.
*
@@ -4248,16 +4347,14 @@ void tox_callback_group_voice_state(Tox *tox, tox_group_voice_state_cb *callback
*
* @see the `Group chat founder contols` section for the respective set function.
*/
-Tox_Group_Topic_Lock tox_group_get_topic_lock(const Tox *tox, uint32_t group_number,
+Tox_Group_Topic_Lock tox_group_get_topic_lock(const Tox *tox, Tox_Group_Number group_number,
Tox_Err_Group_State_Queries *error);
/**
* @param group_number The group number of the group for which the topic lock has changed.
* @param topic_lock The new topic lock state.
*/
-typedef void tox_group_topic_lock_cb(Tox *tox, uint32_t group_number, Tox_Group_Topic_Lock topic_lock, void *user_data);
-
-
+typedef void tox_group_topic_lock_cb(Tox *tox, Tox_Group_Number group_number, Tox_Group_Topic_Lock topic_lock, void *user_data);
/**
* Set the callback for the `group_topic_lock` event. Pass NULL to unset.
@@ -4275,14 +4372,13 @@ void tox_callback_group_topic_lock(Tox *tox, tox_group_topic_lock_cb *callback);
*
* @see the `Group chat founder controls` section for the respective set function.
*/
-uint16_t tox_group_get_peer_limit(const Tox *tox, uint32_t group_number, Tox_Err_Group_State_Queries *error);
+uint16_t tox_group_get_peer_limit(const Tox *tox, Tox_Group_Number group_number, Tox_Err_Group_State_Queries *error);
/**
* @param group_number The group number of the group for which the peer limit has changed.
* @param peer_limit The new peer limit for the group.
*/
-typedef void tox_group_peer_limit_cb(Tox *tox, uint32_t group_number, uint32_t peer_limit, void *user_data);
-
+typedef void tox_group_peer_limit_cb(Tox *tox, Tox_Group_Number group_number, uint32_t peer_limit, void *user_data);
/**
* Set the callback for the `group_peer_limit` event. Pass NULL to unset.
@@ -4295,7 +4391,7 @@ void tox_callback_group_peer_limit(Tox *tox, tox_group_peer_limit_cb *callback);
* Return the length of the group password. If the group number is invalid, the
* return value is unspecified.
*/
-size_t tox_group_get_password_size(const Tox *tox, uint32_t group_number, Tox_Err_Group_State_Queries *error);
+size_t tox_group_get_password_size(const Tox *tox, Tox_Group_Number group_number, Tox_Err_Group_State_Queries *error);
/**
* Write the password for the group designated by the given group number to a byte array.
@@ -4312,17 +4408,19 @@ size_t tox_group_get_password_size(const Tox *tox, uint32_t group_number, Tox_Er
*
* @return true on success.
*/
-bool tox_group_get_password(const Tox *tox, uint32_t group_number, uint8_t *password,
- Tox_Err_Group_State_Queries *error);
+bool tox_group_get_password(
+ const Tox *tox, Tox_Group_Number group_number, uint8_t password[],
+ Tox_Err_Group_State_Queries *error);
/**
* @param group_number The group number of the group for which the password has changed.
* @param password The new group password.
* @param length The length of the password.
*/
-typedef void tox_group_password_cb(Tox *tox, uint32_t group_number, const uint8_t *password, size_t length,
- void *user_data);
-
+typedef void tox_group_password_cb(
+ Tox *tox, Tox_Group_Number group_number,
+ const uint8_t password[], size_t length,
+ void *user_data);
/**
* Set the callback for the `group_password` event. Pass NULL to unset.
@@ -4331,15 +4429,12 @@ typedef void tox_group_password_cb(Tox *tox, uint32_t group_number, const uint8_
*/
void tox_callback_group_password(Tox *tox, tox_group_password_cb *callback);
-
/*******************************************************************************
*
* :: Group chat message sending
*
******************************************************************************/
-
-
typedef enum Tox_Err_Group_Send_Message {
/**
@@ -4384,6 +4479,7 @@ 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.
@@ -4400,14 +4496,14 @@ typedef enum Tox_Err_Group_Send_Message {
* @param message A non-NULL pointer to the first element of a byte array
* containing the message text.
* @param length Length of the message to be sent.
- * @param message_id A pointer to a uint32_t. The message_id of this message will be returned
- * unless the parameter is NULL, in which case the returned parameter value will be undefined.
- * If this function returns false the returned parameter `message_id` value will also be undefined.
*
- * @return true on success.
+ * @return The message_id of this message. If this function has an error, the
+ * returned message ID value will be undefined.
*/
-bool tox_group_send_message(const Tox *tox, uint32_t group_number, Tox_Message_Type type, const uint8_t *message,
- size_t length, uint32_t *message_id, Tox_Err_Group_Send_Message *error);
+Tox_Group_Message_Id tox_group_send_message(
+ const Tox *tox, Tox_Group_Number group_number, Tox_Message_Type type,
+ const uint8_t message[], size_t length,
+ Tox_Err_Group_Send_Message *error);
typedef enum Tox_Err_Group_Send_Private_Message {
@@ -4458,6 +4554,7 @@ 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.
@@ -4477,8 +4574,10 @@ typedef enum Tox_Err_Group_Send_Private_Message {
*
* @return true on success.
*/
-bool tox_group_send_private_message(const Tox *tox, uint32_t group_number, uint32_t peer_id, Tox_Message_Type type,
- const uint8_t *message, size_t length, Tox_Err_Group_Send_Private_Message *error);
+bool tox_group_send_private_message(
+ const Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id, Tox_Message_Type type,
+ const uint8_t message[], size_t length,
+ Tox_Err_Group_Send_Private_Message *error);
typedef enum Tox_Err_Group_Send_Custom_Packet {
@@ -4514,8 +4613,15 @@ typedef enum Tox_Err_Group_Send_Custom_Packet {
*/
TOX_ERR_GROUP_SEND_CUSTOM_PACKET_DISCONNECTED,
+ /**
+ * The packet did not successfully send to any peer. This often indicates
+ * a connection issue on the sender's side.
+ */
+ TOX_ERR_GROUP_SEND_CUSTOM_PACKET_FAIL_SEND,
+
} 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.
@@ -4541,10 +4647,10 @@ typedef enum Tox_Err_Group_Send_Custom_Packet {
*
* @return true on success.
*/
-bool tox_group_send_custom_packet(const Tox *tox, uint32_t group_number, bool lossless, const uint8_t *data,
- size_t length,
- Tox_Err_Group_Send_Custom_Packet *error);
-
+bool tox_group_send_custom_packet(
+ const Tox *tox, Tox_Group_Number group_number, bool lossless,
+ const uint8_t data[], size_t length,
+ Tox_Err_Group_Send_Custom_Packet *error);
typedef enum Tox_Err_Group_Send_Custom_Private_Packet {
@@ -4592,6 +4698,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.
*
@@ -4617,19 +4725,16 @@ typedef enum Tox_Err_Group_Send_Custom_Private_Packet {
*
* @return true on success.
*/
-bool tox_group_send_custom_private_packet(const Tox *tox, uint32_t group_number, uint32_t peer_id, bool lossless,
- const uint8_t *data, size_t length,
+bool tox_group_send_custom_private_packet(const Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id, bool lossless,
+ const uint8_t data[], size_t length,
Tox_Err_Group_Send_Custom_Private_Packet *error);
-
/*******************************************************************************
*
* :: Group chat message receiving
*
******************************************************************************/
-
-
/**
* @param group_number The group number of the group the message is intended for.
* @param peer_id The ID of the peer who sent the message.
@@ -4638,9 +4743,9 @@ bool tox_group_send_custom_private_packet(const Tox *tox, uint32_t group_number,
* @param message_id A pseudo message id that clients can use to uniquely identify this group message.
* @param length The length of the message.
*/
-typedef void tox_group_message_cb(Tox *tox, uint32_t group_number, uint32_t peer_id, Tox_Message_Type type,
- const uint8_t *message, size_t length, uint32_t message_id, void *user_data);
-
+typedef void tox_group_message_cb(
+ Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id, Tox_Message_Type type,
+ const uint8_t message[], size_t length, Tox_Group_Message_Id message_id, void *user_data);
/**
* Set the callback for the `group_message` event. Pass NULL to unset.
@@ -4655,9 +4760,9 @@ void tox_callback_group_message(Tox *tox, tox_group_message_cb *callback);
* @param message The message data.
* @param length The length of the message.
*/
-typedef void tox_group_private_message_cb(Tox *tox, uint32_t group_number, uint32_t peer_id, Tox_Message_Type type,
- const uint8_t *message, size_t length, void *user_data);
-
+typedef void tox_group_private_message_cb(
+ Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id, Tox_Message_Type type,
+ const uint8_t message[], size_t length, void *user_data);
/**
* Set the callback for the `group_private_message` event. Pass NULL to unset.
@@ -4672,9 +4777,9 @@ void tox_callback_group_private_message(Tox *tox, tox_group_private_message_cb *
* @param data The packet data.
* @param length The length of the data.
*/
-typedef void tox_group_custom_packet_cb(Tox *tox, uint32_t group_number, uint32_t peer_id, const uint8_t *data,
- size_t length, void *user_data);
-
+typedef void tox_group_custom_packet_cb(
+ Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id,
+ const uint8_t data[], size_t length, void *user_data);
/**
* Set the callback for the `group_custom_packet` event. Pass NULL to unset.
@@ -4689,9 +4794,9 @@ void tox_callback_group_custom_packet(Tox *tox, tox_group_custom_packet_cb *call
* @param data The packet data.
* @param length The length of the data.
*/
-typedef void tox_group_custom_private_packet_cb(Tox *tox, uint32_t group_number, uint32_t peer_id, const uint8_t *data,
- size_t length, void *user_data);
-
+typedef void tox_group_custom_private_packet_cb(
+ Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id,
+ const uint8_t data[], size_t length, void *user_data);
/**
* Set the callback for the `group_custom_private_packet` event. Pass NULL to unset.
@@ -4700,15 +4805,12 @@ typedef void tox_group_custom_private_packet_cb(Tox *tox, uint32_t group_number,
*/
void tox_callback_group_custom_private_packet(Tox *tox, tox_group_custom_private_packet_cb *callback);
-
/*******************************************************************************
*
* :: Group chat inviting and join/part events
*
******************************************************************************/
-
-
typedef enum Tox_Err_Group_Invite_Friend {
/**
@@ -4743,6 +4845,7 @@ 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.
@@ -4754,8 +4857,9 @@ typedef enum Tox_Err_Group_Invite_Friend {
*
* @return true on success.
*/
-bool tox_group_invite_friend(const Tox *tox, uint32_t group_number, uint32_t friend_number,
- Tox_Err_Group_Invite_Friend *error);
+bool tox_group_invite_friend(
+ const Tox *tox, Tox_Group_Number group_number, Tox_Friend_Number friend_number,
+ Tox_Err_Group_Invite_Friend *error);
typedef enum Tox_Err_Group_Invite_Accept {
@@ -4801,6 +4905,7 @@ 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
@@ -4817,18 +4922,23 @@ typedef enum Tox_Err_Group_Invite_Accept {
*
* @return the group_number on success, UINT32_MAX on failure.
*/
-uint32_t tox_group_invite_accept(Tox *tox, uint32_t friend_number, const uint8_t *invite_data, size_t length,
- const uint8_t *name, size_t name_length, const uint8_t *password, size_t password_length,
- Tox_Err_Group_Invite_Accept *error);
+Tox_Group_Number tox_group_invite_accept(
+ Tox *tox, Tox_Friend_Number friend_number,
+ const uint8_t invite_data[], size_t length,
+ const uint8_t name[], size_t name_length,
+ const uint8_t password[], size_t password_length,
+ Tox_Err_Group_Invite_Accept *error);
/**
* @param friend_number The friend number of the contact who sent the invite.
* @param invite_data The invite data.
* @param length The length of invite_data.
*/
-typedef void tox_group_invite_cb(Tox *tox, uint32_t friend_number, const uint8_t *invite_data, size_t length,
- const uint8_t *group_name, size_t group_name_length, void *user_data);
-
+typedef void tox_group_invite_cb(
+ Tox *tox, Tox_Friend_Number friend_number,
+ const uint8_t invite_data[], size_t length,
+ const uint8_t group_name[], size_t group_name_length,
+ void *user_data);
/**
* Set the callback for the `group_invite` event. Pass NULL to unset.
@@ -4843,8 +4953,7 @@ void tox_callback_group_invite(Tox *tox, tox_group_invite_cb *callback);
* @param peer_id The permanent ID of the new peer. This id should not be relied on for
* client behaviour and should be treated as a random value.
*/
-typedef void tox_group_peer_join_cb(Tox *tox, uint32_t group_number, uint32_t peer_id, void *user_data);
-
+typedef void tox_group_peer_join_cb(Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id, void *user_data);
/**
* Set the callback for the `group_peer_join` event. Pass NULL to unset.
@@ -4891,6 +5000,7 @@ 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.
@@ -4902,9 +5012,10 @@ typedef enum Tox_Group_Exit_Type {
* @param part_message The parting message data.
* @param part_message_length The length of the parting message.
*/
-typedef void tox_group_peer_exit_cb(Tox *tox, uint32_t group_number, uint32_t peer_id, Tox_Group_Exit_Type exit_type,
- const uint8_t *name, size_t name_length, const uint8_t *part_message, size_t part_message_length, void *user_data);
-
+typedef void tox_group_peer_exit_cb(
+ Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id, Tox_Group_Exit_Type exit_type,
+ const uint8_t name[], size_t name_length,
+ const uint8_t part_message[], size_t part_message_length, void *user_data);
/**
* Set the callback for the `group_peer_exit` event. Pass NULL to unset.
@@ -4916,8 +5027,7 @@ void tox_callback_group_peer_exit(Tox *tox, tox_group_peer_exit_cb *callback);
/**
* @param group_number The group number of the group that the client has joined.
*/
-typedef void tox_group_self_join_cb(Tox *tox, uint32_t group_number, void *user_data);
-
+typedef void tox_group_self_join_cb(Tox *tox, Tox_Group_Number group_number, void *user_data);
/**
* Set the callback for the `group_self_join` event. Pass NULL to unset.
@@ -4951,13 +5061,13 @@ 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.
* @param fail_type The type of group rejection.
*/
-typedef void tox_group_join_fail_cb(Tox *tox, uint32_t group_number, Tox_Group_Join_Fail fail_type, void *user_data);
-
+typedef void tox_group_join_fail_cb(Tox *tox, Tox_Group_Number group_number, Tox_Group_Join_Fail fail_type, void *user_data);
/**
* Set the callback for the `group_join_fail` event. Pass NULL to unset.
@@ -4966,15 +5076,12 @@ typedef void tox_group_join_fail_cb(Tox *tox, uint32_t group_number, Tox_Group_J
*/
void tox_callback_group_join_fail(Tox *tox, tox_group_join_fail_cb *callback);
-
/*******************************************************************************
*
* :: Group chat founder controls (these only work for the group founder)
*
******************************************************************************/
-
-
typedef enum Tox_Err_Group_Founder_Set_Password {
/**
@@ -5014,6 +5121,7 @@ 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.
@@ -5027,8 +5135,10 @@ typedef enum Tox_Err_Group_Founder_Set_Password {
*
* @return true on success.
*/
-bool tox_group_founder_set_password(const Tox *tox, uint32_t group_number, const uint8_t *password, size_t length,
- Tox_Err_Group_Founder_Set_Password *error);
+bool tox_group_founder_set_password(
+ Tox *tox, Tox_Group_Number group_number,
+ const uint8_t password[], size_t length,
+ Tox_Err_Group_Founder_Set_Password *error);
typedef enum Tox_Err_Group_Founder_Set_Topic_Lock {
@@ -5070,6 +5180,7 @@ 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.
@@ -5085,7 +5196,7 @@ typedef enum Tox_Err_Group_Founder_Set_Topic_Lock {
*
* @return true on success.
*/
-bool tox_group_founder_set_topic_lock(const Tox *tox, uint32_t group_number, Tox_Group_Topic_Lock topic_lock,
+bool tox_group_founder_set_topic_lock(Tox *tox, Tox_Group_Number group_number, Tox_Group_Topic_Lock topic_lock,
Tox_Err_Group_Founder_Set_Topic_Lock *error);
typedef enum Tox_Err_Group_Founder_Set_Voice_State {
@@ -5123,6 +5234,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.
*
@@ -5137,7 +5250,7 @@ typedef enum Tox_Err_Group_Founder_Set_Voice_State {
*
* @return true on success.
*/
-bool tox_group_founder_set_voice_state(const Tox *tox, uint32_t group_number, Tox_Group_Voice_State voice_state,
+bool tox_group_founder_set_voice_state(Tox *tox, Tox_Group_Number group_number, Tox_Group_Voice_State voice_state,
Tox_Err_Group_Founder_Set_Voice_State *error);
typedef enum Tox_Err_Group_Founder_Set_Privacy_State {
@@ -5175,6 +5288,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.
*
@@ -5189,7 +5304,7 @@ typedef enum Tox_Err_Group_Founder_Set_Privacy_State {
*
* @return true on success.
*/
-bool tox_group_founder_set_privacy_state(const Tox *tox, uint32_t group_number, Tox_Group_Privacy_State privacy_state,
+bool tox_group_founder_set_privacy_state(Tox *tox, Tox_Group_Number group_number, Tox_Group_Privacy_State privacy_state,
Tox_Err_Group_Founder_Set_Privacy_State *error);
typedef enum Tox_Err_Group_Founder_Set_Peer_Limit {
@@ -5227,6 +5342,7 @@ 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.
@@ -5235,22 +5351,19 @@ typedef enum Tox_Err_Group_Founder_Set_Peer_Limit {
* group shared state including the change, and distributes it to the rest of the group.
*
* @param group_number The group number of the group for which we wish to set the peer limit.
- * @param max_peers The maximum number of peers to allow in the group.
+ * @param peer_limit The maximum number of peers to allow in the group.
*
* @return true on success.
*/
-bool tox_group_founder_set_peer_limit(const Tox *tox, uint32_t group_number, uint16_t max_peers,
+bool tox_group_founder_set_peer_limit(Tox *tox, Tox_Group_Number group_number, uint16_t peer_limit,
Tox_Err_Group_Founder_Set_Peer_Limit *error);
-
/*******************************************************************************
*
* :: Group chat moderation
*
******************************************************************************/
-
-
typedef enum Tox_Err_Group_Set_Ignore {
/**
@@ -5275,6 +5388,7 @@ 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.
@@ -5285,7 +5399,7 @@ typedef enum Tox_Err_Group_Set_Ignore {
*
* @return true on success.
*/
-bool tox_group_set_ignore(const Tox *tox, uint32_t group_number, uint32_t peer_id, bool ignore,
+bool tox_group_set_ignore(Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id, bool ignore,
Tox_Err_Group_Set_Ignore *error);
typedef enum Tox_Err_Group_Mod_Set_Role {
@@ -5329,6 +5443,7 @@ 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.
@@ -5343,7 +5458,7 @@ typedef enum Tox_Err_Group_Mod_Set_Role {
*
* @return true on success.
*/
-bool tox_group_mod_set_role(const Tox *tox, uint32_t group_number, uint32_t peer_id, Tox_Group_Role role,
+bool tox_group_mod_set_role(Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id, Tox_Group_Role role,
Tox_Err_Group_Mod_Set_Role *error);
typedef enum Tox_Err_Group_Mod_Kick_Peer {
@@ -5385,6 +5500,7 @@ 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.
@@ -5398,7 +5514,7 @@ typedef enum Tox_Err_Group_Mod_Kick_Peer {
*
* @return true on success.
*/
-bool tox_group_mod_kick_peer(const Tox *tox, uint32_t group_number, uint32_t peer_id,
+bool tox_group_mod_kick_peer(const Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id,
Tox_Err_Group_Mod_Kick_Peer *error);
/**
@@ -5428,6 +5544,7 @@ 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.
@@ -5435,9 +5552,9 @@ typedef enum Tox_Group_Mod_Event {
* @param target_peer_id The ID of the peer who is the target of the event.
* @param mod_type The type of event.
*/
-typedef void tox_group_moderation_cb(Tox *tox, uint32_t group_number, uint32_t source_peer_id, uint32_t target_peer_id,
- Tox_Group_Mod_Event mod_type, void *user_data);
-
+typedef void tox_group_moderation_cb(
+ Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number source_peer_id, Tox_Group_Peer_Number target_peer_id,
+ Tox_Group_Mod_Event mod_type, void *user_data);
/**
* Set the callback for the `group_moderation` event. Pass NULL to unset.
@@ -5456,7 +5573,7 @@ void tox_callback_group_moderation(Tox *tox, tox_group_moderation_cb *callback);
/** @} */
#ifdef __cplusplus
-}
+} /* extern "C" */
#endif
//!TOKSTYLE-
@@ -5505,4 +5622,4 @@ typedef enum Tox_File_Kind TOX_FILE_KIND;
#endif
//!TOKSTYLE+
-#endif // C_TOXCORE_TOXCORE_TOX_H
+#endif /* C_TOXCORE_TOXCORE_TOX_H */
diff --git a/protocols/Tox/libtox/src/toxcore/tox_api.c b/protocols/Tox/libtox/src/toxcore/tox_api.c
index 61c248c30d..02791674b5 100644
--- a/protocols/Tox/libtox/src/toxcore/tox_api.c
+++ b/protocols/Tox/libtox/src/toxcore/tox_api.c
@@ -4,7 +4,6 @@
#include "tox.h"
#include <stdlib.h>
-#include <string.h>
#include "ccompat.h"
#include "tox_private.h"
@@ -124,6 +123,10 @@ uint32_t tox_group_peer_public_key_size(void)
{
return TOX_GROUP_PEER_PUBLIC_KEY_SIZE;
}
+uint32_t tox_group_peer_ip_string_max_length(void)
+{
+ return TOX_GROUP_PEER_IP_STRING_MAX_LENGTH;
+}
uint32_t tox_dht_node_ip_string_size(void)
{
return TOX_DHT_NODE_IP_STRING_SIZE;
@@ -133,53 +136,168 @@ uint32_t tox_dht_node_public_key_size(void)
return TOX_DHT_NODE_PUBLIC_KEY_SIZE;
}
-//!TOKSTYLE-
-
-#define ACCESSORS(type, ns, name) \
-type tox_options_get_##ns##name(const struct Tox_Options *options) \
-{ \
- return options->ns##name; \
-} \
-void tox_options_set_##ns##name(struct Tox_Options *options, type name) \
-{ \
- options->ns##name = name; \
-}
-
-ACCESSORS(bool,, ipv6_enabled)
-ACCESSORS(bool,, udp_enabled)
-ACCESSORS(Tox_Proxy_Type, proxy_, type)
-ACCESSORS(const char *, proxy_, host)
-ACCESSORS(uint16_t, proxy_, port)
-ACCESSORS(uint16_t,, start_port)
-ACCESSORS(uint16_t,, end_port)
-ACCESSORS(uint16_t,, tcp_port)
-ACCESSORS(bool,, hole_punching_enabled)
-ACCESSORS(Tox_Savedata_Type, savedata_, type)
-ACCESSORS(size_t, savedata_, length)
-ACCESSORS(tox_log_cb *, log_, callback)
-ACCESSORS(void *, log_, user_data)
-ACCESSORS(bool,, local_discovery_enabled)
-ACCESSORS(bool,, dht_announcements_enabled)
-ACCESSORS(bool,, experimental_thread_safety)
-ACCESSORS(const Tox_System *,, operating_system)
-
-//!TOKSTYLE+
-
-const uint8_t *tox_options_get_savedata_data(const struct Tox_Options *options)
+bool tox_options_get_ipv6_enabled(const Tox_Options *options)
+{
+ return options->ipv6_enabled;
+}
+void tox_options_set_ipv6_enabled(Tox_Options *options, bool ipv6_enabled)
+{
+ options->ipv6_enabled = ipv6_enabled;
+}
+bool tox_options_get_udp_enabled(const Tox_Options *options)
+{
+ return options->udp_enabled;
+}
+void tox_options_set_udp_enabled(Tox_Options *options, bool udp_enabled)
+{
+ options->udp_enabled = udp_enabled;
+}
+Tox_Proxy_Type tox_options_get_proxy_type(const Tox_Options *options)
+{
+ return options->proxy_type;
+}
+void tox_options_set_proxy_type(Tox_Options *options, Tox_Proxy_Type proxy_type)
+{
+ options->proxy_type = proxy_type;
+}
+const char *tox_options_get_proxy_host(const Tox_Options *options)
+{
+ return options->proxy_host;
+}
+void tox_options_set_proxy_host(Tox_Options *options, const char *proxy_host)
+{
+ options->proxy_host = proxy_host;
+}
+uint16_t tox_options_get_proxy_port(const Tox_Options *options)
+{
+ return options->proxy_port;
+}
+void tox_options_set_proxy_port(Tox_Options *options, uint16_t proxy_port)
+{
+ options->proxy_port = proxy_port;
+}
+uint16_t tox_options_get_start_port(const Tox_Options *options)
+{
+ return options->start_port;
+}
+void tox_options_set_start_port(Tox_Options *options, uint16_t start_port)
+{
+ options->start_port = start_port;
+}
+uint16_t tox_options_get_end_port(const Tox_Options *options)
+{
+ return options->end_port;
+}
+void tox_options_set_end_port(Tox_Options *options, uint16_t end_port)
+{
+ options->end_port = end_port;
+}
+uint16_t tox_options_get_tcp_port(const Tox_Options *options)
+{
+ return options->tcp_port;
+}
+void tox_options_set_tcp_port(Tox_Options *options, uint16_t tcp_port)
+{
+ options->tcp_port = tcp_port;
+}
+bool tox_options_get_hole_punching_enabled(const Tox_Options *options)
+{
+ return options->hole_punching_enabled;
+}
+void tox_options_set_hole_punching_enabled(Tox_Options *options, bool hole_punching_enabled)
+{
+ options->hole_punching_enabled = hole_punching_enabled;
+}
+Tox_Savedata_Type tox_options_get_savedata_type(const Tox_Options *options)
+{
+ return options->savedata_type;
+}
+void tox_options_set_savedata_type(Tox_Options *options, Tox_Savedata_Type savedata_type)
+{
+ options->savedata_type = savedata_type;
+}
+size_t tox_options_get_savedata_length(const Tox_Options *options)
+{
+ return options->savedata_length;
+}
+void tox_options_set_savedata_length(Tox_Options *options, size_t savedata_length)
+{
+ options->savedata_length = savedata_length;
+}
+tox_log_cb *tox_options_get_log_callback(const Tox_Options *options)
+{
+ return options->log_callback;
+}
+void tox_options_set_log_callback(Tox_Options *options, tox_log_cb *log_callback)
+{
+ options->log_callback = log_callback;
+}
+void *tox_options_get_log_user_data(const Tox_Options *options)
+{
+ return options->log_user_data;
+}
+void tox_options_set_log_user_data(Tox_Options *options, void *log_user_data)
+{
+ options->log_user_data = log_user_data;
+}
+bool tox_options_get_local_discovery_enabled(const Tox_Options *options)
+{
+ return options->local_discovery_enabled;
+}
+void tox_options_set_local_discovery_enabled(Tox_Options *options, bool local_discovery_enabled)
+{
+ options->local_discovery_enabled = local_discovery_enabled;
+}
+bool tox_options_get_dht_announcements_enabled(const Tox_Options *options)
+{
+ return options->dht_announcements_enabled;
+}
+void tox_options_set_dht_announcements_enabled(Tox_Options *options, bool dht_announcements_enabled)
+{
+ options->dht_announcements_enabled = dht_announcements_enabled;
+}
+bool tox_options_get_experimental_thread_safety(const Tox_Options *options)
+{
+ return options->experimental_thread_safety;
+}
+void tox_options_set_experimental_thread_safety(
+ Tox_Options *options, bool experimental_thread_safety)
+{
+ options->experimental_thread_safety = experimental_thread_safety;
+}
+const Tox_System *tox_options_get_operating_system(const Tox_Options *options)
+{
+ return options->operating_system;
+}
+void tox_options_set_operating_system(Tox_Options *options, const Tox_System *operating_system)
+{
+ options->operating_system = operating_system;
+}
+bool tox_options_get_experimental_groups_persistence(const Tox_Options *options)
+{
+ return options->experimental_groups_persistence;
+}
+void tox_options_set_experimental_groups_persistence(
+ Tox_Options *options, bool experimental_groups_persistence)
+{
+ options->experimental_groups_persistence = experimental_groups_persistence;
+}
+
+const uint8_t *tox_options_get_savedata_data(const Tox_Options *options)
{
return options->savedata_data;
}
-void tox_options_set_savedata_data(struct Tox_Options *options, const uint8_t *data, size_t length)
+void tox_options_set_savedata_data(Tox_Options *options, const uint8_t *savedata_data, size_t length)
{
- options->savedata_data = data;
+ options->savedata_data = savedata_data;
options->savedata_length = length;
}
-void tox_options_default(struct Tox_Options *options)
+void tox_options_default(Tox_Options *options)
{
if (options != nullptr) {
- const struct Tox_Options default_options = {0};
+ const Tox_Options default_options = {false};
*options = default_options;
tox_options_set_ipv6_enabled(options, true);
tox_options_set_udp_enabled(options, true);
@@ -188,12 +306,13 @@ void tox_options_default(struct Tox_Options *options)
tox_options_set_local_discovery_enabled(options, true);
tox_options_set_dht_announcements_enabled(options, true);
tox_options_set_experimental_thread_safety(options, false);
+ tox_options_set_experimental_groups_persistence(options, false);
}
}
-struct Tox_Options *tox_options_new(Tox_Err_Options_New *error)
+Tox_Options *tox_options_new(Tox_Err_Options_New *error)
{
- struct Tox_Options *options = (struct Tox_Options *)calloc(1, sizeof(struct Tox_Options));
+ Tox_Options *options = (Tox_Options *)calloc(1, sizeof(Tox_Options));
if (options != nullptr) {
tox_options_default(options);
@@ -205,7 +324,1400 @@ struct Tox_Options *tox_options_new(Tox_Err_Options_New *error)
return nullptr;
}
-void tox_options_free(struct Tox_Options *options)
+void tox_options_free(Tox_Options *options)
{
free(options);
}
+
+const char *tox_user_status_to_string(Tox_User_Status value)
+{
+ switch (value) {
+ case TOX_USER_STATUS_NONE:
+ return "TOX_USER_STATUS_NONE";
+
+ case TOX_USER_STATUS_AWAY:
+ return "TOX_USER_STATUS_AWAY";
+
+ case TOX_USER_STATUS_BUSY:
+ return "TOX_USER_STATUS_BUSY";
+ }
+
+ return "<invalid Tox_User_Status>";
+}
+const char *tox_message_type_to_string(Tox_Message_Type value)
+{
+ switch (value) {
+ case TOX_MESSAGE_TYPE_NORMAL:
+ return "TOX_MESSAGE_TYPE_NORMAL";
+
+ case TOX_MESSAGE_TYPE_ACTION:
+ return "TOX_MESSAGE_TYPE_ACTION";
+ }
+
+ return "<invalid Tox_Message_Type>";
+}
+const char *tox_proxy_type_to_string(Tox_Proxy_Type value)
+{
+ switch (value) {
+ case TOX_PROXY_TYPE_NONE:
+ return "TOX_PROXY_TYPE_NONE";
+
+ case TOX_PROXY_TYPE_HTTP:
+ return "TOX_PROXY_TYPE_HTTP";
+
+ case TOX_PROXY_TYPE_SOCKS5:
+ return "TOX_PROXY_TYPE_SOCKS5";
+ }
+
+ return "<invalid Tox_Proxy_Type>";
+}
+const char *tox_savedata_type_to_string(Tox_Savedata_Type value)
+{
+ switch (value) {
+ case TOX_SAVEDATA_TYPE_NONE:
+ return "TOX_SAVEDATA_TYPE_NONE";
+
+ case TOX_SAVEDATA_TYPE_TOX_SAVE:
+ return "TOX_SAVEDATA_TYPE_TOX_SAVE";
+
+ case TOX_SAVEDATA_TYPE_SECRET_KEY:
+ return "TOX_SAVEDATA_TYPE_SECRET_KEY";
+ }
+
+ return "<invalid Tox_Savedata_Type>";
+}
+const char *tox_log_level_to_string(Tox_Log_Level value)
+{
+ switch (value) {
+ case TOX_LOG_LEVEL_TRACE:
+ return "TOX_LOG_LEVEL_TRACE";
+
+ case TOX_LOG_LEVEL_DEBUG:
+ return "TOX_LOG_LEVEL_DEBUG";
+
+ case TOX_LOG_LEVEL_INFO:
+ return "TOX_LOG_LEVEL_INFO";
+
+ case TOX_LOG_LEVEL_WARNING:
+ return "TOX_LOG_LEVEL_WARNING";
+
+ case TOX_LOG_LEVEL_ERROR:
+ return "TOX_LOG_LEVEL_ERROR";
+ }
+
+ return "<invalid Tox_Log_Level>";
+}
+const char *tox_err_options_new_to_string(Tox_Err_Options_New value)
+{
+ switch (value) {
+ case TOX_ERR_OPTIONS_NEW_OK:
+ return "TOX_ERR_OPTIONS_NEW_OK";
+
+ case TOX_ERR_OPTIONS_NEW_MALLOC:
+ return "TOX_ERR_OPTIONS_NEW_MALLOC";
+ }
+
+ return "<invalid Tox_Err_Options_New>";
+}
+const char *tox_err_new_to_string(Tox_Err_New value)
+{
+ switch (value) {
+ case TOX_ERR_NEW_OK:
+ return "TOX_ERR_NEW_OK";
+
+ case TOX_ERR_NEW_NULL:
+ return "TOX_ERR_NEW_NULL";
+
+ case TOX_ERR_NEW_MALLOC:
+ return "TOX_ERR_NEW_MALLOC";
+
+ case TOX_ERR_NEW_PORT_ALLOC:
+ return "TOX_ERR_NEW_PORT_ALLOC";
+
+ case TOX_ERR_NEW_PROXY_BAD_TYPE:
+ return "TOX_ERR_NEW_PROXY_BAD_TYPE";
+
+ case TOX_ERR_NEW_PROXY_BAD_HOST:
+ return "TOX_ERR_NEW_PROXY_BAD_HOST";
+
+ case TOX_ERR_NEW_PROXY_BAD_PORT:
+ return "TOX_ERR_NEW_PROXY_BAD_PORT";
+
+ case TOX_ERR_NEW_PROXY_NOT_FOUND:
+ return "TOX_ERR_NEW_PROXY_NOT_FOUND";
+
+ case TOX_ERR_NEW_LOAD_ENCRYPTED:
+ return "TOX_ERR_NEW_LOAD_ENCRYPTED";
+
+ case TOX_ERR_NEW_LOAD_BAD_FORMAT:
+ return "TOX_ERR_NEW_LOAD_BAD_FORMAT";
+ }
+
+ return "<invalid Tox_Err_New>";
+}
+const char *tox_err_bootstrap_to_string(Tox_Err_Bootstrap value)
+{
+ switch (value) {
+ case TOX_ERR_BOOTSTRAP_OK:
+ return "TOX_ERR_BOOTSTRAP_OK";
+
+ case TOX_ERR_BOOTSTRAP_NULL:
+ return "TOX_ERR_BOOTSTRAP_NULL";
+
+ case TOX_ERR_BOOTSTRAP_BAD_HOST:
+ return "TOX_ERR_BOOTSTRAP_BAD_HOST";
+
+ case TOX_ERR_BOOTSTRAP_BAD_PORT:
+ return "TOX_ERR_BOOTSTRAP_BAD_PORT";
+ }
+
+ return "<invalid Tox_Err_Bootstrap>";
+}
+const char *tox_connection_to_string(Tox_Connection value)
+{
+ switch (value) {
+ case TOX_CONNECTION_NONE:
+ return "TOX_CONNECTION_NONE";
+
+ case TOX_CONNECTION_TCP:
+ return "TOX_CONNECTION_TCP";
+
+ case TOX_CONNECTION_UDP:
+ return "TOX_CONNECTION_UDP";
+ }
+
+ return "<invalid Tox_Connection>";
+}
+const char *tox_err_set_info_to_string(Tox_Err_Set_Info value)
+{
+ switch (value) {
+ case TOX_ERR_SET_INFO_OK:
+ return "TOX_ERR_SET_INFO_OK";
+
+ case TOX_ERR_SET_INFO_NULL:
+ return "TOX_ERR_SET_INFO_NULL";
+
+ case TOX_ERR_SET_INFO_TOO_LONG:
+ return "TOX_ERR_SET_INFO_TOO_LONG";
+ }
+
+ return "<invalid Tox_Err_Set_Info>";
+}
+const char *tox_err_friend_add_to_string(Tox_Err_Friend_Add value)
+{
+ switch (value) {
+ case TOX_ERR_FRIEND_ADD_OK:
+ return "TOX_ERR_FRIEND_ADD_OK";
+
+ case TOX_ERR_FRIEND_ADD_NULL:
+ return "TOX_ERR_FRIEND_ADD_NULL";
+
+ case TOX_ERR_FRIEND_ADD_TOO_LONG:
+ return "TOX_ERR_FRIEND_ADD_TOO_LONG";
+
+ case TOX_ERR_FRIEND_ADD_NO_MESSAGE:
+ return "TOX_ERR_FRIEND_ADD_NO_MESSAGE";
+
+ case TOX_ERR_FRIEND_ADD_OWN_KEY:
+ return "TOX_ERR_FRIEND_ADD_OWN_KEY";
+
+ case TOX_ERR_FRIEND_ADD_ALREADY_SENT:
+ return "TOX_ERR_FRIEND_ADD_ALREADY_SENT";
+
+ case TOX_ERR_FRIEND_ADD_BAD_CHECKSUM:
+ return "TOX_ERR_FRIEND_ADD_BAD_CHECKSUM";
+
+ case TOX_ERR_FRIEND_ADD_SET_NEW_NOSPAM:
+ return "TOX_ERR_FRIEND_ADD_SET_NEW_NOSPAM";
+
+ case TOX_ERR_FRIEND_ADD_MALLOC:
+ return "TOX_ERR_FRIEND_ADD_MALLOC";
+ }
+
+ return "<invalid Tox_Err_Friend_Add>";
+}
+const char *tox_err_friend_delete_to_string(Tox_Err_Friend_Delete value)
+{
+ switch (value) {
+ case TOX_ERR_FRIEND_DELETE_OK:
+ return "TOX_ERR_FRIEND_DELETE_OK";
+
+ case TOX_ERR_FRIEND_DELETE_FRIEND_NOT_FOUND:
+ return "TOX_ERR_FRIEND_DELETE_FRIEND_NOT_FOUND";
+ }
+
+ return "<invalid Tox_Err_Friend_Delete>";
+}
+const char *tox_err_friend_by_public_key_to_string(Tox_Err_Friend_By_Public_Key value)
+{
+ switch (value) {
+ case TOX_ERR_FRIEND_BY_PUBLIC_KEY_OK:
+ return "TOX_ERR_FRIEND_BY_PUBLIC_KEY_OK";
+
+ case TOX_ERR_FRIEND_BY_PUBLIC_KEY_NULL:
+ return "TOX_ERR_FRIEND_BY_PUBLIC_KEY_NULL";
+
+ case TOX_ERR_FRIEND_BY_PUBLIC_KEY_NOT_FOUND:
+ return "TOX_ERR_FRIEND_BY_PUBLIC_KEY_NOT_FOUND";
+ }
+
+ return "<invalid Tox_Err_Friend_By_Public_Key>";
+}
+const char *tox_err_friend_get_public_key_to_string(Tox_Err_Friend_Get_Public_Key value)
+{
+ switch (value) {
+ case TOX_ERR_FRIEND_GET_PUBLIC_KEY_OK:
+ return "TOX_ERR_FRIEND_GET_PUBLIC_KEY_OK";
+
+ case TOX_ERR_FRIEND_GET_PUBLIC_KEY_FRIEND_NOT_FOUND:
+ return "TOX_ERR_FRIEND_GET_PUBLIC_KEY_FRIEND_NOT_FOUND";
+ }
+
+ return "<invalid Tox_Err_Friend_Get_Public_Key>";
+}
+const char *tox_err_friend_get_last_online_to_string(Tox_Err_Friend_Get_Last_Online value)
+{
+ switch (value) {
+ case TOX_ERR_FRIEND_GET_LAST_ONLINE_OK:
+ return "TOX_ERR_FRIEND_GET_LAST_ONLINE_OK";
+
+ case TOX_ERR_FRIEND_GET_LAST_ONLINE_FRIEND_NOT_FOUND:
+ return "TOX_ERR_FRIEND_GET_LAST_ONLINE_FRIEND_NOT_FOUND";
+ }
+
+ return "<invalid Tox_Err_Friend_Get_Last_Online>";
+}
+const char *tox_err_friend_query_to_string(Tox_Err_Friend_Query value)
+{
+ switch (value) {
+ case TOX_ERR_FRIEND_QUERY_OK:
+ return "TOX_ERR_FRIEND_QUERY_OK";
+
+ case TOX_ERR_FRIEND_QUERY_NULL:
+ return "TOX_ERR_FRIEND_QUERY_NULL";
+
+ case TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND:
+ return "TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND";
+ }
+
+ return "<invalid Tox_Err_Friend_Query>";
+}
+const char *tox_err_set_typing_to_string(Tox_Err_Set_Typing value)
+{
+ switch (value) {
+ case TOX_ERR_SET_TYPING_OK:
+ return "TOX_ERR_SET_TYPING_OK";
+
+ case TOX_ERR_SET_TYPING_FRIEND_NOT_FOUND:
+ return "TOX_ERR_SET_TYPING_FRIEND_NOT_FOUND";
+ }
+
+ return "<invalid Tox_Err_Set_Typing>";
+}
+const char *tox_err_friend_send_message_to_string(Tox_Err_Friend_Send_Message value)
+{
+ switch (value) {
+ case TOX_ERR_FRIEND_SEND_MESSAGE_OK:
+ return "TOX_ERR_FRIEND_SEND_MESSAGE_OK";
+
+ case TOX_ERR_FRIEND_SEND_MESSAGE_NULL:
+ return "TOX_ERR_FRIEND_SEND_MESSAGE_NULL";
+
+ case TOX_ERR_FRIEND_SEND_MESSAGE_FRIEND_NOT_FOUND:
+ return "TOX_ERR_FRIEND_SEND_MESSAGE_FRIEND_NOT_FOUND";
+
+ case TOX_ERR_FRIEND_SEND_MESSAGE_FRIEND_NOT_CONNECTED:
+ return "TOX_ERR_FRIEND_SEND_MESSAGE_FRIEND_NOT_CONNECTED";
+
+ case TOX_ERR_FRIEND_SEND_MESSAGE_SENDQ:
+ return "TOX_ERR_FRIEND_SEND_MESSAGE_SENDQ";
+
+ case TOX_ERR_FRIEND_SEND_MESSAGE_TOO_LONG:
+ return "TOX_ERR_FRIEND_SEND_MESSAGE_TOO_LONG";
+
+ case TOX_ERR_FRIEND_SEND_MESSAGE_EMPTY:
+ return "TOX_ERR_FRIEND_SEND_MESSAGE_EMPTY";
+ }
+
+ return "<invalid Tox_Err_Friend_Send_Message>";
+}
+const char *tox_file_control_to_string(Tox_File_Control value)
+{
+ switch (value) {
+ case TOX_FILE_CONTROL_RESUME:
+ return "TOX_FILE_CONTROL_RESUME";
+
+ case TOX_FILE_CONTROL_PAUSE:
+ return "TOX_FILE_CONTROL_PAUSE";
+
+ case TOX_FILE_CONTROL_CANCEL:
+ return "TOX_FILE_CONTROL_CANCEL";
+ }
+
+ return "<invalid Tox_File_Control>";
+}
+const char *tox_err_file_control_to_string(Tox_Err_File_Control value)
+{
+ switch (value) {
+ case TOX_ERR_FILE_CONTROL_OK:
+ return "TOX_ERR_FILE_CONTROL_OK";
+
+ case TOX_ERR_FILE_CONTROL_FRIEND_NOT_FOUND:
+ return "TOX_ERR_FILE_CONTROL_FRIEND_NOT_FOUND";
+
+ case TOX_ERR_FILE_CONTROL_FRIEND_NOT_CONNECTED:
+ return "TOX_ERR_FILE_CONTROL_FRIEND_NOT_CONNECTED";
+
+ case TOX_ERR_FILE_CONTROL_NOT_FOUND:
+ return "TOX_ERR_FILE_CONTROL_NOT_FOUND";
+
+ case TOX_ERR_FILE_CONTROL_NOT_PAUSED:
+ return "TOX_ERR_FILE_CONTROL_NOT_PAUSED";
+
+ case TOX_ERR_FILE_CONTROL_DENIED:
+ return "TOX_ERR_FILE_CONTROL_DENIED";
+
+ case TOX_ERR_FILE_CONTROL_ALREADY_PAUSED:
+ return "TOX_ERR_FILE_CONTROL_ALREADY_PAUSED";
+
+ case TOX_ERR_FILE_CONTROL_SENDQ:
+ return "TOX_ERR_FILE_CONTROL_SENDQ";
+ }
+
+ return "<invalid Tox_Err_File_Control>";
+}
+const char *tox_err_file_seek_to_string(Tox_Err_File_Seek value)
+{
+ switch (value) {
+ case TOX_ERR_FILE_SEEK_OK:
+ return "TOX_ERR_FILE_SEEK_OK";
+
+ case TOX_ERR_FILE_SEEK_FRIEND_NOT_FOUND:
+ return "TOX_ERR_FILE_SEEK_FRIEND_NOT_FOUND";
+
+ case TOX_ERR_FILE_SEEK_FRIEND_NOT_CONNECTED:
+ return "TOX_ERR_FILE_SEEK_FRIEND_NOT_CONNECTED";
+
+ case TOX_ERR_FILE_SEEK_NOT_FOUND:
+ return "TOX_ERR_FILE_SEEK_NOT_FOUND";
+
+ case TOX_ERR_FILE_SEEK_DENIED:
+ return "TOX_ERR_FILE_SEEK_DENIED";
+
+ case TOX_ERR_FILE_SEEK_INVALID_POSITION:
+ return "TOX_ERR_FILE_SEEK_INVALID_POSITION";
+
+ case TOX_ERR_FILE_SEEK_SENDQ:
+ return "TOX_ERR_FILE_SEEK_SENDQ";
+ }
+
+ return "<invalid Tox_Err_File_Seek>";
+}
+const char *tox_err_file_get_to_string(Tox_Err_File_Get value)
+{
+ switch (value) {
+ case TOX_ERR_FILE_GET_OK:
+ return "TOX_ERR_FILE_GET_OK";
+
+ case TOX_ERR_FILE_GET_NULL:
+ return "TOX_ERR_FILE_GET_NULL";
+
+ case TOX_ERR_FILE_GET_FRIEND_NOT_FOUND:
+ return "TOX_ERR_FILE_GET_FRIEND_NOT_FOUND";
+
+ case TOX_ERR_FILE_GET_NOT_FOUND:
+ return "TOX_ERR_FILE_GET_NOT_FOUND";
+ }
+
+ return "<invalid Tox_Err_File_Get>";
+}
+const char *tox_err_file_send_to_string(Tox_Err_File_Send value)
+{
+ switch (value) {
+ case TOX_ERR_FILE_SEND_OK:
+ return "TOX_ERR_FILE_SEND_OK";
+
+ case TOX_ERR_FILE_SEND_NULL:
+ return "TOX_ERR_FILE_SEND_NULL";
+
+ case TOX_ERR_FILE_SEND_FRIEND_NOT_FOUND:
+ return "TOX_ERR_FILE_SEND_FRIEND_NOT_FOUND";
+
+ case TOX_ERR_FILE_SEND_FRIEND_NOT_CONNECTED:
+ return "TOX_ERR_FILE_SEND_FRIEND_NOT_CONNECTED";
+
+ case TOX_ERR_FILE_SEND_NAME_TOO_LONG:
+ return "TOX_ERR_FILE_SEND_NAME_TOO_LONG";
+
+ case TOX_ERR_FILE_SEND_TOO_MANY:
+ return "TOX_ERR_FILE_SEND_TOO_MANY";
+ }
+
+ return "<invalid Tox_Err_File_Send>";
+}
+const char *tox_err_file_send_chunk_to_string(Tox_Err_File_Send_Chunk value)
+{
+ switch (value) {
+ case TOX_ERR_FILE_SEND_CHUNK_OK:
+ return "TOX_ERR_FILE_SEND_CHUNK_OK";
+
+ case TOX_ERR_FILE_SEND_CHUNK_NULL:
+ return "TOX_ERR_FILE_SEND_CHUNK_NULL";
+
+ case TOX_ERR_FILE_SEND_CHUNK_FRIEND_NOT_FOUND:
+ return "TOX_ERR_FILE_SEND_CHUNK_FRIEND_NOT_FOUND";
+
+ case TOX_ERR_FILE_SEND_CHUNK_FRIEND_NOT_CONNECTED:
+ return "TOX_ERR_FILE_SEND_CHUNK_FRIEND_NOT_CONNECTED";
+
+ case TOX_ERR_FILE_SEND_CHUNK_NOT_FOUND:
+ return "TOX_ERR_FILE_SEND_CHUNK_NOT_FOUND";
+
+ case TOX_ERR_FILE_SEND_CHUNK_NOT_TRANSFERRING:
+ return "TOX_ERR_FILE_SEND_CHUNK_NOT_TRANSFERRING";
+
+ case TOX_ERR_FILE_SEND_CHUNK_INVALID_LENGTH:
+ return "TOX_ERR_FILE_SEND_CHUNK_INVALID_LENGTH";
+
+ case TOX_ERR_FILE_SEND_CHUNK_SENDQ:
+ return "TOX_ERR_FILE_SEND_CHUNK_SENDQ";
+
+ case TOX_ERR_FILE_SEND_CHUNK_WRONG_POSITION:
+ return "TOX_ERR_FILE_SEND_CHUNK_WRONG_POSITION";
+ }
+
+ return "<invalid Tox_Err_File_Send_Chunk>";
+}
+const char *tox_conference_type_to_string(Tox_Conference_Type value)
+{
+ switch (value) {
+ case TOX_CONFERENCE_TYPE_TEXT:
+ return "TOX_CONFERENCE_TYPE_TEXT";
+
+ case TOX_CONFERENCE_TYPE_AV:
+ return "TOX_CONFERENCE_TYPE_AV";
+ }
+
+ return "<invalid Tox_Conference_Type>";
+}
+const char *tox_err_conference_new_to_string(Tox_Err_Conference_New value)
+{
+ switch (value) {
+ case TOX_ERR_CONFERENCE_NEW_OK:
+ return "TOX_ERR_CONFERENCE_NEW_OK";
+
+ case TOX_ERR_CONFERENCE_NEW_INIT:
+ return "TOX_ERR_CONFERENCE_NEW_INIT";
+ }
+
+ return "<invalid Tox_Err_Conference_New>";
+}
+const char *tox_err_conference_delete_to_string(Tox_Err_Conference_Delete value)
+{
+ switch (value) {
+ case TOX_ERR_CONFERENCE_DELETE_OK:
+ return "TOX_ERR_CONFERENCE_DELETE_OK";
+
+ case TOX_ERR_CONFERENCE_DELETE_CONFERENCE_NOT_FOUND:
+ return "TOX_ERR_CONFERENCE_DELETE_CONFERENCE_NOT_FOUND";
+ }
+
+ return "<invalid Tox_Err_Conference_Delete>";
+}
+const char *tox_err_conference_peer_query_to_string(Tox_Err_Conference_Peer_Query value)
+{
+ switch (value) {
+ case TOX_ERR_CONFERENCE_PEER_QUERY_OK:
+ return "TOX_ERR_CONFERENCE_PEER_QUERY_OK";
+
+ case TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND:
+ return "TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND";
+
+ case TOX_ERR_CONFERENCE_PEER_QUERY_PEER_NOT_FOUND:
+ return "TOX_ERR_CONFERENCE_PEER_QUERY_PEER_NOT_FOUND";
+
+ case TOX_ERR_CONFERENCE_PEER_QUERY_NO_CONNECTION:
+ return "TOX_ERR_CONFERENCE_PEER_QUERY_NO_CONNECTION";
+ }
+
+ return "<invalid Tox_Err_Conference_Peer_Query>";
+}
+const char *tox_err_conference_set_max_offline_to_string(Tox_Err_Conference_Set_Max_Offline value)
+{
+ switch (value) {
+ case TOX_ERR_CONFERENCE_SET_MAX_OFFLINE_OK:
+ return "TOX_ERR_CONFERENCE_SET_MAX_OFFLINE_OK";
+
+ case TOX_ERR_CONFERENCE_SET_MAX_OFFLINE_CONFERENCE_NOT_FOUND:
+ return "TOX_ERR_CONFERENCE_SET_MAX_OFFLINE_CONFERENCE_NOT_FOUND";
+ }
+
+ return "<invalid Tox_Err_Conference_Set_Max_Offline>";
+}
+const char *tox_err_conference_invite_to_string(Tox_Err_Conference_Invite value)
+{
+ switch (value) {
+ case TOX_ERR_CONFERENCE_INVITE_OK:
+ return "TOX_ERR_CONFERENCE_INVITE_OK";
+
+ case TOX_ERR_CONFERENCE_INVITE_CONFERENCE_NOT_FOUND:
+ return "TOX_ERR_CONFERENCE_INVITE_CONFERENCE_NOT_FOUND";
+
+ case TOX_ERR_CONFERENCE_INVITE_FAIL_SEND:
+ return "TOX_ERR_CONFERENCE_INVITE_FAIL_SEND";
+
+ case TOX_ERR_CONFERENCE_INVITE_NO_CONNECTION:
+ return "TOX_ERR_CONFERENCE_INVITE_NO_CONNECTION";
+ }
+
+ return "<invalid Tox_Err_Conference_Invite>";
+}
+const char *tox_err_conference_join_to_string(Tox_Err_Conference_Join value)
+{
+ switch (value) {
+ case TOX_ERR_CONFERENCE_JOIN_OK:
+ return "TOX_ERR_CONFERENCE_JOIN_OK";
+
+ case TOX_ERR_CONFERENCE_JOIN_INVALID_LENGTH:
+ return "TOX_ERR_CONFERENCE_JOIN_INVALID_LENGTH";
+
+ case TOX_ERR_CONFERENCE_JOIN_WRONG_TYPE:
+ return "TOX_ERR_CONFERENCE_JOIN_WRONG_TYPE";
+
+ case TOX_ERR_CONFERENCE_JOIN_FRIEND_NOT_FOUND:
+ return "TOX_ERR_CONFERENCE_JOIN_FRIEND_NOT_FOUND";
+
+ case TOX_ERR_CONFERENCE_JOIN_DUPLICATE:
+ return "TOX_ERR_CONFERENCE_JOIN_DUPLICATE";
+
+ case TOX_ERR_CONFERENCE_JOIN_INIT_FAIL:
+ return "TOX_ERR_CONFERENCE_JOIN_INIT_FAIL";
+
+ case TOX_ERR_CONFERENCE_JOIN_FAIL_SEND:
+ return "TOX_ERR_CONFERENCE_JOIN_FAIL_SEND";
+ }
+
+ return "<invalid Tox_Err_Conference_Join>";
+}
+const char *tox_err_conference_send_message_to_string(Tox_Err_Conference_Send_Message value)
+{
+ switch (value) {
+ case TOX_ERR_CONFERENCE_SEND_MESSAGE_OK:
+ return "TOX_ERR_CONFERENCE_SEND_MESSAGE_OK";
+
+ case TOX_ERR_CONFERENCE_SEND_MESSAGE_CONFERENCE_NOT_FOUND:
+ return "TOX_ERR_CONFERENCE_SEND_MESSAGE_CONFERENCE_NOT_FOUND";
+
+ case TOX_ERR_CONFERENCE_SEND_MESSAGE_TOO_LONG:
+ return "TOX_ERR_CONFERENCE_SEND_MESSAGE_TOO_LONG";
+
+ case TOX_ERR_CONFERENCE_SEND_MESSAGE_NO_CONNECTION:
+ return "TOX_ERR_CONFERENCE_SEND_MESSAGE_NO_CONNECTION";
+
+ case TOX_ERR_CONFERENCE_SEND_MESSAGE_FAIL_SEND:
+ return "TOX_ERR_CONFERENCE_SEND_MESSAGE_FAIL_SEND";
+ }
+
+ return "<invalid Tox_Err_Conference_Send_Message>";
+}
+const char *tox_err_conference_title_to_string(Tox_Err_Conference_Title value)
+{
+ switch (value) {
+ case TOX_ERR_CONFERENCE_TITLE_OK:
+ return "TOX_ERR_CONFERENCE_TITLE_OK";
+
+ case TOX_ERR_CONFERENCE_TITLE_CONFERENCE_NOT_FOUND:
+ return "TOX_ERR_CONFERENCE_TITLE_CONFERENCE_NOT_FOUND";
+
+ case TOX_ERR_CONFERENCE_TITLE_INVALID_LENGTH:
+ return "TOX_ERR_CONFERENCE_TITLE_INVALID_LENGTH";
+
+ case TOX_ERR_CONFERENCE_TITLE_FAIL_SEND:
+ return "TOX_ERR_CONFERENCE_TITLE_FAIL_SEND";
+ }
+
+ return "<invalid Tox_Err_Conference_Title>";
+}
+const char *tox_err_conference_get_type_to_string(Tox_Err_Conference_Get_Type value)
+{
+ switch (value) {
+ case TOX_ERR_CONFERENCE_GET_TYPE_OK:
+ return "TOX_ERR_CONFERENCE_GET_TYPE_OK";
+
+ case TOX_ERR_CONFERENCE_GET_TYPE_CONFERENCE_NOT_FOUND:
+ return "TOX_ERR_CONFERENCE_GET_TYPE_CONFERENCE_NOT_FOUND";
+ }
+
+ return "<invalid Tox_Err_Conference_Get_Type>";
+}
+const char *tox_err_conference_by_id_to_string(Tox_Err_Conference_By_Id value)
+{
+ switch (value) {
+ case TOX_ERR_CONFERENCE_BY_ID_OK:
+ return "TOX_ERR_CONFERENCE_BY_ID_OK";
+
+ case TOX_ERR_CONFERENCE_BY_ID_NULL:
+ return "TOX_ERR_CONFERENCE_BY_ID_NULL";
+
+ case TOX_ERR_CONFERENCE_BY_ID_NOT_FOUND:
+ return "TOX_ERR_CONFERENCE_BY_ID_NOT_FOUND";
+ }
+
+ return "<invalid Tox_Err_Conference_By_Id>";
+}
+const char *tox_err_conference_by_uid_to_string(Tox_Err_Conference_By_Uid value)
+{
+ switch (value) {
+ case TOX_ERR_CONFERENCE_BY_UID_OK:
+ return "TOX_ERR_CONFERENCE_BY_UID_OK";
+
+ case TOX_ERR_CONFERENCE_BY_UID_NULL:
+ return "TOX_ERR_CONFERENCE_BY_UID_NULL";
+
+ case TOX_ERR_CONFERENCE_BY_UID_NOT_FOUND:
+ return "TOX_ERR_CONFERENCE_BY_UID_NOT_FOUND";
+ }
+
+ return "<invalid Tox_Err_Conference_By_Uid>";
+}
+const char *tox_err_friend_custom_packet_to_string(Tox_Err_Friend_Custom_Packet value)
+{
+ switch (value) {
+ case TOX_ERR_FRIEND_CUSTOM_PACKET_OK:
+ return "TOX_ERR_FRIEND_CUSTOM_PACKET_OK";
+
+ case TOX_ERR_FRIEND_CUSTOM_PACKET_NULL:
+ return "TOX_ERR_FRIEND_CUSTOM_PACKET_NULL";
+
+ case TOX_ERR_FRIEND_CUSTOM_PACKET_FRIEND_NOT_FOUND:
+ return "TOX_ERR_FRIEND_CUSTOM_PACKET_FRIEND_NOT_FOUND";
+
+ case TOX_ERR_FRIEND_CUSTOM_PACKET_FRIEND_NOT_CONNECTED:
+ return "TOX_ERR_FRIEND_CUSTOM_PACKET_FRIEND_NOT_CONNECTED";
+
+ case TOX_ERR_FRIEND_CUSTOM_PACKET_INVALID:
+ return "TOX_ERR_FRIEND_CUSTOM_PACKET_INVALID";
+
+ case TOX_ERR_FRIEND_CUSTOM_PACKET_EMPTY:
+ return "TOX_ERR_FRIEND_CUSTOM_PACKET_EMPTY";
+
+ case TOX_ERR_FRIEND_CUSTOM_PACKET_TOO_LONG:
+ return "TOX_ERR_FRIEND_CUSTOM_PACKET_TOO_LONG";
+
+ case TOX_ERR_FRIEND_CUSTOM_PACKET_SENDQ:
+ return "TOX_ERR_FRIEND_CUSTOM_PACKET_SENDQ";
+ }
+
+ return "<invalid Tox_Err_Friend_Custom_Packet>";
+}
+const char *tox_err_get_port_to_string(Tox_Err_Get_Port value)
+{
+ switch (value) {
+ case TOX_ERR_GET_PORT_OK:
+ return "TOX_ERR_GET_PORT_OK";
+
+ case TOX_ERR_GET_PORT_NOT_BOUND:
+ return "TOX_ERR_GET_PORT_NOT_BOUND";
+ }
+
+ return "<invalid Tox_Err_Get_Port>";
+}
+const char *tox_group_privacy_state_to_string(Tox_Group_Privacy_State value)
+{
+ switch (value) {
+ case TOX_GROUP_PRIVACY_STATE_PUBLIC:
+ return "TOX_GROUP_PRIVACY_STATE_PUBLIC";
+
+ case TOX_GROUP_PRIVACY_STATE_PRIVATE:
+ return "TOX_GROUP_PRIVACY_STATE_PRIVATE";
+ }
+
+ return "<invalid Tox_Group_Privacy_State>";
+}
+const char *tox_group_topic_lock_to_string(Tox_Group_Topic_Lock value)
+{
+ switch (value) {
+ case TOX_GROUP_TOPIC_LOCK_ENABLED:
+ return "TOX_GROUP_TOPIC_LOCK_ENABLED";
+
+ case TOX_GROUP_TOPIC_LOCK_DISABLED:
+ return "TOX_GROUP_TOPIC_LOCK_DISABLED";
+ }
+
+ return "<invalid Tox_Group_Topic_Lock>";
+}
+const char *tox_group_voice_state_to_string(Tox_Group_Voice_State value)
+{
+ switch (value) {
+ case TOX_GROUP_VOICE_STATE_ALL:
+ return "TOX_GROUP_VOICE_STATE_ALL";
+
+ case TOX_GROUP_VOICE_STATE_MODERATOR:
+ return "TOX_GROUP_VOICE_STATE_MODERATOR";
+
+ case TOX_GROUP_VOICE_STATE_FOUNDER:
+ return "TOX_GROUP_VOICE_STATE_FOUNDER";
+ }
+
+ return "<invalid Tox_Group_Voice_State>";
+}
+const char *tox_group_role_to_string(Tox_Group_Role value)
+{
+ switch (value) {
+ case TOX_GROUP_ROLE_FOUNDER:
+ return "TOX_GROUP_ROLE_FOUNDER";
+
+ case TOX_GROUP_ROLE_MODERATOR:
+ return "TOX_GROUP_ROLE_MODERATOR";
+
+ case TOX_GROUP_ROLE_USER:
+ return "TOX_GROUP_ROLE_USER";
+
+ case TOX_GROUP_ROLE_OBSERVER:
+ return "TOX_GROUP_ROLE_OBSERVER";
+ }
+
+ return "<invalid Tox_Group_Role>";
+}
+const char *tox_err_group_new_to_string(Tox_Err_Group_New value)
+{
+ switch (value) {
+ case TOX_ERR_GROUP_NEW_OK:
+ return "TOX_ERR_GROUP_NEW_OK";
+
+ case TOX_ERR_GROUP_NEW_TOO_LONG:
+ return "TOX_ERR_GROUP_NEW_TOO_LONG";
+
+ case TOX_ERR_GROUP_NEW_EMPTY:
+ return "TOX_ERR_GROUP_NEW_EMPTY";
+
+ case TOX_ERR_GROUP_NEW_INIT:
+ return "TOX_ERR_GROUP_NEW_INIT";
+
+ case TOX_ERR_GROUP_NEW_STATE:
+ return "TOX_ERR_GROUP_NEW_STATE";
+
+ case TOX_ERR_GROUP_NEW_ANNOUNCE:
+ return "TOX_ERR_GROUP_NEW_ANNOUNCE";
+ }
+
+ return "<invalid Tox_Err_Group_New>";
+}
+const char *tox_err_group_join_to_string(Tox_Err_Group_Join value)
+{
+ switch (value) {
+ case TOX_ERR_GROUP_JOIN_OK:
+ return "TOX_ERR_GROUP_JOIN_OK";
+
+ case TOX_ERR_GROUP_JOIN_INIT:
+ return "TOX_ERR_GROUP_JOIN_INIT";
+
+ case TOX_ERR_GROUP_JOIN_BAD_CHAT_ID:
+ return "TOX_ERR_GROUP_JOIN_BAD_CHAT_ID";
+
+ case TOX_ERR_GROUP_JOIN_EMPTY:
+ return "TOX_ERR_GROUP_JOIN_EMPTY";
+
+ case TOX_ERR_GROUP_JOIN_TOO_LONG:
+ return "TOX_ERR_GROUP_JOIN_TOO_LONG";
+
+ case TOX_ERR_GROUP_JOIN_PASSWORD:
+ return "TOX_ERR_GROUP_JOIN_PASSWORD";
+
+ case TOX_ERR_GROUP_JOIN_CORE:
+ return "TOX_ERR_GROUP_JOIN_CORE";
+ }
+
+ return "<invalid Tox_Err_Group_Join>";
+}
+const char *tox_err_group_is_connected_to_string(Tox_Err_Group_Is_Connected value)
+{
+ switch (value) {
+ case TOX_ERR_GROUP_IS_CONNECTED_OK:
+ return "TOX_ERR_GROUP_IS_CONNECTED_OK";
+
+ case TOX_ERR_GROUP_IS_CONNECTED_GROUP_NOT_FOUND:
+ return "TOX_ERR_GROUP_IS_CONNECTED_GROUP_NOT_FOUND";
+ }
+
+ return "<invalid Tox_Err_Group_Is_Connected>";
+}
+const char *tox_err_group_disconnect_to_string(Tox_Err_Group_Disconnect value)
+{
+ switch (value) {
+ case TOX_ERR_GROUP_DISCONNECT_OK:
+ return "TOX_ERR_GROUP_DISCONNECT_OK";
+
+ case TOX_ERR_GROUP_DISCONNECT_GROUP_NOT_FOUND:
+ return "TOX_ERR_GROUP_DISCONNECT_GROUP_NOT_FOUND";
+
+ case TOX_ERR_GROUP_DISCONNECT_ALREADY_DISCONNECTED:
+ return "TOX_ERR_GROUP_DISCONNECT_ALREADY_DISCONNECTED";
+ }
+
+ return "<invalid Tox_Err_Group_Disconnect>";
+}
+const char *tox_err_group_reconnect_to_string(Tox_Err_Group_Reconnect value)
+{
+ switch (value) {
+ case TOX_ERR_GROUP_RECONNECT_OK:
+ return "TOX_ERR_GROUP_RECONNECT_OK";
+
+ case TOX_ERR_GROUP_RECONNECT_GROUP_NOT_FOUND:
+ return "TOX_ERR_GROUP_RECONNECT_GROUP_NOT_FOUND";
+
+ case TOX_ERR_GROUP_RECONNECT_CORE:
+ return "TOX_ERR_GROUP_RECONNECT_CORE";
+ }
+
+ return "<invalid Tox_Err_Group_Reconnect>";
+}
+const char *tox_err_group_leave_to_string(Tox_Err_Group_Leave value)
+{
+ switch (value) {
+ case TOX_ERR_GROUP_LEAVE_OK:
+ return "TOX_ERR_GROUP_LEAVE_OK";
+
+ case TOX_ERR_GROUP_LEAVE_GROUP_NOT_FOUND:
+ return "TOX_ERR_GROUP_LEAVE_GROUP_NOT_FOUND";
+
+ case TOX_ERR_GROUP_LEAVE_TOO_LONG:
+ return "TOX_ERR_GROUP_LEAVE_TOO_LONG";
+
+ case TOX_ERR_GROUP_LEAVE_FAIL_SEND:
+ return "TOX_ERR_GROUP_LEAVE_FAIL_SEND";
+ }
+
+ return "<invalid Tox_Err_Group_Leave>";
+}
+const char *tox_err_group_self_query_to_string(Tox_Err_Group_Self_Query value)
+{
+ switch (value) {
+ case TOX_ERR_GROUP_SELF_QUERY_OK:
+ return "TOX_ERR_GROUP_SELF_QUERY_OK";
+
+ case TOX_ERR_GROUP_SELF_QUERY_GROUP_NOT_FOUND:
+ return "TOX_ERR_GROUP_SELF_QUERY_GROUP_NOT_FOUND";
+ }
+
+ return "<invalid Tox_Err_Group_Self_Query>";
+}
+const char *tox_err_group_self_name_set_to_string(Tox_Err_Group_Self_Name_Set value)
+{
+ switch (value) {
+ case TOX_ERR_GROUP_SELF_NAME_SET_OK:
+ return "TOX_ERR_GROUP_SELF_NAME_SET_OK";
+
+ case TOX_ERR_GROUP_SELF_NAME_SET_GROUP_NOT_FOUND:
+ return "TOX_ERR_GROUP_SELF_NAME_SET_GROUP_NOT_FOUND";
+
+ case TOX_ERR_GROUP_SELF_NAME_SET_TOO_LONG:
+ return "TOX_ERR_GROUP_SELF_NAME_SET_TOO_LONG";
+
+ case TOX_ERR_GROUP_SELF_NAME_SET_INVALID:
+ return "TOX_ERR_GROUP_SELF_NAME_SET_INVALID";
+
+ case TOX_ERR_GROUP_SELF_NAME_SET_FAIL_SEND:
+ return "TOX_ERR_GROUP_SELF_NAME_SET_FAIL_SEND";
+ }
+
+ return "<invalid Tox_Err_Group_Self_Name_Set>";
+}
+const char *tox_err_group_self_status_set_to_string(Tox_Err_Group_Self_Status_Set value)
+{
+ switch (value) {
+ case TOX_ERR_GROUP_SELF_STATUS_SET_OK:
+ return "TOX_ERR_GROUP_SELF_STATUS_SET_OK";
+
+ case TOX_ERR_GROUP_SELF_STATUS_SET_GROUP_NOT_FOUND:
+ return "TOX_ERR_GROUP_SELF_STATUS_SET_GROUP_NOT_FOUND";
+
+ case TOX_ERR_GROUP_SELF_STATUS_SET_FAIL_SEND:
+ return "TOX_ERR_GROUP_SELF_STATUS_SET_FAIL_SEND";
+ }
+
+ return "<invalid Tox_Err_Group_Self_Status_Set>";
+}
+const char *tox_err_group_peer_query_to_string(Tox_Err_Group_Peer_Query value)
+{
+ switch (value) {
+ case TOX_ERR_GROUP_PEER_QUERY_OK:
+ return "TOX_ERR_GROUP_PEER_QUERY_OK";
+
+ case TOX_ERR_GROUP_PEER_QUERY_GROUP_NOT_FOUND:
+ return "TOX_ERR_GROUP_PEER_QUERY_GROUP_NOT_FOUND";
+
+ case TOX_ERR_GROUP_PEER_QUERY_PEER_NOT_FOUND:
+ return "TOX_ERR_GROUP_PEER_QUERY_PEER_NOT_FOUND";
+ }
+
+ return "<invalid Tox_Err_Group_Peer_Query>";
+}
+const char *tox_err_group_state_queries_to_string(Tox_Err_Group_State_Queries value)
+{
+ switch (value) {
+ case TOX_ERR_GROUP_STATE_QUERIES_OK:
+ return "TOX_ERR_GROUP_STATE_QUERIES_OK";
+
+ case TOX_ERR_GROUP_STATE_QUERIES_GROUP_NOT_FOUND:
+ return "TOX_ERR_GROUP_STATE_QUERIES_GROUP_NOT_FOUND";
+ }
+
+ return "<invalid Tox_Err_Group_State_Queries>";
+}
+const char *tox_err_group_topic_set_to_string(Tox_Err_Group_Topic_Set value)
+{
+ switch (value) {
+ case TOX_ERR_GROUP_TOPIC_SET_OK:
+ return "TOX_ERR_GROUP_TOPIC_SET_OK";
+
+ case TOX_ERR_GROUP_TOPIC_SET_GROUP_NOT_FOUND:
+ return "TOX_ERR_GROUP_TOPIC_SET_GROUP_NOT_FOUND";
+
+ case TOX_ERR_GROUP_TOPIC_SET_TOO_LONG:
+ return "TOX_ERR_GROUP_TOPIC_SET_TOO_LONG";
+
+ case TOX_ERR_GROUP_TOPIC_SET_PERMISSIONS:
+ return "TOX_ERR_GROUP_TOPIC_SET_PERMISSIONS";
+
+ case TOX_ERR_GROUP_TOPIC_SET_FAIL_CREATE:
+ return "TOX_ERR_GROUP_TOPIC_SET_FAIL_CREATE";
+
+ case TOX_ERR_GROUP_TOPIC_SET_FAIL_SEND:
+ return "TOX_ERR_GROUP_TOPIC_SET_FAIL_SEND";
+
+ case TOX_ERR_GROUP_TOPIC_SET_DISCONNECTED:
+ return "TOX_ERR_GROUP_TOPIC_SET_DISCONNECTED";
+ }
+
+ return "<invalid Tox_Err_Group_Topic_Set>";
+}
+const char *tox_err_group_send_message_to_string(Tox_Err_Group_Send_Message value)
+{
+ switch (value) {
+ case TOX_ERR_GROUP_SEND_MESSAGE_OK:
+ return "TOX_ERR_GROUP_SEND_MESSAGE_OK";
+
+ case TOX_ERR_GROUP_SEND_MESSAGE_GROUP_NOT_FOUND:
+ return "TOX_ERR_GROUP_SEND_MESSAGE_GROUP_NOT_FOUND";
+
+ case TOX_ERR_GROUP_SEND_MESSAGE_TOO_LONG:
+ return "TOX_ERR_GROUP_SEND_MESSAGE_TOO_LONG";
+
+ case TOX_ERR_GROUP_SEND_MESSAGE_EMPTY:
+ return "TOX_ERR_GROUP_SEND_MESSAGE_EMPTY";
+
+ case TOX_ERR_GROUP_SEND_MESSAGE_BAD_TYPE:
+ return "TOX_ERR_GROUP_SEND_MESSAGE_BAD_TYPE";
+
+ case TOX_ERR_GROUP_SEND_MESSAGE_PERMISSIONS:
+ return "TOX_ERR_GROUP_SEND_MESSAGE_PERMISSIONS";
+
+ case TOX_ERR_GROUP_SEND_MESSAGE_FAIL_SEND:
+ return "TOX_ERR_GROUP_SEND_MESSAGE_FAIL_SEND";
+
+ case TOX_ERR_GROUP_SEND_MESSAGE_DISCONNECTED:
+ return "TOX_ERR_GROUP_SEND_MESSAGE_DISCONNECTED";
+ }
+
+ return "<invalid Tox_Err_Group_Send_Message>";
+}
+const char *tox_err_group_send_private_message_to_string(Tox_Err_Group_Send_Private_Message value)
+{
+ switch (value) {
+ case TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_OK:
+ return "TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_OK";
+
+ case TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_GROUP_NOT_FOUND:
+ return "TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_GROUP_NOT_FOUND";
+
+ case TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_PEER_NOT_FOUND:
+ return "TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_PEER_NOT_FOUND";
+
+ case TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_TOO_LONG:
+ return "TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_TOO_LONG";
+
+ case TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_EMPTY:
+ return "TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_EMPTY";
+
+ case TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_PERMISSIONS:
+ return "TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_PERMISSIONS";
+
+ case TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_FAIL_SEND:
+ return "TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_FAIL_SEND";
+
+ case TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_DISCONNECTED:
+ return "TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_DISCONNECTED";
+
+ case TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_BAD_TYPE:
+ return "TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_BAD_TYPE";
+ }
+
+ return "<invalid Tox_Err_Group_Send_Private_Message>";
+}
+const char *tox_err_group_send_custom_packet_to_string(Tox_Err_Group_Send_Custom_Packet value)
+{
+ switch (value) {
+ case TOX_ERR_GROUP_SEND_CUSTOM_PACKET_OK:
+ return "TOX_ERR_GROUP_SEND_CUSTOM_PACKET_OK";
+
+ case TOX_ERR_GROUP_SEND_CUSTOM_PACKET_GROUP_NOT_FOUND:
+ return "TOX_ERR_GROUP_SEND_CUSTOM_PACKET_GROUP_NOT_FOUND";
+
+ case TOX_ERR_GROUP_SEND_CUSTOM_PACKET_TOO_LONG:
+ return "TOX_ERR_GROUP_SEND_CUSTOM_PACKET_TOO_LONG";
+
+ case TOX_ERR_GROUP_SEND_CUSTOM_PACKET_EMPTY:
+ return "TOX_ERR_GROUP_SEND_CUSTOM_PACKET_EMPTY";
+
+ case TOX_ERR_GROUP_SEND_CUSTOM_PACKET_PERMISSIONS:
+ return "TOX_ERR_GROUP_SEND_CUSTOM_PACKET_PERMISSIONS";
+
+ case TOX_ERR_GROUP_SEND_CUSTOM_PACKET_DISCONNECTED:
+ return "TOX_ERR_GROUP_SEND_CUSTOM_PACKET_DISCONNECTED";
+
+ case TOX_ERR_GROUP_SEND_CUSTOM_PACKET_FAIL_SEND:
+ return "TOX_ERR_GROUP_SEND_CUSTOM_PACKET_FAIL_SEND";
+ }
+
+ return "<invalid Tox_Err_Group_Send_Custom_Packet>";
+}
+const char *tox_err_group_send_custom_private_packet_to_string(Tox_Err_Group_Send_Custom_Private_Packet value)
+{
+ switch (value) {
+ case TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_OK:
+ return "TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_OK";
+
+ case TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_GROUP_NOT_FOUND:
+ return "TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_GROUP_NOT_FOUND";
+
+ case TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_TOO_LONG:
+ return "TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_TOO_LONG";
+
+ case TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_EMPTY:
+ return "TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_EMPTY";
+
+ case TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_PEER_NOT_FOUND:
+ return "TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_PEER_NOT_FOUND";
+
+ case TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_PERMISSIONS:
+ return "TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_PERMISSIONS";
+
+ case TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_FAIL_SEND:
+ return "TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_FAIL_SEND";
+
+ case TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_DISCONNECTED:
+ return "TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_DISCONNECTED";
+ }
+
+ return "<invalid Tox_Err_Group_Send_Custom_Private_Packet>";
+}
+const char *tox_err_group_invite_friend_to_string(Tox_Err_Group_Invite_Friend value)
+{
+ switch (value) {
+ case TOX_ERR_GROUP_INVITE_FRIEND_OK:
+ return "TOX_ERR_GROUP_INVITE_FRIEND_OK";
+
+ case TOX_ERR_GROUP_INVITE_FRIEND_GROUP_NOT_FOUND:
+ return "TOX_ERR_GROUP_INVITE_FRIEND_GROUP_NOT_FOUND";
+
+ case TOX_ERR_GROUP_INVITE_FRIEND_FRIEND_NOT_FOUND:
+ return "TOX_ERR_GROUP_INVITE_FRIEND_FRIEND_NOT_FOUND";
+
+ case TOX_ERR_GROUP_INVITE_FRIEND_INVITE_FAIL:
+ return "TOX_ERR_GROUP_INVITE_FRIEND_INVITE_FAIL";
+
+ case TOX_ERR_GROUP_INVITE_FRIEND_FAIL_SEND:
+ return "TOX_ERR_GROUP_INVITE_FRIEND_FAIL_SEND";
+
+ case TOX_ERR_GROUP_INVITE_FRIEND_DISCONNECTED:
+ return "TOX_ERR_GROUP_INVITE_FRIEND_DISCONNECTED";
+ }
+
+ return "<invalid Tox_Err_Group_Invite_Friend>";
+}
+const char *tox_err_group_invite_accept_to_string(Tox_Err_Group_Invite_Accept value)
+{
+ switch (value) {
+ case TOX_ERR_GROUP_INVITE_ACCEPT_OK:
+ return "TOX_ERR_GROUP_INVITE_ACCEPT_OK";
+
+ case TOX_ERR_GROUP_INVITE_ACCEPT_BAD_INVITE:
+ return "TOX_ERR_GROUP_INVITE_ACCEPT_BAD_INVITE";
+
+ case TOX_ERR_GROUP_INVITE_ACCEPT_INIT_FAILED:
+ return "TOX_ERR_GROUP_INVITE_ACCEPT_INIT_FAILED";
+
+ case TOX_ERR_GROUP_INVITE_ACCEPT_TOO_LONG:
+ return "TOX_ERR_GROUP_INVITE_ACCEPT_TOO_LONG";
+
+ case TOX_ERR_GROUP_INVITE_ACCEPT_EMPTY:
+ return "TOX_ERR_GROUP_INVITE_ACCEPT_EMPTY";
+
+ case TOX_ERR_GROUP_INVITE_ACCEPT_PASSWORD:
+ return "TOX_ERR_GROUP_INVITE_ACCEPT_PASSWORD";
+
+ case TOX_ERR_GROUP_INVITE_ACCEPT_CORE:
+ return "TOX_ERR_GROUP_INVITE_ACCEPT_CORE";
+
+ case TOX_ERR_GROUP_INVITE_ACCEPT_FAIL_SEND:
+ return "TOX_ERR_GROUP_INVITE_ACCEPT_FAIL_SEND";
+ }
+
+ return "<invalid Tox_Err_Group_Invite_Accept>";
+}
+const char *tox_group_exit_type_to_string(Tox_Group_Exit_Type value)
+{
+ switch (value) {
+ case TOX_GROUP_EXIT_TYPE_QUIT:
+ return "TOX_GROUP_EXIT_TYPE_QUIT";
+
+ case TOX_GROUP_EXIT_TYPE_TIMEOUT:
+ return "TOX_GROUP_EXIT_TYPE_TIMEOUT";
+
+ case TOX_GROUP_EXIT_TYPE_DISCONNECTED:
+ return "TOX_GROUP_EXIT_TYPE_DISCONNECTED";
+
+ case TOX_GROUP_EXIT_TYPE_SELF_DISCONNECTED:
+ return "TOX_GROUP_EXIT_TYPE_SELF_DISCONNECTED";
+
+ case TOX_GROUP_EXIT_TYPE_KICK:
+ return "TOX_GROUP_EXIT_TYPE_KICK";
+
+ case TOX_GROUP_EXIT_TYPE_SYNC_ERROR:
+ return "TOX_GROUP_EXIT_TYPE_SYNC_ERROR";
+ }
+
+ return "<invalid Tox_Group_Exit_Type>";
+}
+const char *tox_group_join_fail_to_string(Tox_Group_Join_Fail value)
+{
+ switch (value) {
+ case TOX_GROUP_JOIN_FAIL_PEER_LIMIT:
+ return "TOX_GROUP_JOIN_FAIL_PEER_LIMIT";
+
+ case TOX_GROUP_JOIN_FAIL_INVALID_PASSWORD:
+ return "TOX_GROUP_JOIN_FAIL_INVALID_PASSWORD";
+
+ case TOX_GROUP_JOIN_FAIL_UNKNOWN:
+ return "TOX_GROUP_JOIN_FAIL_UNKNOWN";
+ }
+
+ return "<invalid Tox_Group_Join_Fail>";
+}
+const char *tox_err_group_founder_set_password_to_string(Tox_Err_Group_Founder_Set_Password value)
+{
+ switch (value) {
+ case TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_OK:
+ return "TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_OK";
+
+ case TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_GROUP_NOT_FOUND:
+ return "TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_GROUP_NOT_FOUND";
+
+ case TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_PERMISSIONS:
+ return "TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_PERMISSIONS";
+
+ case TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_TOO_LONG:
+ return "TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_TOO_LONG";
+
+ case TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_FAIL_SEND:
+ return "TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_FAIL_SEND";
+
+ case TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_MALLOC:
+ return "TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_MALLOC";
+
+ case TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_DISCONNECTED:
+ return "TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_DISCONNECTED";
+ }
+
+ return "<invalid Tox_Err_Group_Founder_Set_Password>";
+}
+const char *tox_err_group_founder_set_topic_lock_to_string(Tox_Err_Group_Founder_Set_Topic_Lock value)
+{
+ switch (value) {
+ case TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_OK:
+ return "TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_OK";
+
+ case TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_GROUP_NOT_FOUND:
+ return "TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_GROUP_NOT_FOUND";
+
+ case TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_INVALID:
+ return "TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_INVALID";
+
+ case TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_PERMISSIONS:
+ return "TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_PERMISSIONS";
+
+ case TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_FAIL_SET:
+ return "TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_FAIL_SET";
+
+ case TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_FAIL_SEND:
+ return "TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_FAIL_SEND";
+
+ case TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_DISCONNECTED:
+ return "TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_DISCONNECTED";
+ }
+
+ return "<invalid Tox_Err_Group_Founder_Set_Topic_Lock>";
+}
+const char *tox_err_group_founder_set_voice_state_to_string(Tox_Err_Group_Founder_Set_Voice_State value)
+{
+ switch (value) {
+ case TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_OK:
+ return "TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_OK";
+
+ case TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_GROUP_NOT_FOUND:
+ return "TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_GROUP_NOT_FOUND";
+
+ case TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_PERMISSIONS:
+ return "TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_PERMISSIONS";
+
+ case TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_FAIL_SET:
+ return "TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_FAIL_SET";
+
+ case TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_FAIL_SEND:
+ return "TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_FAIL_SEND";
+
+ case TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_DISCONNECTED:
+ return "TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_DISCONNECTED";
+ }
+
+ return "<invalid Tox_Err_Group_Founder_Set_Voice_State>";
+}
+const char *tox_err_group_founder_set_privacy_state_to_string(Tox_Err_Group_Founder_Set_Privacy_State value)
+{
+ switch (value) {
+ case TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_OK:
+ return "TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_OK";
+
+ case TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_GROUP_NOT_FOUND:
+ return "TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_GROUP_NOT_FOUND";
+
+ case TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_PERMISSIONS:
+ return "TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_PERMISSIONS";
+
+ case TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_FAIL_SET:
+ return "TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_FAIL_SET";
+
+ case TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_FAIL_SEND:
+ return "TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_FAIL_SEND";
+
+ case TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_DISCONNECTED:
+ return "TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_DISCONNECTED";
+ }
+
+ return "<invalid Tox_Err_Group_Founder_Set_Privacy_State>";
+}
+const char *tox_err_group_founder_set_peer_limit_to_string(Tox_Err_Group_Founder_Set_Peer_Limit value)
+{
+ switch (value) {
+ case TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_OK:
+ return "TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_OK";
+
+ case TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_GROUP_NOT_FOUND:
+ return "TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_GROUP_NOT_FOUND";
+
+ case TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_PERMISSIONS:
+ return "TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_PERMISSIONS";
+
+ case TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_FAIL_SET:
+ return "TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_FAIL_SET";
+
+ case TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_FAIL_SEND:
+ return "TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_FAIL_SEND";
+
+ case TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_DISCONNECTED:
+ return "TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_DISCONNECTED";
+ }
+
+ return "<invalid Tox_Err_Group_Founder_Set_Peer_Limit>";
+}
+const char *tox_err_group_set_ignore_to_string(Tox_Err_Group_Set_Ignore value)
+{
+ switch (value) {
+ case TOX_ERR_GROUP_SET_IGNORE_OK:
+ return "TOX_ERR_GROUP_SET_IGNORE_OK";
+
+ case TOX_ERR_GROUP_SET_IGNORE_GROUP_NOT_FOUND:
+ return "TOX_ERR_GROUP_SET_IGNORE_GROUP_NOT_FOUND";
+
+ case TOX_ERR_GROUP_SET_IGNORE_PEER_NOT_FOUND:
+ return "TOX_ERR_GROUP_SET_IGNORE_PEER_NOT_FOUND";
+
+ case TOX_ERR_GROUP_SET_IGNORE_SELF:
+ return "TOX_ERR_GROUP_SET_IGNORE_SELF";
+ }
+
+ return "<invalid Tox_Err_Group_Set_Ignore>";
+}
+const char *tox_err_group_mod_set_role_to_string(Tox_Err_Group_Mod_Set_Role value)
+{
+ switch (value) {
+ case TOX_ERR_GROUP_MOD_SET_ROLE_OK:
+ return "TOX_ERR_GROUP_MOD_SET_ROLE_OK";
+
+ case TOX_ERR_GROUP_MOD_SET_ROLE_GROUP_NOT_FOUND:
+ return "TOX_ERR_GROUP_MOD_SET_ROLE_GROUP_NOT_FOUND";
+
+ case TOX_ERR_GROUP_MOD_SET_ROLE_PEER_NOT_FOUND:
+ return "TOX_ERR_GROUP_MOD_SET_ROLE_PEER_NOT_FOUND";
+
+ case TOX_ERR_GROUP_MOD_SET_ROLE_PERMISSIONS:
+ return "TOX_ERR_GROUP_MOD_SET_ROLE_PERMISSIONS";
+
+ case TOX_ERR_GROUP_MOD_SET_ROLE_ASSIGNMENT:
+ return "TOX_ERR_GROUP_MOD_SET_ROLE_ASSIGNMENT";
+
+ case TOX_ERR_GROUP_MOD_SET_ROLE_FAIL_ACTION:
+ return "TOX_ERR_GROUP_MOD_SET_ROLE_FAIL_ACTION";
+
+ case TOX_ERR_GROUP_MOD_SET_ROLE_SELF:
+ return "TOX_ERR_GROUP_MOD_SET_ROLE_SELF";
+ }
+
+ return "<invalid Tox_Err_Group_Mod_Set_Role>";
+}
+const char *tox_err_group_mod_kick_peer_to_string(Tox_Err_Group_Mod_Kick_Peer value)
+{
+ switch (value) {
+ case TOX_ERR_GROUP_MOD_KICK_PEER_OK:
+ return "TOX_ERR_GROUP_MOD_KICK_PEER_OK";
+
+ case TOX_ERR_GROUP_MOD_KICK_PEER_GROUP_NOT_FOUND:
+ return "TOX_ERR_GROUP_MOD_KICK_PEER_GROUP_NOT_FOUND";
+
+ case TOX_ERR_GROUP_MOD_KICK_PEER_PEER_NOT_FOUND:
+ return "TOX_ERR_GROUP_MOD_KICK_PEER_PEER_NOT_FOUND";
+
+ case TOX_ERR_GROUP_MOD_KICK_PEER_PERMISSIONS:
+ return "TOX_ERR_GROUP_MOD_KICK_PEER_PERMISSIONS";
+
+ case TOX_ERR_GROUP_MOD_KICK_PEER_FAIL_ACTION:
+ return "TOX_ERR_GROUP_MOD_KICK_PEER_FAIL_ACTION";
+
+ case TOX_ERR_GROUP_MOD_KICK_PEER_FAIL_SEND:
+ return "TOX_ERR_GROUP_MOD_KICK_PEER_FAIL_SEND";
+
+ case TOX_ERR_GROUP_MOD_KICK_PEER_SELF:
+ return "TOX_ERR_GROUP_MOD_KICK_PEER_SELF";
+ }
+
+ return "<invalid Tox_Err_Group_Mod_Kick_Peer>";
+}
+const char *tox_group_mod_event_to_string(Tox_Group_Mod_Event value)
+{
+ switch (value) {
+ case TOX_GROUP_MOD_EVENT_KICK:
+ return "TOX_GROUP_MOD_EVENT_KICK";
+
+ case TOX_GROUP_MOD_EVENT_OBSERVER:
+ return "TOX_GROUP_MOD_EVENT_OBSERVER";
+
+ case TOX_GROUP_MOD_EVENT_USER:
+ return "TOX_GROUP_MOD_EVENT_USER";
+
+ case TOX_GROUP_MOD_EVENT_MODERATOR:
+ return "TOX_GROUP_MOD_EVENT_MODERATOR";
+ }
+
+ return "<invalid Tox_Group_Mod_Event>";
+}
diff --git a/protocols/Tox/libtox/src/toxcore/tox_dispatch.c b/protocols/Tox/libtox/src/toxcore/tox_dispatch.c
index 5427851470..5383925bfa 100644
--- a/protocols/Tox/libtox/src/toxcore/tox_dispatch.c
+++ b/protocols/Tox/libtox/src/toxcore/tox_dispatch.c
@@ -6,7 +6,12 @@
#include <stdlib.h>
+#include "attributes.h"
#include "ccompat.h"
+#include "events/events_alloc.h" // IWYU pragma: keep
+#include "tox.h"
+#include "tox_event.h"
+#include "tox_events.h"
struct Tox_Dispatch {
tox_events_conference_connected_cb *conference_connected_callback;
@@ -30,6 +35,25 @@ struct Tox_Dispatch {
tox_events_friend_status_message_cb *friend_status_message_callback;
tox_events_friend_typing_cb *friend_typing_callback;
tox_events_self_connection_status_cb *self_connection_status_callback;
+ tox_events_group_peer_name_cb *group_peer_name_callback;
+ tox_events_group_peer_status_cb *group_peer_status_callback;
+ tox_events_group_topic_cb *group_topic_callback;
+ tox_events_group_privacy_state_cb *group_privacy_state_callback;
+ tox_events_group_voice_state_cb *group_voice_state_callback;
+ tox_events_group_topic_lock_cb *group_topic_lock_callback;
+ tox_events_group_peer_limit_cb *group_peer_limit_callback;
+ tox_events_group_password_cb *group_password_callback;
+ tox_events_group_message_cb *group_message_callback;
+ tox_events_group_private_message_cb *group_private_message_callback;
+ tox_events_group_custom_packet_cb *group_custom_packet_callback;
+ tox_events_group_custom_private_packet_cb *group_custom_private_packet_callback;
+ tox_events_group_invite_cb *group_invite_callback;
+ tox_events_group_peer_join_cb *group_peer_join_callback;
+ tox_events_group_peer_exit_cb *group_peer_exit_callback;
+ tox_events_group_self_join_cb *group_self_join_callback;
+ tox_events_group_join_fail_cb *group_join_fail_callback;
+ tox_events_group_moderation_cb *group_moderation_callback;
+ tox_events_dht_get_nodes_response_cb *dht_get_nodes_response_callback;
};
Tox_Dispatch *tox_dispatch_new(Tox_Err_Dispatch_New *error)
@@ -165,322 +189,437 @@ void tox_events_callback_self_connection_status(
{
dispatch->self_connection_status_callback = callback;
}
+void tox_events_callback_group_peer_name(
+ Tox_Dispatch *dispatch, tox_events_group_peer_name_cb *callback)
+{
+ dispatch->group_peer_name_callback = callback;
+}
+void tox_events_callback_group_peer_status(
+ Tox_Dispatch *dispatch, tox_events_group_peer_status_cb *callback)
+{
+ dispatch->group_peer_status_callback = callback;
+}
+void tox_events_callback_group_topic(
+ Tox_Dispatch *dispatch, tox_events_group_topic_cb *callback)
+{
+ dispatch->group_topic_callback = callback;
+}
+void tox_events_callback_group_privacy_state(
+ Tox_Dispatch *dispatch, tox_events_group_privacy_state_cb *callback)
+{
+ dispatch->group_privacy_state_callback = callback;
+}
+void tox_events_callback_group_voice_state(
+ Tox_Dispatch *dispatch, tox_events_group_voice_state_cb *callback)
+{
+ dispatch->group_voice_state_callback = callback;
+}
+void tox_events_callback_group_topic_lock(
+ Tox_Dispatch *dispatch, tox_events_group_topic_lock_cb *callback)
+{
+ dispatch->group_topic_lock_callback = callback;
+}
+void tox_events_callback_group_peer_limit(
+ Tox_Dispatch *dispatch, tox_events_group_peer_limit_cb *callback)
+{
+ dispatch->group_peer_limit_callback = callback;
+}
+void tox_events_callback_group_password(
+ Tox_Dispatch *dispatch, tox_events_group_password_cb *callback)
+{
+ dispatch->group_password_callback = callback;
+}
+void tox_events_callback_group_message(
+ Tox_Dispatch *dispatch, tox_events_group_message_cb *callback)
+{
+ dispatch->group_message_callback = callback;
+}
+void tox_events_callback_group_private_message(
+ Tox_Dispatch *dispatch, tox_events_group_private_message_cb *callback)
+{
+ dispatch->group_private_message_callback = callback;
+}
+void tox_events_callback_group_custom_packet(
+ Tox_Dispatch *dispatch, tox_events_group_custom_packet_cb *callback)
+{
+ dispatch->group_custom_packet_callback = callback;
+}
+void tox_events_callback_group_custom_private_packet(
+ Tox_Dispatch *dispatch, tox_events_group_custom_private_packet_cb *callback)
+{
+ dispatch->group_custom_private_packet_callback = callback;
+}
+void tox_events_callback_group_invite(
+ Tox_Dispatch *dispatch, tox_events_group_invite_cb *callback)
+{
+ dispatch->group_invite_callback = callback;
+}
+void tox_events_callback_group_peer_join(
+ Tox_Dispatch *dispatch, tox_events_group_peer_join_cb *callback)
+{
+ dispatch->group_peer_join_callback = callback;
+}
+void tox_events_callback_group_peer_exit(
+ Tox_Dispatch *dispatch, tox_events_group_peer_exit_cb *callback)
+{
+ dispatch->group_peer_exit_callback = callback;
+}
+void tox_events_callback_group_self_join(
+ Tox_Dispatch *dispatch, tox_events_group_self_join_cb *callback)
+{
+ dispatch->group_self_join_callback = callback;
+}
+void tox_events_callback_group_join_fail(
+ Tox_Dispatch *dispatch, tox_events_group_join_fail_cb *callback)
+{
+ dispatch->group_join_fail_callback = callback;
+}
+void tox_events_callback_group_moderation(
+ Tox_Dispatch *dispatch, tox_events_group_moderation_cb *callback)
+{
+ dispatch->group_moderation_callback = callback;
+}
+void tox_events_callback_dht_get_nodes_response(
+ Tox_Dispatch *dispatch, tox_events_dht_get_nodes_response_cb *callback)
+{
+ dispatch->dht_get_nodes_response_callback = callback;
+}
-non_null(1, 3) nullable(2, 4)
-static void tox_dispatch_invoke_conference_connected(
- const Tox_Dispatch *dispatch, const Tox_Events *events, Tox *tox, void *user_data)
+non_null(1, 2) nullable(3)
+static void tox_dispatch_invoke_event(const Tox_Dispatch *dispatch, const Tox_Event *event, void *user_data)
{
- const uint32_t size = tox_events_get_conference_connected_size(events);
+ switch (event->type) {
+ case TOX_EVENT_CONFERENCE_CONNECTED: {
+ if (dispatch->conference_connected_callback != nullptr) {
+ dispatch->conference_connected_callback(event->data.conference_connected, user_data);
+ }
- for (uint32_t i = 0; i < size; ++i) {
- if (dispatch->conference_connected_callback != nullptr) {
- dispatch->conference_connected_callback(
- tox, tox_events_get_conference_connected(events, i), user_data);
+ break;
}
- }
-}
-non_null(1, 3) nullable(2, 4)
-static void tox_dispatch_invoke_conference_invite(
- const Tox_Dispatch *dispatch, const Tox_Events *events, Tox *tox, void *user_data)
-{
- const uint32_t size = tox_events_get_conference_invite_size(events);
+ case TOX_EVENT_CONFERENCE_INVITE: {
+ if (dispatch->conference_invite_callback != nullptr) {
+ dispatch->conference_invite_callback(event->data.conference_invite, user_data);
+ }
- for (uint32_t i = 0; i < size; ++i) {
- if (dispatch->conference_invite_callback != nullptr) {
- dispatch->conference_invite_callback(
- tox, tox_events_get_conference_invite(events, i), user_data);
+ break;
}
- }
-}
-non_null(1, 3) nullable(2, 4)
-static void tox_dispatch_invoke_conference_message(
- const Tox_Dispatch *dispatch, const Tox_Events *events, Tox *tox, void *user_data)
-{
- const uint32_t size = tox_events_get_conference_message_size(events);
+ case TOX_EVENT_CONFERENCE_MESSAGE: {
+ if (dispatch->conference_message_callback != nullptr) {
+ dispatch->conference_message_callback(event->data.conference_message, user_data);
+ }
- for (uint32_t i = 0; i < size; ++i) {
- if (dispatch->conference_message_callback != nullptr) {
- dispatch->conference_message_callback(
- tox, tox_events_get_conference_message(events, i), user_data);
+ break;
}
- }
-}
-non_null(1, 3) nullable(2, 4)
-static void tox_dispatch_invoke_conference_peer_list_changed(
- const Tox_Dispatch *dispatch, const Tox_Events *events, Tox *tox, void *user_data)
-{
- const uint32_t size = tox_events_get_conference_peer_list_changed_size(events);
+ case TOX_EVENT_CONFERENCE_PEER_LIST_CHANGED: {
+ if (dispatch->conference_peer_list_changed_callback != nullptr) {
+ dispatch->conference_peer_list_changed_callback(event->data.conference_peer_list_changed, user_data);
+ }
- for (uint32_t i = 0; i < size; ++i) {
- if (dispatch->conference_peer_list_changed_callback != nullptr) {
- dispatch->conference_peer_list_changed_callback(
- tox, tox_events_get_conference_peer_list_changed(events, i), user_data);
+ break;
}
- }
-}
-non_null(1, 3) nullable(2, 4)
-static void tox_dispatch_invoke_conference_peer_name(
- const Tox_Dispatch *dispatch, const Tox_Events *events, Tox *tox, void *user_data)
-{
- const uint32_t size = tox_events_get_conference_peer_name_size(events);
+ case TOX_EVENT_CONFERENCE_PEER_NAME: {
+ if (dispatch->conference_peer_name_callback != nullptr) {
+ dispatch->conference_peer_name_callback(event->data.conference_peer_name, user_data);
+ }
- for (uint32_t i = 0; i < size; ++i) {
- if (dispatch->conference_peer_name_callback != nullptr) {
- dispatch->conference_peer_name_callback(
- tox, tox_events_get_conference_peer_name(events, i), user_data);
+ break;
}
- }
-}
-non_null(1, 3) nullable(2, 4)
-static void tox_dispatch_invoke_conference_title(
- const Tox_Dispatch *dispatch, const Tox_Events *events, Tox *tox, void *user_data)
-{
- const uint32_t size = tox_events_get_conference_title_size(events);
+ case TOX_EVENT_CONFERENCE_TITLE: {
+ if (dispatch->conference_title_callback != nullptr) {
+ dispatch->conference_title_callback(event->data.conference_title, user_data);
+ }
- for (uint32_t i = 0; i < size; ++i) {
- if (dispatch->conference_title_callback != nullptr) {
- dispatch->conference_title_callback(
- tox, tox_events_get_conference_title(events, i), user_data);
+ break;
}
- }
-}
-non_null(1, 3) nullable(2, 4)
-static void tox_dispatch_invoke_file_chunk_request(
- const Tox_Dispatch *dispatch, const Tox_Events *events, Tox *tox, void *user_data)
-{
- const uint32_t size = tox_events_get_file_chunk_request_size(events);
+ case TOX_EVENT_FILE_CHUNK_REQUEST: {
+ if (dispatch->file_chunk_request_callback != nullptr) {
+ dispatch->file_chunk_request_callback(event->data.file_chunk_request, user_data);
+ }
- for (uint32_t i = 0; i < size; ++i) {
- if (dispatch->file_chunk_request_callback != nullptr) {
- dispatch->file_chunk_request_callback(
- tox, tox_events_get_file_chunk_request(events, i), user_data);
+ break;
}
- }
-}
-non_null(1, 3) nullable(2, 4)
-static void tox_dispatch_invoke_file_recv(
- const Tox_Dispatch *dispatch, const Tox_Events *events, Tox *tox, void *user_data)
-{
- const uint32_t size = tox_events_get_file_recv_size(events);
+ case TOX_EVENT_FILE_RECV_CHUNK: {
+ if (dispatch->file_recv_chunk_callback != nullptr) {
+ dispatch->file_recv_chunk_callback(event->data.file_recv_chunk, user_data);
+ }
- for (uint32_t i = 0; i < size; ++i) {
- if (dispatch->file_recv_callback != nullptr) {
- dispatch->file_recv_callback(
- tox, tox_events_get_file_recv(events, i), user_data);
+ break;
}
- }
-}
-non_null(1, 3) nullable(2, 4)
-static void tox_dispatch_invoke_file_recv_chunk(
- const Tox_Dispatch *dispatch, const Tox_Events *events, Tox *tox, void *user_data)
-{
- const uint32_t size = tox_events_get_file_recv_chunk_size(events);
+ case TOX_EVENT_FILE_RECV_CONTROL: {
+ if (dispatch->file_recv_control_callback != nullptr) {
+ dispatch->file_recv_control_callback(event->data.file_recv_control, user_data);
+ }
- for (uint32_t i = 0; i < size; ++i) {
- if (dispatch->file_recv_chunk_callback != nullptr) {
- dispatch->file_recv_chunk_callback(
- tox, tox_events_get_file_recv_chunk(events, i), user_data);
+ break;
}
- }
-}
-non_null(1, 3) nullable(2, 4)
-static void tox_dispatch_invoke_file_recv_control(
- const Tox_Dispatch *dispatch, const Tox_Events *events, Tox *tox, void *user_data)
-{
- const uint32_t size = tox_events_get_file_recv_control_size(events);
+ case TOX_EVENT_FILE_RECV: {
+ if (dispatch->file_recv_callback != nullptr) {
+ dispatch->file_recv_callback(event->data.file_recv, user_data);
+ }
- for (uint32_t i = 0; i < size; ++i) {
- if (dispatch->file_recv_control_callback != nullptr) {
- dispatch->file_recv_control_callback(
- tox, tox_events_get_file_recv_control(events, i), user_data);
+ break;
}
- }
-}
-non_null(1, 3) nullable(2, 4)
-static void tox_dispatch_invoke_friend_connection_status(
- const Tox_Dispatch *dispatch, const Tox_Events *events, Tox *tox, void *user_data)
-{
- const uint32_t size = tox_events_get_friend_connection_status_size(events);
+ case TOX_EVENT_FRIEND_CONNECTION_STATUS: {
+ if (dispatch->friend_connection_status_callback != nullptr) {
+ dispatch->friend_connection_status_callback(event->data.friend_connection_status, user_data);
+ }
- for (uint32_t i = 0; i < size; ++i) {
- if (dispatch->friend_connection_status_callback != nullptr) {
- dispatch->friend_connection_status_callback(
- tox, tox_events_get_friend_connection_status(events, i), user_data);
+ break;
}
- }
-}
-non_null(1, 3) nullable(2, 4)
-static void tox_dispatch_invoke_friend_lossless_packet(
- const Tox_Dispatch *dispatch, const Tox_Events *events, Tox *tox, void *user_data)
-{
- const uint32_t size = tox_events_get_friend_lossless_packet_size(events);
+ case TOX_EVENT_FRIEND_LOSSLESS_PACKET: {
+ if (dispatch->friend_lossless_packet_callback != nullptr) {
+ dispatch->friend_lossless_packet_callback(event->data.friend_lossless_packet, user_data);
+ }
- for (uint32_t i = 0; i < size; ++i) {
- if (dispatch->friend_lossless_packet_callback != nullptr) {
- dispatch->friend_lossless_packet_callback(
- tox, tox_events_get_friend_lossless_packet(events, i), user_data);
+ break;
}
- }
-}
-non_null(1, 3) nullable(2, 4)
-static void tox_dispatch_invoke_friend_lossy_packet(
- const Tox_Dispatch *dispatch, const Tox_Events *events, Tox *tox, void *user_data)
-{
- const uint32_t size = tox_events_get_friend_lossy_packet_size(events);
+ case TOX_EVENT_FRIEND_LOSSY_PACKET: {
+ if (dispatch->friend_lossy_packet_callback != nullptr) {
+ dispatch->friend_lossy_packet_callback(event->data.friend_lossy_packet, user_data);
+ }
- for (uint32_t i = 0; i < size; ++i) {
- if (dispatch->friend_lossy_packet_callback != nullptr) {
- dispatch->friend_lossy_packet_callback(
- tox, tox_events_get_friend_lossy_packet(events, i), user_data);
+ break;
}
- }
-}
-non_null(1, 3) nullable(2, 4)
-static void tox_dispatch_invoke_friend_message(
- const Tox_Dispatch *dispatch, const Tox_Events *events, Tox *tox, void *user_data)
-{
- const uint32_t size = tox_events_get_friend_message_size(events);
+ case TOX_EVENT_FRIEND_MESSAGE: {
+ if (dispatch->friend_message_callback != nullptr) {
+ dispatch->friend_message_callback(event->data.friend_message, user_data);
+ }
- for (uint32_t i = 0; i < size; ++i) {
- if (dispatch->friend_message_callback != nullptr) {
- dispatch->friend_message_callback(
- tox, tox_events_get_friend_message(events, i), user_data);
+ break;
}
- }
-}
-non_null(1, 3) nullable(2, 4)
-static void tox_dispatch_invoke_friend_name(
- const Tox_Dispatch *dispatch, const Tox_Events *events, Tox *tox, void *user_data)
-{
- const uint32_t size = tox_events_get_friend_name_size(events);
+ case TOX_EVENT_FRIEND_NAME: {
+ if (dispatch->friend_name_callback != nullptr) {
+ dispatch->friend_name_callback(event->data.friend_name, user_data);
+ }
- for (uint32_t i = 0; i < size; ++i) {
- if (dispatch->friend_name_callback != nullptr) {
- dispatch->friend_name_callback(
- tox, tox_events_get_friend_name(events, i), user_data);
+ break;
}
- }
-}
-non_null(1, 3) nullable(2, 4)
-static void tox_dispatch_invoke_friend_read_receipt(
- const Tox_Dispatch *dispatch, const Tox_Events *events, Tox *tox, void *user_data)
-{
- const uint32_t size = tox_events_get_friend_read_receipt_size(events);
+ case TOX_EVENT_FRIEND_READ_RECEIPT: {
+ if (dispatch->friend_read_receipt_callback != nullptr) {
+ dispatch->friend_read_receipt_callback(event->data.friend_read_receipt, user_data);
+ }
- for (uint32_t i = 0; i < size; ++i) {
- if (dispatch->friend_read_receipt_callback != nullptr) {
- dispatch->friend_read_receipt_callback(
- tox, tox_events_get_friend_read_receipt(events, i), user_data);
+ break;
}
- }
-}
-non_null(1, 3) nullable(2, 4)
-static void tox_dispatch_invoke_friend_request(
- const Tox_Dispatch *dispatch, const Tox_Events *events, Tox *tox, void *user_data)
-{
- const uint32_t size = tox_events_get_friend_request_size(events);
+ case TOX_EVENT_FRIEND_REQUEST: {
+ if (dispatch->friend_request_callback != nullptr) {
+ dispatch->friend_request_callback(event->data.friend_request, user_data);
+ }
- for (uint32_t i = 0; i < size; ++i) {
- if (dispatch->friend_request_callback != nullptr) {
- dispatch->friend_request_callback(
- tox, tox_events_get_friend_request(events, i), user_data);
+ break;
}
- }
-}
-non_null(1, 3) nullable(2, 4)
-static void tox_dispatch_invoke_friend_status(
- const Tox_Dispatch *dispatch, const Tox_Events *events, Tox *tox, void *user_data)
-{
- const uint32_t size = tox_events_get_friend_status_size(events);
+ case TOX_EVENT_FRIEND_STATUS: {
+ if (dispatch->friend_status_callback != nullptr) {
+ dispatch->friend_status_callback(event->data.friend_status, user_data);
+ }
- for (uint32_t i = 0; i < size; ++i) {
- if (dispatch->friend_status_callback != nullptr) {
- dispatch->friend_status_callback(
- tox, tox_events_get_friend_status(events, i), user_data);
+ break;
}
- }
-}
-non_null(1, 3) nullable(2, 4)
-static void tox_dispatch_invoke_friend_status_message(
- const Tox_Dispatch *dispatch, const Tox_Events *events, Tox *tox, void *user_data)
-{
- const uint32_t size = tox_events_get_friend_status_message_size(events);
+ case TOX_EVENT_FRIEND_STATUS_MESSAGE: {
+ if (dispatch->friend_status_message_callback != nullptr) {
+ dispatch->friend_status_message_callback(event->data.friend_status_message, user_data);
+ }
- for (uint32_t i = 0; i < size; ++i) {
- if (dispatch->friend_status_message_callback != nullptr) {
- dispatch->friend_status_message_callback(
- tox, tox_events_get_friend_status_message(events, i), user_data);
+ break;
}
- }
-}
-non_null(1, 3) nullable(2, 4)
-static void tox_dispatch_invoke_friend_typing(
- const Tox_Dispatch *dispatch, const Tox_Events *events, Tox *tox, void *user_data)
-{
- const uint32_t size = tox_events_get_friend_typing_size(events);
+ case TOX_EVENT_FRIEND_TYPING: {
+ if (dispatch->friend_typing_callback != nullptr) {
+ dispatch->friend_typing_callback(event->data.friend_typing, user_data);
+ }
- for (uint32_t i = 0; i < size; ++i) {
- if (dispatch->friend_typing_callback != nullptr) {
- dispatch->friend_typing_callback(
- tox, tox_events_get_friend_typing(events, i), user_data);
+ break;
}
- }
-}
-non_null(1, 3) nullable(2, 4)
-static void tox_dispatch_invoke_self_connection_status(
- const Tox_Dispatch *dispatch, const Tox_Events *events, Tox *tox, void *user_data)
-{
- const uint32_t size = tox_events_get_self_connection_status_size(events);
+ case TOX_EVENT_SELF_CONNECTION_STATUS: {
+ if (dispatch->self_connection_status_callback != nullptr) {
+ dispatch->self_connection_status_callback(event->data.self_connection_status, user_data);
+ }
- for (uint32_t i = 0; i < size; ++i) {
- if (dispatch->self_connection_status_callback != nullptr) {
- dispatch->self_connection_status_callback(
- tox, tox_events_get_self_connection_status(events, i), user_data);
+ break;
+ }
+
+ case TOX_EVENT_GROUP_PEER_NAME: {
+ if (dispatch->group_peer_name_callback != nullptr) {
+ dispatch->group_peer_name_callback(event->data.group_peer_name, user_data);
+ }
+
+ break;
+ }
+
+ case TOX_EVENT_GROUP_PEER_STATUS: {
+ if (dispatch->group_peer_status_callback != nullptr) {
+ dispatch->group_peer_status_callback(event->data.group_peer_status, user_data);
+ }
+
+ break;
+ }
+
+ case TOX_EVENT_GROUP_TOPIC: {
+ if (dispatch->group_topic_callback != nullptr) {
+ dispatch->group_topic_callback(event->data.group_topic, user_data);
+ }
+
+ break;
+ }
+
+ case TOX_EVENT_GROUP_PRIVACY_STATE: {
+ if (dispatch->group_privacy_state_callback != nullptr) {
+ dispatch->group_privacy_state_callback(event->data.group_privacy_state, user_data);
+ }
+
+ break;
+ }
+
+ case TOX_EVENT_GROUP_VOICE_STATE: {
+ if (dispatch->group_voice_state_callback != nullptr) {
+ dispatch->group_voice_state_callback(event->data.group_voice_state, user_data);
+ }
+
+ break;
+ }
+
+ case TOX_EVENT_GROUP_TOPIC_LOCK: {
+ if (dispatch->group_topic_lock_callback != nullptr) {
+ dispatch->group_topic_lock_callback(event->data.group_topic_lock, user_data);
+ }
+
+ break;
+ }
+
+ case TOX_EVENT_GROUP_PEER_LIMIT: {
+ if (dispatch->group_peer_limit_callback != nullptr) {
+ dispatch->group_peer_limit_callback(event->data.group_peer_limit, user_data);
+ }
+
+ break;
+ }
+
+ case TOX_EVENT_GROUP_PASSWORD: {
+ if (dispatch->group_password_callback != nullptr) {
+ dispatch->group_password_callback(event->data.group_password, user_data);
+ }
+
+ break;
+ }
+
+ case TOX_EVENT_GROUP_MESSAGE: {
+ if (dispatch->group_message_callback != nullptr) {
+ dispatch->group_message_callback(event->data.group_message, user_data);
+ }
+
+ break;
+ }
+
+ case TOX_EVENT_GROUP_PRIVATE_MESSAGE: {
+ if (dispatch->group_private_message_callback != nullptr) {
+ dispatch->group_private_message_callback(event->data.group_private_message, user_data);
+ }
+
+ break;
+ }
+
+ case TOX_EVENT_GROUP_CUSTOM_PACKET: {
+ if (dispatch->group_custom_packet_callback != nullptr) {
+ dispatch->group_custom_packet_callback(event->data.group_custom_packet, user_data);
+ }
+
+ break;
+ }
+
+ case TOX_EVENT_GROUP_CUSTOM_PRIVATE_PACKET: {
+ if (dispatch->group_custom_private_packet_callback != nullptr) {
+ dispatch->group_custom_private_packet_callback(event->data.group_custom_private_packet, user_data);
+ }
+
+ break;
+ }
+
+ case TOX_EVENT_GROUP_INVITE: {
+ if (dispatch->group_invite_callback != nullptr) {
+ dispatch->group_invite_callback(event->data.group_invite, user_data);
+ }
+
+ break;
+ }
+
+ case TOX_EVENT_GROUP_PEER_JOIN: {
+ if (dispatch->group_peer_join_callback != nullptr) {
+ dispatch->group_peer_join_callback(event->data.group_peer_join, user_data);
+ }
+
+ break;
+ }
+
+ case TOX_EVENT_GROUP_PEER_EXIT: {
+ if (dispatch->group_peer_exit_callback != nullptr) {
+ dispatch->group_peer_exit_callback(event->data.group_peer_exit, user_data);
+ }
+
+ break;
+ }
+
+ case TOX_EVENT_GROUP_SELF_JOIN: {
+ if (dispatch->group_self_join_callback != nullptr) {
+ dispatch->group_self_join_callback(event->data.group_self_join, user_data);
+ }
+
+ break;
+ }
+
+ case TOX_EVENT_GROUP_JOIN_FAIL: {
+ if (dispatch->group_join_fail_callback != nullptr) {
+ dispatch->group_join_fail_callback(event->data.group_join_fail, user_data);
+ }
+
+ break;
+ }
+
+ case TOX_EVENT_GROUP_MODERATION: {
+ if (dispatch->group_moderation_callback != nullptr) {
+ dispatch->group_moderation_callback(event->data.group_moderation, user_data);
+ }
+
+ break;
+ }
+
+ case TOX_EVENT_DHT_GET_NODES_RESPONSE: {
+ if (dispatch->dht_get_nodes_response_callback != nullptr) {
+ dispatch->dht_get_nodes_response_callback(event->data.dht_get_nodes_response, user_data);
+ }
+
+ break;
+ }
+
+ case TOX_EVENT_INVALID: {
+ break;
}
}
}
-void tox_dispatch_invoke(const Tox_Dispatch *dispatch, const Tox_Events *events, Tox *tox, void *user_data)
-{
- tox_dispatch_invoke_conference_connected(dispatch, events, tox, user_data);
- tox_dispatch_invoke_conference_invite(dispatch, events, tox, user_data);
- tox_dispatch_invoke_conference_message(dispatch, events, tox, user_data);
- tox_dispatch_invoke_conference_peer_list_changed(dispatch, events, tox, user_data);
- tox_dispatch_invoke_conference_peer_name(dispatch, events, tox, user_data);
- tox_dispatch_invoke_conference_title(dispatch, events, tox, user_data);
- tox_dispatch_invoke_file_chunk_request(dispatch, events, tox, user_data);
- tox_dispatch_invoke_file_recv(dispatch, events, tox, user_data);
- tox_dispatch_invoke_file_recv_chunk(dispatch, events, tox, user_data);
- tox_dispatch_invoke_file_recv_control(dispatch, events, tox, user_data);
- tox_dispatch_invoke_friend_connection_status(dispatch, events, tox, user_data);
- tox_dispatch_invoke_friend_lossless_packet(dispatch, events, tox, user_data);
- tox_dispatch_invoke_friend_lossy_packet(dispatch, events, tox, user_data);
- tox_dispatch_invoke_friend_message(dispatch, events, tox, user_data);
- tox_dispatch_invoke_friend_name(dispatch, events, tox, user_data);
- tox_dispatch_invoke_friend_read_receipt(dispatch, events, tox, user_data);
- tox_dispatch_invoke_friend_request(dispatch, events, tox, user_data);
- tox_dispatch_invoke_friend_status(dispatch, events, tox, user_data);
- tox_dispatch_invoke_friend_status_message(dispatch, events, tox, user_data);
- tox_dispatch_invoke_friend_typing(dispatch, events, tox, user_data);
- tox_dispatch_invoke_self_connection_status(dispatch, events, tox, user_data);
+void tox_dispatch_invoke(const Tox_Dispatch *dispatch, const Tox_Events *events, void *user_data)
+{
+ const uint32_t size = tox_events_get_size(events);
+ for (uint32_t i = 0; i < size; ++i) {
+ const Tox_Event *event = &events->events[i];
+ tox_dispatch_invoke_event(dispatch, event, user_data);
+ }
}
diff --git a/protocols/Tox/libtox/src/toxcore/tox_dispatch.h b/protocols/Tox/libtox/src/toxcore/tox_dispatch.h
index 7e8fbba376..2588065a4d 100644
--- a/protocols/Tox/libtox/src/toxcore/tox_dispatch.h
+++ b/protocols/Tox/libtox/src/toxcore/tox_dispatch.h
@@ -5,6 +5,7 @@
#ifndef C_TOXCORE_TOXCORE_TOX_DISPATCH_H
#define C_TOXCORE_TOXCORE_TOX_DISPATCH_H
+#include "tox.h"
#include "tox_events.h"
#ifdef __cplusplus
@@ -46,53 +47,90 @@ void tox_dispatch_free(Tox_Dispatch *dispatch);
*
* @param dispatch The events dispatch table.
* @param events The events object received from @ref tox_events_iterate.
- * @param tox The tox object to pass down to the callbacks.
* @param user_data User data pointer to pass down to the callbacks.
*/
-void tox_dispatch_invoke(const Tox_Dispatch *dispatch, const Tox_Events *events, Tox *tox, void *user_data);
+void tox_dispatch_invoke(const Tox_Dispatch *dispatch, const Tox_Events *events, void *user_data);
typedef void tox_events_conference_connected_cb(
- Tox *tox, const Tox_Event_Conference_Connected *event, void *user_data);
+ const Tox_Event_Conference_Connected *event, void *user_data);
typedef void tox_events_conference_invite_cb(
- Tox *tox, const Tox_Event_Conference_Invite *event, void *user_data);
+ const Tox_Event_Conference_Invite *event, void *user_data);
typedef void tox_events_conference_message_cb(
- Tox *tox, const Tox_Event_Conference_Message *event, void *user_data);
+ const Tox_Event_Conference_Message *event, void *user_data);
typedef void tox_events_conference_peer_list_changed_cb(
- Tox *tox, const Tox_Event_Conference_Peer_List_Changed *event, void *user_data);
+ const Tox_Event_Conference_Peer_List_Changed *event, void *user_data);
typedef void tox_events_conference_peer_name_cb(
- Tox *tox, const Tox_Event_Conference_Peer_Name *event, void *user_data);
+ const Tox_Event_Conference_Peer_Name *event, void *user_data);
typedef void tox_events_conference_title_cb(
- Tox *tox, const Tox_Event_Conference_Title *event, void *user_data);
+ const Tox_Event_Conference_Title *event, void *user_data);
typedef void tox_events_file_chunk_request_cb(
- Tox *tox, const Tox_Event_File_Chunk_Request *event, void *user_data);
+ const Tox_Event_File_Chunk_Request *event, void *user_data);
typedef void tox_events_file_recv_cb(
- Tox *tox, const Tox_Event_File_Recv *event, void *user_data);
+ const Tox_Event_File_Recv *event, void *user_data);
typedef void tox_events_file_recv_chunk_cb(
- Tox *tox, const Tox_Event_File_Recv_Chunk *event, void *user_data);
+ const Tox_Event_File_Recv_Chunk *event, void *user_data);
typedef void tox_events_file_recv_control_cb(
- Tox *tox, const Tox_Event_File_Recv_Control *event, void *user_data);
+ const Tox_Event_File_Recv_Control *event, void *user_data);
typedef void tox_events_friend_connection_status_cb(
- Tox *tox, const Tox_Event_Friend_Connection_Status *event, void *user_data);
+ const Tox_Event_Friend_Connection_Status *event, void *user_data);
typedef void tox_events_friend_lossless_packet_cb(
- Tox *tox, const Tox_Event_Friend_Lossless_Packet *event, void *user_data);
+ const Tox_Event_Friend_Lossless_Packet *event, void *user_data);
typedef void tox_events_friend_lossy_packet_cb(
- Tox *tox, const Tox_Event_Friend_Lossy_Packet *event, void *user_data);
+ const Tox_Event_Friend_Lossy_Packet *event, void *user_data);
typedef void tox_events_friend_message_cb(
- Tox *tox, const Tox_Event_Friend_Message *event, void *user_data);
+ const Tox_Event_Friend_Message *event, void *user_data);
typedef void tox_events_friend_name_cb(
- Tox *tox, const Tox_Event_Friend_Name *event, void *user_data);
+ const Tox_Event_Friend_Name *event, void *user_data);
typedef void tox_events_friend_read_receipt_cb(
- Tox *tox, const Tox_Event_Friend_Read_Receipt *event, void *user_data);
+ const Tox_Event_Friend_Read_Receipt *event, void *user_data);
typedef void tox_events_friend_request_cb(
- Tox *tox, const Tox_Event_Friend_Request *event, void *user_data);
+ const Tox_Event_Friend_Request *event, void *user_data);
typedef void tox_events_friend_status_cb(
- Tox *tox, const Tox_Event_Friend_Status *event, void *user_data);
+ const Tox_Event_Friend_Status *event, void *user_data);
typedef void tox_events_friend_status_message_cb(
- Tox *tox, const Tox_Event_Friend_Status_Message *event, void *user_data);
+ const Tox_Event_Friend_Status_Message *event, void *user_data);
typedef void tox_events_friend_typing_cb(
- Tox *tox, const Tox_Event_Friend_Typing *event, void *user_data);
+ const Tox_Event_Friend_Typing *event, void *user_data);
typedef void tox_events_self_connection_status_cb(
- Tox *tox, const Tox_Event_Self_Connection_Status *event, void *user_data);
+ const Tox_Event_Self_Connection_Status *event, void *user_data);
+typedef void tox_events_group_peer_name_cb(
+ const Tox_Event_Group_Peer_Name *event, void *user_data);
+typedef void tox_events_group_peer_status_cb(
+ const Tox_Event_Group_Peer_Status *event, void *user_data);
+typedef void tox_events_group_topic_cb(
+ const Tox_Event_Group_Topic *event, void *user_data);
+typedef void tox_events_group_privacy_state_cb(
+ const Tox_Event_Group_Privacy_State *event, void *user_data);
+typedef void tox_events_group_voice_state_cb(
+ const Tox_Event_Group_Voice_State *event, void *user_data);
+typedef void tox_events_group_topic_lock_cb(
+ const Tox_Event_Group_Topic_Lock *event, void *user_data);
+typedef void tox_events_group_peer_limit_cb(
+ const Tox_Event_Group_Peer_Limit *event, void *user_data);
+typedef void tox_events_group_password_cb(
+ const Tox_Event_Group_Password *event, void *user_data);
+typedef void tox_events_group_message_cb(
+ const Tox_Event_Group_Message *event, void *user_data);
+typedef void tox_events_group_private_message_cb(
+ const Tox_Event_Group_Private_Message *event, void *user_data);
+typedef void tox_events_group_custom_packet_cb(
+ const Tox_Event_Group_Custom_Packet *event, void *user_data);
+typedef void tox_events_group_custom_private_packet_cb(
+ const Tox_Event_Group_Custom_Private_Packet *event, void *user_data);
+typedef void tox_events_group_invite_cb(
+ const Tox_Event_Group_Invite *event, void *user_data);
+typedef void tox_events_group_peer_join_cb(
+ const Tox_Event_Group_Peer_Join *event, void *user_data);
+typedef void tox_events_group_peer_exit_cb(
+ const Tox_Event_Group_Peer_Exit *event, void *user_data);
+typedef void tox_events_group_self_join_cb(
+ const Tox_Event_Group_Self_Join *event, void *user_data);
+typedef void tox_events_group_join_fail_cb(
+ const Tox_Event_Group_Join_Fail *event, void *user_data);
+typedef void tox_events_group_moderation_cb(
+ const Tox_Event_Group_Moderation *event, void *user_data);
+typedef void tox_events_dht_get_nodes_response_cb(
+ const Tox_Event_Dht_Get_Nodes_Response *event, void *user_data);
void tox_events_callback_conference_connected(
Tox_Dispatch *dispatch, tox_events_conference_connected_cb *callback);
@@ -136,9 +174,47 @@ void tox_events_callback_friend_typing(
Tox_Dispatch *dispatch, tox_events_friend_typing_cb *callback);
void tox_events_callback_self_connection_status(
Tox_Dispatch *dispatch, tox_events_self_connection_status_cb *callback);
+void tox_events_callback_group_peer_name(
+ Tox_Dispatch *dispatch, tox_events_group_peer_name_cb *callback);
+void tox_events_callback_group_peer_status(
+ Tox_Dispatch *dispatch, tox_events_group_peer_status_cb *callback);
+void tox_events_callback_group_topic(
+ Tox_Dispatch *dispatch, tox_events_group_topic_cb *callback);
+void tox_events_callback_group_privacy_state(
+ Tox_Dispatch *dispatch, tox_events_group_privacy_state_cb *callback);
+void tox_events_callback_group_voice_state(
+ Tox_Dispatch *dispatch, tox_events_group_voice_state_cb *callback);
+void tox_events_callback_group_topic_lock(
+ Tox_Dispatch *dispatch, tox_events_group_topic_lock_cb *callback);
+void tox_events_callback_group_peer_limit(
+ Tox_Dispatch *dispatch, tox_events_group_peer_limit_cb *callback);
+void tox_events_callback_group_password(
+ Tox_Dispatch *dispatch, tox_events_group_password_cb *callback);
+void tox_events_callback_group_message(
+ Tox_Dispatch *dispatch, tox_events_group_message_cb *callback);
+void tox_events_callback_group_private_message(
+ Tox_Dispatch *dispatch, tox_events_group_private_message_cb *callback);
+void tox_events_callback_group_custom_packet(
+ Tox_Dispatch *dispatch, tox_events_group_custom_packet_cb *callback);
+void tox_events_callback_group_custom_private_packet(
+ Tox_Dispatch *dispatch, tox_events_group_custom_private_packet_cb *callback);
+void tox_events_callback_group_invite(
+ Tox_Dispatch *dispatch, tox_events_group_invite_cb *callback);
+void tox_events_callback_group_peer_join(
+ Tox_Dispatch *dispatch, tox_events_group_peer_join_cb *callback);
+void tox_events_callback_group_peer_exit(
+ Tox_Dispatch *dispatch, tox_events_group_peer_exit_cb *callback);
+void tox_events_callback_group_self_join(
+ Tox_Dispatch *dispatch, tox_events_group_self_join_cb *callback);
+void tox_events_callback_group_join_fail(
+ Tox_Dispatch *dispatch, tox_events_group_join_fail_cb *callback);
+void tox_events_callback_group_moderation(
+ Tox_Dispatch *dispatch, tox_events_group_moderation_cb *callback);
+void tox_events_callback_dht_get_nodes_response(
+ Tox_Dispatch *dispatch, tox_events_dht_get_nodes_response_cb *callback);
#ifdef __cplusplus
-}
+} /* extern "C" */
#endif
-#endif // C_TOXCORE_TOXCORE_TOX_DISPATCH_H
+#endif /* C_TOXCORE_TOXCORE_TOX_DISPATCH_H */
diff --git a/protocols/Tox/libtox/src/toxcore/tox_event.c b/protocols/Tox/libtox/src/toxcore/tox_event.c
new file mode 100644
index 0000000000..b0a65503cd
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/tox_event.c
@@ -0,0 +1,1087 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2022 The TokTok team.
+ */
+
+#include "tox_event.h"
+
+#include <assert.h>
+
+#include "attributes.h"
+#include "bin_pack.h"
+#include "bin_unpack.h"
+#include "ccompat.h"
+#include "mem.h"
+#include "tox_events.h"
+
+const char *tox_event_type_to_string(Tox_Event_Type type)
+{
+ switch (type) {
+ case TOX_EVENT_SELF_CONNECTION_STATUS:
+ return "TOX_EVENT_SELF_CONNECTION_STATUS";
+
+ case TOX_EVENT_FRIEND_REQUEST:
+ return "TOX_EVENT_FRIEND_REQUEST";
+
+ case TOX_EVENT_FRIEND_CONNECTION_STATUS:
+ return "TOX_EVENT_FRIEND_CONNECTION_STATUS";
+
+ case TOX_EVENT_FRIEND_LOSSY_PACKET:
+ return "TOX_EVENT_FRIEND_LOSSY_PACKET";
+
+ case TOX_EVENT_FRIEND_LOSSLESS_PACKET:
+ return "TOX_EVENT_FRIEND_LOSSLESS_PACKET";
+
+ case TOX_EVENT_FRIEND_NAME:
+ return "TOX_EVENT_FRIEND_NAME";
+
+ case TOX_EVENT_FRIEND_STATUS:
+ return "TOX_EVENT_FRIEND_STATUS";
+
+ case TOX_EVENT_FRIEND_STATUS_MESSAGE:
+ return "TOX_EVENT_FRIEND_STATUS_MESSAGE";
+
+ case TOX_EVENT_FRIEND_MESSAGE:
+ return "TOX_EVENT_FRIEND_MESSAGE";
+
+ case TOX_EVENT_FRIEND_READ_RECEIPT:
+ return "TOX_EVENT_FRIEND_READ_RECEIPT";
+
+ case TOX_EVENT_FRIEND_TYPING:
+ return "TOX_EVENT_FRIEND_TYPING";
+
+ case TOX_EVENT_FILE_CHUNK_REQUEST:
+ return "TOX_EVENT_FILE_CHUNK_REQUEST";
+
+ case TOX_EVENT_FILE_RECV:
+ return "TOX_EVENT_FILE_RECV";
+
+ case TOX_EVENT_FILE_RECV_CHUNK:
+ return "TOX_EVENT_FILE_RECV_CHUNK";
+
+ case TOX_EVENT_FILE_RECV_CONTROL:
+ return "TOX_EVENT_FILE_RECV_CONTROL";
+
+ case TOX_EVENT_CONFERENCE_INVITE:
+ return "TOX_EVENT_CONFERENCE_INVITE";
+
+ case TOX_EVENT_CONFERENCE_CONNECTED:
+ return "TOX_EVENT_CONFERENCE_CONNECTED";
+
+ case TOX_EVENT_CONFERENCE_PEER_LIST_CHANGED:
+ return "TOX_EVENT_CONFERENCE_PEER_LIST_CHANGED";
+
+ case TOX_EVENT_CONFERENCE_PEER_NAME:
+ return "TOX_EVENT_CONFERENCE_PEER_NAME";
+
+ case TOX_EVENT_CONFERENCE_TITLE:
+ return "TOX_EVENT_CONFERENCE_TITLE";
+
+ case TOX_EVENT_CONFERENCE_MESSAGE:
+ return "TOX_EVENT_CONFERENCE_MESSAGE";
+
+ case TOX_EVENT_GROUP_PEER_NAME:
+ return "TOX_EVENT_GROUP_PEER_NAME";
+
+ case TOX_EVENT_GROUP_PEER_STATUS:
+ return "TOX_EVENT_GROUP_PEER_STATUS";
+
+ case TOX_EVENT_GROUP_TOPIC:
+ return "TOX_EVENT_GROUP_TOPIC";
+
+ case TOX_EVENT_GROUP_PRIVACY_STATE:
+ return "TOX_EVENT_GROUP_PRIVACY_STATE";
+
+ case TOX_EVENT_GROUP_VOICE_STATE:
+ return "TOX_EVENT_GROUP_VOICE_STATE";
+
+ case TOX_EVENT_GROUP_TOPIC_LOCK:
+ return "TOX_EVENT_GROUP_TOPIC_LOCK";
+
+ case TOX_EVENT_GROUP_PEER_LIMIT:
+ return "TOX_EVENT_GROUP_PEER_LIMIT";
+
+ case TOX_EVENT_GROUP_PASSWORD:
+ return "TOX_EVENT_GROUP_PASSWORD";
+
+ case TOX_EVENT_GROUP_MESSAGE:
+ return "TOX_EVENT_GROUP_MESSAGE";
+
+ case TOX_EVENT_GROUP_PRIVATE_MESSAGE:
+ return "TOX_EVENT_GROUP_PRIVATE_MESSAGE";
+
+ case TOX_EVENT_GROUP_CUSTOM_PACKET:
+ return "TOX_EVENT_GROUP_CUSTOM_PACKET";
+
+ case TOX_EVENT_GROUP_CUSTOM_PRIVATE_PACKET:
+ return "TOX_EVENT_GROUP_CUSTOM_PRIVATE_PACKET";
+
+ case TOX_EVENT_GROUP_INVITE:
+ return "TOX_EVENT_GROUP_INVITE";
+
+ case TOX_EVENT_GROUP_PEER_JOIN:
+ return "TOX_EVENT_GROUP_PEER_JOIN";
+
+ case TOX_EVENT_GROUP_PEER_EXIT:
+ return "TOX_EVENT_GROUP_PEER_EXIT";
+
+ case TOX_EVENT_GROUP_SELF_JOIN:
+ return "TOX_EVENT_GROUP_SELF_JOIN";
+
+ case TOX_EVENT_GROUP_JOIN_FAIL:
+ return "TOX_EVENT_GROUP_JOIN_FAIL";
+
+ case TOX_EVENT_GROUP_MODERATION:
+ return "TOX_EVENT_GROUP_MODERATION";
+
+ case TOX_EVENT_DHT_GET_NODES_RESPONSE:
+ return "TOX_EVENT_DHT_GET_NODES_RESPONSE";
+
+ case TOX_EVENT_INVALID:
+ return "TOX_EVENT_INVALID";
+ }
+
+ return "<invalid Tox_Event_Type>";
+}
+
+Tox_Event_Type tox_event_get_type(const Tox_Event *event)
+{
+ assert(event != nullptr);
+ return event->type;
+}
+
+bool tox_event_construct(Tox_Event *event, Tox_Event_Type type, const Memory *mem)
+{
+ event->type = type;
+ event->data.value = nullptr;
+
+ switch (type) {
+ case TOX_EVENT_CONFERENCE_CONNECTED: {
+ event->data.conference_connected = tox_event_conference_connected_new(mem);
+ break;
+ }
+
+ case TOX_EVENT_CONFERENCE_INVITE: {
+ event->data.conference_invite = tox_event_conference_invite_new(mem);
+ break;
+ }
+
+ case TOX_EVENT_CONFERENCE_MESSAGE: {
+ event->data.conference_message = tox_event_conference_message_new(mem);
+ break;
+ }
+
+ case TOX_EVENT_CONFERENCE_PEER_LIST_CHANGED: {
+ event->data.conference_peer_list_changed = tox_event_conference_peer_list_changed_new(mem);
+ break;
+ }
+
+ case TOX_EVENT_CONFERENCE_PEER_NAME: {
+ event->data.conference_peer_name = tox_event_conference_peer_name_new(mem);
+ break;
+ }
+
+ case TOX_EVENT_CONFERENCE_TITLE: {
+ event->data.conference_title = tox_event_conference_title_new(mem);
+ break;
+ }
+
+ case TOX_EVENT_FILE_CHUNK_REQUEST: {
+ event->data.file_chunk_request = tox_event_file_chunk_request_new(mem);
+ break;
+ }
+
+ case TOX_EVENT_FILE_RECV_CHUNK: {
+ event->data.file_recv_chunk = tox_event_file_recv_chunk_new(mem);
+ break;
+ }
+
+ case TOX_EVENT_FILE_RECV_CONTROL: {
+ event->data.file_recv_control = tox_event_file_recv_control_new(mem);
+ break;
+ }
+
+ case TOX_EVENT_FILE_RECV: {
+ event->data.file_recv = tox_event_file_recv_new(mem);
+ break;
+ }
+
+ case TOX_EVENT_FRIEND_CONNECTION_STATUS: {
+ event->data.friend_connection_status = tox_event_friend_connection_status_new(mem);
+ break;
+ }
+
+ case TOX_EVENT_FRIEND_LOSSLESS_PACKET: {
+ event->data.friend_lossless_packet = tox_event_friend_lossless_packet_new(mem);
+ break;
+ }
+
+ case TOX_EVENT_FRIEND_LOSSY_PACKET: {
+ event->data.friend_lossy_packet = tox_event_friend_lossy_packet_new(mem);
+ break;
+ }
+
+ case TOX_EVENT_FRIEND_MESSAGE: {
+ event->data.friend_message = tox_event_friend_message_new(mem);
+ break;
+ }
+
+ case TOX_EVENT_FRIEND_NAME: {
+ event->data.friend_name = tox_event_friend_name_new(mem);
+ break;
+ }
+
+ case TOX_EVENT_FRIEND_READ_RECEIPT: {
+ event->data.friend_read_receipt = tox_event_friend_read_receipt_new(mem);
+ break;
+ }
+
+ case TOX_EVENT_FRIEND_REQUEST: {
+ event->data.friend_request = tox_event_friend_request_new(mem);
+ break;
+ }
+
+ case TOX_EVENT_FRIEND_STATUS: {
+ event->data.friend_status = tox_event_friend_status_new(mem);
+ break;
+ }
+
+ case TOX_EVENT_FRIEND_STATUS_MESSAGE: {
+ event->data.friend_status_message = tox_event_friend_status_message_new(mem);
+ break;
+ }
+
+ case TOX_EVENT_FRIEND_TYPING: {
+ event->data.friend_typing = tox_event_friend_typing_new(mem);
+ break;
+ }
+
+ case TOX_EVENT_SELF_CONNECTION_STATUS: {
+ event->data.self_connection_status = tox_event_self_connection_status_new(mem);
+ break;
+ }
+
+ case TOX_EVENT_GROUP_PEER_NAME: {
+ event->data.group_peer_name = tox_event_group_peer_name_new(mem);
+ break;
+ }
+
+ case TOX_EVENT_GROUP_PEER_STATUS: {
+ event->data.group_peer_status = tox_event_group_peer_status_new(mem);
+ break;
+ }
+
+ case TOX_EVENT_GROUP_TOPIC: {
+ event->data.group_topic = tox_event_group_topic_new(mem);
+ break;
+ }
+
+ case TOX_EVENT_GROUP_PRIVACY_STATE: {
+ event->data.group_privacy_state = tox_event_group_privacy_state_new(mem);
+ break;
+ }
+
+ case TOX_EVENT_GROUP_VOICE_STATE: {
+ event->data.group_voice_state = tox_event_group_voice_state_new(mem);
+ break;
+ }
+
+ case TOX_EVENT_GROUP_TOPIC_LOCK: {
+ event->data.group_topic_lock = tox_event_group_topic_lock_new(mem);
+ break;
+ }
+
+ case TOX_EVENT_GROUP_PEER_LIMIT: {
+ event->data.group_peer_limit = tox_event_group_peer_limit_new(mem);
+ break;
+ }
+
+ case TOX_EVENT_GROUP_PASSWORD: {
+ event->data.group_password = tox_event_group_password_new(mem);
+ break;
+ }
+
+ case TOX_EVENT_GROUP_MESSAGE: {
+ event->data.group_message = tox_event_group_message_new(mem);
+ break;
+ }
+
+ case TOX_EVENT_GROUP_PRIVATE_MESSAGE: {
+ event->data.group_private_message = tox_event_group_private_message_new(mem);
+ break;
+ }
+
+ case TOX_EVENT_GROUP_CUSTOM_PACKET: {
+ event->data.group_custom_packet = tox_event_group_custom_packet_new(mem);
+ break;
+ }
+
+ case TOX_EVENT_GROUP_CUSTOM_PRIVATE_PACKET: {
+ event->data.group_custom_private_packet = tox_event_group_custom_private_packet_new(mem);
+ break;
+ }
+
+ case TOX_EVENT_GROUP_INVITE: {
+ event->data.group_invite = tox_event_group_invite_new(mem);
+ break;
+ }
+
+ case TOX_EVENT_GROUP_PEER_JOIN: {
+ event->data.group_peer_join = tox_event_group_peer_join_new(mem);
+ break;
+ }
+
+ case TOX_EVENT_GROUP_PEER_EXIT: {
+ event->data.group_peer_exit = tox_event_group_peer_exit_new(mem);
+ break;
+ }
+
+ case TOX_EVENT_GROUP_SELF_JOIN: {
+ event->data.group_self_join = tox_event_group_self_join_new(mem);
+ break;
+ }
+
+ case TOX_EVENT_GROUP_JOIN_FAIL: {
+ event->data.group_join_fail = tox_event_group_join_fail_new(mem);
+ break;
+ }
+
+ case TOX_EVENT_GROUP_MODERATION: {
+ event->data.group_moderation = tox_event_group_moderation_new(mem);
+ break;
+ }
+
+ case TOX_EVENT_DHT_GET_NODES_RESPONSE: {
+ event->data.dht_get_nodes_response = tox_event_dht_get_nodes_response_new(mem);
+ break;
+ }
+
+ case TOX_EVENT_INVALID: {
+ return false;
+ }
+ }
+
+ return event->data.value != nullptr;
+}
+
+void tox_event_destruct(Tox_Event *event, const Memory *mem)
+{
+ if (event == nullptr) {
+ return;
+ }
+
+ switch (event->type) {
+ case TOX_EVENT_CONFERENCE_CONNECTED: {
+ tox_event_conference_connected_free(event->data.conference_connected, mem);
+ break;
+ }
+
+ case TOX_EVENT_CONFERENCE_INVITE: {
+ tox_event_conference_invite_free(event->data.conference_invite, mem);
+ break;
+ }
+
+ case TOX_EVENT_CONFERENCE_MESSAGE: {
+ tox_event_conference_message_free(event->data.conference_message, mem);
+ break;
+ }
+
+ case TOX_EVENT_CONFERENCE_PEER_LIST_CHANGED: {
+ tox_event_conference_peer_list_changed_free(event->data.conference_peer_list_changed, mem);
+ break;
+ }
+
+ case TOX_EVENT_CONFERENCE_PEER_NAME: {
+ tox_event_conference_peer_name_free(event->data.conference_peer_name, mem);
+ break;
+ }
+
+ case TOX_EVENT_CONFERENCE_TITLE: {
+ tox_event_conference_title_free(event->data.conference_title, mem);
+ break;
+ }
+
+ case TOX_EVENT_FILE_CHUNK_REQUEST: {
+ tox_event_file_chunk_request_free(event->data.file_chunk_request, mem);
+ break;
+ }
+
+ case TOX_EVENT_FILE_RECV_CHUNK: {
+ tox_event_file_recv_chunk_free(event->data.file_recv_chunk, mem);
+ break;
+ }
+
+ case TOX_EVENT_FILE_RECV_CONTROL: {
+ tox_event_file_recv_control_free(event->data.file_recv_control, mem);
+ break;
+ }
+
+ case TOX_EVENT_FILE_RECV: {
+ tox_event_file_recv_free(event->data.file_recv, mem);
+ break;
+ }
+
+ case TOX_EVENT_FRIEND_CONNECTION_STATUS: {
+ tox_event_friend_connection_status_free(event->data.friend_connection_status, mem);
+ break;
+ }
+
+ case TOX_EVENT_FRIEND_LOSSLESS_PACKET: {
+ tox_event_friend_lossless_packet_free(event->data.friend_lossless_packet, mem);
+ break;
+ }
+
+ case TOX_EVENT_FRIEND_LOSSY_PACKET: {
+ tox_event_friend_lossy_packet_free(event->data.friend_lossy_packet, mem);
+ break;
+ }
+
+ case TOX_EVENT_FRIEND_MESSAGE: {
+ tox_event_friend_message_free(event->data.friend_message, mem);
+ break;
+ }
+
+ case TOX_EVENT_FRIEND_NAME: {
+ tox_event_friend_name_free(event->data.friend_name, mem);
+ break;
+ }
+
+ case TOX_EVENT_FRIEND_READ_RECEIPT: {
+ tox_event_friend_read_receipt_free(event->data.friend_read_receipt, mem);
+ break;
+ }
+
+ case TOX_EVENT_FRIEND_REQUEST: {
+ tox_event_friend_request_free(event->data.friend_request, mem);
+ break;
+ }
+
+ case TOX_EVENT_FRIEND_STATUS: {
+ tox_event_friend_status_free(event->data.friend_status, mem);
+ break;
+ }
+
+ case TOX_EVENT_FRIEND_STATUS_MESSAGE: {
+ tox_event_friend_status_message_free(event->data.friend_status_message, mem);
+ break;
+ }
+
+ case TOX_EVENT_FRIEND_TYPING: {
+ tox_event_friend_typing_free(event->data.friend_typing, mem);
+ break;
+ }
+
+ case TOX_EVENT_SELF_CONNECTION_STATUS: {
+ tox_event_self_connection_status_free(event->data.self_connection_status, mem);
+ break;
+ }
+
+ case TOX_EVENT_GROUP_PEER_NAME: {
+ tox_event_group_peer_name_free(event->data.group_peer_name, mem);
+ break;
+ }
+
+ case TOX_EVENT_GROUP_PEER_STATUS: {
+ tox_event_group_peer_status_free(event->data.group_peer_status, mem);
+ break;
+ }
+
+ case TOX_EVENT_GROUP_TOPIC: {
+ tox_event_group_topic_free(event->data.group_topic, mem);
+ break;
+ }
+
+ case TOX_EVENT_GROUP_PRIVACY_STATE: {
+ tox_event_group_privacy_state_free(event->data.group_privacy_state, mem);
+ break;
+ }
+
+ case TOX_EVENT_GROUP_VOICE_STATE: {
+ tox_event_group_voice_state_free(event->data.group_voice_state, mem);
+ break;
+ }
+
+ case TOX_EVENT_GROUP_TOPIC_LOCK: {
+ tox_event_group_topic_lock_free(event->data.group_topic_lock, mem);
+ break;
+ }
+
+ case TOX_EVENT_GROUP_PEER_LIMIT: {
+ tox_event_group_peer_limit_free(event->data.group_peer_limit, mem);
+ break;
+ }
+
+ case TOX_EVENT_GROUP_PASSWORD: {
+ tox_event_group_password_free(event->data.group_password, mem);
+ break;
+ }
+
+ case TOX_EVENT_GROUP_MESSAGE: {
+ tox_event_group_message_free(event->data.group_message, mem);
+ break;
+ }
+
+ case TOX_EVENT_GROUP_PRIVATE_MESSAGE: {
+ tox_event_group_private_message_free(event->data.group_private_message, mem);
+ break;
+ }
+
+ case TOX_EVENT_GROUP_CUSTOM_PACKET: {
+ tox_event_group_custom_packet_free(event->data.group_custom_packet, mem);
+ break;
+ }
+
+ case TOX_EVENT_GROUP_CUSTOM_PRIVATE_PACKET: {
+ tox_event_group_custom_private_packet_free(event->data.group_custom_private_packet, mem);
+ break;
+ }
+
+ case TOX_EVENT_GROUP_INVITE: {
+ tox_event_group_invite_free(event->data.group_invite, mem);
+ break;
+ }
+
+ case TOX_EVENT_GROUP_PEER_JOIN: {
+ tox_event_group_peer_join_free(event->data.group_peer_join, mem);
+ break;
+ }
+
+ case TOX_EVENT_GROUP_PEER_EXIT: {
+ tox_event_group_peer_exit_free(event->data.group_peer_exit, mem);
+ break;
+ }
+
+ case TOX_EVENT_GROUP_SELF_JOIN: {
+ tox_event_group_self_join_free(event->data.group_self_join, mem);
+ break;
+ }
+
+ case TOX_EVENT_GROUP_JOIN_FAIL: {
+ tox_event_group_join_fail_free(event->data.group_join_fail, mem);
+ break;
+ }
+
+ case TOX_EVENT_GROUP_MODERATION: {
+ tox_event_group_moderation_free(event->data.group_moderation, mem);
+ break;
+ }
+
+ case TOX_EVENT_DHT_GET_NODES_RESPONSE: {
+ tox_event_dht_get_nodes_response_free(event->data.dht_get_nodes_response, mem);
+ break;
+ }
+
+ case TOX_EVENT_INVALID: {
+ break;
+ }
+ }
+
+ event->data.value = nullptr;
+}
+
+non_null()
+static bool tox_event_type_pack(Tox_Event_Type type, Bin_Pack *bp)
+{
+ return bin_pack_u32(bp, (uint32_t)type);
+}
+
+non_null()
+static bool tox_event_data_pack(Tox_Event_Type type, const Tox_Event_Data *data, Bin_Pack *bp)
+{
+ switch (type) {
+ case TOX_EVENT_CONFERENCE_CONNECTED:
+ return tox_event_conference_connected_pack(data->conference_connected, bp);
+
+ case TOX_EVENT_CONFERENCE_INVITE:
+ return tox_event_conference_invite_pack(data->conference_invite, bp);
+
+ case TOX_EVENT_CONFERENCE_MESSAGE:
+ return tox_event_conference_message_pack(data->conference_message, bp);
+
+ case TOX_EVENT_CONFERENCE_PEER_LIST_CHANGED:
+ return tox_event_conference_peer_list_changed_pack(data->conference_peer_list_changed, bp);
+
+ case TOX_EVENT_CONFERENCE_PEER_NAME:
+ return tox_event_conference_peer_name_pack(data->conference_peer_name, bp);
+
+ case TOX_EVENT_CONFERENCE_TITLE:
+ return tox_event_conference_title_pack(data->conference_title, bp);
+
+ case TOX_EVENT_FILE_CHUNK_REQUEST:
+ return tox_event_file_chunk_request_pack(data->file_chunk_request, bp);
+
+ case TOX_EVENT_FILE_RECV_CHUNK:
+ return tox_event_file_recv_chunk_pack(data->file_recv_chunk, bp);
+
+ case TOX_EVENT_FILE_RECV_CONTROL:
+ return tox_event_file_recv_control_pack(data->file_recv_control, bp);
+
+ case TOX_EVENT_FILE_RECV:
+ return tox_event_file_recv_pack(data->file_recv, bp);
+
+ case TOX_EVENT_FRIEND_CONNECTION_STATUS:
+ return tox_event_friend_connection_status_pack(data->friend_connection_status, bp);
+
+ case TOX_EVENT_FRIEND_LOSSLESS_PACKET:
+ return tox_event_friend_lossless_packet_pack(data->friend_lossless_packet, bp);
+
+ case TOX_EVENT_FRIEND_LOSSY_PACKET:
+ return tox_event_friend_lossy_packet_pack(data->friend_lossy_packet, bp);
+
+ case TOX_EVENT_FRIEND_MESSAGE:
+ return tox_event_friend_message_pack(data->friend_message, bp);
+
+ case TOX_EVENT_FRIEND_NAME:
+ return tox_event_friend_name_pack(data->friend_name, bp);
+
+ case TOX_EVENT_FRIEND_READ_RECEIPT:
+ return tox_event_friend_read_receipt_pack(data->friend_read_receipt, bp);
+
+ case TOX_EVENT_FRIEND_REQUEST:
+ return tox_event_friend_request_pack(data->friend_request, bp);
+
+ case TOX_EVENT_FRIEND_STATUS:
+ return tox_event_friend_status_pack(data->friend_status, bp);
+
+ case TOX_EVENT_FRIEND_STATUS_MESSAGE:
+ return tox_event_friend_status_message_pack(data->friend_status_message, bp);
+
+ case TOX_EVENT_FRIEND_TYPING:
+ return tox_event_friend_typing_pack(data->friend_typing, bp);
+
+ case TOX_EVENT_SELF_CONNECTION_STATUS:
+ return tox_event_self_connection_status_pack(data->self_connection_status, bp);
+
+ case TOX_EVENT_GROUP_PEER_NAME:
+ return tox_event_group_peer_name_pack(data->group_peer_name, bp);
+
+ case TOX_EVENT_GROUP_PEER_STATUS:
+ return tox_event_group_peer_status_pack(data->group_peer_status, bp);
+
+ case TOX_EVENT_GROUP_TOPIC:
+ return tox_event_group_topic_pack(data->group_topic, bp);
+
+ case TOX_EVENT_GROUP_PRIVACY_STATE:
+ return tox_event_group_privacy_state_pack(data->group_privacy_state, bp);
+
+ case TOX_EVENT_GROUP_VOICE_STATE:
+ return tox_event_group_voice_state_pack(data->group_voice_state, bp);
+
+ case TOX_EVENT_GROUP_TOPIC_LOCK:
+ return tox_event_group_topic_lock_pack(data->group_topic_lock, bp);
+
+ case TOX_EVENT_GROUP_PEER_LIMIT:
+ return tox_event_group_peer_limit_pack(data->group_peer_limit, bp);
+
+ case TOX_EVENT_GROUP_PASSWORD:
+ return tox_event_group_password_pack(data->group_password, bp);
+
+ case TOX_EVENT_GROUP_MESSAGE:
+ return tox_event_group_message_pack(data->group_message, bp);
+
+ case TOX_EVENT_GROUP_PRIVATE_MESSAGE:
+ return tox_event_group_private_message_pack(data->group_private_message, bp);
+
+ case TOX_EVENT_GROUP_CUSTOM_PACKET:
+ return tox_event_group_custom_packet_pack(data->group_custom_packet, bp);
+
+ case TOX_EVENT_GROUP_CUSTOM_PRIVATE_PACKET:
+ return tox_event_group_custom_private_packet_pack(data->group_custom_private_packet, bp);
+
+ case TOX_EVENT_GROUP_INVITE:
+ return tox_event_group_invite_pack(data->group_invite, bp);
+
+ case TOX_EVENT_GROUP_PEER_JOIN:
+ return tox_event_group_peer_join_pack(data->group_peer_join, bp);
+
+ case TOX_EVENT_GROUP_PEER_EXIT:
+ return tox_event_group_peer_exit_pack(data->group_peer_exit, bp);
+
+ case TOX_EVENT_GROUP_SELF_JOIN:
+ return tox_event_group_self_join_pack(data->group_self_join, bp);
+
+ case TOX_EVENT_GROUP_JOIN_FAIL:
+ return tox_event_group_join_fail_pack(data->group_join_fail, bp);
+
+ case TOX_EVENT_GROUP_MODERATION:
+ return tox_event_group_moderation_pack(data->group_moderation, bp);
+
+ case TOX_EVENT_DHT_GET_NODES_RESPONSE:
+ return tox_event_dht_get_nodes_response_pack(data->dht_get_nodes_response, bp);
+
+ case TOX_EVENT_INVALID:
+ return false;
+ }
+
+ return false;
+}
+
+bool tox_event_pack(const Tox_Event *event, Bin_Pack *bp)
+{
+ assert(event->type != TOX_EVENT_INVALID);
+
+ return bin_pack_array(bp, 2)
+ && tox_event_type_pack(event->type, bp)
+ && tox_event_data_pack(event->type, &event->data, bp);
+}
+
+non_null()
+static bool tox_event_type_from_int(uint32_t value, Tox_Event_Type *out)
+{
+ switch (value) {
+ case TOX_EVENT_SELF_CONNECTION_STATUS: {
+ *out = TOX_EVENT_SELF_CONNECTION_STATUS;
+ return true;
+ }
+
+ case TOX_EVENT_FRIEND_REQUEST: {
+ *out = TOX_EVENT_FRIEND_REQUEST;
+ return true;
+ }
+
+ case TOX_EVENT_FRIEND_CONNECTION_STATUS: {
+ *out = TOX_EVENT_FRIEND_CONNECTION_STATUS;
+ return true;
+ }
+
+ case TOX_EVENT_FRIEND_LOSSY_PACKET: {
+ *out = TOX_EVENT_FRIEND_LOSSY_PACKET;
+ return true;
+ }
+
+ case TOX_EVENT_FRIEND_LOSSLESS_PACKET: {
+ *out = TOX_EVENT_FRIEND_LOSSLESS_PACKET;
+ return true;
+ }
+
+ case TOX_EVENT_FRIEND_NAME: {
+ *out = TOX_EVENT_FRIEND_NAME;
+ return true;
+ }
+
+ case TOX_EVENT_FRIEND_STATUS: {
+ *out = TOX_EVENT_FRIEND_STATUS;
+ return true;
+ }
+
+ case TOX_EVENT_FRIEND_STATUS_MESSAGE: {
+ *out = TOX_EVENT_FRIEND_STATUS_MESSAGE;
+ return true;
+ }
+
+ case TOX_EVENT_FRIEND_MESSAGE: {
+ *out = TOX_EVENT_FRIEND_MESSAGE;
+ return true;
+ }
+
+ case TOX_EVENT_FRIEND_READ_RECEIPT: {
+ *out = TOX_EVENT_FRIEND_READ_RECEIPT;
+ return true;
+ }
+
+ case TOX_EVENT_FRIEND_TYPING: {
+ *out = TOX_EVENT_FRIEND_TYPING;
+ return true;
+ }
+
+ case TOX_EVENT_FILE_CHUNK_REQUEST: {
+ *out = TOX_EVENT_FILE_CHUNK_REQUEST;
+ return true;
+ }
+
+ case TOX_EVENT_FILE_RECV: {
+ *out = TOX_EVENT_FILE_RECV;
+ return true;
+ }
+
+ case TOX_EVENT_FILE_RECV_CHUNK: {
+ *out = TOX_EVENT_FILE_RECV_CHUNK;
+ return true;
+ }
+
+ case TOX_EVENT_FILE_RECV_CONTROL: {
+ *out = TOX_EVENT_FILE_RECV_CONTROL;
+ return true;
+ }
+
+ case TOX_EVENT_CONFERENCE_INVITE: {
+ *out = TOX_EVENT_CONFERENCE_INVITE;
+ return true;
+ }
+
+ case TOX_EVENT_CONFERENCE_CONNECTED: {
+ *out = TOX_EVENT_CONFERENCE_CONNECTED;
+ return true;
+ }
+
+ case TOX_EVENT_CONFERENCE_PEER_LIST_CHANGED: {
+ *out = TOX_EVENT_CONFERENCE_PEER_LIST_CHANGED;
+ return true;
+ }
+
+ case TOX_EVENT_CONFERENCE_PEER_NAME: {
+ *out = TOX_EVENT_CONFERENCE_PEER_NAME;
+ return true;
+ }
+
+ case TOX_EVENT_CONFERENCE_TITLE: {
+ *out = TOX_EVENT_CONFERENCE_TITLE;
+ return true;
+ }
+
+ case TOX_EVENT_CONFERENCE_MESSAGE: {
+ *out = TOX_EVENT_CONFERENCE_MESSAGE;
+ return true;
+ }
+
+ case TOX_EVENT_GROUP_PEER_NAME: {
+ *out = TOX_EVENT_GROUP_PEER_NAME;
+ return true;
+ }
+
+ case TOX_EVENT_GROUP_PEER_STATUS: {
+ *out = TOX_EVENT_GROUP_PEER_STATUS;
+ return true;
+ }
+
+ case TOX_EVENT_GROUP_TOPIC: {
+ *out = TOX_EVENT_GROUP_TOPIC;
+ return true;
+ }
+
+ case TOX_EVENT_GROUP_PRIVACY_STATE: {
+ *out = TOX_EVENT_GROUP_PRIVACY_STATE;
+ return true;
+ }
+
+ case TOX_EVENT_GROUP_VOICE_STATE: {
+ *out = TOX_EVENT_GROUP_VOICE_STATE;
+ return true;
+ }
+
+ case TOX_EVENT_GROUP_TOPIC_LOCK: {
+ *out = TOX_EVENT_GROUP_TOPIC_LOCK;
+ return true;
+ }
+
+ case TOX_EVENT_GROUP_PEER_LIMIT: {
+ *out = TOX_EVENT_GROUP_PEER_LIMIT;
+ return true;
+ }
+
+ case TOX_EVENT_GROUP_PASSWORD: {
+ *out = TOX_EVENT_GROUP_PASSWORD;
+ return true;
+ }
+
+ case TOX_EVENT_GROUP_MESSAGE: {
+ *out = TOX_EVENT_GROUP_MESSAGE;
+ return true;
+ }
+
+ case TOX_EVENT_GROUP_PRIVATE_MESSAGE: {
+ *out = TOX_EVENT_GROUP_PRIVATE_MESSAGE;
+ return true;
+ }
+
+ case TOX_EVENT_GROUP_CUSTOM_PACKET: {
+ *out = TOX_EVENT_GROUP_CUSTOM_PACKET;
+ return true;
+ }
+
+ case TOX_EVENT_GROUP_CUSTOM_PRIVATE_PACKET: {
+ *out = TOX_EVENT_GROUP_CUSTOM_PRIVATE_PACKET;
+ return true;
+ }
+
+ case TOX_EVENT_GROUP_INVITE: {
+ *out = TOX_EVENT_GROUP_INVITE;
+ return true;
+ }
+
+ case TOX_EVENT_GROUP_PEER_JOIN: {
+ *out = TOX_EVENT_GROUP_PEER_JOIN;
+ return true;
+ }
+
+ case TOX_EVENT_GROUP_PEER_EXIT: {
+ *out = TOX_EVENT_GROUP_PEER_EXIT;
+ return true;
+ }
+
+ case TOX_EVENT_GROUP_SELF_JOIN: {
+ *out = TOX_EVENT_GROUP_SELF_JOIN;
+ return true;
+ }
+
+ case TOX_EVENT_GROUP_JOIN_FAIL: {
+ *out = TOX_EVENT_GROUP_JOIN_FAIL;
+ return true;
+ }
+
+ case TOX_EVENT_GROUP_MODERATION: {
+ *out = TOX_EVENT_GROUP_MODERATION;
+ return true;
+ }
+
+ case TOX_EVENT_DHT_GET_NODES_RESPONSE: {
+ *out = TOX_EVENT_DHT_GET_NODES_RESPONSE;
+ return true;
+ }
+
+ case TOX_EVENT_INVALID: {
+ *out = TOX_EVENT_INVALID;
+ return true;
+ }
+
+ default: {
+ *out = TOX_EVENT_INVALID;
+ return false;
+ }
+ }
+}
+
+non_null()
+static bool tox_event_type_unpack(Tox_Event_Type *val, Bin_Unpack *bu)
+{
+ uint32_t u32;
+ return bin_unpack_u32(bu, &u32)
+ && tox_event_type_from_int(u32, val);
+}
+
+non_null()
+static bool tox_event_data_unpack(Tox_Event_Type type, Tox_Event_Data *data, Bin_Unpack *bu, const Memory *mem)
+{
+ switch (type) {
+ case TOX_EVENT_CONFERENCE_CONNECTED:
+ return tox_event_conference_connected_unpack(&data->conference_connected, bu, mem);
+
+ case TOX_EVENT_CONFERENCE_INVITE:
+ return tox_event_conference_invite_unpack(&data->conference_invite, bu, mem);
+
+ case TOX_EVENT_CONFERENCE_MESSAGE:
+ return tox_event_conference_message_unpack(&data->conference_message, bu, mem);
+
+ case TOX_EVENT_CONFERENCE_PEER_LIST_CHANGED:
+ return tox_event_conference_peer_list_changed_unpack(&data->conference_peer_list_changed, bu, mem);
+
+ case TOX_EVENT_CONFERENCE_PEER_NAME:
+ return tox_event_conference_peer_name_unpack(&data->conference_peer_name, bu, mem);
+
+ case TOX_EVENT_CONFERENCE_TITLE:
+ return tox_event_conference_title_unpack(&data->conference_title, bu, mem);
+
+ case TOX_EVENT_FILE_CHUNK_REQUEST:
+ return tox_event_file_chunk_request_unpack(&data->file_chunk_request, bu, mem);
+
+ case TOX_EVENT_FILE_RECV_CHUNK:
+ return tox_event_file_recv_chunk_unpack(&data->file_recv_chunk, bu, mem);
+
+ case TOX_EVENT_FILE_RECV_CONTROL:
+ return tox_event_file_recv_control_unpack(&data->file_recv_control, bu, mem);
+
+ case TOX_EVENT_FILE_RECV:
+ return tox_event_file_recv_unpack(&data->file_recv, bu, mem);
+
+ case TOX_EVENT_FRIEND_CONNECTION_STATUS:
+ return tox_event_friend_connection_status_unpack(&data->friend_connection_status, bu, mem);
+
+ case TOX_EVENT_FRIEND_LOSSLESS_PACKET:
+ return tox_event_friend_lossless_packet_unpack(&data->friend_lossless_packet, bu, mem);
+
+ case TOX_EVENT_FRIEND_LOSSY_PACKET:
+ return tox_event_friend_lossy_packet_unpack(&data->friend_lossy_packet, bu, mem);
+
+ case TOX_EVENT_FRIEND_MESSAGE:
+ return tox_event_friend_message_unpack(&data->friend_message, bu, mem);
+
+ case TOX_EVENT_FRIEND_NAME:
+ return tox_event_friend_name_unpack(&data->friend_name, bu, mem);
+
+ case TOX_EVENT_FRIEND_READ_RECEIPT:
+ return tox_event_friend_read_receipt_unpack(&data->friend_read_receipt, bu, mem);
+
+ case TOX_EVENT_FRIEND_REQUEST:
+ return tox_event_friend_request_unpack(&data->friend_request, bu, mem);
+
+ case TOX_EVENT_FRIEND_STATUS_MESSAGE:
+ return tox_event_friend_status_message_unpack(&data->friend_status_message, bu, mem);
+
+ case TOX_EVENT_FRIEND_STATUS:
+ return tox_event_friend_status_unpack(&data->friend_status, bu, mem);
+
+ case TOX_EVENT_FRIEND_TYPING:
+ return tox_event_friend_typing_unpack(&data->friend_typing, bu, mem);
+
+ case TOX_EVENT_SELF_CONNECTION_STATUS:
+ return tox_event_self_connection_status_unpack(&data->self_connection_status, bu, mem);
+
+ case TOX_EVENT_GROUP_PEER_NAME:
+ return tox_event_group_peer_name_unpack(&data->group_peer_name, bu, mem);
+
+ case TOX_EVENT_GROUP_PEER_STATUS:
+ return tox_event_group_peer_status_unpack(&data->group_peer_status, bu, mem);
+
+ case TOX_EVENT_GROUP_TOPIC:
+ return tox_event_group_topic_unpack(&data->group_topic, bu, mem);
+
+ case TOX_EVENT_GROUP_PRIVACY_STATE:
+ return tox_event_group_privacy_state_unpack(&data->group_privacy_state, bu, mem);
+
+ case TOX_EVENT_GROUP_VOICE_STATE:
+ return tox_event_group_voice_state_unpack(&data->group_voice_state, bu, mem);
+
+ case TOX_EVENT_GROUP_TOPIC_LOCK:
+ return tox_event_group_topic_lock_unpack(&data->group_topic_lock, bu, mem);
+
+ case TOX_EVENT_GROUP_PEER_LIMIT:
+ return tox_event_group_peer_limit_unpack(&data->group_peer_limit, bu, mem);
+
+ case TOX_EVENT_GROUP_PASSWORD:
+ return tox_event_group_password_unpack(&data->group_password, bu, mem);
+
+ case TOX_EVENT_GROUP_MESSAGE:
+ return tox_event_group_message_unpack(&data->group_message, bu, mem);
+
+ case TOX_EVENT_GROUP_PRIVATE_MESSAGE:
+ return tox_event_group_private_message_unpack(&data->group_private_message, bu, mem);
+
+ case TOX_EVENT_GROUP_CUSTOM_PACKET:
+ return tox_event_group_custom_packet_unpack(&data->group_custom_packet, bu, mem);
+
+ case TOX_EVENT_GROUP_CUSTOM_PRIVATE_PACKET:
+ return tox_event_group_custom_private_packet_unpack(&data->group_custom_private_packet, bu, mem);
+
+ case TOX_EVENT_GROUP_INVITE:
+ return tox_event_group_invite_unpack(&data->group_invite, bu, mem);
+
+ case TOX_EVENT_GROUP_PEER_JOIN:
+ return tox_event_group_peer_join_unpack(&data->group_peer_join, bu, mem);
+
+ case TOX_EVENT_GROUP_PEER_EXIT:
+ return tox_event_group_peer_exit_unpack(&data->group_peer_exit, bu, mem);
+
+ case TOX_EVENT_GROUP_SELF_JOIN:
+ return tox_event_group_self_join_unpack(&data->group_self_join, bu, mem);
+
+ case TOX_EVENT_GROUP_JOIN_FAIL:
+ return tox_event_group_join_fail_unpack(&data->group_join_fail, bu, mem);
+
+ case TOX_EVENT_GROUP_MODERATION:
+ return tox_event_group_moderation_unpack(&data->group_moderation, bu, mem);
+
+ case TOX_EVENT_DHT_GET_NODES_RESPONSE:
+ return tox_event_dht_get_nodes_response_unpack(&data->dht_get_nodes_response, bu, mem);
+
+ case TOX_EVENT_INVALID:
+ return false;
+ }
+
+ return false;
+}
+
+bool tox_event_unpack_into(Tox_Event *event, Bin_Unpack *bu, const Memory *mem)
+{
+ return bin_unpack_array_fixed(bu, 2, nullptr) //
+ && tox_event_type_unpack(&event->type, bu) //
+ && tox_event_data_unpack(event->type, &event->data, bu, mem);
+}
diff --git a/protocols/Tox/libtox/src/toxcore/tox_event.h b/protocols/Tox/libtox/src/toxcore/tox_event.h
new file mode 100644
index 0000000000..fa98aae229
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/tox_event.h
@@ -0,0 +1,260 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2022 The TokTok team.
+ */
+
+#ifndef C_TOXCORE_TOXCORE_TOX_EVENT_H
+#define C_TOXCORE_TOXCORE_TOX_EVENT_H
+
+#include "attributes.h"
+#include "bin_pack.h"
+#include "bin_unpack.h"
+#include "mem.h"
+#include "tox_events.h"
+#include "tox_private.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef union Tox_Event_Data {
+ /**
+ * Opaque pointer just to check whether any value is set.
+ */
+ void *value;
+
+ Tox_Event_Conference_Connected *conference_connected;
+ Tox_Event_Conference_Invite *conference_invite;
+ Tox_Event_Conference_Message *conference_message;
+ Tox_Event_Conference_Peer_List_Changed *conference_peer_list_changed;
+ Tox_Event_Conference_Peer_Name *conference_peer_name;
+ Tox_Event_Conference_Title *conference_title;
+ Tox_Event_File_Chunk_Request *file_chunk_request;
+ Tox_Event_File_Recv *file_recv;
+ Tox_Event_File_Recv_Chunk *file_recv_chunk;
+ Tox_Event_File_Recv_Control *file_recv_control;
+ Tox_Event_Friend_Connection_Status *friend_connection_status;
+ Tox_Event_Friend_Lossless_Packet *friend_lossless_packet;
+ Tox_Event_Friend_Lossy_Packet *friend_lossy_packet;
+ Tox_Event_Friend_Message *friend_message;
+ Tox_Event_Friend_Name *friend_name;
+ Tox_Event_Friend_Read_Receipt *friend_read_receipt;
+ Tox_Event_Friend_Request *friend_request;
+ Tox_Event_Friend_Status *friend_status;
+ Tox_Event_Friend_Status_Message *friend_status_message;
+ Tox_Event_Friend_Typing *friend_typing;
+ Tox_Event_Self_Connection_Status *self_connection_status;
+ Tox_Event_Group_Peer_Name *group_peer_name;
+ Tox_Event_Group_Peer_Status *group_peer_status;
+ Tox_Event_Group_Topic *group_topic;
+ Tox_Event_Group_Privacy_State *group_privacy_state;
+ Tox_Event_Group_Voice_State *group_voice_state;
+ Tox_Event_Group_Topic_Lock *group_topic_lock;
+ Tox_Event_Group_Peer_Limit *group_peer_limit;
+ Tox_Event_Group_Password *group_password;
+ Tox_Event_Group_Message *group_message;
+ Tox_Event_Group_Private_Message *group_private_message;
+ Tox_Event_Group_Custom_Packet *group_custom_packet;
+ Tox_Event_Group_Custom_Private_Packet *group_custom_private_packet;
+ Tox_Event_Group_Invite *group_invite;
+ Tox_Event_Group_Peer_Join *group_peer_join;
+ Tox_Event_Group_Peer_Exit *group_peer_exit;
+ Tox_Event_Group_Self_Join *group_self_join;
+ Tox_Event_Group_Join_Fail *group_join_fail;
+ Tox_Event_Group_Moderation *group_moderation;
+ Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response;
+} Tox_Event_Data;
+
+struct Tox_Event {
+ Tox_Event_Type type;
+ Tox_Event_Data data;
+};
+
+/**
+ * Constructor.
+ */
+non_null() bool tox_event_construct(Tox_Event *event, Tox_Event_Type type, const Memory *mem);
+
+non_null() Tox_Event_Conference_Connected *tox_event_conference_connected_new(const Memory *mem);
+non_null() Tox_Event_Conference_Invite *tox_event_conference_invite_new(const Memory *mem);
+non_null() Tox_Event_Conference_Message *tox_event_conference_message_new(const Memory *mem);
+non_null() Tox_Event_Conference_Peer_List_Changed *tox_event_conference_peer_list_changed_new(const Memory *mem);
+non_null() Tox_Event_Conference_Peer_Name *tox_event_conference_peer_name_new(const Memory *mem);
+non_null() Tox_Event_Conference_Title *tox_event_conference_title_new(const Memory *mem);
+non_null() Tox_Event_File_Chunk_Request *tox_event_file_chunk_request_new(const Memory *mem);
+non_null() Tox_Event_File_Recv_Chunk *tox_event_file_recv_chunk_new(const Memory *mem);
+non_null() Tox_Event_File_Recv_Control *tox_event_file_recv_control_new(const Memory *mem);
+non_null() Tox_Event_File_Recv *tox_event_file_recv_new(const Memory *mem);
+non_null() Tox_Event_Friend_Connection_Status *tox_event_friend_connection_status_new(const Memory *mem);
+non_null() Tox_Event_Friend_Lossless_Packet *tox_event_friend_lossless_packet_new(const Memory *mem);
+non_null() Tox_Event_Friend_Lossy_Packet *tox_event_friend_lossy_packet_new(const Memory *mem);
+non_null() Tox_Event_Friend_Message *tox_event_friend_message_new(const Memory *mem);
+non_null() Tox_Event_Friend_Name *tox_event_friend_name_new(const Memory *mem);
+non_null() Tox_Event_Friend_Read_Receipt *tox_event_friend_read_receipt_new(const Memory *mem);
+non_null() Tox_Event_Friend_Request *tox_event_friend_request_new(const Memory *mem);
+non_null() Tox_Event_Friend_Status_Message *tox_event_friend_status_message_new(const Memory *mem);
+non_null() Tox_Event_Friend_Status *tox_event_friend_status_new(const Memory *mem);
+non_null() Tox_Event_Friend_Typing *tox_event_friend_typing_new(const Memory *mem);
+non_null() Tox_Event_Self_Connection_Status *tox_event_self_connection_status_new(const Memory *mem);
+non_null() Tox_Event_Group_Peer_Name *tox_event_group_peer_name_new(const Memory *mem);
+non_null() Tox_Event_Group_Peer_Status *tox_event_group_peer_status_new(const Memory *mem);
+non_null() Tox_Event_Group_Topic *tox_event_group_topic_new(const Memory *mem);
+non_null() Tox_Event_Group_Privacy_State *tox_event_group_privacy_state_new(const Memory *mem);
+non_null() Tox_Event_Group_Voice_State *tox_event_group_voice_state_new(const Memory *mem);
+non_null() Tox_Event_Group_Topic_Lock *tox_event_group_topic_lock_new(const Memory *mem);
+non_null() Tox_Event_Group_Peer_Limit *tox_event_group_peer_limit_new(const Memory *mem);
+non_null() Tox_Event_Group_Password *tox_event_group_password_new(const Memory *mem);
+non_null() Tox_Event_Group_Message *tox_event_group_message_new(const Memory *mem);
+non_null() Tox_Event_Group_Private_Message *tox_event_group_private_message_new(const Memory *mem);
+non_null() Tox_Event_Group_Custom_Packet *tox_event_group_custom_packet_new(const Memory *mem);
+non_null() Tox_Event_Group_Custom_Private_Packet *tox_event_group_custom_private_packet_new(const Memory *mem);
+non_null() Tox_Event_Group_Invite *tox_event_group_invite_new(const Memory *mem);
+non_null() Tox_Event_Group_Peer_Join *tox_event_group_peer_join_new(const Memory *mem);
+non_null() Tox_Event_Group_Peer_Exit *tox_event_group_peer_exit_new(const Memory *mem);
+non_null() Tox_Event_Group_Self_Join *tox_event_group_self_join_new(const Memory *mem);
+non_null() Tox_Event_Group_Join_Fail *tox_event_group_join_fail_new(const Memory *mem);
+non_null() Tox_Event_Group_Moderation *tox_event_group_moderation_new(const Memory *mem);
+non_null() Tox_Event_Dht_Get_Nodes_Response *tox_event_dht_get_nodes_response_new(const Memory *mem);
+
+/**
+ * Destructor.
+ */
+non_null(2) nullable(1) void tox_event_destruct(Tox_Event *event, const Memory *mem);
+
+non_null(2) nullable(1) void tox_event_conference_connected_free(Tox_Event_Conference_Connected *conference_connected, const Memory *mem);
+non_null(2) nullable(1) void tox_event_conference_invite_free(Tox_Event_Conference_Invite *conference_invite, const Memory *mem);
+non_null(2) nullable(1) void tox_event_conference_message_free(Tox_Event_Conference_Message *conference_message, const Memory *mem);
+non_null(2) nullable(1) void tox_event_conference_peer_list_changed_free(Tox_Event_Conference_Peer_List_Changed *conference_peer_list_changed, const Memory *mem);
+non_null(2) nullable(1) void tox_event_conference_peer_name_free(Tox_Event_Conference_Peer_Name *conference_peer_name, const Memory *mem);
+non_null(2) nullable(1) void tox_event_conference_title_free(Tox_Event_Conference_Title *conference_title, const Memory *mem);
+non_null(2) nullable(1) void tox_event_file_chunk_request_free(Tox_Event_File_Chunk_Request *file_chunk_request, const Memory *mem);
+non_null(2) nullable(1) void tox_event_file_recv_chunk_free(Tox_Event_File_Recv_Chunk *file_recv_chunk, const Memory *mem);
+non_null(2) nullable(1) void tox_event_file_recv_control_free(Tox_Event_File_Recv_Control *file_recv_control, const Memory *mem);
+non_null(2) nullable(1) void tox_event_file_recv_free(Tox_Event_File_Recv *file_recv, const Memory *mem);
+non_null(2) nullable(1) void tox_event_friend_connection_status_free(Tox_Event_Friend_Connection_Status *friend_connection_status, const Memory *mem);
+non_null(2) nullable(1) void tox_event_friend_lossless_packet_free(Tox_Event_Friend_Lossless_Packet *friend_lossless_packet, const Memory *mem);
+non_null(2) nullable(1) void tox_event_friend_lossy_packet_free(Tox_Event_Friend_Lossy_Packet *friend_lossy_packet, const Memory *mem);
+non_null(2) nullable(1) void tox_event_friend_message_free(Tox_Event_Friend_Message *friend_message, const Memory *mem);
+non_null(2) nullable(1) void tox_event_friend_name_free(Tox_Event_Friend_Name *friend_name, const Memory *mem);
+non_null(2) nullable(1) void tox_event_friend_read_receipt_free(Tox_Event_Friend_Read_Receipt *friend_read_receipt, const Memory *mem);
+non_null(2) nullable(1) void tox_event_friend_request_free(Tox_Event_Friend_Request *friend_request, const Memory *mem);
+non_null(2) nullable(1) void tox_event_friend_status_message_free(Tox_Event_Friend_Status_Message *friend_status_message, const Memory *mem);
+non_null(2) nullable(1) void tox_event_friend_status_free(Tox_Event_Friend_Status *friend_status, const Memory *mem);
+non_null(2) nullable(1) void tox_event_friend_typing_free(Tox_Event_Friend_Typing *friend_typing, const Memory *mem);
+non_null(2) nullable(1) void tox_event_self_connection_status_free(Tox_Event_Self_Connection_Status *self_connection_status, const Memory *mem);
+non_null(2) nullable(1) void tox_event_group_peer_name_free(Tox_Event_Group_Peer_Name *group_peer_name, const Memory *mem);
+non_null(2) nullable(1) void tox_event_group_peer_status_free(Tox_Event_Group_Peer_Status *group_peer_status, const Memory *mem);
+non_null(2) nullable(1) void tox_event_group_topic_free(Tox_Event_Group_Topic *group_topic, const Memory *mem);
+non_null(2) nullable(1) void tox_event_group_privacy_state_free(Tox_Event_Group_Privacy_State *group_privacy_state, const Memory *mem);
+non_null(2) nullable(1) void tox_event_group_voice_state_free(Tox_Event_Group_Voice_State *group_voice_state, const Memory *mem);
+non_null(2) nullable(1) void tox_event_group_topic_lock_free(Tox_Event_Group_Topic_Lock *group_topic_lock, const Memory *mem);
+non_null(2) nullable(1) void tox_event_group_peer_limit_free(Tox_Event_Group_Peer_Limit *group_peer_limit, const Memory *mem);
+non_null(2) nullable(1) void tox_event_group_password_free(Tox_Event_Group_Password *group_password, const Memory *mem);
+non_null(2) nullable(1) void tox_event_group_message_free(Tox_Event_Group_Message *group_message, const Memory *mem);
+non_null(2) nullable(1) void tox_event_group_private_message_free(Tox_Event_Group_Private_Message *group_private_message, const Memory *mem);
+non_null(2) nullable(1) void tox_event_group_custom_packet_free(Tox_Event_Group_Custom_Packet *group_custom_packet, const Memory *mem);
+non_null(2) nullable(1) void tox_event_group_custom_private_packet_free(Tox_Event_Group_Custom_Private_Packet *group_custom_private_packet, const Memory *mem);
+non_null(2) nullable(1) void tox_event_group_invite_free(Tox_Event_Group_Invite *group_invite, const Memory *mem);
+non_null(2) nullable(1) void tox_event_group_peer_join_free(Tox_Event_Group_Peer_Join *group_peer_join, const Memory *mem);
+non_null(2) nullable(1) void tox_event_group_peer_exit_free(Tox_Event_Group_Peer_Exit *group_peer_exit, const Memory *mem);
+non_null(2) nullable(1) void tox_event_group_self_join_free(Tox_Event_Group_Self_Join *group_self_join, const Memory *mem);
+non_null(2) nullable(1) void tox_event_group_join_fail_free(Tox_Event_Group_Join_Fail *group_join_fail, const Memory *mem);
+non_null(2) nullable(1) void tox_event_group_moderation_free(Tox_Event_Group_Moderation *group_moderation, const Memory *mem);
+non_null(2) nullable(1) void tox_event_dht_get_nodes_response_free(Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response, const Memory *mem);
+
+/**
+ * Pack into msgpack.
+ */
+non_null() bool tox_event_pack(const Tox_Event *event, Bin_Pack *bp);
+
+non_null() bool tox_event_conference_connected_pack(const Tox_Event_Conference_Connected *event, Bin_Pack *bp);
+non_null() bool tox_event_conference_invite_pack(const Tox_Event_Conference_Invite *event, Bin_Pack *bp);
+non_null() bool tox_event_conference_message_pack(const Tox_Event_Conference_Message *event, Bin_Pack *bp);
+non_null() bool tox_event_conference_peer_list_changed_pack(const Tox_Event_Conference_Peer_List_Changed *event, Bin_Pack *bp);
+non_null() bool tox_event_conference_peer_name_pack(const Tox_Event_Conference_Peer_Name *event, Bin_Pack *bp);
+non_null() bool tox_event_conference_title_pack(const Tox_Event_Conference_Title *event, Bin_Pack *bp);
+non_null() bool tox_event_file_chunk_request_pack(const Tox_Event_File_Chunk_Request *event, Bin_Pack *bp);
+non_null() bool tox_event_file_recv_chunk_pack(const Tox_Event_File_Recv_Chunk *event, Bin_Pack *bp);
+non_null() bool tox_event_file_recv_control_pack(const Tox_Event_File_Recv_Control *event, Bin_Pack *bp);
+non_null() bool tox_event_file_recv_pack(const Tox_Event_File_Recv *event, Bin_Pack *bp);
+non_null() bool tox_event_friend_connection_status_pack(const Tox_Event_Friend_Connection_Status *event, Bin_Pack *bp);
+non_null() bool tox_event_friend_lossless_packet_pack(const Tox_Event_Friend_Lossless_Packet *event, Bin_Pack *bp);
+non_null() bool tox_event_friend_lossy_packet_pack(const Tox_Event_Friend_Lossy_Packet *event, Bin_Pack *bp);
+non_null() bool tox_event_friend_message_pack(const Tox_Event_Friend_Message *event, Bin_Pack *bp);
+non_null() bool tox_event_friend_name_pack(const Tox_Event_Friend_Name *event, Bin_Pack *bp);
+non_null() bool tox_event_friend_read_receipt_pack(const Tox_Event_Friend_Read_Receipt *event, Bin_Pack *bp);
+non_null() bool tox_event_friend_request_pack(const Tox_Event_Friend_Request *event, Bin_Pack *bp);
+non_null() bool tox_event_friend_status_message_pack(const Tox_Event_Friend_Status_Message *event, Bin_Pack *bp);
+non_null() bool tox_event_friend_status_pack(const Tox_Event_Friend_Status *event, Bin_Pack *bp);
+non_null() bool tox_event_friend_typing_pack(const Tox_Event_Friend_Typing *event, Bin_Pack *bp);
+non_null() bool tox_event_self_connection_status_pack(const Tox_Event_Self_Connection_Status *event, Bin_Pack *bp);
+non_null() bool tox_event_group_peer_name_pack(const Tox_Event_Group_Peer_Name *event, Bin_Pack *bp);
+non_null() bool tox_event_group_peer_status_pack(const Tox_Event_Group_Peer_Status *event, Bin_Pack *bp);
+non_null() bool tox_event_group_topic_pack(const Tox_Event_Group_Topic *event, Bin_Pack *bp);
+non_null() bool tox_event_group_privacy_state_pack(const Tox_Event_Group_Privacy_State *event, Bin_Pack *bp);
+non_null() bool tox_event_group_voice_state_pack(const Tox_Event_Group_Voice_State *event, Bin_Pack *bp);
+non_null() bool tox_event_group_topic_lock_pack(const Tox_Event_Group_Topic_Lock *event, Bin_Pack *bp);
+non_null() bool tox_event_group_peer_limit_pack(const Tox_Event_Group_Peer_Limit *event, Bin_Pack *bp);
+non_null() bool tox_event_group_password_pack(const Tox_Event_Group_Password *event, Bin_Pack *bp);
+non_null() bool tox_event_group_message_pack(const Tox_Event_Group_Message *event, Bin_Pack *bp);
+non_null() bool tox_event_group_private_message_pack(const Tox_Event_Group_Private_Message *event, Bin_Pack *bp);
+non_null() bool tox_event_group_custom_packet_pack(const Tox_Event_Group_Custom_Packet *event, Bin_Pack *bp);
+non_null() bool tox_event_group_custom_private_packet_pack(const Tox_Event_Group_Custom_Private_Packet *event, Bin_Pack *bp);
+non_null() bool tox_event_group_invite_pack(const Tox_Event_Group_Invite *event, Bin_Pack *bp);
+non_null() bool tox_event_group_peer_join_pack(const Tox_Event_Group_Peer_Join *event, Bin_Pack *bp);
+non_null() bool tox_event_group_peer_exit_pack(const Tox_Event_Group_Peer_Exit *event, Bin_Pack *bp);
+non_null() bool tox_event_group_self_join_pack(const Tox_Event_Group_Self_Join *event, Bin_Pack *bp);
+non_null() bool tox_event_group_join_fail_pack(const Tox_Event_Group_Join_Fail *event, Bin_Pack *bp);
+non_null() bool tox_event_group_moderation_pack(const Tox_Event_Group_Moderation *event, Bin_Pack *bp);
+non_null() bool tox_event_dht_get_nodes_response_pack(const Tox_Event_Dht_Get_Nodes_Response *event, Bin_Pack *bp);
+
+/**
+ * Unpack from msgpack.
+ */
+non_null() bool tox_event_unpack_into(Tox_Event *event, Bin_Unpack *bu, const Memory *mem);
+
+non_null() bool tox_event_conference_connected_unpack(Tox_Event_Conference_Connected **event, Bin_Unpack *bu, const Memory *mem);
+non_null() bool tox_event_conference_invite_unpack(Tox_Event_Conference_Invite **event, Bin_Unpack *bu, const Memory *mem);
+non_null() bool tox_event_conference_message_unpack(Tox_Event_Conference_Message **event, Bin_Unpack *bu, const Memory *mem);
+non_null() bool tox_event_conference_peer_list_changed_unpack(Tox_Event_Conference_Peer_List_Changed **event, Bin_Unpack *bu, const Memory *mem);
+non_null() bool tox_event_conference_peer_name_unpack(Tox_Event_Conference_Peer_Name **event, Bin_Unpack *bu, const Memory *mem);
+non_null() bool tox_event_conference_title_unpack(Tox_Event_Conference_Title **event, Bin_Unpack *bu, const Memory *mem);
+non_null() bool tox_event_file_chunk_request_unpack(Tox_Event_File_Chunk_Request **event, Bin_Unpack *bu, const Memory *mem);
+non_null() bool tox_event_file_recv_chunk_unpack(Tox_Event_File_Recv_Chunk **event, Bin_Unpack *bu, const Memory *mem);
+non_null() bool tox_event_file_recv_control_unpack(Tox_Event_File_Recv_Control **event, Bin_Unpack *bu, const Memory *mem);
+non_null() bool tox_event_file_recv_unpack(Tox_Event_File_Recv **event, Bin_Unpack *bu, const Memory *mem);
+non_null() bool tox_event_friend_connection_status_unpack(Tox_Event_Friend_Connection_Status **event, Bin_Unpack *bu, const Memory *mem);
+non_null() bool tox_event_friend_lossless_packet_unpack(Tox_Event_Friend_Lossless_Packet **event, Bin_Unpack *bu, const Memory *mem);
+non_null() bool tox_event_friend_lossy_packet_unpack(Tox_Event_Friend_Lossy_Packet **event, Bin_Unpack *bu, const Memory *mem);
+non_null() bool tox_event_friend_message_unpack(Tox_Event_Friend_Message **event, Bin_Unpack *bu, const Memory *mem);
+non_null() bool tox_event_friend_name_unpack(Tox_Event_Friend_Name **event, Bin_Unpack *bu, const Memory *mem);
+non_null() bool tox_event_friend_read_receipt_unpack(Tox_Event_Friend_Read_Receipt **event, Bin_Unpack *bu, const Memory *mem);
+non_null() bool tox_event_friend_request_unpack(Tox_Event_Friend_Request **event, Bin_Unpack *bu, const Memory *mem);
+non_null() bool tox_event_friend_status_message_unpack(Tox_Event_Friend_Status_Message **event, Bin_Unpack *bu, const Memory *mem);
+non_null() bool tox_event_friend_status_unpack(Tox_Event_Friend_Status **event, Bin_Unpack *bu, const Memory *mem);
+non_null() bool tox_event_friend_typing_unpack(Tox_Event_Friend_Typing **event, Bin_Unpack *bu, const Memory *mem);
+non_null() bool tox_event_self_connection_status_unpack(Tox_Event_Self_Connection_Status **event, Bin_Unpack *bu, const Memory *mem);
+non_null() bool tox_event_group_peer_name_unpack(Tox_Event_Group_Peer_Name **event, Bin_Unpack *bu, const Memory *mem);
+non_null() bool tox_event_group_peer_status_unpack(Tox_Event_Group_Peer_Status **event, Bin_Unpack *bu, const Memory *mem);
+non_null() bool tox_event_group_topic_unpack(Tox_Event_Group_Topic **event, Bin_Unpack *bu, const Memory *mem);
+non_null() bool tox_event_group_privacy_state_unpack(Tox_Event_Group_Privacy_State **event, Bin_Unpack *bu, const Memory *mem);
+non_null() bool tox_event_group_voice_state_unpack(Tox_Event_Group_Voice_State **event, Bin_Unpack *bu, const Memory *mem);
+non_null() bool tox_event_group_topic_lock_unpack(Tox_Event_Group_Topic_Lock **event, Bin_Unpack *bu, const Memory *mem);
+non_null() bool tox_event_group_peer_limit_unpack(Tox_Event_Group_Peer_Limit **event, Bin_Unpack *bu, const Memory *mem);
+non_null() bool tox_event_group_password_unpack(Tox_Event_Group_Password **event, Bin_Unpack *bu, const Memory *mem);
+non_null() bool tox_event_group_message_unpack(Tox_Event_Group_Message **event, Bin_Unpack *bu, const Memory *mem);
+non_null() bool tox_event_group_private_message_unpack(Tox_Event_Group_Private_Message **event, Bin_Unpack *bu, const Memory *mem);
+non_null() bool tox_event_group_custom_packet_unpack(Tox_Event_Group_Custom_Packet **event, Bin_Unpack *bu, const Memory *mem);
+non_null() bool tox_event_group_custom_private_packet_unpack(Tox_Event_Group_Custom_Private_Packet **event, Bin_Unpack *bu, const Memory *mem);
+non_null() bool tox_event_group_invite_unpack(Tox_Event_Group_Invite **event, Bin_Unpack *bu, const Memory *mem);
+non_null() bool tox_event_group_peer_join_unpack(Tox_Event_Group_Peer_Join **event, Bin_Unpack *bu, const Memory *mem);
+non_null() bool tox_event_group_peer_exit_unpack(Tox_Event_Group_Peer_Exit **event, Bin_Unpack *bu, const Memory *mem);
+non_null() bool tox_event_group_self_join_unpack(Tox_Event_Group_Self_Join **event, Bin_Unpack *bu, const Memory *mem);
+non_null() bool tox_event_group_join_fail_unpack(Tox_Event_Group_Join_Fail **event, Bin_Unpack *bu, const Memory *mem);
+non_null() bool tox_event_group_moderation_unpack(Tox_Event_Group_Moderation **event, Bin_Unpack *bu, const Memory *mem);
+non_null() bool tox_event_dht_get_nodes_response_unpack(Tox_Event_Dht_Get_Nodes_Response **event, Bin_Unpack *bu, const Memory *mem);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* C_TOXCORE_TOXCORE_TOX_EVENT_H */
diff --git a/protocols/Tox/libtox/src/toxcore/tox_events.c b/protocols/Tox/libtox/src/toxcore/tox_events.c
index 91a7767f7b..a5d995cf50 100644
--- a/protocols/Tox/libtox/src/toxcore/tox_events.c
+++ b/protocols/Tox/libtox/src/toxcore/tox_events.c
@@ -1,18 +1,23 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2022 The TokTok team.
+ * Copyright © 2022-2024 The TokTok team.
*/
#include "tox_events.h"
-#include <stdio.h>
-#include <stdlib.h>
+#include <assert.h>
#include <string.h>
+#include "attributes.h"
+#include "bin_pack.h"
#include "bin_unpack.h"
#include "ccompat.h"
#include "events/events_alloc.h"
+#include "logger.h"
+#include "mem.h"
#include "tox.h"
-
+#include "tox_event.h"
+#include "tox_private.h"
+#include "tox_struct.h"
/*****************************************************
*
@@ -20,7 +25,6 @@
*
*****************************************************/
-
void tox_events_init(Tox *tox)
{
tox_callback_conference_connected(tox, tox_events_handle_conference_connected);
@@ -44,11 +48,51 @@ void tox_events_init(Tox *tox)
tox_callback_friend_status(tox, tox_events_handle_friend_status);
tox_callback_friend_typing(tox, tox_events_handle_friend_typing);
tox_callback_self_connection_status(tox, tox_events_handle_self_connection_status);
+ tox_callback_group_peer_name(tox, tox_events_handle_group_peer_name);
+ tox_callback_group_peer_status(tox, tox_events_handle_group_peer_status);
+ tox_callback_group_topic(tox, tox_events_handle_group_topic);
+ tox_callback_group_privacy_state(tox, tox_events_handle_group_privacy_state);
+ tox_callback_group_voice_state(tox, tox_events_handle_group_voice_state);
+ tox_callback_group_topic_lock(tox, tox_events_handle_group_topic_lock);
+ tox_callback_group_peer_limit(tox, tox_events_handle_group_peer_limit);
+ tox_callback_group_password(tox, tox_events_handle_group_password);
+ tox_callback_group_message(tox, tox_events_handle_group_message);
+ tox_callback_group_private_message(tox, tox_events_handle_group_private_message);
+ tox_callback_group_custom_packet(tox, tox_events_handle_group_custom_packet);
+ tox_callback_group_custom_private_packet(tox, tox_events_handle_group_custom_private_packet);
+ tox_callback_group_invite(tox, tox_events_handle_group_invite);
+ tox_callback_group_peer_join(tox, tox_events_handle_group_peer_join);
+ tox_callback_group_peer_exit(tox, tox_events_handle_group_peer_exit);
+ tox_callback_group_self_join(tox, tox_events_handle_group_self_join);
+ tox_callback_group_join_fail(tox, tox_events_handle_group_join_fail);
+ tox_callback_group_moderation(tox, tox_events_handle_group_moderation);
+ tox_callback_dht_get_nodes_response(tox, tox_events_handle_dht_get_nodes_response);
+}
+
+uint32_t tox_events_get_size(const Tox_Events *events)
+{
+ return events == nullptr ? 0 : events->events_size;
+}
+
+nullable(1)
+static const Tox_Event *tox_events_get_events(const Tox_Events *events)
+{
+ return events == nullptr ? nullptr : events->events;
+}
+
+const Tox_Event *tox_events_get(const Tox_Events *events, uint32_t index)
+{
+ if (index >= tox_events_get_size(events)) {
+ return nullptr;
+ }
+
+ return &events->events[index];
}
Tox_Events *tox_events_iterate(Tox *tox, bool fail_hard, Tox_Err_Events_Iterate *error)
{
- Tox_Events_State state = {TOX_ERR_EVENTS_ITERATE_OK};
+ const Tox_System *sys = tox_get_system(tox);
+ Tox_Events_State state = {TOX_ERR_EVENTS_ITERATE_OK, sys->mem};
tox_iterate(tox, &state);
if (error != nullptr) {
@@ -63,205 +107,85 @@ Tox_Events *tox_events_iterate(Tox *tox, bool fail_hard, Tox_Err_Events_Iterate
return state.events;
}
-bool tox_events_pack(const Tox_Events *events, Bin_Pack *bp)
+non_null()
+static bool tox_event_pack_handler(const void *arr, uint32_t index, const Logger *logger, Bin_Pack *bp)
{
- const uint32_t count = tox_events_get_conference_connected_size(events)
- + tox_events_get_conference_invite_size(events)
- + tox_events_get_conference_message_size(events)
- + tox_events_get_conference_peer_list_changed_size(events)
- + tox_events_get_conference_peer_name_size(events)
- + tox_events_get_conference_title_size(events)
- + tox_events_get_file_chunk_request_size(events)
- + tox_events_get_file_recv_chunk_size(events)
- + tox_events_get_file_recv_control_size(events)
- + tox_events_get_file_recv_size(events)
- + tox_events_get_friend_connection_status_size(events)
- + tox_events_get_friend_lossless_packet_size(events)
- + tox_events_get_friend_lossy_packet_size(events)
- + tox_events_get_friend_message_size(events)
- + tox_events_get_friend_name_size(events)
- + tox_events_get_friend_read_receipt_size(events)
- + tox_events_get_friend_request_size(events)
- + tox_events_get_friend_status_message_size(events)
- + tox_events_get_friend_status_size(events)
- + tox_events_get_friend_typing_size(events)
- + tox_events_get_self_connection_status_size(events);
-
- return bin_pack_array(bp, count)
- && tox_events_pack_conference_connected(events, bp)
- && tox_events_pack_conference_invite(events, bp)
- && tox_events_pack_conference_message(events, bp)
- && tox_events_pack_conference_peer_list_changed(events, bp)
- && tox_events_pack_conference_peer_name(events, bp)
- && tox_events_pack_conference_title(events, bp)
- && tox_events_pack_file_chunk_request(events, bp)
- && tox_events_pack_file_recv_chunk(events, bp)
- && tox_events_pack_file_recv_control(events, bp)
- && tox_events_pack_file_recv(events, bp)
- && tox_events_pack_friend_connection_status(events, bp)
- && tox_events_pack_friend_lossless_packet(events, bp)
- && tox_events_pack_friend_lossy_packet(events, bp)
- && tox_events_pack_friend_message(events, bp)
- && tox_events_pack_friend_name(events, bp)
- && tox_events_pack_friend_read_receipt(events, bp)
- && tox_events_pack_friend_request(events, bp)
- && tox_events_pack_friend_status_message(events, bp)
- && tox_events_pack_friend_status(events, bp)
- && tox_events_pack_friend_typing(events, bp)
- && tox_events_pack_self_connection_status(events, bp);
+ const Tox_Event *events = (const Tox_Event *)arr;
+ assert(events != nullptr);
+ return tox_event_pack(&events[index], bp);
}
-non_null()
-static bool tox_event_unpack(Tox_Events *events, Bin_Unpack *bu)
+non_null(3) nullable(1, 2)
+static bool tox_events_pack_handler(const void *obj, const Logger *logger, Bin_Pack *bp)
{
- uint32_t size;
- if (!bin_unpack_array(bu, &size)) {
- return false;
- }
-
- if (size != 2) {
- return false;
- }
-
- uint8_t type;
- if (!bin_unpack_u08(bu, &type)) {
- return false;
- }
-
- switch (type) {
- case TOX_EVENT_CONFERENCE_CONNECTED:
- return tox_events_unpack_conference_connected(events, bu);
-
- case TOX_EVENT_CONFERENCE_INVITE:
- return tox_events_unpack_conference_invite(events, bu);
-
- case TOX_EVENT_CONFERENCE_MESSAGE:
- return tox_events_unpack_conference_message(events, bu);
-
- case TOX_EVENT_CONFERENCE_PEER_LIST_CHANGED:
- return tox_events_unpack_conference_peer_list_changed(events, bu);
-
- case TOX_EVENT_CONFERENCE_PEER_NAME:
- return tox_events_unpack_conference_peer_name(events, bu);
-
- case TOX_EVENT_CONFERENCE_TITLE:
- return tox_events_unpack_conference_title(events, bu);
-
- case TOX_EVENT_FILE_CHUNK_REQUEST:
- return tox_events_unpack_file_chunk_request(events, bu);
-
- case TOX_EVENT_FILE_RECV_CHUNK:
- return tox_events_unpack_file_recv_chunk(events, bu);
-
- case TOX_EVENT_FILE_RECV_CONTROL:
- return tox_events_unpack_file_recv_control(events, bu);
-
- case TOX_EVENT_FILE_RECV:
- return tox_events_unpack_file_recv(events, bu);
-
- case TOX_EVENT_FRIEND_CONNECTION_STATUS:
- return tox_events_unpack_friend_connection_status(events, bu);
-
- case TOX_EVENT_FRIEND_LOSSLESS_PACKET:
- return tox_events_unpack_friend_lossless_packet(events, bu);
-
- case TOX_EVENT_FRIEND_LOSSY_PACKET:
- return tox_events_unpack_friend_lossy_packet(events, bu);
-
- case TOX_EVENT_FRIEND_MESSAGE:
- return tox_events_unpack_friend_message(events, bu);
-
- case TOX_EVENT_FRIEND_NAME:
- return tox_events_unpack_friend_name(events, bu);
-
- case TOX_EVENT_FRIEND_READ_RECEIPT:
- return tox_events_unpack_friend_read_receipt(events, bu);
-
- case TOX_EVENT_FRIEND_REQUEST:
- return tox_events_unpack_friend_request(events, bu);
-
- case TOX_EVENT_FRIEND_STATUS_MESSAGE:
- return tox_events_unpack_friend_status_message(events, bu);
-
- case TOX_EVENT_FRIEND_STATUS:
- return tox_events_unpack_friend_status(events, bu);
-
- case TOX_EVENT_FRIEND_TYPING:
- return tox_events_unpack_friend_typing(events, bu);
-
- case TOX_EVENT_SELF_CONNECTION_STATUS:
- return tox_events_unpack_self_connection_status(events, bu);
+ const Tox_Events *events = (const Tox_Events *)obj;
+ return bin_pack_obj_array(bp, tox_event_pack_handler, tox_events_get_events(events), tox_events_get_size(events), logger);
+}
- default:
- return false;
- }
+uint32_t tox_events_bytes_size(const Tox_Events *events)
+{
+ return bin_pack_obj_size(tox_events_pack_handler, events, nullptr);
+}
- return true;
+bool tox_events_get_bytes(const Tox_Events *events, uint8_t *bytes)
+{
+ return bin_pack_obj(tox_events_pack_handler, events, nullptr, bytes, UINT32_MAX);
}
-bool tox_events_unpack(Tox_Events *events, Bin_Unpack *bu)
+non_null()
+static bool tox_events_unpack_handler(void *obj, Bin_Unpack *bu)
{
+ Tox_Events *events = (Tox_Events *)obj;
+
uint32_t size;
if (!bin_unpack_array(bu, &size)) {
return false;
}
for (uint32_t i = 0; i < size; ++i) {
- if (!tox_event_unpack(events, bu)) {
+ Tox_Event event = {TOX_EVENT_INVALID};
+ if (!tox_event_unpack_into(&event, bu, events->mem)) {
+ tox_event_destruct(&event, events->mem);
+ return false;
+ }
+
+ if (!tox_events_add(events, &event)) {
+ tox_event_destruct(&event, events->mem);
return false;
}
}
+ // Invariant: if all adds worked, the events size must be the input array size.
+ assert(tox_events_get_size(events) == size);
return true;
}
-non_null(1) nullable(2)
-static bool tox_events_bin_pack_handler(Bin_Pack *bp, const void *obj)
-{
- return tox_events_pack((const Tox_Events *)obj, bp);
-}
-
-uint32_t tox_events_bytes_size(const Tox_Events *events)
-{
- return bin_pack_obj_size(tox_events_bin_pack_handler, events);
-}
-
-void tox_events_get_bytes(const Tox_Events *events, uint8_t *bytes)
+Tox_Events *tox_events_load(const Tox_System *sys, const uint8_t *bytes, uint32_t bytes_size)
{
- bin_pack_obj(tox_events_bin_pack_handler, events, bytes, UINT32_MAX);
-}
-
-Tox_Events *tox_events_load(const uint8_t *bytes, uint32_t bytes_size)
-{
- Bin_Unpack *bu = bin_unpack_new(bytes, bytes_size);
-
- if (bu == nullptr) {
- return nullptr;
- }
-
- Tox_Events *events = (Tox_Events *)calloc(1, sizeof(Tox_Events));
+ Tox_Events *events = (Tox_Events *)mem_alloc(sys->mem, sizeof(Tox_Events));
if (events == nullptr) {
- bin_unpack_free(bu);
return nullptr;
}
*events = (Tox_Events) {
nullptr
};
+ events->mem = sys->mem;
- if (!tox_events_unpack(events, bu)) {
+ if (!bin_unpack_obj(tox_events_unpack_handler, events, bytes, bytes_size)) {
tox_events_free(events);
- bin_unpack_free(bu);
return nullptr;
}
- bin_unpack_free(bu);
return events;
}
-bool tox_events_equal(const Tox_Events *a, const Tox_Events *b)
+bool tox_events_equal(const Tox_System *sys, const Tox_Events *a, const Tox_Events *b)
{
+ assert(sys != nullptr);
+ assert(sys->mem != nullptr);
+
const uint32_t a_size = tox_events_bytes_size(a);
const uint32_t b_size = tox_events_bytes_size(b);
@@ -269,12 +193,12 @@ bool tox_events_equal(const Tox_Events *a, const Tox_Events *b)
return false;
}
- uint8_t *a_bytes = (uint8_t *)malloc(a_size);
- uint8_t *b_bytes = (uint8_t *)malloc(b_size);
+ uint8_t *a_bytes = (uint8_t *)mem_balloc(sys->mem, a_size);
+ uint8_t *b_bytes = (uint8_t *)mem_balloc(sys->mem, b_size);
if (a_bytes == nullptr || b_bytes == nullptr) {
- free(b_bytes);
- free(a_bytes);
+ mem_delete(sys->mem, b_bytes);
+ mem_delete(sys->mem, a_bytes);
return false;
}
@@ -283,8 +207,8 @@ bool tox_events_equal(const Tox_Events *a, const Tox_Events *b)
const bool ret = memcmp(a_bytes, b_bytes, a_size) == 0;
- free(b_bytes);
- free(a_bytes);
+ mem_delete(sys->mem, b_bytes);
+ mem_delete(sys->mem, a_bytes);
return ret;
}
diff --git a/protocols/Tox/libtox/src/toxcore/tox_events.h b/protocols/Tox/libtox/src/toxcore/tox_events.h
index f33a71b29c..3edaa7d06b 100644
--- a/protocols/Tox/libtox/src/toxcore/tox_events.h
+++ b/protocols/Tox/libtox/src/toxcore/tox_events.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2022 The TokTok team.
+ * Copyright © 2022-2024 The TokTok team.
*/
#ifndef C_TOXCORE_TOXCORE_TOX_EVENTS_H
@@ -88,7 +88,7 @@ uint32_t tox_event_file_recv_get_kind(
typedef struct Tox_Event_File_Recv_Chunk Tox_Event_File_Recv_Chunk;
const uint8_t *tox_event_file_recv_chunk_get_data(
const Tox_Event_File_Recv_Chunk *file_recv_chunk);
-uint32_t tox_event_file_recv_chunk_get_length(
+uint32_t tox_event_file_recv_chunk_get_data_length(
const Tox_Event_File_Recv_Chunk *file_recv_chunk);
uint32_t tox_event_file_recv_chunk_get_file_number(
const Tox_Event_File_Recv_Chunk *file_recv_chunk);
@@ -183,8 +183,177 @@ typedef struct Tox_Event_Self_Connection_Status Tox_Event_Self_Connection_Status
Tox_Connection tox_event_self_connection_status_get_connection_status(
const Tox_Event_Self_Connection_Status *self_connection_status);
-
-typedef enum Tox_Event {
+typedef struct Tox_Event_Group_Peer_Name Tox_Event_Group_Peer_Name;
+uint32_t tox_event_group_peer_name_get_group_number(
+ const Tox_Event_Group_Peer_Name *group_peer_name);
+uint32_t tox_event_group_peer_name_get_peer_id(
+ const Tox_Event_Group_Peer_Name *group_peer_name);
+const uint8_t *tox_event_group_peer_name_get_name(
+ const Tox_Event_Group_Peer_Name *group_peer_name);
+uint32_t tox_event_group_peer_name_get_name_length(
+ const Tox_Event_Group_Peer_Name *group_peer_name);
+
+typedef struct Tox_Event_Group_Peer_Status Tox_Event_Group_Peer_Status;
+uint32_t tox_event_group_peer_status_get_group_number(
+ const Tox_Event_Group_Peer_Status *group_peer_status);
+uint32_t tox_event_group_peer_status_get_peer_id(
+ const Tox_Event_Group_Peer_Status *group_peer_status);
+Tox_User_Status tox_event_group_peer_status_get_status(
+ const Tox_Event_Group_Peer_Status *group_peer_status);
+
+typedef struct Tox_Event_Group_Topic Tox_Event_Group_Topic;
+uint32_t tox_event_group_topic_get_group_number(
+ const Tox_Event_Group_Topic *group_topic);
+uint32_t tox_event_group_topic_get_peer_id(
+ const Tox_Event_Group_Topic *group_topic);
+const uint8_t *tox_event_group_topic_get_topic(
+ const Tox_Event_Group_Topic *group_topic);
+uint32_t tox_event_group_topic_get_topic_length(
+ const Tox_Event_Group_Topic *group_topic);
+
+typedef struct Tox_Event_Group_Privacy_State Tox_Event_Group_Privacy_State;
+uint32_t tox_event_group_privacy_state_get_group_number(
+ const Tox_Event_Group_Privacy_State *group_privacy_state);
+Tox_Group_Privacy_State tox_event_group_privacy_state_get_privacy_state(
+ const Tox_Event_Group_Privacy_State *group_privacy_state);
+
+typedef struct Tox_Event_Group_Voice_State Tox_Event_Group_Voice_State;
+uint32_t tox_event_group_voice_state_get_group_number(
+ const Tox_Event_Group_Voice_State *group_voice_state);
+Tox_Group_Voice_State tox_event_group_voice_state_get_voice_state(
+ const Tox_Event_Group_Voice_State *group_voice_state);
+
+typedef struct Tox_Event_Group_Topic_Lock Tox_Event_Group_Topic_Lock;
+uint32_t tox_event_group_topic_lock_get_group_number(
+ const Tox_Event_Group_Topic_Lock *group_topic_lock);
+Tox_Group_Topic_Lock tox_event_group_topic_lock_get_topic_lock(
+ const Tox_Event_Group_Topic_Lock *group_topic_lock);
+
+typedef struct Tox_Event_Group_Peer_Limit Tox_Event_Group_Peer_Limit;
+uint32_t tox_event_group_peer_limit_get_group_number(
+ const Tox_Event_Group_Peer_Limit *group_peer_limit);
+uint32_t tox_event_group_peer_limit_get_peer_limit(
+ const Tox_Event_Group_Peer_Limit *group_peer_limit);
+
+typedef struct Tox_Event_Group_Password Tox_Event_Group_Password;
+uint32_t tox_event_group_password_get_group_number(
+ const Tox_Event_Group_Password *group_password);
+const uint8_t *tox_event_group_password_get_password(
+ const Tox_Event_Group_Password *group_password);
+uint32_t tox_event_group_password_get_password_length(
+ const Tox_Event_Group_Password *group_password);
+
+typedef struct Tox_Event_Group_Message Tox_Event_Group_Message;
+uint32_t tox_event_group_message_get_group_number(
+ const Tox_Event_Group_Message *group_message);
+uint32_t tox_event_group_message_get_peer_id(
+ const Tox_Event_Group_Message *group_message);
+Tox_Message_Type tox_event_group_message_get_type(
+ const Tox_Event_Group_Message *group_message);
+const uint8_t *tox_event_group_message_get_message(
+ const Tox_Event_Group_Message *group_message);
+uint32_t tox_event_group_message_get_message_length(
+ const Tox_Event_Group_Message *group_message);
+uint32_t tox_event_group_message_get_message_id(
+ const Tox_Event_Group_Message *group_message);
+
+typedef struct Tox_Event_Group_Private_Message Tox_Event_Group_Private_Message;
+uint32_t tox_event_group_private_message_get_group_number(
+ const Tox_Event_Group_Private_Message *group_private_message);
+uint32_t tox_event_group_private_message_get_peer_id(
+ const Tox_Event_Group_Private_Message *group_private_message);
+Tox_Message_Type tox_event_group_private_message_get_type(
+ const Tox_Event_Group_Private_Message *group_private_message);
+const uint8_t *tox_event_group_private_message_get_message(
+ const Tox_Event_Group_Private_Message *group_private_message);
+uint32_t tox_event_group_private_message_get_message_length(
+ const Tox_Event_Group_Private_Message *group_private_message);
+
+typedef struct Tox_Event_Group_Custom_Packet Tox_Event_Group_Custom_Packet;
+uint32_t tox_event_group_custom_packet_get_group_number(
+ const Tox_Event_Group_Custom_Packet *group_custom_packet);
+uint32_t tox_event_group_custom_packet_get_peer_id(
+ const Tox_Event_Group_Custom_Packet *group_custom_packet);
+const uint8_t *tox_event_group_custom_packet_get_data(
+ const Tox_Event_Group_Custom_Packet *group_custom_packet);
+uint32_t tox_event_group_custom_packet_get_data_length(
+ const Tox_Event_Group_Custom_Packet *group_custom_packet);
+
+typedef struct Tox_Event_Group_Custom_Private_Packet Tox_Event_Group_Custom_Private_Packet;
+uint32_t tox_event_group_custom_private_packet_get_group_number(
+ const Tox_Event_Group_Custom_Private_Packet *group_custom_private_packet);
+uint32_t tox_event_group_custom_private_packet_get_peer_id(
+ const Tox_Event_Group_Custom_Private_Packet *group_custom_private_packet);
+const uint8_t *tox_event_group_custom_private_packet_get_data(
+ const Tox_Event_Group_Custom_Private_Packet *group_custom_private_packet);
+uint32_t tox_event_group_custom_private_packet_get_data_length(
+ const Tox_Event_Group_Custom_Private_Packet *group_custom_private_packet);
+
+typedef struct Tox_Event_Group_Invite Tox_Event_Group_Invite;
+uint32_t tox_event_group_invite_get_friend_number(
+ const Tox_Event_Group_Invite *group_invite);
+const uint8_t *tox_event_group_invite_get_invite_data(
+ const Tox_Event_Group_Invite *group_invite);
+uint32_t tox_event_group_invite_get_invite_data_length(
+ const Tox_Event_Group_Invite *group_invite);
+const uint8_t *tox_event_group_invite_get_group_name(
+ const Tox_Event_Group_Invite *group_invite);
+uint32_t tox_event_group_invite_get_group_name_length(
+ const Tox_Event_Group_Invite *group_invite);
+
+typedef struct Tox_Event_Group_Peer_Join Tox_Event_Group_Peer_Join;
+uint32_t tox_event_group_peer_join_get_group_number(
+ const Tox_Event_Group_Peer_Join *group_peer_join);
+uint32_t tox_event_group_peer_join_get_peer_id(
+ const Tox_Event_Group_Peer_Join *group_peer_join);
+
+typedef struct Tox_Event_Group_Peer_Exit Tox_Event_Group_Peer_Exit;
+uint32_t tox_event_group_peer_exit_get_group_number(
+ const Tox_Event_Group_Peer_Exit *group_peer_exit);
+uint32_t tox_event_group_peer_exit_get_peer_id(
+ const Tox_Event_Group_Peer_Exit *group_peer_exit);
+Tox_Group_Exit_Type tox_event_group_peer_exit_get_exit_type(
+ const Tox_Event_Group_Peer_Exit *group_peer_exit);
+const uint8_t *tox_event_group_peer_exit_get_name(
+ const Tox_Event_Group_Peer_Exit *group_peer_exit);
+uint32_t tox_event_group_peer_exit_get_name_length(
+ const Tox_Event_Group_Peer_Exit *group_peer_exit);
+const uint8_t *tox_event_group_peer_exit_get_part_message(
+ const Tox_Event_Group_Peer_Exit *group_peer_exit);
+uint32_t tox_event_group_peer_exit_get_part_message_length(
+ const Tox_Event_Group_Peer_Exit *group_peer_exit);
+
+typedef struct Tox_Event_Group_Self_Join Tox_Event_Group_Self_Join;
+uint32_t tox_event_group_self_join_get_group_number(
+ const Tox_Event_Group_Self_Join *group_self_join);
+
+typedef struct Tox_Event_Group_Join_Fail Tox_Event_Group_Join_Fail;
+uint32_t tox_event_group_join_fail_get_group_number(
+ const Tox_Event_Group_Join_Fail *group_join_fail);
+Tox_Group_Join_Fail tox_event_group_join_fail_get_fail_type(
+ const Tox_Event_Group_Join_Fail *group_join_fail);
+
+typedef struct Tox_Event_Group_Moderation Tox_Event_Group_Moderation;
+uint32_t tox_event_group_moderation_get_group_number(
+ const Tox_Event_Group_Moderation *group_moderation);
+uint32_t tox_event_group_moderation_get_source_peer_id(
+ const Tox_Event_Group_Moderation *group_moderation);
+uint32_t tox_event_group_moderation_get_target_peer_id(
+ const Tox_Event_Group_Moderation *group_moderation);
+Tox_Group_Mod_Event tox_event_group_moderation_get_mod_type(
+ const Tox_Event_Group_Moderation *group_moderation);
+
+typedef struct Tox_Event_Dht_Get_Nodes_Response Tox_Event_Dht_Get_Nodes_Response;
+const uint8_t *tox_event_dht_get_nodes_response_get_public_key(
+ const Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response);
+const uint8_t *tox_event_dht_get_nodes_response_get_ip(
+ const Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response);
+uint32_t tox_event_dht_get_nodes_response_get_ip_length(
+ const Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response);
+uint16_t tox_event_dht_get_nodes_response_get_port(
+ const Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response);
+
+typedef enum Tox_Event_Type {
TOX_EVENT_SELF_CONNECTION_STATUS = 0,
TOX_EVENT_FRIEND_REQUEST = 1,
@@ -212,7 +381,125 @@ typedef enum Tox_Event {
TOX_EVENT_CONFERENCE_TITLE = 19,
TOX_EVENT_CONFERENCE_MESSAGE = 20,
-} Tox_Event;
+
+ TOX_EVENT_GROUP_PEER_NAME = 21,
+ TOX_EVENT_GROUP_PEER_STATUS = 22,
+ TOX_EVENT_GROUP_TOPIC = 23,
+ TOX_EVENT_GROUP_PRIVACY_STATE = 24,
+ TOX_EVENT_GROUP_VOICE_STATE = 25,
+ TOX_EVENT_GROUP_TOPIC_LOCK = 26,
+ TOX_EVENT_GROUP_PEER_LIMIT = 27,
+ TOX_EVENT_GROUP_PASSWORD = 28,
+ TOX_EVENT_GROUP_MESSAGE = 29,
+ TOX_EVENT_GROUP_PRIVATE_MESSAGE = 30,
+ TOX_EVENT_GROUP_CUSTOM_PACKET = 31,
+ TOX_EVENT_GROUP_CUSTOM_PRIVATE_PACKET = 32,
+ TOX_EVENT_GROUP_INVITE = 33,
+ TOX_EVENT_GROUP_PEER_JOIN = 34,
+ TOX_EVENT_GROUP_PEER_EXIT = 35,
+ TOX_EVENT_GROUP_SELF_JOIN = 36,
+ TOX_EVENT_GROUP_JOIN_FAIL = 37,
+ TOX_EVENT_GROUP_MODERATION = 38,
+
+ TOX_EVENT_DHT_GET_NODES_RESPONSE = 39,
+
+ TOX_EVENT_INVALID = 255,
+} Tox_Event_Type;
+
+const char *tox_event_type_to_string(Tox_Event_Type type);
+
+/**
+ * A single Tox core event.
+ *
+ * It could contain any of the above event types. Use `tox_event_get_type` to
+ * find out which one it is, then use one of the `get` functions to get the
+ * actual event object out. The `get` functions will return NULL in case of type
+ * mismatch.
+ */
+typedef struct Tox_Event Tox_Event;
+
+Tox_Event_Type tox_event_get_type(const Tox_Event *event);
+
+const Tox_Event_Conference_Connected *tox_event_get_conference_connected(
+ const Tox_Event *event);
+const Tox_Event_Conference_Invite *tox_event_get_conference_invite(
+ const Tox_Event *event);
+const Tox_Event_Conference_Message *tox_event_get_conference_message(
+ const Tox_Event *event);
+const Tox_Event_Conference_Peer_List_Changed *tox_event_get_conference_peer_list_changed(
+ const Tox_Event *event);
+const Tox_Event_Conference_Peer_Name *tox_event_get_conference_peer_name(
+ const Tox_Event *event);
+const Tox_Event_Conference_Title *tox_event_get_conference_title(
+ const Tox_Event *event);
+const Tox_Event_File_Chunk_Request *tox_event_get_file_chunk_request(
+ const Tox_Event *event);
+const Tox_Event_File_Recv_Chunk *tox_event_get_file_recv_chunk(
+ const Tox_Event *event);
+const Tox_Event_File_Recv_Control *tox_event_get_file_recv_control(
+ const Tox_Event *event);
+const Tox_Event_File_Recv *tox_event_get_file_recv(
+ const Tox_Event *event);
+const Tox_Event_Friend_Connection_Status *tox_event_get_friend_connection_status(
+ const Tox_Event *event);
+const Tox_Event_Friend_Lossless_Packet *tox_event_get_friend_lossless_packet(
+ const Tox_Event *event);
+const Tox_Event_Friend_Lossy_Packet *tox_event_get_friend_lossy_packet(
+ const Tox_Event *event);
+const Tox_Event_Friend_Message *tox_event_get_friend_message(
+ const Tox_Event *event);
+const Tox_Event_Friend_Name *tox_event_get_friend_name(
+ const Tox_Event *event);
+const Tox_Event_Friend_Read_Receipt *tox_event_get_friend_read_receipt(
+ const Tox_Event *event);
+const Tox_Event_Friend_Request *tox_event_get_friend_request(
+ const Tox_Event *event);
+const Tox_Event_Friend_Status_Message *tox_event_get_friend_status_message(
+ const Tox_Event *event);
+const Tox_Event_Friend_Status *tox_event_get_friend_status(
+ const Tox_Event *event);
+const Tox_Event_Friend_Typing *tox_event_get_friend_typing(
+ const Tox_Event *event);
+const Tox_Event_Self_Connection_Status *tox_event_get_self_connection_status(
+ const Tox_Event *event);
+const Tox_Event_Group_Peer_Name *tox_event_get_group_peer_name(
+ const Tox_Event *event);
+const Tox_Event_Group_Peer_Status *tox_event_get_group_peer_status(
+ const Tox_Event *event);
+const Tox_Event_Group_Topic *tox_event_get_group_topic(
+ const Tox_Event *event);
+const Tox_Event_Group_Privacy_State *tox_event_get_group_privacy_state(
+ const Tox_Event *event);
+const Tox_Event_Group_Voice_State *tox_event_get_group_voice_state(
+ const Tox_Event *event);
+const Tox_Event_Group_Topic_Lock *tox_event_get_group_topic_lock(
+ const Tox_Event *event);
+const Tox_Event_Group_Peer_Limit *tox_event_get_group_peer_limit(
+ const Tox_Event *event);
+const Tox_Event_Group_Password *tox_event_get_group_password(
+ const Tox_Event *event);
+const Tox_Event_Group_Message *tox_event_get_group_message(
+ const Tox_Event *event);
+const Tox_Event_Group_Private_Message *tox_event_get_group_private_message(
+ const Tox_Event *event);
+const Tox_Event_Group_Custom_Packet *tox_event_get_group_custom_packet(
+ const Tox_Event *event);
+const Tox_Event_Group_Custom_Private_Packet *tox_event_get_group_custom_private_packet(
+ const Tox_Event *event);
+const Tox_Event_Group_Invite *tox_event_get_group_invite(
+ const Tox_Event *event);
+const Tox_Event_Group_Peer_Join *tox_event_get_group_peer_join(
+ const Tox_Event *event);
+const Tox_Event_Group_Peer_Exit *tox_event_get_group_peer_exit(
+ const Tox_Event *event);
+const Tox_Event_Group_Self_Join *tox_event_get_group_self_join(
+ const Tox_Event *event);
+const Tox_Event_Group_Join_Fail *tox_event_get_group_join_fail(
+ const Tox_Event *event);
+const Tox_Event_Group_Moderation *tox_event_get_group_moderation(
+ const Tox_Event *event);
+const Tox_Event_Dht_Get_Nodes_Response *tox_event_get_dht_get_nodes_response(
+ const Tox_Event *event);
/**
* Container object for all Tox core events.
@@ -221,70 +508,8 @@ typedef enum Tox_Event {
*/
typedef struct Tox_Events Tox_Events;
-uint32_t tox_events_get_conference_connected_size(const Tox_Events *events);
-uint32_t tox_events_get_conference_invite_size(const Tox_Events *events);
-uint32_t tox_events_get_conference_message_size(const Tox_Events *events);
-uint32_t tox_events_get_conference_peer_list_changed_size(const Tox_Events *events);
-uint32_t tox_events_get_conference_peer_name_size(const Tox_Events *events);
-uint32_t tox_events_get_conference_title_size(const Tox_Events *events);
-uint32_t tox_events_get_file_chunk_request_size(const Tox_Events *events);
-uint32_t tox_events_get_file_recv_chunk_size(const Tox_Events *events);
-uint32_t tox_events_get_file_recv_control_size(const Tox_Events *events);
-uint32_t tox_events_get_file_recv_size(const Tox_Events *events);
-uint32_t tox_events_get_friend_connection_status_size(const Tox_Events *events);
-uint32_t tox_events_get_friend_lossless_packet_size(const Tox_Events *events);
-uint32_t tox_events_get_friend_lossy_packet_size(const Tox_Events *events);
-uint32_t tox_events_get_friend_message_size(const Tox_Events *events);
-uint32_t tox_events_get_friend_name_size(const Tox_Events *events);
-uint32_t tox_events_get_friend_read_receipt_size(const Tox_Events *events);
-uint32_t tox_events_get_friend_request_size(const Tox_Events *events);
-uint32_t tox_events_get_friend_status_message_size(const Tox_Events *events);
-uint32_t tox_events_get_friend_status_size(const Tox_Events *events);
-uint32_t tox_events_get_friend_typing_size(const Tox_Events *events);
-uint32_t tox_events_get_self_connection_status_size(const Tox_Events *events);
-
-const Tox_Event_Conference_Connected *tox_events_get_conference_connected(
- const Tox_Events *events, uint32_t index);
-const Tox_Event_Conference_Invite *tox_events_get_conference_invite(
- const Tox_Events *events, uint32_t index);
-const Tox_Event_Conference_Message *tox_events_get_conference_message(
- const Tox_Events *events, uint32_t index);
-const Tox_Event_Conference_Peer_List_Changed *tox_events_get_conference_peer_list_changed(
- const Tox_Events *events, uint32_t index);
-const Tox_Event_Conference_Peer_Name *tox_events_get_conference_peer_name(
- const Tox_Events *events, uint32_t index);
-const Tox_Event_Conference_Title *tox_events_get_conference_title(
- const Tox_Events *events, uint32_t index);
-const Tox_Event_File_Chunk_Request *tox_events_get_file_chunk_request(
- const Tox_Events *events, uint32_t index);
-const Tox_Event_File_Recv_Chunk *tox_events_get_file_recv_chunk(
- const Tox_Events *events, uint32_t index);
-const Tox_Event_File_Recv_Control *tox_events_get_file_recv_control(
- const Tox_Events *events, uint32_t index);
-const Tox_Event_File_Recv *tox_events_get_file_recv(
- const Tox_Events *events, uint32_t index);
-const Tox_Event_Friend_Connection_Status *tox_events_get_friend_connection_status(
- const Tox_Events *events, uint32_t index);
-const Tox_Event_Friend_Lossless_Packet *tox_events_get_friend_lossless_packet(
- const Tox_Events *events, uint32_t index);
-const Tox_Event_Friend_Lossy_Packet *tox_events_get_friend_lossy_packet(
- const Tox_Events *events, uint32_t index);
-const Tox_Event_Friend_Message *tox_events_get_friend_message(
- const Tox_Events *events, uint32_t index);
-const Tox_Event_Friend_Name *tox_events_get_friend_name(
- const Tox_Events *events, uint32_t index);
-const Tox_Event_Friend_Read_Receipt *tox_events_get_friend_read_receipt(
- const Tox_Events *events, uint32_t index);
-const Tox_Event_Friend_Request *tox_events_get_friend_request(
- const Tox_Events *events, uint32_t index);
-const Tox_Event_Friend_Status_Message *tox_events_get_friend_status_message(
- const Tox_Events *events, uint32_t index);
-const Tox_Event_Friend_Status *tox_events_get_friend_status(
- const Tox_Events *events, uint32_t index);
-const Tox_Event_Friend_Typing *tox_events_get_friend_typing(
- const Tox_Events *events, uint32_t index);
-const Tox_Event_Self_Connection_Status *tox_events_get_self_connection_status(
- const Tox_Events *events, uint32_t index);
+uint32_t tox_events_get_size(const Tox_Events *events);
+const Tox_Event *tox_events_get(const Tox_Events *events, uint32_t index);
/**
* Initialise the events recording system.
@@ -341,14 +566,14 @@ Tox_Events *tox_events_iterate(Tox *tox, bool fail_hard, Tox_Err_Events_Iterate
void tox_events_free(Tox_Events *events);
uint32_t tox_events_bytes_size(const Tox_Events *events);
-void tox_events_get_bytes(const Tox_Events *events, uint8_t *bytes);
+bool tox_events_get_bytes(const Tox_Events *events, uint8_t *bytes);
-Tox_Events *tox_events_load(const uint8_t *bytes, uint32_t bytes_size);
+Tox_Events *tox_events_load(const Tox_System *sys, const uint8_t *bytes, uint32_t bytes_size);
-bool tox_events_equal(const Tox_Events *a, const Tox_Events *b);
+bool tox_events_equal(const Tox_System *sys, const Tox_Events *a, const Tox_Events *b);
#ifdef __cplusplus
-}
+} /* extern "C" */
#endif
-#endif // C_TOXCORE_TOXCORE_TOX_EVENTS_H
+#endif /* C_TOXCORE_TOXCORE_TOX_EVENTS_H */
diff --git a/protocols/Tox/libtox/src/toxcore/tox_pack.c b/protocols/Tox/libtox/src/toxcore/tox_pack.c
new file mode 100644
index 0000000000..3d584ac708
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/tox_pack.c
@@ -0,0 +1,55 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2022 The TokTok team.
+ */
+
+#include "tox_pack.h"
+
+#include <stdint.h>
+
+#include "bin_pack.h"
+#include "tox.h"
+
+bool tox_conference_type_pack(Tox_Conference_Type val, Bin_Pack *bp)
+{
+ return bin_pack_u32(bp, (uint32_t)val);
+}
+bool tox_connection_pack(Tox_Connection val, Bin_Pack *bp)
+{
+ return bin_pack_u32(bp, (uint32_t)val);
+}
+bool tox_file_control_pack(Tox_File_Control val, Bin_Pack *bp)
+{
+ return bin_pack_u32(bp, (uint32_t)val);
+}
+bool tox_message_type_pack(Tox_Message_Type val, Bin_Pack *bp)
+{
+ return bin_pack_u32(bp, (uint32_t)val);
+}
+bool tox_user_status_pack(Tox_User_Status val, Bin_Pack *bp)
+{
+ return bin_pack_u32(bp, (uint32_t)val);
+}
+bool tox_group_privacy_state_pack(Tox_Group_Privacy_State val, Bin_Pack *bp)
+{
+ return bin_pack_u32(bp, (uint32_t)val);
+}
+bool tox_group_voice_state_pack(Tox_Group_Voice_State val, Bin_Pack *bp)
+{
+ return bin_pack_u32(bp, (uint32_t)val);
+}
+bool tox_group_topic_lock_pack(Tox_Group_Topic_Lock val, Bin_Pack *bp)
+{
+ return bin_pack_u32(bp, (uint32_t)val);
+}
+bool tox_group_join_fail_pack(Tox_Group_Join_Fail val, Bin_Pack *bp)
+{
+ return bin_pack_u32(bp, (uint32_t)val);
+}
+bool tox_group_mod_event_pack(Tox_Group_Mod_Event val, Bin_Pack *bp)
+{
+ return bin_pack_u32(bp, (uint32_t)val);
+}
+bool tox_group_exit_type_pack(Tox_Group_Exit_Type val, Bin_Pack *bp)
+{
+ return bin_pack_u32(bp, (uint32_t)val);
+}
diff --git a/protocols/Tox/libtox/src/toxcore/tox_pack.h b/protocols/Tox/libtox/src/toxcore/tox_pack.h
new file mode 100644
index 0000000000..ea8605dcc3
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/tox_pack.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2022 The TokTok team.
+ */
+
+#ifndef C_TOXCORE_TOXCORE_TOX_PACK_H
+#define C_TOXCORE_TOXCORE_TOX_PACK_H
+
+#include "attributes.h"
+#include "bin_pack.h"
+#include "tox.h"
+
+non_null() bool tox_conference_type_pack(Tox_Conference_Type val, Bin_Pack *bp);
+non_null() bool tox_connection_pack(Tox_Connection val, Bin_Pack *bp);
+non_null() bool tox_file_control_pack(Tox_File_Control val, Bin_Pack *bp);
+non_null() bool tox_message_type_pack(Tox_Message_Type val, Bin_Pack *bp);
+non_null() bool tox_user_status_pack(Tox_User_Status val, Bin_Pack *bp);
+non_null() bool tox_group_privacy_state_pack(Tox_Group_Privacy_State val, Bin_Pack *bp);
+non_null() bool tox_group_voice_state_pack(Tox_Group_Voice_State val, Bin_Pack *bp);
+non_null() bool tox_group_topic_lock_pack(Tox_Group_Topic_Lock val, Bin_Pack *bp);
+non_null() bool tox_group_join_fail_pack(Tox_Group_Join_Fail val, Bin_Pack *bp);
+non_null() bool tox_group_mod_event_pack(Tox_Group_Mod_Event val, Bin_Pack *bp);
+non_null() bool tox_group_exit_type_pack(Tox_Group_Exit_Type val, Bin_Pack *bp);
+
+#endif /* C_TOXCORE_TOXCORE_TOX_PACK_H */
diff --git a/protocols/Tox/libtox/src/toxcore/tox_private.c b/protocols/Tox/libtox/src/toxcore/tox_private.c
index 847e96d426..7b6050a9f8 100644
--- a/protocols/Tox/libtox/src/toxcore/tox_private.c
+++ b/protocols/Tox/libtox/src/toxcore/tox_private.c
@@ -10,8 +10,16 @@
#include <assert.h>
+#include "DHT.h"
+#include "attributes.h"
#include "ccompat.h"
+#include "crypto_core.h"
+#include "group_chats.h"
+#include "group_common.h"
+#include "mem.h"
+#include "net_crypto.h"
#include "network.h"
+#include "tox.h"
#include "tox_struct.h"
#define SET_ERROR_PARAMETER(param, x) \
@@ -26,8 +34,9 @@ Tox_System tox_default_system(void)
const Tox_System sys = {
nullptr, // mono_time_callback
nullptr, // mono_time_user_data
- system_random(),
- system_network(),
+ os_random(),
+ os_network(),
+ os_memory(),
};
return sys;
}
@@ -115,11 +124,11 @@ bool tox_dht_get_nodes(const Tox *tox, const uint8_t *public_key, const char *ip
IP_Port *root;
- const int32_t count = net_getipport(ip, &root, TOX_SOCK_DGRAM);
+ const int32_t count = net_getipport(tox->sys.mem, ip, &root, TOX_SOCK_DGRAM);
if (count < 1) {
SET_ERROR_PARAMETER(error, TOX_ERR_DHT_GET_NODES_BAD_IP);
- net_freeipport(root);
+ net_freeipport(tox->sys.mem, root);
tox_unlock(tox);
return false;
}
@@ -136,7 +145,7 @@ bool tox_dht_get_nodes(const Tox *tox, const uint8_t *public_key, const char *ip
tox_unlock(tox);
- net_freeipport(root);
+ net_freeipport(tox->sys.mem, root);
if (!success) {
SET_ERROR_PARAMETER(error, TOX_ERR_DHT_GET_NODES_FAIL);
@@ -147,3 +156,73 @@ bool tox_dht_get_nodes(const Tox *tox, const uint8_t *public_key, const char *ip
return true;
}
+
+uint16_t tox_dht_get_num_closelist(const Tox *tox)
+{
+ tox_lock(tox);
+ const uint16_t num_total = dht_get_num_closelist(tox->m->dht);
+ tox_unlock(tox);
+
+ return num_total;
+}
+
+uint16_t tox_dht_get_num_closelist_announce_capable(const Tox *tox)
+{
+ tox_lock(tox);
+ const uint16_t num_cap = dht_get_num_closelist_announce_capable(tox->m->dht);
+ tox_unlock(tox);
+
+ return num_cap;
+}
+
+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, gc_peer_id_from_int(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, gc_peer_id_from_int(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;
+}
diff --git a/protocols/Tox/libtox/src/toxcore/tox_private.h b/protocols/Tox/libtox/src/toxcore/tox_private.h
index 71d7a97601..d36ab026c3 100644
--- a/protocols/Tox/libtox/src/toxcore/tox_private.h
+++ b/protocols/Tox/libtox/src/toxcore/tox_private.h
@@ -23,6 +23,7 @@ struct Tox_System {
void *mono_time_user_data;
const struct Random *rng;
const struct Network *ns;
+ const struct Memory *mem;
};
Tox_System tox_default_system(void);
@@ -30,6 +31,8 @@ Tox_System tox_default_system(void);
void tox_lock(const Tox *tox);
void tox_unlock(const Tox *tox);
+const Tox_System *tox_get_system(Tox *tox);
+
/**
* Set the callback for the `friend_lossy_packet` event for a specific packet ID.
* Pass NULL to unset.
@@ -53,7 +56,6 @@ void tox_callback_friend_lossless_packet_per_pktid(Tox *tox, tox_friend_lossless
void tox_set_av_object(Tox *tox, void *object);
void *tox_get_av_object(const Tox *tox);
-
/*******************************************************************************
*
* :: DHT network queries.
@@ -82,7 +84,6 @@ uint32_t tox_dht_node_public_key_size(void);
typedef void tox_dht_get_nodes_response_cb(Tox *tox, const uint8_t *public_key, const char *ip, uint16_t port,
void *user_data);
-
/**
* Set the callback for the `dht_get_nodes_response` event. Pass NULL to unset.
*
@@ -90,7 +91,6 @@ typedef void tox_dht_get_nodes_response_cb(Tox *tox, const uint8_t *public_key,
*/
void tox_callback_dht_get_nodes_response(Tox *tox, tox_dht_get_nodes_response_cb *callback);
-
typedef enum Tox_Err_Dht_Get_Nodes {
/**
* The function returned successfully.
@@ -139,8 +139,68 @@ typedef enum Tox_Err_Dht_Get_Nodes {
bool tox_dht_get_nodes(const Tox *tox, const uint8_t *public_key, const char *ip, uint16_t port,
const uint8_t *target_public_key, Tox_Err_Dht_Get_Nodes *error);
+/**
+ * This function returns the ratio of close dht nodes that are known to support announce/store.
+ * This function returns the number of DHT nodes in the closelist.
+ *
+ * @return number
+ */
+uint16_t tox_dht_get_num_closelist(const Tox *tox);
+
+/**
+ * This function returns the number of DHT nodes in the closelist,
+ * that are capable to store annouce data (introduced in version 0.2.18).
+ *
+ * @return number
+ */
+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
-}
+} /* extern "C" */
#endif
-#endif // C_TOXCORE_TOXCORE_TOX_PRIVATE_H
+#endif /* C_TOXCORE_TOXCORE_TOX_PRIVATE_H */
diff --git a/protocols/Tox/libtox/src/toxcore/tox_struct.h b/protocols/Tox/libtox/src/toxcore/tox_struct.h
index 8b95d83bbc..bd42fcce8d 100644
--- a/protocols/Tox/libtox/src/toxcore/tox_struct.h
+++ b/protocols/Tox/libtox/src/toxcore/tox_struct.h
@@ -6,7 +6,11 @@
#ifndef C_TOXCORE_TOXCORE_TOX_STRUCT_H
#define C_TOXCORE_TOXCORE_TOX_STRUCT_H
+#include <pthread.h>
+
#include "Messenger.h"
+#include "mem.h"
+#include "mono_time.h"
#include "tox.h"
#include "tox_private.h"
@@ -17,8 +21,7 @@ extern "C" {
struct Tox {
Messenger *m;
Mono_Time *mono_time;
- Random rng;
- Network ns;
+ Tox_System sys;
pthread_mutex_t *mutex;
tox_log_cb *log_callback;
@@ -67,7 +70,7 @@ struct Tox {
};
#ifdef __cplusplus
-}
+} /* extern "C" */
#endif
-#endif // C_TOXCORE_TOXCORE_TOX_STRUCT_H
+#endif /* C_TOXCORE_TOXCORE_TOX_STRUCT_H */
diff --git a/protocols/Tox/libtox/src/toxcore/tox_unpack.c b/protocols/Tox/libtox/src/toxcore/tox_unpack.c
index 6508399e7e..b5e05da872 100644
--- a/protocols/Tox/libtox/src/toxcore/tox_unpack.c
+++ b/protocols/Tox/libtox/src/toxcore/tox_unpack.c
@@ -6,65 +6,341 @@
#include <stdint.h>
+#include "attributes.h"
#include "bin_unpack.h"
-#include "ccompat.h"
+#include "tox.h"
-bool tox_unpack_conference_type(Bin_Unpack *bu, Tox_Conference_Type *val)
+non_null()
+static bool tox_conference_type_from_int(uint32_t value, Tox_Conference_Type *out)
{
- uint32_t u32;
+ switch (value) {
+ case TOX_CONFERENCE_TYPE_TEXT: {
+ *out = TOX_CONFERENCE_TYPE_TEXT;
+ return true;
+ }
+
+ case TOX_CONFERENCE_TYPE_AV: {
+ *out = TOX_CONFERENCE_TYPE_AV;
+ return true;
+ }
- if (!bin_unpack_u32(bu, &u32)) {
- return false;
+ default: {
+ *out = TOX_CONFERENCE_TYPE_TEXT;
+ return false;
+ }
}
+}
+bool tox_conference_type_unpack(Tox_Conference_Type *val, Bin_Unpack *bu)
+{
+ uint32_t u32;
+ return bin_unpack_u32(bu, &u32)
+ && tox_conference_type_from_int(u32, val);
+}
+
+non_null()
+static bool tox_connection_from_int(uint32_t value, Tox_Connection *out)
+{
+ switch (value) {
+ case TOX_CONNECTION_NONE: {
+ *out = TOX_CONNECTION_NONE;
+ return true;
+ }
- *val = (Tox_Conference_Type)u32;
- return true;
+ case TOX_CONNECTION_TCP: {
+ *out = TOX_CONNECTION_TCP;
+ return true;
+ }
+
+ case TOX_CONNECTION_UDP: {
+ *out = TOX_CONNECTION_UDP;
+ return true;
+ }
+
+ default: {
+ *out = TOX_CONNECTION_NONE;
+ return false;
+ }
+ }
}
-bool tox_unpack_connection(Bin_Unpack *bu, Tox_Connection *val)
+bool tox_connection_unpack(Tox_Connection *val, Bin_Unpack *bu)
{
uint32_t u32;
+ return bin_unpack_u32(bu, &u32)
+ && tox_connection_from_int(u32, val);
+}
- if (!bin_unpack_u32(bu, &u32)) {
- return false;
- }
+non_null()
+static bool tox_file_control_from_int(uint32_t value, Tox_File_Control *out)
+{
+ switch (value) {
+ case TOX_FILE_CONTROL_RESUME: {
+ *out = TOX_FILE_CONTROL_RESUME;
+ return true;
+ }
+
+ case TOX_FILE_CONTROL_PAUSE: {
+ *out = TOX_FILE_CONTROL_PAUSE;
+ return true;
+ }
+
+ case TOX_FILE_CONTROL_CANCEL: {
+ *out = TOX_FILE_CONTROL_CANCEL;
+ return true;
+ }
- *val = (Tox_Connection)u32;
- return true;
+ default: {
+ *out = TOX_FILE_CONTROL_RESUME;
+ return false;
+ }
+ }
}
-bool tox_unpack_file_control(Bin_Unpack *bu, Tox_File_Control *val)
+bool tox_file_control_unpack(Tox_File_Control *val, Bin_Unpack *bu)
{
uint32_t u32;
+ return bin_unpack_u32(bu, &u32)
+ && tox_file_control_from_int(u32, val);
+}
+
+non_null()
+static bool tox_message_type_from_int(uint32_t value, Tox_Message_Type *out)
+{
+ switch (value) {
+ case TOX_MESSAGE_TYPE_NORMAL: {
+ *out = TOX_MESSAGE_TYPE_NORMAL;
+ return true;
+ }
- if (!bin_unpack_u32(bu, &u32)) {
- return false;
+ case TOX_MESSAGE_TYPE_ACTION: {
+ *out = TOX_MESSAGE_TYPE_ACTION;
+ return true;
+ }
+
+ default: {
+ *out = TOX_MESSAGE_TYPE_NORMAL;
+ return false;
+ }
}
+}
- *val = (Tox_File_Control)u32;
- return true;
+bool tox_message_type_unpack(Tox_Message_Type *val, Bin_Unpack *bu)
+{
+ uint32_t u32;
+ return bin_unpack_u32(bu, &u32)
+ && tox_message_type_from_int(u32, val);
+}
+
+non_null()
+static bool tox_user_status_from_int(uint32_t value, Tox_User_Status *out)
+{
+ switch (value) {
+ case TOX_USER_STATUS_NONE: {
+ *out = TOX_USER_STATUS_NONE;
+ return true;
+ }
+
+ case TOX_USER_STATUS_AWAY: {
+ *out = TOX_USER_STATUS_AWAY;
+ return true;
+ }
+
+ case TOX_USER_STATUS_BUSY: {
+ *out = TOX_USER_STATUS_BUSY;
+ return true;
+ }
+
+ default: {
+ *out = TOX_USER_STATUS_NONE;
+ return false;
+ }
+ }
}
-bool tox_unpack_message_type(Bin_Unpack *bu, Tox_Message_Type *val)
+bool tox_user_status_unpack(Tox_User_Status *val, Bin_Unpack *bu)
{
uint32_t u32;
+ return bin_unpack_u32(bu, &u32)
+ && tox_user_status_from_int(u32, val);
+}
- if (!bin_unpack_u32(bu, &u32)) {
- return false;
+non_null()
+static bool tox_group_privacy_state_from_int(uint32_t value, Tox_Group_Privacy_State *out)
+{
+ switch (value) {
+ case TOX_GROUP_PRIVACY_STATE_PUBLIC: {
+ *out = TOX_GROUP_PRIVACY_STATE_PUBLIC;
+ return true;
+ }
+ case TOX_GROUP_PRIVACY_STATE_PRIVATE: {
+ *out = TOX_GROUP_PRIVACY_STATE_PRIVATE;
+ return true;
+ }
+ default: {
+ *out = TOX_GROUP_PRIVACY_STATE_PUBLIC;
+ return false;
+ }
+ }
+}
+bool tox_group_privacy_state_unpack(Tox_Group_Privacy_State *val, Bin_Unpack *bu)
+{
+ uint32_t u32;
+ return bin_unpack_u32(bu, &u32)
+ && tox_group_privacy_state_from_int(u32, val);
+}
+non_null()
+static bool tox_group_voice_state_from_int(uint32_t value, Tox_Group_Voice_State *out)
+{
+ switch (value) {
+ case TOX_GROUP_VOICE_STATE_ALL: {
+ *out = TOX_GROUP_VOICE_STATE_ALL;
+ return true;
+ }
+ case TOX_GROUP_VOICE_STATE_MODERATOR: {
+ *out = TOX_GROUP_VOICE_STATE_MODERATOR;
+ return true;
+ }
+ case TOX_GROUP_VOICE_STATE_FOUNDER: {
+ *out = TOX_GROUP_VOICE_STATE_FOUNDER;
+ return true;
+ }
+ default: {
+ *out = TOX_GROUP_VOICE_STATE_ALL;
+ return false;
+ }
}
+}
+bool tox_group_voice_state_unpack(Tox_Group_Voice_State *val, Bin_Unpack *bu)
+{
+ uint32_t u32;
+ return bin_unpack_u32(bu, &u32)
+ && tox_group_voice_state_from_int(u32, val);
+}
- *val = (Tox_Message_Type)u32;
- return true;
+non_null()
+static bool tox_group_topic_lock_from_int(uint32_t value, Tox_Group_Topic_Lock *out)
+{
+ switch (value) {
+ case TOX_GROUP_TOPIC_LOCK_ENABLED: {
+ *out = TOX_GROUP_TOPIC_LOCK_ENABLED;
+ return true;
+ }
+ case TOX_GROUP_TOPIC_LOCK_DISABLED: {
+ *out = TOX_GROUP_TOPIC_LOCK_DISABLED;
+ return true;
+ }
+ default: {
+ *out = TOX_GROUP_TOPIC_LOCK_ENABLED;
+ return false;
+ }
+ }
+}
+bool tox_group_topic_lock_unpack(Tox_Group_Topic_Lock *val, Bin_Unpack *bu)
+{
+ uint32_t u32;
+ return bin_unpack_u32(bu, &u32)
+ && tox_group_topic_lock_from_int(u32, val);
}
-bool tox_unpack_user_status(Bin_Unpack *bu, Tox_User_Status *val)
+non_null()
+static bool tox_group_join_fail_from_int(uint32_t value, Tox_Group_Join_Fail *out)
+{
+ switch (value) {
+ case TOX_GROUP_JOIN_FAIL_PEER_LIMIT: {
+ *out = TOX_GROUP_JOIN_FAIL_PEER_LIMIT;
+ return true;
+ }
+ case TOX_GROUP_JOIN_FAIL_INVALID_PASSWORD: {
+ *out = TOX_GROUP_JOIN_FAIL_INVALID_PASSWORD;
+ return true;
+ }
+ case TOX_GROUP_JOIN_FAIL_UNKNOWN: {
+ *out = TOX_GROUP_JOIN_FAIL_UNKNOWN;
+ return true;
+ }
+ default: {
+ *out = TOX_GROUP_JOIN_FAIL_PEER_LIMIT;
+ return false;
+ }
+ }
+}
+bool tox_group_join_fail_unpack(Tox_Group_Join_Fail *val, Bin_Unpack *bu)
{
uint32_t u32;
+ return bin_unpack_u32(bu, &u32)
+ && tox_group_join_fail_from_int(u32, val);
+}
- if (!bin_unpack_u32(bu, &u32)) {
- return false;
+non_null()
+static bool tox_group_mod_event_from_int(uint32_t value, Tox_Group_Mod_Event *out)
+{
+ switch (value) {
+ case TOX_GROUP_MOD_EVENT_KICK: {
+ *out = TOX_GROUP_MOD_EVENT_KICK;
+ return true;
+ }
+ case TOX_GROUP_MOD_EVENT_OBSERVER: {
+ *out = TOX_GROUP_MOD_EVENT_OBSERVER;
+ return true;
+ }
+ case TOX_GROUP_MOD_EVENT_USER: {
+ *out = TOX_GROUP_MOD_EVENT_USER;
+ return true;
+ }
+ case TOX_GROUP_MOD_EVENT_MODERATOR: {
+ *out = TOX_GROUP_MOD_EVENT_MODERATOR;
+ return true;
+ }
+ default: {
+ *out = TOX_GROUP_MOD_EVENT_KICK;
+ return false;
+ }
}
+}
+bool tox_group_mod_event_unpack(Tox_Group_Mod_Event *val, Bin_Unpack *bu)
+{
+ uint32_t u32;
+ return bin_unpack_u32(bu, &u32)
+ && tox_group_mod_event_from_int(u32, val);
+}
- *val = (Tox_User_Status)u32;
- return true;
+non_null()
+static bool tox_group_exit_type_from_int(uint32_t value, Tox_Group_Exit_Type *out)
+{
+ switch (value) {
+ case TOX_GROUP_EXIT_TYPE_QUIT: {
+ *out = TOX_GROUP_EXIT_TYPE_QUIT;
+ return true;
+ }
+ case TOX_GROUP_EXIT_TYPE_TIMEOUT: {
+ *out = TOX_GROUP_EXIT_TYPE_TIMEOUT;
+ return true;
+ }
+ case TOX_GROUP_EXIT_TYPE_DISCONNECTED: {
+ *out = TOX_GROUP_EXIT_TYPE_DISCONNECTED;
+ return true;
+ }
+ case TOX_GROUP_EXIT_TYPE_SELF_DISCONNECTED: {
+ *out = TOX_GROUP_EXIT_TYPE_SELF_DISCONNECTED;
+ return true;
+ }
+ case TOX_GROUP_EXIT_TYPE_KICK: {
+ *out = TOX_GROUP_EXIT_TYPE_KICK;
+ return true;
+ }
+ case TOX_GROUP_EXIT_TYPE_SYNC_ERROR: {
+ *out = TOX_GROUP_EXIT_TYPE_SYNC_ERROR;
+ return true;
+ }
+ default: {
+ *out = TOX_GROUP_EXIT_TYPE_QUIT;
+ return false;
+ }
+ }
+}
+bool tox_group_exit_type_unpack(Tox_Group_Exit_Type *val, Bin_Unpack *bu)
+{
+ uint32_t u32;
+ return bin_unpack_u32(bu, &u32)
+ && tox_group_exit_type_from_int(u32, val);
}
diff --git a/protocols/Tox/libtox/src/toxcore/tox_unpack.h b/protocols/Tox/libtox/src/toxcore/tox_unpack.h
index 5f0b18ad1b..828d2947a6 100644
--- a/protocols/Tox/libtox/src/toxcore/tox_unpack.h
+++ b/protocols/Tox/libtox/src/toxcore/tox_unpack.h
@@ -9,10 +9,16 @@
#include "bin_unpack.h"
#include "tox.h"
-non_null() bool tox_unpack_conference_type(Bin_Unpack *bu, Tox_Conference_Type *val);
-non_null() bool tox_unpack_connection(Bin_Unpack *bu, Tox_Connection *val);
-non_null() bool tox_unpack_file_control(Bin_Unpack *bu, Tox_File_Control *val);
-non_null() bool tox_unpack_message_type(Bin_Unpack *bu, Tox_Message_Type *val);
-non_null() bool tox_unpack_user_status(Bin_Unpack *bu, Tox_User_Status *val);
+non_null() bool tox_conference_type_unpack(Tox_Conference_Type *val, Bin_Unpack *bu);
+non_null() bool tox_connection_unpack(Tox_Connection *val, Bin_Unpack *bu);
+non_null() bool tox_file_control_unpack(Tox_File_Control *val, Bin_Unpack *bu);
+non_null() bool tox_message_type_unpack(Tox_Message_Type *val, Bin_Unpack *bu);
+non_null() bool tox_user_status_unpack(Tox_User_Status *val, Bin_Unpack *bu);
+non_null() bool tox_group_privacy_state_unpack(Tox_Group_Privacy_State *val, Bin_Unpack *bu);
+non_null() bool tox_group_voice_state_unpack(Tox_Group_Voice_State *val, Bin_Unpack *bu);
+non_null() bool tox_group_topic_lock_unpack(Tox_Group_Topic_Lock *val, Bin_Unpack *bu);
+non_null() bool tox_group_join_fail_unpack(Tox_Group_Join_Fail *val, Bin_Unpack *bu);
+non_null() bool tox_group_mod_event_unpack(Tox_Group_Mod_Event *val, Bin_Unpack *bu);
+non_null() bool tox_group_exit_type_unpack(Tox_Group_Exit_Type *val, Bin_Unpack *bu);
-#endif // C_TOXCORE_TOXCORE_TOX_UNPACK_H
+#endif /* C_TOXCORE_TOXCORE_TOX_UNPACK_H */
diff --git a/protocols/Tox/libtox/src/toxcore/util.c b/protocols/Tox/libtox/src/toxcore/util.c
index 402977a680..1851e58a08 100644
--- a/protocols/Tox/libtox/src/toxcore/util.c
+++ b/protocols/Tox/libtox/src/toxcore/util.c
@@ -9,22 +9,22 @@
*/
#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE 600
-#endif
+#endif /* _XOPEN_SOURCE */
#include "util.h"
#include <stdlib.h>
#include <string.h>
-#include <time.h>
#include "ccompat.h"
+#include "mem.h"
bool is_power_of_2(uint64_t x)
{
return x != 0 && (x & (~x + 1)) == x;
}
-void free_uint8_t_pointer_array(uint8_t **ary, size_t n_items)
+void free_uint8_t_pointer_array(const Memory *mem, uint8_t **ary, size_t n_items)
{
if (ary == nullptr) {
return;
@@ -32,11 +32,11 @@ void free_uint8_t_pointer_array(uint8_t **ary, size_t n_items)
for (size_t i = 0; i < n_items; ++i) {
if (ary[i] != nullptr) {
- free(ary[i]);
+ mem_delete(mem, ary[i]);
}
}
- free(ary);
+ mem_delete(mem, ary);
}
uint16_t data_checksum(const uint8_t *data, uint32_t length)
@@ -81,6 +81,30 @@ bool memeq(const uint8_t *a, size_t a_size, const uint8_t *b, size_t b_size)
return a_size == b_size && memcmp(a, b, a_size) == 0;
}
+uint8_t *memdup(const uint8_t *data, size_t data_size)
+{
+ if (data == nullptr || data_size == 0) {
+ return nullptr;
+ }
+
+ uint8_t *copy = (uint8_t *)malloc(data_size);
+
+ if (copy != nullptr) {
+ memcpy(copy, data, data_size);
+ }
+
+ return copy;
+}
+
+void memzero(uint8_t *data, size_t data_size)
+{
+ if (data == nullptr || data_size == 0) {
+ return;
+ }
+
+ memset(data, 0, data_size);
+}
+
int16_t max_s16(int16_t a, int16_t b)
{
return a > b ? a : b;
@@ -107,6 +131,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;
@@ -133,6 +161,11 @@ uint64_t min_u64(uint64_t a, uint64_t b)
return a < b ? a : b;
}
+int cmp_uint(uint64_t a, uint64_t b)
+{
+ return (a > b ? 1 : 0) - (a < b ? 1 : 0);
+}
+
uint32_t jenkins_one_at_a_time_hash(const uint8_t *key, size_t len)
{
uint32_t hash = 0;
diff --git a/protocols/Tox/libtox/src/toxcore/util.h b/protocols/Tox/libtox/src/toxcore/util.h
index 588feb5694..5be74a8d86 100644
--- a/protocols/Tox/libtox/src/toxcore/util.h
+++ b/protocols/Tox/libtox/src/toxcore/util.h
@@ -16,6 +16,7 @@
#include <stdint.h>
#include "attributes.h"
+#include "mem.h"
#ifdef __cplusplus
extern "C" {
@@ -24,8 +25,8 @@ extern "C" {
bool is_power_of_2(uint64_t x);
/** @brief Frees all pointers in a uint8_t pointer array, as well as the array itself. */
-nullable(1)
-void free_uint8_t_pointer_array(uint8_t **ary, size_t n_items);
+non_null(1) nullable(2)
+void free_uint8_t_pointer_array(const Memory *mem, uint8_t **ary, size_t n_items);
/** Returns -1 if failed or 0 if success */
non_null() int create_recursive_mutex(pthread_mutex_t *mutex);
@@ -40,6 +41,23 @@ non_null() int create_recursive_mutex(pthread_mutex_t *mutex);
*/
non_null() bool memeq(const uint8_t *a, size_t a_size, const uint8_t *b, size_t b_size);
+/**
+ * @brief Copies a byte array of a given size into a newly allocated one.
+ *
+ * @return nullptr on allocation failure or if the input data was nullptr or data_size was 0.
+ */
+nullable(1) uint8_t *memdup(const uint8_t *data, size_t data_size);
+
+/**
+ * @brief Set all bytes in `data` to 0.
+ *
+ * NOTE: This does not securely zero out data. DO NOT USE for sensitive data. Use
+ * `crypto_memzero` from `crypto_core.h`, instead. This function is ok to use for
+ * message buffers, public keys, encrypted data, etc. It is not ok for buffers
+ * containing key material (secret keys, shared keys).
+ */
+nullable(1) void memzero(uint8_t *data, size_t data_size);
+
// Safe min/max functions with specific types. This forces the conversion to the
// desired type before the comparison expression, giving the choice of
// conversion to the caller. Use these instead of inline comparisons or MIN/MAX
@@ -52,6 +70,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);
@@ -60,6 +79,9 @@ uint16_t min_u16(uint16_t a, uint16_t b);
uint32_t min_u32(uint32_t a, uint32_t b);
uint64_t min_u64(uint64_t a, uint64_t b);
+// Comparison function: return -1 if a<b, 0 if a==b, 1 if a>b.
+int cmp_uint(uint64_t a, uint64_t b);
+
/** @brief Returns a 32-bit hash of key of size len */
non_null()
uint32_t jenkins_one_at_a_time_hash(const uint8_t *key, size_t len);
@@ -75,7 +97,7 @@ non_null()
uint16_t data_checksum(const uint8_t *data, uint32_t length);
#ifdef __cplusplus
-} // extern "C"
+} /* extern "C" */
#endif
-#endif // C_TOXCORE_TOXCORE_UTIL_H
+#endif /* C_TOXCORE_TOXCORE_UTIL_H */
diff --git a/protocols/Tox/libtox/src/toxencryptsave/defines.h b/protocols/Tox/libtox/src/toxencryptsave/defines.h
index 71c0f105a5..ac80cc7893 100644
--- a/protocols/Tox/libtox/src/toxencryptsave/defines.h
+++ b/protocols/Tox/libtox/src/toxencryptsave/defines.h
@@ -9,4 +9,4 @@
#define TOX_ENC_SAVE_MAGIC_NUMBER ((const uint8_t *)"toxEsave")
#define TOX_ENC_SAVE_MAGIC_LENGTH 8
-#endif
+#endif /* C_TOXCORE_TOXENCRYPTSAVE_DEFINES_H */
diff --git a/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.c b/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.c
index 45003055f4..c43e357528 100644
--- a/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.c
+++ b/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.c
@@ -79,7 +79,9 @@ void tox_pass_key_free(Tox_Pass_Key *key)
*
* @return true on success.
*/
-bool tox_get_salt(const uint8_t *ciphertext, uint8_t *salt, Tox_Err_Get_Salt *error)
+bool tox_get_salt(
+ const uint8_t ciphertext[TOX_PASS_ENCRYPTION_EXTRA_LENGTH],
+ uint8_t salt[TOX_PASS_SALT_LENGTH], Tox_Err_Get_Salt *error)
{
if (ciphertext == nullptr || salt == nullptr) {
SET_ERROR_PARAMETER(error, TOX_ERR_GET_SALT_NULL);
@@ -112,10 +114,11 @@ bool tox_get_salt(const uint8_t *ciphertext, uint8_t *salt, Tox_Err_Get_Salt *er
*
* @return new symmetric key on success, NULL on failure.
*/
-Tox_Pass_Key *tox_pass_key_derive(const uint8_t *passphrase, size_t passphrase_len,
- Tox_Err_Key_Derivation *error)
+Tox_Pass_Key *tox_pass_key_derive(
+ const uint8_t passphrase[], size_t passphrase_len,
+ Tox_Err_Key_Derivation *error)
{
- const Random *rng = system_random();
+ const Random *rng = os_random();
if (rng == nullptr) {
SET_ERROR_PARAMETER(error, TOX_ERR_KEY_DERIVATION_FAILED);
@@ -136,8 +139,9 @@ Tox_Pass_Key *tox_pass_key_derive(const uint8_t *passphrase, size_t passphrase_l
*
* @return new symmetric key on success, NULL on failure.
*/
-Tox_Pass_Key *tox_pass_key_derive_with_salt(const uint8_t *passphrase, size_t passphrase_len,
- const uint8_t *salt, Tox_Err_Key_Derivation *error)
+Tox_Pass_Key *tox_pass_key_derive_with_salt(
+ const uint8_t passphrase[], size_t passphrase_len,
+ const uint8_t salt[TOX_PASS_SALT_LENGTH], Tox_Err_Key_Derivation *error)
{
if (salt == nullptr || (passphrase == nullptr && passphrase_len != 0)) {
SET_ERROR_PARAMETER(error, TOX_ERR_KEY_DERIVATION_NULL);
@@ -189,10 +193,10 @@ Tox_Pass_Key *tox_pass_key_derive_with_salt(const uint8_t *passphrase, size_t pa
*
* @return true on success.
*/
-bool tox_pass_key_encrypt(const Tox_Pass_Key *key, const uint8_t *plaintext, size_t plaintext_len,
- uint8_t *ciphertext, Tox_Err_Encryption *error)
+bool tox_pass_key_encrypt(const Tox_Pass_Key *key, const uint8_t plaintext[], size_t plaintext_len,
+ uint8_t ciphertext[], Tox_Err_Encryption *error)
{
- const Random *rng = system_random();
+ const Random *rng = os_random();
if (rng == nullptr) {
SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_FAILED);
@@ -250,8 +254,8 @@ bool tox_pass_key_encrypt(const Tox_Pass_Key *key, const uint8_t *plaintext, siz
*
* @return true on success.
*/
-bool tox_pass_encrypt(const uint8_t *plaintext, size_t plaintext_len, const uint8_t *passphrase, size_t passphrase_len,
- uint8_t *ciphertext, Tox_Err_Encryption *error)
+bool tox_pass_encrypt(const uint8_t plaintext[], size_t plaintext_len, const uint8_t passphrase[], size_t passphrase_len,
+ uint8_t ciphertext[/*! plaintext_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH */], Tox_Err_Encryption *error)
{
Tox_Err_Key_Derivation err;
Tox_Pass_Key *key = tox_pass_key_derive(passphrase, passphrase_len, &err);
@@ -281,8 +285,8 @@ bool tox_pass_encrypt(const uint8_t *plaintext, size_t plaintext_len, const uint
*
* @return true on success.
*/
-bool tox_pass_key_decrypt(const Tox_Pass_Key *key, const uint8_t *ciphertext, size_t ciphertext_len,
- uint8_t *plaintext, Tox_Err_Decryption *error)
+bool tox_pass_key_decrypt(const Tox_Pass_Key *key, const uint8_t ciphertext[], size_t ciphertext_len,
+ uint8_t plaintext[], Tox_Err_Decryption *error)
{
if (ciphertext_len <= TOX_PASS_ENCRYPTION_EXTRA_LENGTH) {
SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_INVALID_LENGTH);
@@ -333,8 +337,8 @@ bool tox_pass_key_decrypt(const Tox_Pass_Key *key, const uint8_t *ciphertext, si
*
* @return true on success.
*/
-bool tox_pass_decrypt(const uint8_t *ciphertext, size_t ciphertext_len, const uint8_t *passphrase,
- size_t passphrase_len, uint8_t *plaintext, Tox_Err_Decryption *error)
+bool tox_pass_decrypt(const uint8_t ciphertext[], size_t ciphertext_len, const uint8_t passphrase[],
+ size_t passphrase_len, uint8_t plaintext[/*! ciphertext_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH */], Tox_Err_Decryption *error)
{
if (ciphertext_len <= TOX_PASS_ENCRYPTION_EXTRA_LENGTH) {
SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_INVALID_LENGTH);
@@ -382,7 +386,7 @@ bool tox_pass_decrypt(const uint8_t *ciphertext, size_t ciphertext_len, const ui
*
* @return true if the data is encrypted by this module.
*/
-bool tox_is_data_encrypted(const uint8_t *data)
+bool tox_is_data_encrypted(const uint8_t data[TOX_PASS_ENCRYPTION_EXTRA_LENGTH])
{
return memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) == 0;
}
diff --git a/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.h b/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.h
index 90d8255eec..b9691551c7 100644
--- a/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.h
+++ b/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.h
@@ -14,7 +14,6 @@
#include <stddef.h>
#include <stdint.h>
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -46,8 +45,6 @@ extern "C" {
*
******************************************************************************/
-
-
/**
* The size of the salt part of a pass-key.
*/
@@ -91,7 +88,6 @@ typedef enum Tox_Err_Key_Derivation {
} Tox_Err_Key_Derivation;
-
typedef enum Tox_Err_Encryption {
/**
@@ -118,7 +114,6 @@ typedef enum Tox_Err_Encryption {
} Tox_Err_Encryption;
-
typedef enum Tox_Err_Decryption {
/**
@@ -157,8 +152,6 @@ typedef enum Tox_Err_Decryption {
} Tox_Err_Decryption;
-
-
/*******************************************************************************
*
* BEGIN PART 1
@@ -169,8 +162,6 @@ typedef enum Tox_Err_Decryption {
*
******************************************************************************/
-
-
/**
* Encrypts the given data with the given passphrase.
*
@@ -186,8 +177,8 @@ typedef enum Tox_Err_Decryption {
*
* @return true on success.
*/
-bool tox_pass_encrypt(const uint8_t *plaintext, size_t plaintext_len, const uint8_t *passphrase, size_t passphrase_len,
- uint8_t *ciphertext, Tox_Err_Encryption *error);
+bool tox_pass_encrypt(const uint8_t plaintext[], size_t plaintext_len, const uint8_t passphrase[], size_t passphrase_len,
+ uint8_t ciphertext[/*! plaintext_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH */], Tox_Err_Encryption *error);
/**
* Decrypts the given data with the given passphrase.
@@ -203,9 +194,8 @@ bool tox_pass_encrypt(const uint8_t *plaintext, size_t plaintext_len, const uint
*
* @return true on success.
*/
-bool tox_pass_decrypt(const uint8_t *ciphertext, size_t ciphertext_len, const uint8_t *passphrase,
- size_t passphrase_len, uint8_t *plaintext, Tox_Err_Decryption *error);
-
+bool tox_pass_decrypt(const uint8_t ciphertext[], size_t ciphertext_len, const uint8_t passphrase[],
+ size_t passphrase_len, uint8_t plaintext[/*! ciphertext_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH */], Tox_Err_Decryption *error);
/*******************************************************************************
*
@@ -216,8 +206,6 @@ bool tox_pass_decrypt(const uint8_t *ciphertext, size_t ciphertext_len, const ui
*
******************************************************************************/
-
-
/**
* This type represents a pass-key.
*
@@ -255,8 +243,9 @@ void tox_pass_key_free(Tox_Pass_Key *key);
*
* @return new symmetric key on success, NULL on failure.
*/
-Tox_Pass_Key *tox_pass_key_derive(const uint8_t *passphrase, size_t passphrase_len,
- Tox_Err_Key_Derivation *error);
+Tox_Pass_Key *tox_pass_key_derive(
+ const uint8_t passphrase[], size_t passphrase_len,
+ Tox_Err_Key_Derivation *error);
/**
* Same as above, except use the given salt for deterministic key derivation.
@@ -267,8 +256,9 @@ Tox_Pass_Key *tox_pass_key_derive(const uint8_t *passphrase, size_t passphrase_l
*
* @return new symmetric key on success, NULL on failure.
*/
-Tox_Pass_Key *tox_pass_key_derive_with_salt(const uint8_t *passphrase, size_t passphrase_len,
- const uint8_t *salt, Tox_Err_Key_Derivation *error);
+Tox_Pass_Key *tox_pass_key_derive_with_salt(
+ const uint8_t passphrase[], size_t passphrase_len,
+ const uint8_t salt[TOX_PASS_SALT_LENGTH], Tox_Err_Key_Derivation *error);
/**
* Encrypt a plain text with a key produced by tox_pass_key_derive or tox_pass_key_derive_with_salt.
@@ -282,8 +272,8 @@ Tox_Pass_Key *tox_pass_key_derive_with_salt(const uint8_t *passphrase, size_t pa
*
* @return true on success.
*/
-bool tox_pass_key_encrypt(const Tox_Pass_Key *key, const uint8_t *plaintext, size_t plaintext_len,
- uint8_t *ciphertext, Tox_Err_Encryption *error);
+bool tox_pass_key_encrypt(const Tox_Pass_Key *key, const uint8_t plaintext[], size_t plaintext_len,
+ uint8_t ciphertext[/*! plaintext_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH */], Tox_Err_Encryption *error);
/**
* This is the inverse of tox_pass_key_encrypt, also using only keys produced by
@@ -295,8 +285,8 @@ bool tox_pass_key_encrypt(const Tox_Pass_Key *key, const uint8_t *plaintext, siz
*
* @return true on success.
*/
-bool tox_pass_key_decrypt(const Tox_Pass_Key *key, const uint8_t *ciphertext, size_t ciphertext_len,
- uint8_t *plaintext, Tox_Err_Decryption *error);
+bool tox_pass_key_decrypt(const Tox_Pass_Key *key, const uint8_t ciphertext[], size_t ciphertext_len,
+ uint8_t plaintext[/*! ciphertext_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH */], Tox_Err_Decryption *error);
typedef enum Tox_Err_Get_Salt {
@@ -318,7 +308,6 @@ typedef enum Tox_Err_Get_Salt {
} Tox_Err_Get_Salt;
-
/**
* Retrieves the salt used to encrypt the given data.
*
@@ -338,7 +327,9 @@ typedef enum Tox_Err_Get_Salt {
*
* @return true on success.
*/
-bool tox_get_salt(const uint8_t *ciphertext, uint8_t *salt, Tox_Err_Get_Salt *error);
+bool tox_get_salt(
+ const uint8_t ciphertext[TOX_PASS_ENCRYPTION_EXTRA_LENGTH],
+ uint8_t salt[TOX_PASS_SALT_LENGTH], Tox_Err_Get_Salt *error);
/**
* Determines whether or not the given data is encrypted by this module.
@@ -354,11 +345,10 @@ bool tox_get_salt(const uint8_t *ciphertext, uint8_t *salt, Tox_Err_Get_Salt *er
*
* @return true if the data is encrypted by this module.
*/
-bool tox_is_data_encrypted(const uint8_t *data);
-
+bool tox_is_data_encrypted(const uint8_t data[TOX_PASS_ENCRYPTION_EXTRA_LENGTH]);
#ifdef __cplusplus
-}
+} /* extern "C" */
#endif
//!TOKSTYLE-
@@ -370,4 +360,4 @@ typedef Tox_Err_Get_Salt TOX_ERR_GET_SALT;
//!TOKSTYLE+
-#endif // C_TOXCORE_TOXENCRYPTSAVE_TOXENCRYPTSAVE_H
+#endif /* C_TOXCORE_TOXENCRYPTSAVE_TOXENCRYPTSAVE_H */