diff options
Diffstat (limited to 'protocols')
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 */ |