diff --git a/.circleci/config.yml b/.circleci/config.yml index 3beb3dc0..50430f16 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -76,6 +76,7 @@ jobs: testing/misc_tools.c toxav/*.c toxcore/*.c + toxcore/*/*.c toxencryptsave/*.c -lpthread $(pkg-config --cflags --libs libsodium opus vpx) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8fd89868..fda0dd0b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -109,6 +109,7 @@ jobs: testing/misc_tools.c toxav/*.c toxcore/*.c + toxcore/*/*.c toxencryptsave/*.c $(pkg-config --cflags --libs libsodium opus vpx) - name: Run the test @@ -146,6 +147,7 @@ jobs: testing/misc_tools.c toxav/*.c toxcore/*.c + toxcore/*/*.c toxencryptsave/*.c -D__COMPCERT__ -DDISABLE_VLA -lpthread $(pkg-config --cflags --libs libsodium opus vpx) diff --git a/CMakeLists.txt b/CMakeLists.txt index bd2368cf..862e4d3c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -161,6 +161,7 @@ set(toxcore_PKGCONFIG_REQUIRES) # LAYER 1: Crypto core # -------------------- set(toxcore_SOURCES ${toxcore_SOURCES} + toxcore/ccompat.c toxcore/ccompat.h toxcore/crypto_core.c toxcore/crypto_core.h) @@ -240,10 +241,47 @@ set(toxcore_SOURCES ${toxcore_SOURCES} set(toxcore_SOURCES ${toxcore_SOURCES} toxcore/tox_api.c toxcore/tox.c - toxcore/tox_private.h - toxcore/tox.h) + toxcore/tox.h + toxcore/tox_private.h) set(toxcore_API_HEADERS ${toxcore_API_HEADERS} ${toxcore_SOURCE_DIR}/toxcore/tox.h^tox) +# LAYER 9: New async events API +# ------------------- +set(toxcore_SOURCES ${toxcore_SOURCES} + toxcore/events/conference_connected.c + toxcore/events/conference_invite.c + toxcore/events/conference_message.c + toxcore/events/conference_peer_list_changed.c + toxcore/events/conference_peer_name.c + toxcore/events/conference_title.c + toxcore/events/file_chunk_request.c + toxcore/events/file_recv.c + toxcore/events/file_recv_chunk.c + toxcore/events/file_recv_control.c + toxcore/events/friend_connection_status.c + toxcore/events/friend_lossless_packet.c + toxcore/events/friend_lossy_packet.c + toxcore/events/friend_message.c + toxcore/events/friend_name.c + toxcore/events/friend_read_receipt.c + toxcore/events/friend_request.c + toxcore/events/friend_status.c + toxcore/events/friend_status_message.c + toxcore/events/friend_typing.c + toxcore/events/events_alloc.c + toxcore/events/events_alloc.h + toxcore/events/self_connection_status.c + toxcore/tox_events.c + toxcore/tox_events.h) +set(toxcore_API_HEADERS ${toxcore_API_HEADERS} ${toxcore_SOURCE_DIR}/toxcore/tox_events.h^tox) + +# LAYER 10: Dispatch recorded events to callbacks. +# ------------------- +set(toxcore_SOURCES ${toxcore_SOURCES} + toxcore/tox_dispatch.c + toxcore/tox_dispatch.h) +set(toxcore_API_HEADERS ${toxcore_API_HEADERS} ${toxcore_SOURCE_DIR}/toxcore/tox_dispatch.h^tox) + ################################################################################ # # :: Audio/Video Library @@ -441,6 +479,8 @@ auto_test(save_load) auto_test(send_message) auto_test(set_name) auto_test(set_status_message) +auto_test(tox_dispatch) +auto_test(tox_events) auto_test(tox_many) auto_test(tox_many_tcp) auto_test(tox_one) @@ -558,4 +598,3 @@ if (BUILD_FUZZ_TESTS) add_executable(bootstrap_fuzzer testing/fuzzing/bootstrap_harness.cc) target_link_libraries(bootstrap_fuzzer toxcore_static fuzz_adapter -fsanitize=fuzzer) endif() - diff --git a/auto_tests/BUILD.bazel b/auto_tests/BUILD.bazel index 5838cb77..b9455912 100644 --- a/auto_tests/BUILD.bazel +++ b/auto_tests/BUILD.bazel @@ -61,6 +61,8 @@ flaky_tests = { "//c-toxcore/toxcore:onion", "//c-toxcore/toxcore:onion_announce", "//c-toxcore/toxcore:onion_client", + "//c-toxcore/toxcore:tox_dispatch", + "//c-toxcore/toxcore:tox_events", "//c-toxcore/toxencryptsave", "@libsodium", "@libvpx", diff --git a/auto_tests/tox_dispatch_test.c b/auto_tests/tox_dispatch_test.c new file mode 100644 index 00000000..b50c6333 --- /dev/null +++ b/auto_tests/tox_dispatch_test.c @@ -0,0 +1,122 @@ +/* Auto Tests: Many clients. + */ + +#include +#include +#include +#include + +#include "../testing/misc_tools.h" +#include "../toxcore/tox.h" +#include "../toxcore/tox_dispatch.h" +#include "../toxcore/tox_events.h" +#include "check_compat.h" + +static void handle_events_friend_message(Tox *tox, const Tox_Event_Friend_Message *event, void *user_data) +{ + bool *success = (bool *)user_data; + + ck_assert(tox_event_friend_message_get_message_length(event) == sizeof("hello")); + const uint8_t *msg = tox_event_friend_message_get_message(event); + ck_assert_msg(memcmp(msg, "hello", sizeof("hello")) == 0, + "message was not expected 'hello' but '%s'", (const char *)msg); + + *success = true; +} + +static bool await_message(Tox **toxes, const Tox_Dispatch *dispatch) +{ + for (uint32_t i = 0; i < 100; ++i) { + // Ignore events on tox 1. + tox_events_free(tox_events_iterate(toxes[0], nullptr)); + // Check if tox 2 got the message from tox 1. + Tox_Events *events = tox_events_iterate(toxes[1], nullptr); + + bool success = false; + tox_dispatch_invoke(dispatch, events, toxes[1], &success); + tox_events_free(events); + + if (success) { + return true; + } + + c_sleep(tox_iteration_interval(toxes[0])); + } + + return false; +} + +static void test_tox_events(void) +{ + uint8_t message[sizeof("hello")]; + memcpy(message, "hello", sizeof(message)); + + Tox *toxes[2]; + uint32_t index[2]; + + for (uint32_t i = 0; i < 2; ++i) { + index[i] = i + 1; + toxes[i] = tox_new_log(nullptr, nullptr, &index[i]); + tox_events_init(toxes[i]); + ck_assert_msg(toxes[i] != nullptr, "failed to create tox instances %u", i); + } + + Tox_Dispatch *dispatch = tox_dispatch_new(nullptr); + ck_assert_msg(dispatch != nullptr, "failed to create event dispatcher"); + + tox_events_callback_friend_message(dispatch, handle_events_friend_message); + + uint8_t pk[TOX_PUBLIC_KEY_SIZE]; + tox_self_get_dht_id(toxes[0], pk); + tox_bootstrap(toxes[1], "localhost", tox_self_get_udp_port(toxes[0], nullptr), pk, nullptr); + + tox_self_get_public_key(toxes[0], pk); + tox_friend_add_norequest(toxes[1], pk, nullptr); + + tox_self_get_public_key(toxes[1], pk); + tox_friend_add_norequest(toxes[0], pk, nullptr); + + printf("bootstrapping and connecting 2 toxes\n"); + + while (tox_self_get_connection_status(toxes[0]) == TOX_CONNECTION_NONE || + tox_self_get_connection_status(toxes[1]) == TOX_CONNECTION_NONE) { + // Ignore connection events for now. + tox_events_free(tox_events_iterate(toxes[0], nullptr)); + tox_events_free(tox_events_iterate(toxes[1], nullptr)); + + c_sleep(tox_iteration_interval(toxes[0])); + } + + printf("toxes online, waiting for friend connection\n"); + + while (tox_friend_get_connection_status(toxes[0], 0, nullptr) == TOX_CONNECTION_NONE || + tox_friend_get_connection_status(toxes[1], 0, nullptr) == TOX_CONNECTION_NONE) { + // Ignore connection events for now. + tox_events_free(tox_events_iterate(toxes[0], nullptr)); + tox_events_free(tox_events_iterate(toxes[1], nullptr)); + + c_sleep(tox_iteration_interval(toxes[0])); + } + + printf("friends are connected via %s, now sending message\n", + tox_friend_get_connection_status(toxes[0], 0, nullptr) == TOX_CONNECTION_TCP ? "TCP" : "UDP"); + + Tox_Err_Friend_Send_Message err; + tox_friend_send_message(toxes[0], 0, TOX_MESSAGE_TYPE_NORMAL, message, sizeof(message), &err); + ck_assert(err == TOX_ERR_FRIEND_SEND_MESSAGE_OK); + + ck_assert(await_message(toxes, dispatch)); + + tox_dispatch_free(dispatch); + + for (uint32_t i = 0; i < 2; ++i) { + tox_kill(toxes[i]); + } +} + +int main(void) +{ + setvbuf(stdout, nullptr, _IONBF, 0); + test_tox_events(); + return 0; +} diff --git a/auto_tests/tox_events_test.c b/auto_tests/tox_events_test.c new file mode 100644 index 00000000..ed8e9490 --- /dev/null +++ b/auto_tests/tox_events_test.c @@ -0,0 +1,105 @@ +/* Auto Tests: Many clients. + */ + +#include +#include +#include +#include + +#include "../testing/misc_tools.h" +#include "../toxcore/tox.h" +#include "../toxcore/tox_events.h" +#include "check_compat.h" + +static bool await_message(Tox **toxes) +{ + for (uint32_t i = 0; i < 100; ++i) { + // Ignore events on tox 1. + tox_events_free(tox_events_iterate(toxes[0], nullptr)); + // Check if tox 2 got the message from tox 1. + Tox_Events *events = tox_events_iterate(toxes[1], nullptr); + + if (events != nullptr) { + ck_assert(tox_events_get_friend_message_size(events) == 1); + const Tox_Event_Friend_Message *msg_event = tox_events_get_friend_message(events, 0); + ck_assert(tox_event_friend_message_get_message_length(msg_event) == sizeof("hello")); + const uint8_t *msg = tox_event_friend_message_get_message(msg_event); + ck_assert_msg(memcmp(msg, "hello", sizeof("hello")) == 0, + "message was not expected 'hello' but '%s'", (const char *)msg); + tox_events_free(events); + return true; + } + + c_sleep(tox_iteration_interval(toxes[0])); + } + + return false; +} + +static void test_tox_events(void) +{ + uint8_t message[sizeof("hello")]; + memcpy(message, "hello", sizeof(message)); + + Tox *toxes[2]; + uint32_t index[2]; + + for (uint32_t i = 0; i < 2; ++i) { + index[i] = i + 1; + toxes[i] = tox_new_log(nullptr, nullptr, &index[i]); + tox_events_init(toxes[i]); + ck_assert_msg(toxes[i] != nullptr, "failed to create tox instances %u", i); + } + + uint8_t pk[TOX_PUBLIC_KEY_SIZE]; + tox_self_get_dht_id(toxes[0], pk); + tox_bootstrap(toxes[1], "localhost", tox_self_get_udp_port(toxes[0], nullptr), pk, nullptr); + + tox_self_get_public_key(toxes[0], pk); + tox_friend_add_norequest(toxes[1], pk, nullptr); + + tox_self_get_public_key(toxes[1], pk); + tox_friend_add_norequest(toxes[0], pk, nullptr); + + printf("bootstrapping and connecting 2 toxes\n"); + + while (tox_self_get_connection_status(toxes[0]) == TOX_CONNECTION_NONE || + tox_self_get_connection_status(toxes[1]) == TOX_CONNECTION_NONE) { + // Ignore connection events for now. + tox_events_free(tox_events_iterate(toxes[0], nullptr)); + tox_events_free(tox_events_iterate(toxes[1], nullptr)); + + c_sleep(tox_iteration_interval(toxes[0])); + } + + printf("toxes online, waiting for friend connection\n"); + + while (tox_friend_get_connection_status(toxes[0], 0, nullptr) == TOX_CONNECTION_NONE || + tox_friend_get_connection_status(toxes[1], 0, nullptr) == TOX_CONNECTION_NONE) { + // Ignore connection events for now. + tox_events_free(tox_events_iterate(toxes[0], nullptr)); + tox_events_free(tox_events_iterate(toxes[1], nullptr)); + + c_sleep(tox_iteration_interval(toxes[0])); + } + + printf("friends are connected via %s, now sending message\n", + tox_friend_get_connection_status(toxes[0], 0, nullptr) == TOX_CONNECTION_TCP ? "TCP" : "UDP"); + + Tox_Err_Friend_Send_Message err; + tox_friend_send_message(toxes[0], 0, TOX_MESSAGE_TYPE_NORMAL, message, sizeof(message), &err); + ck_assert(err == TOX_ERR_FRIEND_SEND_MESSAGE_OK); + + ck_assert(await_message(toxes)); + + for (uint32_t i = 0; i < 2; ++i) { + tox_kill(toxes[i]); + } +} + +int main(void) +{ + setvbuf(stdout, nullptr, _IONBF, 0); + test_tox_events(); + return 0; +} diff --git a/other/analysis/gen-file.sh b/other/analysis/gen-file.sh index bbbd27da..2453e794 100644 --- a/other/analysis/gen-file.sh +++ b/other/analysis/gen-file.sh @@ -10,6 +10,7 @@ CPPFLAGS+=("-Itesting") CPPFLAGS+=("-Itesting/fuzzing") CPPFLAGS+=("-Itesting/groupchats") CPPFLAGS+=("-Itoxcore") +CPPFLAGS+=("-Itoxcore/events") CPPFLAGS+=("-Itoxav") CPPFLAGS+=("-Itoxencryptsave") diff --git a/other/make_single_file b/other/make_single_file index 557ee029..af44940a 100755 --- a/other/make_single_file +++ b/other/make_single_file @@ -48,7 +48,7 @@ if (@ARGV and $ARGV[0] eq "-core") { emit(abs_path $fn); } } else { - for my $fn (, , ) { + for my $fn (, , , ) { emit(abs_path $fn); } } diff --git a/toxcore/BUILD.bazel b/toxcore/BUILD.bazel index 07a8ce24..0fc9ef90 100644 --- a/toxcore/BUILD.bazel +++ b/toxcore/BUILD.bazel @@ -10,6 +10,7 @@ exports_files( cc_library( name = "ccompat", + srcs = ["ccompat.c"], hdrs = ["ccompat.h"], visibility = ["//c-toxcore:__subpackages__"], ) @@ -459,9 +460,36 @@ cc_library( ], ) +cc_library( + name = "tox_events", + srcs = ["tox_events.c"] + glob([ + "events/*.c", + "events/*.h", + ]), + hdrs = ["tox_events.h"], + visibility = ["//c-toxcore:__subpackages__"], + deps = [ + ":ccompat", + ":toxcore", + ], +) + +cc_library( + name = "tox_dispatch", + srcs = ["tox_dispatch.c"], + hdrs = ["tox_dispatch.h"], + visibility = ["//c-toxcore:__subpackages__"], + deps = [ + ":ccompat", + ":tox_events", + ], +) + sh_library( name = "cimple_files", srcs = glob([ + "events/*.c", + "events/*.h", "*.c", "*.h", ]), diff --git a/toxcore/Makefile.inc b/toxcore/Makefile.inc index 4aedb522..fb1812df 100644 --- a/toxcore/Makefile.inc +++ b/toxcore/Makefile.inc @@ -6,6 +6,30 @@ libtoxcore_la_include_HEADERS = \ libtoxcore_la_includedir = $(includedir)/tox libtoxcore_la_SOURCES = ../toxcore/ccompat.h \ + ../toxcore/events/conference_connected.c \ + ../toxcore/events/conference_invite.c \ + ../toxcore/events/conference_message.c \ + ../toxcore/events/conference_peer_list_changed.c \ + ../toxcore/events/conference_peer_name.c \ + ../toxcore/events/conference_title.c \ + ../toxcore/events/file_chunk_request.c \ + ../toxcore/events/file_recv.c \ + ../toxcore/events/file_recv_chunk.c \ + ../toxcore/events/file_recv_control.c \ + ../toxcore/events/friend_connection_status.c \ + ../toxcore/events/friend_lossless_packet.c \ + ../toxcore/events/friend_lossy_packet.c \ + ../toxcore/events/friend_message.c \ + ../toxcore/events/friend_message.c \ + ../toxcore/events/friend_name.c \ + ../toxcore/events/friend_read_receipt.c \ + ../toxcore/events/friend_request.c \ + ../toxcore/events/friend_status.c \ + ../toxcore/events/friend_status_message.c \ + ../toxcore/events/friend_typing.c \ + ../toxcore/events/events_alloc.c \ + ../toxcore/events/events_alloc.h \ + ../toxcore/events/self_connection_status.c \ ../toxcore/DHT.h \ ../toxcore/DHT.c \ ../toxcore/mono_time.h \ @@ -31,8 +55,12 @@ libtoxcore_la_SOURCES = ../toxcore/ccompat.h \ ../toxcore/state.h \ ../toxcore/state.c \ ../toxcore/tox.h \ - ../toxcore/tox_private.h \ ../toxcore/tox.c \ + ../toxcore/tox_dispatch.h \ + ../toxcore/tox_dispatch.c \ + ../toxcore/tox_events.h \ + ../toxcore/tox_events.c \ + ../toxcore/tox_private.h \ ../toxcore/tox_api.c \ ../toxcore/util.h \ ../toxcore/util.c \ diff --git a/toxcore/ccompat.c b/toxcore/ccompat.c new file mode 100644 index 00000000..30e689d0 --- /dev/null +++ b/toxcore/ccompat.c @@ -0,0 +1,4 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2022 The TokTok team. + */ +#include "ccompat.h" diff --git a/toxcore/ccompat.h b/toxcore/ccompat.h index 295cd10d..29d38dc8 100644 --- a/toxcore/ccompat.h +++ b/toxcore/ccompat.h @@ -9,6 +9,7 @@ #define C_TOXCORE_TOXCORE_CCOMPAT_H #include +#include bool unused_for_tokstyle(void); @@ -47,9 +48,9 @@ bool unused_for_tokstyle(void); #endif #define VLA(type, name, size) \ - const size_t name##_size = (size) * sizeof(type); \ - type *const name = (type *)alloca(name##_size) -#define SIZEOF_VLA(name) 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 #endif diff --git a/toxcore/events/conference_connected.c b/toxcore/events/conference_connected.c new file mode 100644 index 00000000..769b8feb --- /dev/null +++ b/toxcore/events/conference_connected.c @@ -0,0 +1,134 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2022 The TokTok team. + */ + +#include "events_alloc.h" + +#include +#include +#include + +#include "../ccompat.h" +#include "../tox.h" +#include "../tox_events.h" + + +/***************************************************** + * + * :: struct and accessors + * + *****************************************************/ + + +struct Tox_Event_Conference_Connected { + uint32_t conference_number; +}; + +static void tox_event_conference_connected_construct(Tox_Event_Conference_Connected *conference_connected) +{ + *conference_connected = (Tox_Event_Conference_Connected) { + 0 + }; +} +static void tox_event_conference_connected_destruct(Tox_Event_Conference_Connected *conference_connected) +{ + return; +} + +static void tox_event_conference_connected_set_conference_number(Tox_Event_Conference_Connected *conference_connected, + uint32_t conference_number) +{ + assert(conference_connected != nullptr); + conference_connected->conference_number = conference_number; +} +uint32_t tox_event_conference_connected_get_conference_number(const Tox_Event_Conference_Connected + *conference_connected) +{ + assert(conference_connected != nullptr); + return conference_connected->conference_number; +} + + +/***************************************************** + * + * :: add/clear/get + * + *****************************************************/ + + +static Tox_Event_Conference_Connected *tox_events_add_conference_connected(Tox_Events *events) +{ + 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)); + + if (new_conference_connected == nullptr) { + return nullptr; + } + + events->conference_connected = new_conference_connected; + events->conference_connected_capacity = new_conference_connected_capacity; + } + + 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) +{ + if (events == nullptr) { + return; + } + + for (uint32_t i = 0; i < events->conference_connected_size; ++i) { + tox_event_conference_connected_destruct(&events->conference_connected[i]); + } + + free(events->conference_connected); + events->conference_connected = nullptr; + events->conference_connected_size = 0; + events->conference_connected_capacity = 0; +} + +uint32_t tox_events_get_conference_connected_size(const Tox_Events *events) +{ + return events->conference_connected_size; +} + +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]; +} + + +/***************************************************** + * + * :: event handler + * + *****************************************************/ + + +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); + + Tox_Event_Conference_Connected *conference_connected = tox_events_add_conference_connected(state->events); + + if (conference_connected == nullptr) { + state->error = TOX_ERR_EVENTS_ITERATE_MALLOC; + return; + } + + tox_event_conference_connected_set_conference_number(conference_connected, conference_number); +} diff --git a/toxcore/events/conference_invite.c b/toxcore/events/conference_invite.c new file mode 100644 index 00000000..19882a0b --- /dev/null +++ b/toxcore/events/conference_invite.c @@ -0,0 +1,183 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2022 The TokTok team. + */ + +#include "events_alloc.h" + +#include +#include +#include + +#include "../ccompat.h" +#include "../tox.h" +#include "../tox_events.h" + + +/***************************************************** + * + * :: struct and accessors + * + *****************************************************/ + + +struct Tox_Event_Conference_Invite { + uint32_t friend_number; + Tox_Conference_Type type; + uint8_t *cookie; + size_t cookie_length; +}; + +static void tox_event_conference_invite_construct(Tox_Event_Conference_Invite *conference_invite) +{ + *conference_invite = (Tox_Event_Conference_Invite) { + 0 + }; +} +static void tox_event_conference_invite_destruct(Tox_Event_Conference_Invite *conference_invite) +{ + free(conference_invite->cookie); +} + +static void tox_event_conference_invite_set_friend_number(Tox_Event_Conference_Invite *conference_invite, + uint32_t friend_number) +{ + assert(conference_invite != nullptr); + conference_invite->friend_number = friend_number; +} +uint32_t tox_event_conference_invite_get_friend_number(const Tox_Event_Conference_Invite *conference_invite) +{ + assert(conference_invite != nullptr); + return conference_invite->friend_number; +} + +static void tox_event_conference_invite_set_type(Tox_Event_Conference_Invite *conference_invite, + Tox_Conference_Type type) +{ + assert(conference_invite != nullptr); + conference_invite->type = type; +} +Tox_Conference_Type tox_event_conference_invite_get_type(const Tox_Event_Conference_Invite *conference_invite) +{ + assert(conference_invite != nullptr); + return conference_invite->type; +} + +static bool tox_event_conference_invite_set_cookie(Tox_Event_Conference_Invite *conference_invite, + const uint8_t *cookie, + size_t cookie_length) +{ + assert(conference_invite != nullptr); + + if (conference_invite->cookie != nullptr) { + free(conference_invite->cookie); + conference_invite->cookie = nullptr; + conference_invite->cookie_length = 0; + } + + conference_invite->cookie = (uint8_t *)malloc(cookie_length); + + if (conference_invite->cookie == nullptr) { + return false; + } + + memcpy(conference_invite->cookie, cookie, cookie_length); + conference_invite->cookie_length = cookie_length; + return true; +} +size_t tox_event_conference_invite_get_cookie_length(const Tox_Event_Conference_Invite *conference_invite) +{ + assert(conference_invite != nullptr); + return conference_invite->cookie_length; +} +const uint8_t *tox_event_conference_invite_get_cookie(const Tox_Event_Conference_Invite *conference_invite) +{ + assert(conference_invite != nullptr); + return conference_invite->cookie; +} + + +/***************************************************** + * + * :: add/clear/get + * + *****************************************************/ + + +static Tox_Event_Conference_Invite *tox_events_add_conference_invite(Tox_Events *events) +{ + 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)); + + if (new_conference_invite == nullptr) { + return nullptr; + } + + events->conference_invite = new_conference_invite; + events->conference_invite_capacity = new_conference_invite_capacity; + } + + 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) +{ + if (events == nullptr) { + return; + } + + for (uint32_t i = 0; i < events->conference_invite_size; ++i) { + tox_event_conference_invite_destruct(&events->conference_invite[i]); + } + + free(events->conference_invite); + events->conference_invite = nullptr; + events->conference_invite_size = 0; + events->conference_invite_capacity = 0; +} + +uint32_t tox_events_get_conference_invite_size(const Tox_Events *events) +{ + return events->conference_invite_size; +} + +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]; +} + + +/***************************************************** + * + * :: event handler + * + *****************************************************/ + + +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); + + Tox_Event_Conference_Invite *conference_invite = tox_events_add_conference_invite(state->events); + + if (conference_invite == nullptr) { + state->error = TOX_ERR_EVENTS_ITERATE_MALLOC; + return; + } + + tox_event_conference_invite_set_friend_number(conference_invite, friend_number); + tox_event_conference_invite_set_type(conference_invite, type); + tox_event_conference_invite_set_cookie(conference_invite, cookie, length); +} diff --git a/toxcore/events/conference_message.c b/toxcore/events/conference_message.c new file mode 100644 index 00000000..39315c59 --- /dev/null +++ b/toxcore/events/conference_message.c @@ -0,0 +1,196 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2022 The TokTok team. + */ + +#include "events_alloc.h" + +#include +#include +#include + +#include "../ccompat.h" +#include "../tox.h" +#include "../tox_events.h" + + +/***************************************************** + * + * :: struct and accessors + * + *****************************************************/ + + +struct Tox_Event_Conference_Message { + uint32_t conference_number; + uint32_t peer_number; + Tox_Message_Type type; + uint8_t *message; + size_t message_length; +}; + +static void tox_event_conference_message_construct(Tox_Event_Conference_Message *conference_message) +{ + *conference_message = (Tox_Event_Conference_Message) { + 0 + }; +} +static void tox_event_conference_message_destruct(Tox_Event_Conference_Message *conference_message) +{ + free(conference_message->message); +} + +static void tox_event_conference_message_set_conference_number(Tox_Event_Conference_Message *conference_message, + uint32_t conference_number) +{ + assert(conference_message != nullptr); + conference_message->conference_number = conference_number; +} +uint32_t tox_event_conference_message_get_conference_number(const Tox_Event_Conference_Message *conference_message) +{ + assert(conference_message != nullptr); + return conference_message->conference_number; +} + +static void tox_event_conference_message_set_peer_number(Tox_Event_Conference_Message *conference_message, + uint32_t peer_number) +{ + assert(conference_message != nullptr); + conference_message->peer_number = peer_number; +} +uint32_t tox_event_conference_message_get_peer_number(const Tox_Event_Conference_Message *conference_message) +{ + assert(conference_message != nullptr); + return conference_message->peer_number; +} + +static void tox_event_conference_message_set_type(Tox_Event_Conference_Message *conference_message, + Tox_Message_Type type) +{ + assert(conference_message != nullptr); + conference_message->type = type; +} +Tox_Message_Type tox_event_conference_message_get_type(const Tox_Event_Conference_Message *conference_message) +{ + assert(conference_message != nullptr); + return conference_message->type; +} + +static bool tox_event_conference_message_set_message(Tox_Event_Conference_Message *conference_message, + const uint8_t *message, size_t message_length) +{ + assert(conference_message != nullptr); + + if (conference_message->message != nullptr) { + free(conference_message->message); + conference_message->message = nullptr; + conference_message->message_length = 0; + } + + conference_message->message = (uint8_t *)malloc(message_length); + + if (conference_message->message == nullptr) { + return false; + } + + memcpy(conference_message->message, message, message_length); + conference_message->message_length = message_length; + return true; +} +size_t tox_event_conference_message_get_message_length(const Tox_Event_Conference_Message *conference_message) +{ + assert(conference_message != nullptr); + return conference_message->message_length; +} +const uint8_t *tox_event_conference_message_get_message(const Tox_Event_Conference_Message *conference_message) +{ + assert(conference_message != nullptr); + return conference_message->message; +} + + +/***************************************************** + * + * :: add/clear/get + * + *****************************************************/ + + +static Tox_Event_Conference_Message *tox_events_add_conference_message(Tox_Events *events) +{ + 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)); + + if (new_conference_message == nullptr) { + return nullptr; + } + + events->conference_message = new_conference_message; + events->conference_message_capacity = new_conference_message_capacity; + } + + 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) +{ + if (events == nullptr) { + return; + } + + for (uint32_t i = 0; i < events->conference_message_size; ++i) { + tox_event_conference_message_destruct(&events->conference_message[i]); + } + + free(events->conference_message); + events->conference_message = nullptr; + events->conference_message_size = 0; + events->conference_message_capacity = 0; +} + +uint32_t tox_events_get_conference_message_size(const Tox_Events *events) +{ + return events->conference_message_size; +} + +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]; +} + + +/***************************************************** + * + * :: event handler + * + *****************************************************/ + + +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); + + Tox_Event_Conference_Message *conference_message = tox_events_add_conference_message(state->events); + + if (conference_message == nullptr) { + state->error = TOX_ERR_EVENTS_ITERATE_MALLOC; + return; + } + + tox_event_conference_message_set_conference_number(conference_message, conference_number); + tox_event_conference_message_set_peer_number(conference_message, peer_number); + tox_event_conference_message_set_type(conference_message, type); + tox_event_conference_message_set_message(conference_message, message, length); +} diff --git a/toxcore/events/conference_peer_list_changed.c b/toxcore/events/conference_peer_list_changed.c new file mode 100644 index 00000000..c00f85ac --- /dev/null +++ b/toxcore/events/conference_peer_list_changed.c @@ -0,0 +1,140 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2022 The TokTok team. + */ + +#include "events_alloc.h" + +#include +#include +#include + +#include "../ccompat.h" +#include "../tox.h" +#include "../tox_events.h" + + +/***************************************************** + * + * :: struct and accessors + * + *****************************************************/ + + +struct Tox_Event_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) +{ + *conference_peer_list_changed = (Tox_Event_Conference_Peer_List_Changed) { + 0 + }; +} +static void tox_event_conference_peer_list_changed_destruct(Tox_Event_Conference_Peer_List_Changed + *conference_peer_list_changed) +{ + return; +} + +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) +{ + assert(conference_peer_list_changed != nullptr); + conference_peer_list_changed->conference_number = conference_number; +} +uint32_t tox_event_conference_peer_list_changed_get_conference_number(const Tox_Event_Conference_Peer_List_Changed + *conference_peer_list_changed) +{ + assert(conference_peer_list_changed != nullptr); + return conference_peer_list_changed->conference_number; +} + + +/***************************************************** + * + * :: add/clear/get + * + *****************************************************/ + + +static Tox_Event_Conference_Peer_List_Changed *tox_events_add_conference_peer_list_changed(Tox_Events *events) +{ + 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)); + + if (new_conference_peer_list_changed == nullptr) { + return nullptr; + } + + events->conference_peer_list_changed = new_conference_peer_list_changed; + events->conference_peer_list_changed_capacity = new_conference_peer_list_changed_capacity; + } + + 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) +{ + if (events == nullptr) { + return; + } + + 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; +} + +uint32_t tox_events_get_conference_peer_list_changed_size(const Tox_Events *events) +{ + return events->conference_peer_list_changed_size; +} + +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]; +} + + +/***************************************************** + * + * :: event handler + * + *****************************************************/ + + +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); + + Tox_Event_Conference_Peer_List_Changed *conference_peer_list_changed = tox_events_add_conference_peer_list_changed( + state->events); + + if (conference_peer_list_changed == nullptr) { + state->error = TOX_ERR_EVENTS_ITERATE_MALLOC; + return; + } + + tox_event_conference_peer_list_changed_set_conference_number(conference_peer_list_changed, conference_number); +} diff --git a/toxcore/events/conference_peer_name.c b/toxcore/events/conference_peer_name.c new file mode 100644 index 00000000..340a92ff --- /dev/null +++ b/toxcore/events/conference_peer_name.c @@ -0,0 +1,184 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2022 The TokTok team. + */ + +#include "events_alloc.h" + +#include +#include +#include + +#include "../ccompat.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; + uint8_t *name; + size_t name_length; +}; + +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 + }; +} +static void tox_event_conference_peer_name_destruct(Tox_Event_Conference_Peer_Name *conference_peer_name) +{ + free(conference_peer_name->name); +} + +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) +{ + assert(conference_peer_name != nullptr); + return conference_peer_name->conference_number; +} + +static void tox_event_conference_peer_name_set_peer_number(Tox_Event_Conference_Peer_Name *conference_peer_name, + uint32_t peer_number) +{ + assert(conference_peer_name != nullptr); + conference_peer_name->peer_number = peer_number; +} +uint32_t tox_event_conference_peer_name_get_peer_number(const Tox_Event_Conference_Peer_Name *conference_peer_name) +{ + assert(conference_peer_name != nullptr); + return conference_peer_name->peer_number; +} + +static bool tox_event_conference_peer_name_set_name(Tox_Event_Conference_Peer_Name *conference_peer_name, + const uint8_t *name, size_t name_length) +{ + assert(conference_peer_name != nullptr); + + if (conference_peer_name->name != nullptr) { + free(conference_peer_name->name); + conference_peer_name->name = nullptr; + conference_peer_name->name_length = 0; + } + + conference_peer_name->name = (uint8_t *)malloc(name_length); + + if (conference_peer_name->name == nullptr) { + return false; + } + + memcpy(conference_peer_name->name, name, name_length); + conference_peer_name->name_length = name_length; + return true; +} +size_t tox_event_conference_peer_name_get_name_length(const Tox_Event_Conference_Peer_Name *conference_peer_name) +{ + assert(conference_peer_name != nullptr); + return conference_peer_name->name_length; +} +const uint8_t *tox_event_conference_peer_name_get_name(const Tox_Event_Conference_Peer_Name *conference_peer_name) +{ + assert(conference_peer_name != nullptr); + return conference_peer_name->name; +} + + +/***************************************************** + * + * :: add/clear/get + * + *****************************************************/ + + +static Tox_Event_Conference_Peer_Name *tox_events_add_conference_peer_name(Tox_Events *events) +{ + 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)); + + if (new_conference_peer_name == nullptr) { + return nullptr; + } + + events->conference_peer_name = new_conference_peer_name; + events->conference_peer_name_capacity = new_conference_peer_name_capacity; + } + + 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) +{ + if (events == nullptr) { + return; + } + + 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; +} + +uint32_t tox_events_get_conference_peer_name_size(const Tox_Events *events) +{ + return events->conference_peer_name_size; +} + +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]; +} + + +/***************************************************** + * + * :: event handler + * + *****************************************************/ + + +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); + + Tox_Event_Conference_Peer_Name *conference_peer_name = tox_events_add_conference_peer_name(state->events); + + if (conference_peer_name == nullptr) { + state->error = TOX_ERR_EVENTS_ITERATE_MALLOC; + return; + } + + tox_event_conference_peer_name_set_conference_number(conference_peer_name, conference_number); + tox_event_conference_peer_name_set_peer_number(conference_peer_name, peer_number); + tox_event_conference_peer_name_set_name(conference_peer_name, name, length); +} diff --git a/toxcore/events/conference_title.c b/toxcore/events/conference_title.c new file mode 100644 index 00000000..45312f8a --- /dev/null +++ b/toxcore/events/conference_title.c @@ -0,0 +1,182 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2022 The TokTok team. + */ + +#include "events_alloc.h" + +#include +#include +#include + +#include "../ccompat.h" +#include "../tox.h" +#include "../tox_events.h" + + +/***************************************************** + * + * :: struct and accessors + * + *****************************************************/ + + +struct Tox_Event_Conference_Title { + uint32_t conference_number; + uint32_t peer_number; + uint8_t *title; + size_t title_length; +}; + +static void tox_event_conference_title_construct(Tox_Event_Conference_Title *conference_title) +{ + *conference_title = (Tox_Event_Conference_Title) { + 0 + }; +} +static void tox_event_conference_title_destruct(Tox_Event_Conference_Title *conference_title) +{ + free(conference_title->title); +} + +static void tox_event_conference_title_set_conference_number(Tox_Event_Conference_Title *conference_title, + uint32_t conference_number) +{ + assert(conference_title != nullptr); + conference_title->conference_number = conference_number; +} +uint32_t tox_event_conference_title_get_conference_number(const Tox_Event_Conference_Title *conference_title) +{ + assert(conference_title != nullptr); + return conference_title->conference_number; +} + +static void tox_event_conference_title_set_peer_number(Tox_Event_Conference_Title *conference_title, + uint32_t peer_number) +{ + assert(conference_title != nullptr); + conference_title->peer_number = peer_number; +} +uint32_t tox_event_conference_title_get_peer_number(const Tox_Event_Conference_Title *conference_title) +{ + assert(conference_title != nullptr); + return conference_title->peer_number; +} + +static bool tox_event_conference_title_set_title(Tox_Event_Conference_Title *conference_title, const uint8_t *title, + size_t title_length) +{ + assert(conference_title != nullptr); + + if (conference_title->title != nullptr) { + free(conference_title->title); + conference_title->title = nullptr; + conference_title->title_length = 0; + } + + conference_title->title = (uint8_t *)malloc(title_length); + + if (conference_title->title == nullptr) { + return false; + } + + memcpy(conference_title->title, title, title_length); + conference_title->title_length = title_length; + return true; +} +size_t tox_event_conference_title_get_title_length(const Tox_Event_Conference_Title *conference_title) +{ + assert(conference_title != nullptr); + return conference_title->title_length; +} +const uint8_t *tox_event_conference_title_get_title(const Tox_Event_Conference_Title *conference_title) +{ + assert(conference_title != nullptr); + return conference_title->title; +} + + +/***************************************************** + * + * :: add/clear/get + * + *****************************************************/ + + +static Tox_Event_Conference_Title *tox_events_add_conference_title(Tox_Events *events) +{ + 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)); + + if (new_conference_title == nullptr) { + return nullptr; + } + + events->conference_title = new_conference_title; + events->conference_title_capacity = new_conference_title_capacity; + } + + 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) +{ + if (events == nullptr) { + return; + } + + for (uint32_t i = 0; i < events->conference_title_size; ++i) { + tox_event_conference_title_destruct(&events->conference_title[i]); + } + + free(events->conference_title); + events->conference_title = nullptr; + events->conference_title_size = 0; + events->conference_title_capacity = 0; +} + +uint32_t tox_events_get_conference_title_size(const Tox_Events *events) +{ + return events->conference_title_size; +} + +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]; +} + + +/***************************************************** + * + * :: event handler + * + *****************************************************/ + + +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); + + Tox_Event_Conference_Title *conference_title = tox_events_add_conference_title(state->events); + + if (conference_title == nullptr) { + state->error = TOX_ERR_EVENTS_ITERATE_MALLOC; + return; + } + + tox_event_conference_title_set_conference_number(conference_title, conference_number); + tox_event_conference_title_set_peer_number(conference_title, peer_number); + tox_event_conference_title_set_title(conference_title, title, length); +} diff --git a/toxcore/events/events_alloc.c b/toxcore/events/events_alloc.c new file mode 100644 index 00000000..f661c5c0 --- /dev/null +++ b/toxcore/events/events_alloc.c @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2022 The TokTok team. + */ + +#include "events_alloc.h" + +#include +#include + +#include "../ccompat.h" + +Tox_Events_State *tox_events_alloc(void *user_data) +{ + Tox_Events_State *state = (Tox_Events_State *)user_data; + assert(state != nullptr); + + if (state->events != nullptr) { + // Already allocated. + return state; + } + + state->events = (Tox_Events *)calloc(1, sizeof(Tox_Events)); + + if (state->events == nullptr) { + // It's still null => allocation failed. + state->error = TOX_ERR_EVENTS_ITERATE_MALLOC; + } else { + *state->events = (Tox_Events) { + nullptr + }; + } + + return state; +} + +void tox_events_free(Tox_Events *events) +{ + if (events == nullptr) { + 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); +} diff --git a/toxcore/events/events_alloc.h b/toxcore/events/events_alloc.h new file mode 100644 index 00000000..9ef60c41 --- /dev/null +++ b/toxcore/events/events_alloc.h @@ -0,0 +1,155 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2022 The TokTok team. + */ + +#ifndef C_TOXCORE_TOXCORE_TOX_EVENTS_INTERNAL_H +#define C_TOXCORE_TOXCORE_TOX_EVENTS_INTERNAL_H + +#include "../tox_events.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_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; +}; + +typedef struct Tox_Events_State { + Tox_Err_Events_Iterate error; + Tox_Events *events; +} Tox_Events_State; + +tox_conference_connected_cb tox_events_handle_conference_connected; +tox_conference_invite_cb tox_events_handle_conference_invite; +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_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; +tox_file_recv_control_cb tox_events_handle_file_recv_control; +tox_friend_connection_status_cb tox_events_handle_friend_connection_status; +tox_friend_lossless_packet_cb tox_events_handle_friend_lossless_packet; +tox_friend_lossy_packet_cb tox_events_handle_friend_lossy_packet; +tox_friend_message_cb tox_events_handle_friend_message; +tox_friend_name_cb tox_events_handle_friend_name; +tox_friend_read_receipt_cb tox_events_handle_friend_read_receipt; +tox_friend_request_cb tox_events_handle_friend_request; +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; + +void tox_events_clear_conference_connected(Tox_Events *events); +void tox_events_clear_conference_invite(Tox_Events *events); +void tox_events_clear_conference_message(Tox_Events *events); +void tox_events_clear_conference_peer_list_changed(Tox_Events *events); +void tox_events_clear_conference_peer_name(Tox_Events *events); +void tox_events_clear_conference_title(Tox_Events *events); +void tox_events_clear_file_chunk_request(Tox_Events *events); +void tox_events_clear_file_recv_chunk(Tox_Events *events); +void tox_events_clear_file_recv_control(Tox_Events *events); +void tox_events_clear_file_recv(Tox_Events *events); +void tox_events_clear_friend_connection_status(Tox_Events *events); +void tox_events_clear_friend_lossless_packet(Tox_Events *events); +void tox_events_clear_friend_lossy_packet(Tox_Events *events); +void tox_events_clear_friend_message(Tox_Events *events); +void tox_events_clear_friend_name(Tox_Events *events); +void tox_events_clear_friend_read_receipt(Tox_Events *events); +void tox_events_clear_friend_request(Tox_Events *events); +void tox_events_clear_friend_status_message(Tox_Events *events); +void tox_events_clear_friend_status(Tox_Events *events); +void tox_events_clear_friend_typing(Tox_Events *events); +void tox_events_clear_self_connection_status(Tox_Events *events); + +Tox_Events_State *tox_events_alloc(void *user_data); + +#ifdef __cplusplus +} +#endif + +#endif // C_TOXCORE_TOXCORE_TOX_EVENTS_INTERNAL_H diff --git a/toxcore/events/file_chunk_request.c b/toxcore/events/file_chunk_request.c new file mode 100644 index 00000000..597c4af6 --- /dev/null +++ b/toxcore/events/file_chunk_request.c @@ -0,0 +1,174 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2022 The TokTok team. + */ + +#include "events_alloc.h" + +#include +#include +#include + +#include "../ccompat.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; + uint64_t position; + size_t length; +}; + +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 + }; +} +static void tox_event_file_chunk_request_destruct(Tox_Event_File_Chunk_Request *file_chunk_request) +{ + return; +} + +static void tox_event_file_chunk_request_set_friend_number(Tox_Event_File_Chunk_Request *file_chunk_request, + uint32_t friend_number) +{ + assert(file_chunk_request != nullptr); + file_chunk_request->friend_number = friend_number; +} +uint32_t tox_event_file_chunk_request_get_friend_number(const Tox_Event_File_Chunk_Request *file_chunk_request) +{ + assert(file_chunk_request != nullptr); + return file_chunk_request->friend_number; +} + +static void tox_event_file_chunk_request_set_file_number(Tox_Event_File_Chunk_Request *file_chunk_request, + uint32_t file_number) +{ + assert(file_chunk_request != nullptr); + file_chunk_request->file_number = file_number; +} +uint32_t tox_event_file_chunk_request_get_file_number(const Tox_Event_File_Chunk_Request *file_chunk_request) +{ + assert(file_chunk_request != nullptr); + return file_chunk_request->file_number; +} + +static void tox_event_file_chunk_request_set_position(Tox_Event_File_Chunk_Request *file_chunk_request, + uint64_t position) +{ + assert(file_chunk_request != nullptr); + file_chunk_request->position = position; +} +uint64_t tox_event_file_chunk_request_get_position(const Tox_Event_File_Chunk_Request *file_chunk_request) +{ + assert(file_chunk_request != nullptr); + return file_chunk_request->position; +} + +static void tox_event_file_chunk_request_set_length(Tox_Event_File_Chunk_Request *file_chunk_request, size_t length) +{ + assert(file_chunk_request != nullptr); + file_chunk_request->length = length; +} +size_t tox_event_file_chunk_request_get_length(const Tox_Event_File_Chunk_Request *file_chunk_request) +{ + assert(file_chunk_request != nullptr); + return file_chunk_request->length; +} + + +/***************************************************** + * + * :: add/clear/get + * + *****************************************************/ + + +static Tox_Event_File_Chunk_Request *tox_events_add_file_chunk_request(Tox_Events *events) +{ + 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)); + + if (new_file_chunk_request == nullptr) { + return nullptr; + } + + events->file_chunk_request = new_file_chunk_request; + events->file_chunk_request_capacity = new_file_chunk_request_capacity; + } + + 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) +{ + if (events == nullptr) { + return; + } + + 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; +} + +uint32_t tox_events_get_file_chunk_request_size(const Tox_Events *events) +{ + return events->file_chunk_request_size; +} + +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]; +} + + +/***************************************************** + * + * :: event handler + * + *****************************************************/ + + +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); + + Tox_Event_File_Chunk_Request *file_chunk_request = tox_events_add_file_chunk_request(state->events); + + if (file_chunk_request == nullptr) { + state->error = TOX_ERR_EVENTS_ITERATE_MALLOC; + return; + } + + tox_event_file_chunk_request_set_friend_number(file_chunk_request, friend_number); + tox_event_file_chunk_request_set_file_number(file_chunk_request, file_number); + tox_event_file_chunk_request_set_position(file_chunk_request, position); + tox_event_file_chunk_request_set_length(file_chunk_request, length); +} diff --git a/toxcore/events/file_recv.c b/toxcore/events/file_recv.c new file mode 100644 index 00000000..fb63a346 --- /dev/null +++ b/toxcore/events/file_recv.c @@ -0,0 +1,210 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2022 The TokTok team. + */ + +#include "events_alloc.h" + +#include +#include +#include + +#include "../ccompat.h" +#include "../tox.h" +#include "../tox_events.h" + + +/***************************************************** + * + * :: struct and accessors + * + *****************************************************/ + + +struct Tox_Event_File_Recv { + uint32_t friend_number; + uint32_t file_number; + uint32_t kind; + uint64_t file_size; + uint8_t *filename; + size_t filename_length; +}; + +static void tox_event_file_recv_construct(Tox_Event_File_Recv *file_recv) +{ + *file_recv = (Tox_Event_File_Recv) { + 0 + }; +} +static void tox_event_file_recv_destruct(Tox_Event_File_Recv *file_recv) +{ + free(file_recv->filename); +} + +static void tox_event_file_recv_set_friend_number(Tox_Event_File_Recv *file_recv, + uint32_t friend_number) +{ + assert(file_recv != nullptr); + file_recv->friend_number = friend_number; +} +uint32_t tox_event_file_recv_get_friend_number(const Tox_Event_File_Recv *file_recv) +{ + assert(file_recv != nullptr); + return file_recv->friend_number; +} + +static void tox_event_file_recv_set_file_number(Tox_Event_File_Recv *file_recv, + uint32_t file_number) +{ + assert(file_recv != nullptr); + file_recv->file_number = file_number; +} +uint32_t tox_event_file_recv_get_file_number(const Tox_Event_File_Recv *file_recv) +{ + assert(file_recv != nullptr); + return file_recv->file_number; +} + +static void tox_event_file_recv_set_kind(Tox_Event_File_Recv *file_recv, + uint32_t kind) +{ + assert(file_recv != nullptr); + file_recv->kind = kind; +} +uint32_t tox_event_file_recv_get_kind(const Tox_Event_File_Recv *file_recv) +{ + assert(file_recv != nullptr); + return file_recv->kind; +} + +static void tox_event_file_recv_set_file_size(Tox_Event_File_Recv *file_recv, + uint32_t file_size) +{ + assert(file_recv != nullptr); + file_recv->file_size = file_size; +} +uint32_t tox_event_file_recv_get_file_size(const Tox_Event_File_Recv *file_recv) +{ + assert(file_recv != nullptr); + return file_recv->file_size; +} + +static bool tox_event_file_recv_set_filename(Tox_Event_File_Recv *file_recv, const uint8_t *filename, + size_t filename_length) +{ + assert(file_recv != nullptr); + + if (file_recv->filename != nullptr) { + free(file_recv->filename); + file_recv->filename = nullptr; + file_recv->filename_length = 0; + } + + file_recv->filename = (uint8_t *)malloc(filename_length); + + if (file_recv->filename == nullptr) { + return false; + } + + memcpy(file_recv->filename, filename, filename_length); + file_recv->filename_length = filename_length; + return true; +} +size_t tox_event_file_recv_get_filename_length(const Tox_Event_File_Recv *file_recv) +{ + assert(file_recv != nullptr); + return file_recv->filename_length; +} +const uint8_t *tox_event_file_recv_get_filename(const Tox_Event_File_Recv *file_recv) +{ + assert(file_recv != nullptr); + return file_recv->filename; +} + + +/***************************************************** + * + * :: add/clear/get + * + *****************************************************/ + + +static Tox_Event_File_Recv *tox_events_add_file_recv(Tox_Events *events) +{ + 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)); + + if (new_file_recv == nullptr) { + return nullptr; + } + + events->file_recv = new_file_recv; + events->file_recv_capacity = new_file_recv_capacity; + } + + 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) +{ + if (events == nullptr) { + return; + } + + for (uint32_t i = 0; i < events->file_recv_size; ++i) { + tox_event_file_recv_destruct(&events->file_recv[i]); + } + + free(events->file_recv); + events->file_recv = nullptr; + events->file_recv_size = 0; + events->file_recv_capacity = 0; +} + +uint32_t tox_events_get_file_recv_size(const Tox_Events *events) +{ + return events->file_recv_size; +} + +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]; +} + + +/***************************************************** + * + * :: event handler + * + *****************************************************/ + + +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); + + Tox_Event_File_Recv *file_recv = tox_events_add_file_recv(state->events); + + if (file_recv == nullptr) { + state->error = TOX_ERR_EVENTS_ITERATE_MALLOC; + return; + } + + tox_event_file_recv_set_friend_number(file_recv, friend_number); + tox_event_file_recv_set_file_number(file_recv, file_number); + tox_event_file_recv_set_kind(file_recv, kind); + tox_event_file_recv_set_file_size(file_recv, file_size); + tox_event_file_recv_set_filename(file_recv, filename, filename_length); +} diff --git a/toxcore/events/file_recv_chunk.c b/toxcore/events/file_recv_chunk.c new file mode 100644 index 00000000..5eb56afd --- /dev/null +++ b/toxcore/events/file_recv_chunk.c @@ -0,0 +1,196 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2022 The TokTok team. + */ + +#include "events_alloc.h" + +#include +#include +#include + +#include "../ccompat.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; + uint64_t position; + uint8_t *data; + size_t data_length; +}; + +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 + }; +} +static void tox_event_file_recv_chunk_destruct(Tox_Event_File_Recv_Chunk *file_recv_chunk) +{ + free(file_recv_chunk->data); +} + +static void tox_event_file_recv_chunk_set_friend_number(Tox_Event_File_Recv_Chunk *file_recv_chunk, + uint32_t friend_number) +{ + assert(file_recv_chunk != nullptr); + file_recv_chunk->friend_number = friend_number; +} +uint32_t tox_event_file_recv_chunk_get_friend_number(const Tox_Event_File_Recv_Chunk *file_recv_chunk) +{ + assert(file_recv_chunk != nullptr); + return file_recv_chunk->friend_number; +} + +static void tox_event_file_recv_chunk_set_file_number(Tox_Event_File_Recv_Chunk *file_recv_chunk, + uint32_t file_number) +{ + assert(file_recv_chunk != nullptr); + file_recv_chunk->file_number = file_number; +} +uint32_t tox_event_file_recv_chunk_get_file_number(const Tox_Event_File_Recv_Chunk *file_recv_chunk) +{ + assert(file_recv_chunk != nullptr); + return file_recv_chunk->file_number; +} + +static void tox_event_file_recv_chunk_set_position(Tox_Event_File_Recv_Chunk *file_recv_chunk, + uint32_t position) +{ + assert(file_recv_chunk != nullptr); + file_recv_chunk->position = position; +} +uint32_t tox_event_file_recv_chunk_get_position(const Tox_Event_File_Recv_Chunk *file_recv_chunk) +{ + assert(file_recv_chunk != nullptr); + return file_recv_chunk->position; +} + +static bool tox_event_file_recv_chunk_set_data(Tox_Event_File_Recv_Chunk *file_recv_chunk, const uint8_t *data, + size_t data_length) +{ + assert(file_recv_chunk != nullptr); + + if (file_recv_chunk->data != nullptr) { + free(file_recv_chunk->data); + file_recv_chunk->data = nullptr; + file_recv_chunk->data_length = 0; + } + + file_recv_chunk->data = (uint8_t *)malloc(data_length); + + if (file_recv_chunk->data == nullptr) { + return false; + } + + memcpy(file_recv_chunk->data, data, data_length); + file_recv_chunk->data_length = data_length; + return true; +} +size_t tox_event_file_recv_chunk_get_length(const Tox_Event_File_Recv_Chunk *file_recv_chunk) +{ + assert(file_recv_chunk != nullptr); + return file_recv_chunk->data_length; +} +const uint8_t *tox_event_file_recv_chunk_get_data(const Tox_Event_File_Recv_Chunk *file_recv_chunk) +{ + assert(file_recv_chunk != nullptr); + return file_recv_chunk->data; +} + + +/***************************************************** + * + * :: add/clear/get + * + *****************************************************/ + + +static Tox_Event_File_Recv_Chunk *tox_events_add_file_recv_chunk(Tox_Events *events) +{ + 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)); + + if (new_file_recv_chunk == nullptr) { + return nullptr; + } + + events->file_recv_chunk = new_file_recv_chunk; + events->file_recv_chunk_capacity = new_file_recv_chunk_capacity; + } + + 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) +{ + 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]); + } + + free(events->file_recv_chunk); + events->file_recv_chunk = nullptr; + events->file_recv_chunk_size = 0; + events->file_recv_chunk_capacity = 0; +} + +uint32_t tox_events_get_file_recv_chunk_size(const Tox_Events *events) +{ + return events->file_recv_chunk_size; +} + +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]; +} + + +/***************************************************** + * + * :: event handler + * + *****************************************************/ + + +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); + + Tox_Event_File_Recv_Chunk *file_recv_chunk = tox_events_add_file_recv_chunk(state->events); + + if (file_recv_chunk == nullptr) { + state->error = TOX_ERR_EVENTS_ITERATE_MALLOC; + return; + } + + tox_event_file_recv_chunk_set_friend_number(file_recv_chunk, friend_number); + tox_event_file_recv_chunk_set_file_number(file_recv_chunk, file_number); + tox_event_file_recv_chunk_set_position(file_recv_chunk, position); + tox_event_file_recv_chunk_set_data(file_recv_chunk, data, length); +} diff --git a/toxcore/events/file_recv_control.c b/toxcore/events/file_recv_control.c new file mode 100644 index 00000000..de31a9eb --- /dev/null +++ b/toxcore/events/file_recv_control.c @@ -0,0 +1,161 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2022 The TokTok team. + */ + +#include "events_alloc.h" + +#include +#include +#include + +#include "../ccompat.h" +#include "../tox.h" +#include "../tox_events.h" + + +/***************************************************** + * + * :: struct and accessors + * + *****************************************************/ + + +struct Tox_Event_File_Recv_Control { + uint32_t friend_number; + uint32_t file_number; + Tox_File_Control control; +}; + +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 + }; +} +static void tox_event_file_recv_control_destruct(Tox_Event_File_Recv_Control *file_recv_control) +{ + return; +} + +static void tox_event_file_recv_control_set_friend_number(Tox_Event_File_Recv_Control *file_recv_control, + uint32_t friend_number) +{ + assert(file_recv_control != nullptr); + file_recv_control->friend_number = friend_number; +} +uint32_t tox_event_file_recv_control_get_friend_number(const Tox_Event_File_Recv_Control *file_recv_control) +{ + assert(file_recv_control != nullptr); + return file_recv_control->friend_number; +} + +static void tox_event_file_recv_control_set_file_number(Tox_Event_File_Recv_Control *file_recv_control, + uint32_t file_number) +{ + assert(file_recv_control != nullptr); + file_recv_control->file_number = file_number; +} +uint32_t tox_event_file_recv_control_get_file_number(const Tox_Event_File_Recv_Control *file_recv_control) +{ + assert(file_recv_control != nullptr); + return file_recv_control->file_number; +} + +static void tox_event_file_recv_control_set_control(Tox_Event_File_Recv_Control *file_recv_control, + Tox_File_Control control) +{ + assert(file_recv_control != nullptr); + file_recv_control->control = control; +} +Tox_File_Control tox_event_file_recv_control_get_control(const Tox_Event_File_Recv_Control *file_recv_control) +{ + assert(file_recv_control != nullptr); + return file_recv_control->control; +} + + +/***************************************************** + * + * :: add/clear/get + * + *****************************************************/ + + +static Tox_Event_File_Recv_Control *tox_events_add_file_recv_control(Tox_Events *events) +{ + 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)); + + if (new_file_recv_control == nullptr) { + return nullptr; + } + + events->file_recv_control = new_file_recv_control; + events->file_recv_control_capacity = new_file_recv_control_capacity; + } + + 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) +{ + if (events == nullptr) { + return; + } + + 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; +} + +uint32_t tox_events_get_file_recv_control_size(const Tox_Events *events) +{ + return events->file_recv_control_size; +} + +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]; +} + + +/***************************************************** + * + * :: event handler + * + *****************************************************/ + + +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); + + Tox_Event_File_Recv_Control *file_recv_control = tox_events_add_file_recv_control(state->events); + + if (file_recv_control == nullptr) { + state->error = TOX_ERR_EVENTS_ITERATE_MALLOC; + return; + } + + tox_event_file_recv_control_set_friend_number(file_recv_control, friend_number); + tox_event_file_recv_control_set_file_number(file_recv_control, file_number); + tox_event_file_recv_control_set_control(file_recv_control, control); +} diff --git a/toxcore/events/friend_connection_status.c b/toxcore/events/friend_connection_status.c new file mode 100644 index 00000000..1ef73015 --- /dev/null +++ b/toxcore/events/friend_connection_status.c @@ -0,0 +1,151 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2022 The TokTok team. + */ + +#include "events_alloc.h" + +#include +#include +#include + +#include "../ccompat.h" +#include "../tox.h" +#include "../tox_events.h" + + +/***************************************************** + * + * :: struct and accessors + * + *****************************************************/ + + +struct Tox_Event_Friend_Connection_Status { + uint32_t friend_number; + Tox_Connection connection_status; +}; + +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 + }; +} +static void tox_event_friend_connection_status_destruct(Tox_Event_Friend_Connection_Status *friend_connection_status) +{ + return; +} + +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) +{ + assert(friend_connection_status != nullptr); + return friend_connection_status->friend_number; +} + +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) +{ + assert(friend_connection_status != nullptr); + return friend_connection_status->connection_status; +} + + +/***************************************************** + * + * :: add/clear/get + * + *****************************************************/ + + +static Tox_Event_Friend_Connection_Status *tox_events_add_friend_connection_status(Tox_Events *events) +{ + 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)); + + if (new_friend_connection_status == nullptr) { + return nullptr; + } + + events->friend_connection_status = new_friend_connection_status; + events->friend_connection_status_capacity = new_friend_connection_status_capacity; + } + + 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) +{ + 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]); + } + + free(events->friend_connection_status); + events->friend_connection_status = nullptr; + events->friend_connection_status_size = 0; + events->friend_connection_status_capacity = 0; +} + +uint32_t tox_events_get_friend_connection_status_size(const Tox_Events *events) +{ + return events->friend_connection_status_size; +} + +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]; +} + + +/***************************************************** + * + * :: event handler + * + *****************************************************/ + + +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); + + Tox_Event_Friend_Connection_Status *friend_connection_status = tox_events_add_friend_connection_status(state->events); + + if (friend_connection_status == nullptr) { + state->error = TOX_ERR_EVENTS_ITERATE_MALLOC; + return; + } + + tox_event_friend_connection_status_set_friend_number(friend_connection_status, friend_number); + tox_event_friend_connection_status_set_connection_status(friend_connection_status, connection_status); +} diff --git a/toxcore/events/friend_lossless_packet.c b/toxcore/events/friend_lossless_packet.c new file mode 100644 index 00000000..1c7ae450 --- /dev/null +++ b/toxcore/events/friend_lossless_packet.c @@ -0,0 +1,170 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2022 The TokTok team. + */ + +#include "events_alloc.h" + +#include +#include +#include + +#include "../ccompat.h" +#include "../tox.h" +#include "../tox_events.h" + + +/***************************************************** + * + * :: struct and accessors + * + *****************************************************/ + + +struct Tox_Event_Friend_Lossless_Packet { + uint32_t friend_number; + uint8_t *data; + size_t data_length; +}; + +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 + }; +} +static void tox_event_friend_lossless_packet_destruct(Tox_Event_Friend_Lossless_Packet *friend_lossless_packet) +{ + free(friend_lossless_packet->data); +} + +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) +{ + assert(friend_lossless_packet != nullptr); + return friend_lossless_packet->friend_number; +} + +static bool tox_event_friend_lossless_packet_set_data(Tox_Event_Friend_Lossless_Packet *friend_lossless_packet, + const uint8_t *data, size_t data_length) +{ + assert(friend_lossless_packet != nullptr); + + if (friend_lossless_packet->data != nullptr) { + free(friend_lossless_packet->data); + friend_lossless_packet->data = nullptr; + friend_lossless_packet->data_length = 0; + } + + friend_lossless_packet->data = (uint8_t *)malloc(data_length); + + if (friend_lossless_packet->data == nullptr) { + return false; + } + + memcpy(friend_lossless_packet->data, data, data_length); + friend_lossless_packet->data_length = data_length; + return true; +} +size_t tox_event_friend_lossless_packet_get_data_length(const Tox_Event_Friend_Lossless_Packet *friend_lossless_packet) +{ + assert(friend_lossless_packet != nullptr); + return friend_lossless_packet->data_length; +} +const uint8_t *tox_event_friend_lossless_packet_get_data(const Tox_Event_Friend_Lossless_Packet *friend_lossless_packet) +{ + assert(friend_lossless_packet != nullptr); + return friend_lossless_packet->data; +} + + +/***************************************************** + * + * :: add/clear/get + * + *****************************************************/ + + +static Tox_Event_Friend_Lossless_Packet *tox_events_add_friend_lossless_packet(Tox_Events *events) +{ + 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)); + + if (new_friend_lossless_packet == nullptr) { + return nullptr; + } + + events->friend_lossless_packet = new_friend_lossless_packet; + events->friend_lossless_packet_capacity = new_friend_lossless_packet_capacity; + } + + 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) +{ + if (events == nullptr) { + return; + } + + 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; +} + +uint32_t tox_events_get_friend_lossless_packet_size(const Tox_Events *events) +{ + return events->friend_lossless_packet_size; +} + +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]; +} + + +/***************************************************** + * + * :: event handler + * + *****************************************************/ + + +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); + + Tox_Event_Friend_Lossless_Packet *friend_lossless_packet = tox_events_add_friend_lossless_packet(state->events); + + if (friend_lossless_packet == nullptr) { + state->error = TOX_ERR_EVENTS_ITERATE_MALLOC; + return; + } + + tox_event_friend_lossless_packet_set_friend_number(friend_lossless_packet, friend_number); + tox_event_friend_lossless_packet_set_data(friend_lossless_packet, data, length); +} diff --git a/toxcore/events/friend_lossy_packet.c b/toxcore/events/friend_lossy_packet.c new file mode 100644 index 00000000..d97586d4 --- /dev/null +++ b/toxcore/events/friend_lossy_packet.c @@ -0,0 +1,169 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2022 The TokTok team. + */ + +#include "events_alloc.h" + +#include +#include +#include + +#include "../ccompat.h" +#include "../tox.h" +#include "../tox_events.h" + + +/***************************************************** + * + * :: struct and accessors + * + *****************************************************/ + + +struct Tox_Event_Friend_Lossy_Packet { + uint32_t friend_number; + uint8_t *data; + size_t data_length; +}; + +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 + }; +} +static void tox_event_friend_lossy_packet_destruct(Tox_Event_Friend_Lossy_Packet *friend_lossy_packet) +{ + free(friend_lossy_packet->data); +} + +static void tox_event_friend_lossy_packet_set_friend_number(Tox_Event_Friend_Lossy_Packet *friend_lossy_packet, + uint32_t friend_number) +{ + assert(friend_lossy_packet != nullptr); + friend_lossy_packet->friend_number = friend_number; +} +uint32_t tox_event_friend_lossy_packet_get_friend_number(const Tox_Event_Friend_Lossy_Packet *friend_lossy_packet) +{ + assert(friend_lossy_packet != nullptr); + return friend_lossy_packet->friend_number; +} + +static bool tox_event_friend_lossy_packet_set_data(Tox_Event_Friend_Lossy_Packet *friend_lossy_packet, + const uint8_t *data, size_t data_length) +{ + assert(friend_lossy_packet != nullptr); + + if (friend_lossy_packet->data != nullptr) { + free(friend_lossy_packet->data); + friend_lossy_packet->data = nullptr; + friend_lossy_packet->data_length = 0; + } + + friend_lossy_packet->data = (uint8_t *)malloc(data_length); + + if (friend_lossy_packet->data == nullptr) { + return false; + } + + memcpy(friend_lossy_packet->data, data, data_length); + friend_lossy_packet->data_length = data_length; + return true; +} +size_t tox_event_friend_lossy_packet_get_data_length(const Tox_Event_Friend_Lossy_Packet *friend_lossy_packet) +{ + assert(friend_lossy_packet != nullptr); + return friend_lossy_packet->data_length; +} +const uint8_t *tox_event_friend_lossy_packet_get_data(const Tox_Event_Friend_Lossy_Packet *friend_lossy_packet) +{ + assert(friend_lossy_packet != nullptr); + return friend_lossy_packet->data; +} + + +/***************************************************** + * + * :: add/clear/get + * + *****************************************************/ + + +static Tox_Event_Friend_Lossy_Packet *tox_events_add_friend_lossy_packet(Tox_Events *events) +{ + 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)); + + if (new_friend_lossy_packet == nullptr) { + return nullptr; + } + + events->friend_lossy_packet = new_friend_lossy_packet; + events->friend_lossy_packet_capacity = new_friend_lossy_packet_capacity; + } + + 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) +{ + if (events == nullptr) { + return; + } + + 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; +} + +uint32_t tox_events_get_friend_lossy_packet_size(const Tox_Events *events) +{ + return events->friend_lossy_packet_size; +} + +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]; +} + + +/***************************************************** + * + * :: event handler + * + *****************************************************/ + + +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); + + Tox_Event_Friend_Lossy_Packet *friend_lossy_packet = tox_events_add_friend_lossy_packet(state->events); + + if (friend_lossy_packet == nullptr) { + state->error = TOX_ERR_EVENTS_ITERATE_MALLOC; + return; + } + + tox_event_friend_lossy_packet_set_friend_number(friend_lossy_packet, friend_number); + tox_event_friend_lossy_packet_set_data(friend_lossy_packet, data, length); +} diff --git a/toxcore/events/friend_message.c b/toxcore/events/friend_message.c new file mode 100644 index 00000000..01551901 --- /dev/null +++ b/toxcore/events/friend_message.c @@ -0,0 +1,181 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2022 The TokTok team. + */ + +#include "events_alloc.h" + +#include +#include +#include + +#include "../ccompat.h" +#include "../tox.h" +#include "../tox_events.h" + + +/***************************************************** + * + * :: struct and accessors + * + *****************************************************/ + + +struct Tox_Event_Friend_Message { + uint32_t friend_number; + Tox_Message_Type type; + uint8_t *message; + size_t message_length; +}; + +static void tox_event_friend_message_construct(Tox_Event_Friend_Message *friend_message) +{ + *friend_message = (Tox_Event_Friend_Message) { + 0 + }; +} +static void tox_event_friend_message_destruct(Tox_Event_Friend_Message *friend_message) +{ + free(friend_message->message); +} + +static void tox_event_friend_message_set_friend_number(Tox_Event_Friend_Message *friend_message, + uint32_t friend_number) +{ + assert(friend_message != nullptr); + friend_message->friend_number = friend_number; +} +uint32_t tox_event_friend_message_get_friend_number(const Tox_Event_Friend_Message *friend_message) +{ + assert(friend_message != nullptr); + return friend_message->friend_number; +} + +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; +} +Tox_Message_Type tox_event_friend_message_get_type(const Tox_Event_Friend_Message *friend_message) +{ + assert(friend_message != nullptr); + return friend_message->type; +} + +static bool tox_event_friend_message_set_message(Tox_Event_Friend_Message *friend_message, const uint8_t *message, + size_t message_length) +{ + assert(friend_message != nullptr); + + if (friend_message->message != nullptr) { + free(friend_message->message); + friend_message->message = nullptr; + friend_message->message_length = 0; + } + + friend_message->message = (uint8_t *)malloc(message_length); + + if (friend_message->message == nullptr) { + return false; + } + + memcpy(friend_message->message, message, message_length); + friend_message->message_length = message_length; + return true; +} +size_t tox_event_friend_message_get_message_length(const Tox_Event_Friend_Message *friend_message) +{ + assert(friend_message != nullptr); + return friend_message->message_length; +} +const uint8_t *tox_event_friend_message_get_message(const Tox_Event_Friend_Message *friend_message) +{ + assert(friend_message != nullptr); + return friend_message->message; +} + + +/***************************************************** + * + * :: add/clear/get + * + *****************************************************/ + + +static Tox_Event_Friend_Message *tox_events_add_friend_message(Tox_Events *events) +{ + 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)); + + if (new_friend_message == nullptr) { + return nullptr; + } + + events->friend_message = new_friend_message; + events->friend_message_capacity = new_friend_message_capacity; + } + + 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) +{ + if (events == nullptr) { + return; + } + + for (uint32_t i = 0; i < events->friend_message_size; ++i) { + tox_event_friend_message_destruct(&events->friend_message[i]); + } + + free(events->friend_message); + events->friend_message = nullptr; + events->friend_message_size = 0; + events->friend_message_capacity = 0; +} + +uint32_t tox_events_get_friend_message_size(const Tox_Events *events) +{ + return events->friend_message_size; +} + +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]; +} + + +/***************************************************** + * + * :: event handler + * + *****************************************************/ + + +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); + + Tox_Event_Friend_Message *friend_message = tox_events_add_friend_message(state->events); + + if (friend_message == nullptr) { + state->error = TOX_ERR_EVENTS_ITERATE_MALLOC; + return; + } + + tox_event_friend_message_set_friend_number(friend_message, friend_number); + tox_event_friend_message_set_type(friend_message, type); + tox_event_friend_message_set_message(friend_message, message, length); +} diff --git a/toxcore/events/friend_name.c b/toxcore/events/friend_name.c new file mode 100644 index 00000000..3c01f886 --- /dev/null +++ b/toxcore/events/friend_name.c @@ -0,0 +1,168 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2022 The TokTok team. + */ + +#include "events_alloc.h" + +#include +#include +#include + +#include "../ccompat.h" +#include "../tox.h" +#include "../tox_events.h" + + +/***************************************************** + * + * :: struct and accessors + * + *****************************************************/ + + +struct Tox_Event_Friend_Name { + uint32_t friend_number; + uint8_t *name; + size_t name_length; +}; + +static void tox_event_friend_name_construct(Tox_Event_Friend_Name *friend_name) +{ + *friend_name = (Tox_Event_Friend_Name) { + 0 + }; +} +static void tox_event_friend_name_destruct(Tox_Event_Friend_Name *friend_name) +{ + free(friend_name->name); +} + +static void tox_event_friend_name_set_friend_number(Tox_Event_Friend_Name *friend_name, + uint32_t friend_number) +{ + assert(friend_name != nullptr); + friend_name->friend_number = friend_number; +} +uint32_t tox_event_friend_name_get_friend_number(const Tox_Event_Friend_Name *friend_name) +{ + assert(friend_name != nullptr); + return friend_name->friend_number; +} + +static bool tox_event_friend_name_set_name(Tox_Event_Friend_Name *friend_name, const uint8_t *name, + size_t name_length) +{ + assert(friend_name != nullptr); + + if (friend_name->name != nullptr) { + free(friend_name->name); + friend_name->name = nullptr; + friend_name->name_length = 0; + } + + friend_name->name = (uint8_t *)malloc(name_length); + + if (friend_name->name == nullptr) { + return false; + } + + memcpy(friend_name->name, name, name_length); + friend_name->name_length = name_length; + return true; +} +size_t tox_event_friend_name_get_name_length(const Tox_Event_Friend_Name *friend_name) +{ + assert(friend_name != nullptr); + return friend_name->name_length; +} +const uint8_t *tox_event_friend_name_get_name(const Tox_Event_Friend_Name *friend_name) +{ + assert(friend_name != nullptr); + return friend_name->name; +} + + +/***************************************************** + * + * :: add/clear/get + * + *****************************************************/ + + +static Tox_Event_Friend_Name *tox_events_add_friend_name(Tox_Events *events) +{ + 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)); + + if (new_friend_name == nullptr) { + return nullptr; + } + + events->friend_name = new_friend_name; + events->friend_name_capacity = new_friend_name_capacity; + } + + 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) +{ + if (events == nullptr) { + return; + } + + for (uint32_t i = 0; i < events->friend_name_size; ++i) { + tox_event_friend_name_destruct(&events->friend_name[i]); + } + + free(events->friend_name); + events->friend_name = nullptr; + events->friend_name_size = 0; + events->friend_name_capacity = 0; +} + +uint32_t tox_events_get_friend_name_size(const Tox_Events *events) +{ + return events->friend_name_size; +} + +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]; +} + + +/***************************************************** + * + * :: event handler + * + *****************************************************/ + + +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); + + Tox_Event_Friend_Name *friend_name = tox_events_add_friend_name(state->events); + + if (friend_name == nullptr) { + state->error = TOX_ERR_EVENTS_ITERATE_MALLOC; + return; + } + + tox_event_friend_name_set_friend_number(friend_name, friend_number); + tox_event_friend_name_set_name(friend_name, name, length); +} diff --git a/toxcore/events/friend_read_receipt.c b/toxcore/events/friend_read_receipt.c new file mode 100644 index 00000000..82ff97f2 --- /dev/null +++ b/toxcore/events/friend_read_receipt.c @@ -0,0 +1,147 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2022 The TokTok team. + */ + +#include "events_alloc.h" + +#include +#include +#include + +#include "../ccompat.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; +}; + +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 + }; +} +static void tox_event_friend_read_receipt_destruct(Tox_Event_Friend_Read_Receipt *friend_read_receipt) +{ + return; +} + +static void tox_event_friend_read_receipt_set_friend_number(Tox_Event_Friend_Read_Receipt *friend_read_receipt, + uint32_t friend_number) +{ + assert(friend_read_receipt != nullptr); + friend_read_receipt->friend_number = friend_number; +} +uint32_t tox_event_friend_read_receipt_get_friend_number(const Tox_Event_Friend_Read_Receipt *friend_read_receipt) +{ + assert(friend_read_receipt != nullptr); + return friend_read_receipt->friend_number; +} + +static void tox_event_friend_read_receipt_set_message_id(Tox_Event_Friend_Read_Receipt *friend_read_receipt, + uint32_t message_id) +{ + assert(friend_read_receipt != nullptr); + friend_read_receipt->message_id = message_id; +} +uint32_t tox_event_friend_read_receipt_get_message_id(const Tox_Event_Friend_Read_Receipt *friend_read_receipt) +{ + assert(friend_read_receipt != nullptr); + return friend_read_receipt->message_id; +} + + +/***************************************************** + * + * :: add/clear/get + * + *****************************************************/ + + +static Tox_Event_Friend_Read_Receipt *tox_events_add_friend_read_receipt(Tox_Events *events) +{ + 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)); + + if (new_friend_read_receipt == nullptr) { + return nullptr; + } + + events->friend_read_receipt = new_friend_read_receipt; + events->friend_read_receipt_capacity = new_friend_read_receipt_capacity; + } + + 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) +{ + 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]); + } + + free(events->friend_read_receipt); + events->friend_read_receipt = nullptr; + events->friend_read_receipt_size = 0; + events->friend_read_receipt_capacity = 0; +} + +uint32_t tox_events_get_friend_read_receipt_size(const Tox_Events *events) +{ + return events->friend_read_receipt_size; +} + +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]; +} + + +/***************************************************** + * + * :: event handler + * + *****************************************************/ + + +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); + + Tox_Event_Friend_Read_Receipt *friend_read_receipt = tox_events_add_friend_read_receipt(state->events); + + if (friend_read_receipt == nullptr) { + state->error = TOX_ERR_EVENTS_ITERATE_MALLOC; + return; + } + + tox_event_friend_read_receipt_set_friend_number(friend_read_receipt, friend_number); + tox_event_friend_read_receipt_set_message_id(friend_read_receipt, message_id); +} diff --git a/toxcore/events/friend_request.c b/toxcore/events/friend_request.c new file mode 100644 index 00000000..ae725067 --- /dev/null +++ b/toxcore/events/friend_request.c @@ -0,0 +1,169 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2022 The TokTok team. + */ + +#include "events_alloc.h" + +#include +#include +#include + +#include "../ccompat.h" +#include "../tox.h" +#include "../tox_events.h" + + +/***************************************************** + * + * :: struct and accessors + * + *****************************************************/ + + +struct Tox_Event_Friend_Request { + uint8_t public_key[TOX_PUBLIC_KEY_SIZE]; + uint8_t *message; + size_t message_length; +}; + +static void tox_event_friend_request_construct(Tox_Event_Friend_Request *friend_request) +{ + *friend_request = (Tox_Event_Friend_Request) { + 0 + }; +} +static void tox_event_friend_request_destruct(Tox_Event_Friend_Request *friend_request) +{ + free(friend_request->message); +} + +static bool tox_event_friend_request_set_public_key(Tox_Event_Friend_Request *friend_request, const uint8_t *public_key) +{ + assert(friend_request != nullptr); + + memcpy(friend_request->public_key, public_key, TOX_PUBLIC_KEY_SIZE); + return true; +} +const uint8_t *tox_event_friend_request_get_public_key(const Tox_Event_Friend_Request *friend_request) +{ + assert(friend_request != nullptr); + return friend_request->public_key; +} + +static bool tox_event_friend_request_set_message(Tox_Event_Friend_Request *friend_request, const uint8_t *message, + size_t message_length) +{ + assert(friend_request != nullptr); + + if (friend_request->message != nullptr) { + free(friend_request->message); + friend_request->message = nullptr; + friend_request->message_length = 0; + } + + friend_request->message = (uint8_t *)malloc(message_length); + + if (friend_request->message == nullptr) { + return false; + } + + memcpy(friend_request->message, message, message_length); + friend_request->message_length = message_length; + return true; +} +size_t tox_event_friend_request_get_message_length(const Tox_Event_Friend_Request *friend_request) +{ + assert(friend_request != nullptr); + return friend_request->message_length; +} +const uint8_t *tox_event_friend_request_get_message(const Tox_Event_Friend_Request *friend_request) +{ + assert(friend_request != nullptr); + return friend_request->message; +} + + +/***************************************************** + * + * :: add/clear/get + * + *****************************************************/ + + +static Tox_Event_Friend_Request *tox_events_add_friend_request(Tox_Events *events) +{ + 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)); + + if (new_friend_request == nullptr) { + return nullptr; + } + + events->friend_request = new_friend_request; + events->friend_request_capacity = new_friend_request_capacity; + } + + 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) +{ + if (events == nullptr) { + return; + } + + 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; +} + +uint32_t tox_events_get_friend_request_size(const Tox_Events *events) +{ + return events->friend_request_size; +} + +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]; +} + + +/***************************************************** + * + * :: event handler + * + *****************************************************/ + + +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); + + Tox_Event_Friend_Request *friend_request = tox_events_add_friend_request(state->events); + + if (friend_request == nullptr) { + state->error = TOX_ERR_EVENTS_ITERATE_MALLOC; + return; + } + + tox_event_friend_request_set_public_key(friend_request, public_key); + tox_event_friend_request_set_message(friend_request, message, length); +} diff --git a/toxcore/events/friend_status.c b/toxcore/events/friend_status.c new file mode 100644 index 00000000..8cce94a7 --- /dev/null +++ b/toxcore/events/friend_status.c @@ -0,0 +1,147 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2022 The TokTok team. + */ + +#include "events_alloc.h" + +#include +#include +#include + +#include "../ccompat.h" +#include "../tox.h" +#include "../tox_events.h" + + +/***************************************************** + * + * :: struct and accessors + * + *****************************************************/ + + +struct Tox_Event_Friend_Status { + uint32_t friend_number; + Tox_User_Status connection_status; +}; + +static void tox_event_friend_status_construct(Tox_Event_Friend_Status *friend_status) +{ + *friend_status = (Tox_Event_Friend_Status) { + 0 + }; +} +static void tox_event_friend_status_destruct(Tox_Event_Friend_Status *friend_status) +{ + return; +} + +static void tox_event_friend_status_set_friend_number(Tox_Event_Friend_Status *friend_status, + uint32_t friend_number) +{ + assert(friend_status != nullptr); + friend_status->friend_number = friend_number; +} +uint32_t tox_event_friend_status_get_friend_number(const Tox_Event_Friend_Status *friend_status) +{ + assert(friend_status != nullptr); + return friend_status->friend_number; +} + +static void tox_event_friend_status_set_connection_status(Tox_Event_Friend_Status *friend_status, + Tox_User_Status connection_status) +{ + assert(friend_status != nullptr); + friend_status->connection_status = connection_status; +} +Tox_User_Status tox_event_friend_status_get_connection_status(const Tox_Event_Friend_Status *friend_status) +{ + assert(friend_status != nullptr); + return friend_status->connection_status; +} + + +/***************************************************** + * + * :: add/clear/get + * + *****************************************************/ + + +static Tox_Event_Friend_Status *tox_events_add_friend_status(Tox_Events *events) +{ + 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)); + + if (new_friend_status == nullptr) { + return nullptr; + } + + events->friend_status = new_friend_status; + events->friend_status_capacity = new_friend_status_capacity; + } + + 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) +{ + if (events == nullptr) { + return; + } + + for (uint32_t i = 0; i < events->friend_status_size; ++i) { + tox_event_friend_status_destruct(&events->friend_status[i]); + } + + free(events->friend_status); + events->friend_status = nullptr; + events->friend_status_size = 0; + events->friend_status_capacity = 0; +} + +uint32_t tox_events_get_friend_status_size(const Tox_Events *events) +{ + return events->friend_status_size; +} + +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]; +} + + +/***************************************************** + * + * :: event handler + * + *****************************************************/ + + +void tox_events_handle_friend_status(Tox *tox, uint32_t friend_number, Tox_User_Status connection_status, + void *user_data) +{ + Tox_Events_State *state = tox_events_alloc(user_data); + assert(state != nullptr); + + Tox_Event_Friend_Status *friend_status = tox_events_add_friend_status(state->events); + + if (friend_status == nullptr) { + state->error = TOX_ERR_EVENTS_ITERATE_MALLOC; + return; + } + + tox_event_friend_status_set_friend_number(friend_status, friend_number); + tox_event_friend_status_set_connection_status(friend_status, connection_status); +} diff --git a/toxcore/events/friend_status_message.c b/toxcore/events/friend_status_message.c new file mode 100644 index 00000000..b593a28a --- /dev/null +++ b/toxcore/events/friend_status_message.c @@ -0,0 +1,171 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2022 The TokTok team. + */ + +#include "events_alloc.h" + +#include +#include +#include + +#include "../ccompat.h" +#include "../tox.h" +#include "../tox_events.h" + + +/***************************************************** + * + * :: struct and accessors + * + *****************************************************/ + + +struct Tox_Event_Friend_Status_Message { + uint32_t friend_number; + uint8_t *status_message; + size_t status_message_length; +}; + +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 + }; +} +static void tox_event_friend_status_message_destruct(Tox_Event_Friend_Status_Message *friend_status_message) +{ + free(friend_status_message->status_message); +} + +static void tox_event_friend_status_message_set_friend_number(Tox_Event_Friend_Status_Message *friend_status_message, + uint32_t friend_number) +{ + assert(friend_status_message != nullptr); + friend_status_message->friend_number = friend_number; +} +uint32_t tox_event_friend_status_message_get_friend_number(const Tox_Event_Friend_Status_Message *friend_status_message) +{ + assert(friend_status_message != nullptr); + return friend_status_message->friend_number; +} + +static bool tox_event_friend_status_message_set_status_message(Tox_Event_Friend_Status_Message *friend_status_message, + const uint8_t *status_message, size_t status_message_length) +{ + assert(friend_status_message != nullptr); + + if (friend_status_message->status_message != nullptr) { + free(friend_status_message->status_message); + friend_status_message->status_message = nullptr; + friend_status_message->status_message_length = 0; + } + + friend_status_message->status_message = (uint8_t *)malloc(status_message_length); + + if (friend_status_message->status_message == nullptr) { + return false; + } + + memcpy(friend_status_message->status_message, status_message, status_message_length); + friend_status_message->status_message_length = status_message_length; + return true; +} +size_t tox_event_friend_status_message_get_status_message_length(const Tox_Event_Friend_Status_Message + *friend_status_message) +{ + assert(friend_status_message != nullptr); + return friend_status_message->status_message_length; +} +const uint8_t *tox_event_friend_status_message_get_status_message(const Tox_Event_Friend_Status_Message + *friend_status_message) +{ + assert(friend_status_message != nullptr); + return friend_status_message->status_message; +} + + +/***************************************************** + * + * :: add/clear/get + * + *****************************************************/ + + +static Tox_Event_Friend_Status_Message *tox_events_add_friend_status_message(Tox_Events *events) +{ + 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)); + + if (new_friend_status_message == nullptr) { + return nullptr; + } + + events->friend_status_message = new_friend_status_message; + events->friend_status_message_capacity = new_friend_status_message_capacity; + } + + 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) +{ + if (events == nullptr) { + return; + } + + 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; +} + +uint32_t tox_events_get_friend_status_message_size(const Tox_Events *events) +{ + return events->friend_status_message_size; +} + +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]; +} + + +/***************************************************** + * + * :: event handler + * + *****************************************************/ + + +void tox_events_handle_friend_status_message(Tox *tox, uint32_t friend_number, const uint8_t *status_message, + size_t length, void *user_data) +{ + Tox_Events_State *state = tox_events_alloc(user_data); + assert(state != nullptr); + + Tox_Event_Friend_Status_Message *friend_status_message = tox_events_add_friend_status_message(state->events); + + if (friend_status_message == nullptr) { + state->error = TOX_ERR_EVENTS_ITERATE_MALLOC; + return; + } + + tox_event_friend_status_message_set_friend_number(friend_status_message, friend_number); + tox_event_friend_status_message_set_status_message(friend_status_message, status_message, length); +} diff --git a/toxcore/events/friend_typing.c b/toxcore/events/friend_typing.c new file mode 100644 index 00000000..93911754 --- /dev/null +++ b/toxcore/events/friend_typing.c @@ -0,0 +1,145 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2022 The TokTok team. + */ + +#include "events_alloc.h" + +#include +#include +#include + +#include "../ccompat.h" +#include "../tox.h" +#include "../tox_events.h" + + +/***************************************************** + * + * :: struct and accessors + * + *****************************************************/ + + +struct Tox_Event_Friend_Typing { + uint32_t friend_number; + bool typing; +}; + +static void tox_event_friend_typing_construct(Tox_Event_Friend_Typing *friend_typing) +{ + *friend_typing = (Tox_Event_Friend_Typing) { + 0 + }; +} +static void tox_event_friend_typing_destruct(Tox_Event_Friend_Typing *friend_typing) +{ + return; +} + +static void tox_event_friend_typing_set_friend_number(Tox_Event_Friend_Typing *friend_typing, + uint32_t friend_number) +{ + assert(friend_typing != nullptr); + friend_typing->friend_number = friend_number; +} +uint32_t tox_event_friend_typing_get_friend_number(const Tox_Event_Friend_Typing *friend_typing) +{ + assert(friend_typing != nullptr); + return friend_typing->friend_number; +} + +static void tox_event_friend_typing_set_typing(Tox_Event_Friend_Typing *friend_typing, bool typing) +{ + assert(friend_typing != nullptr); + friend_typing->typing = typing; +} +bool tox_event_friend_typing_get_typing(const Tox_Event_Friend_Typing *friend_typing) +{ + assert(friend_typing != nullptr); + return friend_typing->typing; +} + + +/***************************************************** + * + * :: add/clear/get + * + *****************************************************/ + + +static Tox_Event_Friend_Typing *tox_events_add_friend_typing(Tox_Events *events) +{ + 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)); + + if (new_friend_typing == nullptr) { + return nullptr; + } + + events->friend_typing = new_friend_typing; + events->friend_typing_capacity = new_friend_typing_capacity; + } + + 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) +{ + if (events == nullptr) { + return; + } + + 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; +} + +uint32_t tox_events_get_friend_typing_size(const Tox_Events *events) +{ + return events->friend_typing_size; +} + +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]; +} + + +/***************************************************** + * + * :: event handler + * + *****************************************************/ + + +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); + + Tox_Event_Friend_Typing *friend_typing = tox_events_add_friend_typing(state->events); + + if (friend_typing == nullptr) { + state->error = TOX_ERR_EVENTS_ITERATE_MALLOC; + return; + } + + tox_event_friend_typing_set_friend_number(friend_typing, friend_number); + tox_event_friend_typing_set_typing(friend_typing, typing); +} diff --git a/toxcore/events/self_connection_status.c b/toxcore/events/self_connection_status.c new file mode 100644 index 00000000..89a303ad --- /dev/null +++ b/toxcore/events/self_connection_status.c @@ -0,0 +1,134 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2022 The TokTok team. + */ + +#include "events_alloc.h" + +#include +#include +#include + +#include "../ccompat.h" +#include "../tox.h" +#include "../tox_events.h" + + +/***************************************************** + * + * :: struct and accessors + * + *****************************************************/ + + +struct Tox_Event_Self_Connection_Status { + Tox_Connection connection_status; +}; + +static void tox_event_self_connection_status_construct(Tox_Event_Self_Connection_Status *self_connection_status) +{ + *self_connection_status = (Tox_Event_Self_Connection_Status) { + TOX_CONNECTION_NONE + }; +} +static void tox_event_self_connection_status_destruct(Tox_Event_Self_Connection_Status *self_connection_status) +{ + return; +} + +static void tox_event_self_connection_status_set_connection_status(Tox_Event_Self_Connection_Status + *self_connection_status, Tox_Connection connection_status) +{ + assert(self_connection_status != nullptr); + self_connection_status->connection_status = connection_status; +} +Tox_Connection tox_event_self_connection_status_get_connection_status(const Tox_Event_Self_Connection_Status + *self_connection_status) +{ + assert(self_connection_status != nullptr); + return self_connection_status->connection_status; +} + + +/***************************************************** + * + * :: add/clear/get + * + *****************************************************/ + + +static Tox_Event_Self_Connection_Status *tox_events_add_self_connection_status(Tox_Events *events) +{ + 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)); + + if (new_self_connection_status == nullptr) { + return nullptr; + } + + events->self_connection_status = new_self_connection_status; + events->self_connection_status_capacity = new_self_connection_status_capacity; + } + + 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) +{ + if (events == nullptr) { + return; + } + + 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; +} + +uint32_t tox_events_get_self_connection_status_size(const Tox_Events *events) +{ + return events->self_connection_status_size; +} + +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]; +} + + +/***************************************************** + * + * :: event handler + * + *****************************************************/ + + +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); + + Tox_Event_Self_Connection_Status *self_connection_status = tox_events_add_self_connection_status(state->events); + + if (self_connection_status == nullptr) { + state->error = TOX_ERR_EVENTS_ITERATE_MALLOC; + return; + } + + tox_event_self_connection_status_set_connection_status(self_connection_status, connection_status); +} diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 77ba2294..99bec89f 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -669,14 +669,14 @@ static int send_packet_to(Net_Crypto *c, int crypt_connection_id, const uint8_t return -1; } - int direct_send_attempt = 0; + bool direct_send_attempt = false; pthread_mutex_lock(conn->mutex); 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)) { - bool direct_connected = 0; + bool direct_connected = false; // FIXME(sudden6): handle return value crypto_connection_status(c, crypt_connection_id, &direct_connected, nullptr); @@ -688,6 +688,7 @@ static int send_packet_to(Net_Crypto *c, int crypt_connection_id, const uint8_t } pthread_mutex_unlock(conn->mutex); + LOGGER_WARNING(c->log, "sending packet of length %d failed", length); return -1; } @@ -697,7 +698,7 @@ static int send_packet_to(Net_Crypto *c, int crypt_connection_id, const uint8_t if ((((UDP_DIRECT_TIMEOUT / 2) + conn->direct_send_attempt_time) < current_time && length < 96) || data[0] == NET_PACKET_COOKIE_REQUEST || data[0] == NET_PACKET_CRYPTO_HS) { if ((uint32_t)sendpacket(dht_get_net(c->dht), &ip_port, data, length) == length) { - direct_send_attempt = 1; + direct_send_attempt = true; conn->direct_send_attempt_time = mono_time_get(c->mono_time); } } @@ -705,7 +706,7 @@ static int send_packet_to(Net_Crypto *c, int crypt_connection_id, const uint8_t pthread_mutex_unlock(conn->mutex); pthread_mutex_lock(&c->tcp_mutex); - int ret = send_packet_tcp_connection(c->tcp_c, conn->connection_number_tcp, data, length); + const int ret = send_packet_tcp_connection(c->tcp_c, conn->connection_number_tcp, data, length); pthread_mutex_unlock(&c->tcp_mutex); pthread_mutex_lock(conn->mutex); @@ -716,11 +717,11 @@ static int send_packet_to(Net_Crypto *c, int crypt_connection_id, const uint8_t pthread_mutex_unlock(conn->mutex); - if (ret == 0 || direct_send_attempt) { + if (direct_send_attempt) { return 0; } - return -1; + return ret; } /*** START: Array Related functions */ @@ -1052,22 +1053,26 @@ static int send_data_packet(Net_Crypto *c, int crypt_connection_id, const uint8_ const uint16_t max_length = MAX_CRYPTO_PACKET_SIZE - (1 + sizeof(uint16_t) + CRYPTO_MAC_SIZE); if (length == 0 || length > max_length) { + LOGGER_WARNING(c->log, "zero-length or too large data packet: %d (max: %d)", length, max_length); return -1; } Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); if (conn == nullptr) { + LOGGER_WARNING(c->log, "connection id %d not found", crypt_connection_id); return -1; } pthread_mutex_lock(conn->mutex); - VLA(uint8_t, packet, 1 + sizeof(uint16_t) + length + CRYPTO_MAC_SIZE); + const uint16_t packet_size = 1 + sizeof(uint16_t) + length + CRYPTO_MAC_SIZE; + VLA(uint8_t, packet, packet_size); packet[0] = NET_PACKET_CRYPTO_DATA; memcpy(packet + 1, conn->sent_nonce + (CRYPTO_NONCE_SIZE - sizeof(uint16_t)), sizeof(uint16_t)); const int len = encrypt_data_symmetric(conn->shared_key, conn->sent_nonce, data, length, packet + 1 + sizeof(uint16_t)); - if (len + 1 + sizeof(uint16_t) != SIZEOF_VLA(packet)) { + if (len + 1 + sizeof(uint16_t) != packet_size) { + LOGGER_WARNING(c->log, "encryption failed: %d", len); pthread_mutex_unlock(conn->mutex); return -1; } @@ -1087,6 +1092,7 @@ static int send_data_packet_helper(Net_Crypto *c, int crypt_connection_id, uint3 const uint8_t *data, uint16_t length) { if (length == 0 || length > MAX_CRYPTO_DATA_SIZE) { + LOGGER_WARNING(c->log, "zero-length or too large data packet: %d (max: %d)", length, MAX_CRYPTO_PACKET_SIZE); return -1; } @@ -1161,7 +1167,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); - int64_t packet_num = add_data_end_of_buffer(&conn->send_array, &dt); + const int64_t packet_num = add_data_end_of_buffer(&conn->send_array, &dt); pthread_mutex_unlock(conn->mutex); if (packet_num == -1) { @@ -1180,7 +1186,7 @@ static int64_t send_lossless_packet(Net_Crypto *c, int crypt_connection_id, cons } } else { conn->maximum_speed_reached = 1; - LOGGER_DEBUG(c->log, "send_data_packet failed"); + LOGGER_DEBUG(c->log, "send_data_packet failed (packet_num = %ld)", (long)packet_num); } return packet_num; diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h index 9a3bd1e2..235ab738 100644 --- a/toxcore/net_crypto.h +++ b/toxcore/net_crypto.h @@ -20,7 +20,7 @@ /*** Ranges. */ -/** Packets in this range are reserved for net_crypto internal use. */ +/** Packets in this range are reserved for net_crypto events_alloc use. */ #define PACKET_ID_RANGE_RESERVED_START 0 #define PACKET_ID_RANGE_RESERVED_END 15 /** Packets in this range are reserved for Messenger use. */ diff --git a/toxcore/tox.h b/toxcore/tox.h index 38ec9f4b..919b39ea 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -465,12 +465,12 @@ typedef enum Tox_Log_Level { TOX_LOG_LEVEL_INFO, /** - * Warnings about internal inconsistency or logic errors. + * Warnings about events_alloc inconsistency or logic errors. */ TOX_LOG_LEVEL_WARNING, /** - * Severe unexpected errors caused by external or internal inconsistency. + * Severe unexpected errors caused by external or events_alloc inconsistency. */ TOX_LOG_LEVEL_ERROR, @@ -478,7 +478,7 @@ typedef enum Tox_Log_Level { /** - * @brief This event is triggered when the toxcore library logs an internal message. + * @brief This event is triggered when the toxcore library logs an events_alloc message. * * This is mostly useful for debugging. This callback can be called from any * function, not just tox_iterate. This means the user data lifetime must at @@ -800,7 +800,7 @@ typedef enum Tox_Err_New { TOX_ERR_NEW_NULL, /** - * The function was unable to allocate enough memory to store the internal + * The function was unable to allocate enough memory to store the events_alloc * structures for the Tox object. */ TOX_ERR_NEW_MALLOC, @@ -1845,7 +1845,7 @@ void tox_callback_friend_message(Tox *tox, tox_friend_message_cb *callback); * If hash is NULL or data is NULL while length is not 0 the function returns false, * otherwise it returns true. * - * This function is a wrapper to internal message-digest functions. + * This function is a wrapper to events_alloc message-digest functions. * * @param hash A valid memory location the hash data. It must be at least * TOX_HASH_LENGTH bytes in size. diff --git a/toxcore/tox_dispatch.c b/toxcore/tox_dispatch.c new file mode 100644 index 00000000..7dfae3dc --- /dev/null +++ b/toxcore/tox_dispatch.c @@ -0,0 +1,460 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2022 The TokTok team. + */ + +#include "tox_dispatch.h" + +#include + +#include "ccompat.h" + +struct Tox_Dispatch { + tox_events_conference_connected_cb *conference_connected_callback; + tox_events_conference_invite_cb *conference_invite_callback; + tox_events_conference_message_cb *conference_message_callback; + tox_events_conference_peer_list_changed_cb *conference_peer_list_changed_callback; + tox_events_conference_peer_name_cb *conference_peer_name_callback; + tox_events_conference_title_cb *conference_title_callback; + tox_events_file_chunk_request_cb *file_chunk_request_callback; + tox_events_file_recv_cb *file_recv_callback; + tox_events_file_recv_chunk_cb *file_recv_chunk_callback; + tox_events_file_recv_control_cb *file_recv_control_callback; + tox_events_friend_connection_status_cb *friend_connection_status_callback; + tox_events_friend_lossless_packet_cb *friend_lossless_packet_callback; + tox_events_friend_lossy_packet_cb *friend_lossy_packet_callback; + tox_events_friend_message_cb *friend_message_callback; + tox_events_friend_name_cb *friend_name_callback; + tox_events_friend_read_receipt_cb *friend_read_receipt_callback; + tox_events_friend_request_cb *friend_request_callback; + tox_events_friend_status_cb *friend_status_callback; + 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_Dispatch *tox_dispatch_new(Tox_Err_Dispatch_New *error) +{ + Tox_Dispatch *dispatch = (Tox_Dispatch *)calloc(1, sizeof(Tox_Dispatch)); + + if (dispatch == nullptr) { + if (error != nullptr) { + *error = TOX_ERR_DISPATCH_NEW_MALLOC; + } + + return nullptr; + } + + *dispatch = (Tox_Dispatch) { + nullptr + }; + return dispatch; +} + +void tox_dispatch_free(Tox_Dispatch *dispatch) +{ + free(dispatch); +} + +void tox_events_callback_conference_connected( + Tox_Dispatch *dispatch, tox_events_conference_connected_cb *callback) +{ + dispatch->conference_connected_callback = callback; +} +void tox_events_callback_conference_invite( + Tox_Dispatch *dispatch, tox_events_conference_invite_cb *callback) +{ + dispatch->conference_invite_callback = callback; +} +void tox_events_callback_conference_message( + Tox_Dispatch *dispatch, tox_events_conference_message_cb *callback) +{ + dispatch->conference_message_callback = callback; +} +void tox_events_callback_conference_peer_list_changed( + Tox_Dispatch *dispatch, tox_events_conference_peer_list_changed_cb *callback) +{ + dispatch->conference_peer_list_changed_callback = callback; +} +void tox_events_callback_conference_peer_name( + Tox_Dispatch *dispatch, tox_events_conference_peer_name_cb *callback) +{ + dispatch->conference_peer_name_callback = callback; +} +void tox_events_callback_conference_title( + Tox_Dispatch *dispatch, tox_events_conference_title_cb *callback) +{ + dispatch->conference_title_callback = callback; +} +void tox_events_callback_file_chunk_request( + Tox_Dispatch *dispatch, tox_events_file_chunk_request_cb *callback) +{ + dispatch->file_chunk_request_callback = callback; +} +void tox_events_callback_file_recv( + Tox_Dispatch *dispatch, tox_events_file_recv_cb *callback) +{ + dispatch->file_recv_callback = callback; +} +void tox_events_callback_file_recv_chunk( + Tox_Dispatch *dispatch, tox_events_file_recv_chunk_cb *callback) +{ + dispatch->file_recv_chunk_callback = callback; +} +void tox_events_callback_file_recv_control( + Tox_Dispatch *dispatch, tox_events_file_recv_control_cb *callback) +{ + dispatch->file_recv_control_callback = callback; +} +void tox_events_callback_friend_connection_status( + Tox_Dispatch *dispatch, tox_events_friend_connection_status_cb *callback) +{ + dispatch->friend_connection_status_callback = callback; +} +void tox_events_callback_friend_lossless_packet( + Tox_Dispatch *dispatch, tox_events_friend_lossless_packet_cb *callback) +{ + dispatch->friend_lossless_packet_callback = callback; +} +void tox_events_callback_friend_lossy_packet( + Tox_Dispatch *dispatch, tox_events_friend_lossy_packet_cb *callback) +{ + dispatch->friend_lossy_packet_callback = callback; +} +void tox_events_callback_friend_message( + Tox_Dispatch *dispatch, tox_events_friend_message_cb *callback) +{ + dispatch->friend_message_callback = callback; +} +void tox_events_callback_friend_name( + Tox_Dispatch *dispatch, tox_events_friend_name_cb *callback) +{ + dispatch->friend_name_callback = callback; +} +void tox_events_callback_friend_read_receipt( + Tox_Dispatch *dispatch, tox_events_friend_read_receipt_cb *callback) +{ + dispatch->friend_read_receipt_callback = callback; +} +void tox_events_callback_friend_request( + Tox_Dispatch *dispatch, tox_events_friend_request_cb *callback) +{ + dispatch->friend_request_callback = callback; +} +void tox_events_callback_friend_status( + Tox_Dispatch *dispatch, tox_events_friend_status_cb *callback) +{ + dispatch->friend_status_callback = callback; +} +void tox_events_callback_friend_status_message( + Tox_Dispatch *dispatch, tox_events_friend_status_message_cb *callback) +{ + dispatch->friend_status_message_callback = callback; +} +void tox_events_callback_friend_typing( + Tox_Dispatch *dispatch, tox_events_friend_typing_cb *callback) +{ + dispatch->friend_typing_callback = callback; +} +void tox_events_callback_self_connection_status( + Tox_Dispatch *dispatch, tox_events_self_connection_status_cb *callback) +{ + dispatch->self_connection_status_callback = callback; +} + +static void tox_dispatch_invoke_conference_connected( + const Tox_Dispatch *dispatch, const Tox_Events *events, Tox *tox, void *user_data) +{ + const uint32_t size = tox_events_get_conference_connected_size(events); + + 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); + } + } +} + +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); + + 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); + } + } +} + +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); + + 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); + } + } +} + +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); + + 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); + } + } +} + +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); + + 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); + } + } +} + +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); + + 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); + } + } +} + +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); + + 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); + } + } +} + +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); + + 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); + } + } +} + +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); + + 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); + } + } +} + +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); + + 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); + } + } +} + +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); + + 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); + } + } +} + +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); + + 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); + } + } +} + +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); + + 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); + } + } +} + +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); + + 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); + } + } +} + +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); + + 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); + } + } +} + +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); + + 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); + } + } +} + +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); + + 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); + } + } +} + +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); + + 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); + } + } +} + +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); + + 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); + } + } +} + +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); + + 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); + } + } +} + +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); + + 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); + } + } +} + +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); +} diff --git a/toxcore/tox_dispatch.h b/toxcore/tox_dispatch.h new file mode 100644 index 00000000..7e8fbba3 --- /dev/null +++ b/toxcore/tox_dispatch.h @@ -0,0 +1,144 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2022 The TokTok team. + */ + +#ifndef C_TOXCORE_TOXCORE_TOX_DISPATCH_H +#define C_TOXCORE_TOXCORE_TOX_DISPATCH_H + +#include "tox_events.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief The events dispatch table. + * + * This holds all the callbacks registered with `tox_events_callback_*` + * functions below. + */ +typedef struct Tox_Dispatch Tox_Dispatch; + +typedef enum Tox_Err_Dispatch_New { + /** + * The function returned successfully. + */ + TOX_ERR_DISPATCH_NEW_OK, + + /** + * The function failed to allocate memory for the dispatch table. + */ + TOX_ERR_DISPATCH_NEW_MALLOC, +} Tox_Err_Dispatch_New; + +/** + * @brief Creates a new empty event dispatch table. + */ +Tox_Dispatch *tox_dispatch_new(Tox_Err_Dispatch_New *error); + +/** + * @brief Deallocate an event dispatch table. + */ +void tox_dispatch_free(Tox_Dispatch *dispatch); + +/** + * @brief Invoke registered callbacks for each of the events. + * + * @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); + +typedef void tox_events_conference_connected_cb( + Tox *tox, 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); +typedef void tox_events_conference_message_cb( + Tox *tox, 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); +typedef void tox_events_conference_peer_name_cb( + Tox *tox, 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); +typedef void tox_events_file_chunk_request_cb( + Tox *tox, 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); +typedef void tox_events_file_recv_chunk_cb( + Tox *tox, 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); +typedef void tox_events_friend_connection_status_cb( + Tox *tox, 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); +typedef void tox_events_friend_lossy_packet_cb( + Tox *tox, 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); +typedef void tox_events_friend_name_cb( + Tox *tox, 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); +typedef void tox_events_friend_request_cb( + Tox *tox, 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); +typedef void tox_events_friend_status_message_cb( + Tox *tox, 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); +typedef void tox_events_self_connection_status_cb( + Tox *tox, const Tox_Event_Self_Connection_Status *event, void *user_data); + +void tox_events_callback_conference_connected( + Tox_Dispatch *dispatch, tox_events_conference_connected_cb *callback); +void tox_events_callback_conference_invite( + Tox_Dispatch *dispatch, tox_events_conference_invite_cb *callback); +void tox_events_callback_conference_message( + Tox_Dispatch *dispatch, tox_events_conference_message_cb *callback); +void tox_events_callback_conference_peer_list_changed( + Tox_Dispatch *dispatch, tox_events_conference_peer_list_changed_cb *callback); +void tox_events_callback_conference_peer_name( + Tox_Dispatch *dispatch, tox_events_conference_peer_name_cb *callback); +void tox_events_callback_conference_title( + Tox_Dispatch *dispatch, tox_events_conference_title_cb *callback); +void tox_events_callback_file_chunk_request( + Tox_Dispatch *dispatch, tox_events_file_chunk_request_cb *callback); +void tox_events_callback_file_recv( + Tox_Dispatch *dispatch, tox_events_file_recv_cb *callback); +void tox_events_callback_file_recv_chunk( + Tox_Dispatch *dispatch, tox_events_file_recv_chunk_cb *callback); +void tox_events_callback_file_recv_control( + Tox_Dispatch *dispatch, tox_events_file_recv_control_cb *callback); +void tox_events_callback_friend_connection_status( + Tox_Dispatch *dispatch, tox_events_friend_connection_status_cb *callback); +void tox_events_callback_friend_lossless_packet( + Tox_Dispatch *dispatch, tox_events_friend_lossless_packet_cb *callback); +void tox_events_callback_friend_lossy_packet( + Tox_Dispatch *dispatch, tox_events_friend_lossy_packet_cb *callback); +void tox_events_callback_friend_message( + Tox_Dispatch *dispatch, tox_events_friend_message_cb *callback); +void tox_events_callback_friend_name( + Tox_Dispatch *dispatch, tox_events_friend_name_cb *callback); +void tox_events_callback_friend_read_receipt( + Tox_Dispatch *dispatch, tox_events_friend_read_receipt_cb *callback); +void tox_events_callback_friend_request( + Tox_Dispatch *dispatch, tox_events_friend_request_cb *callback); +void tox_events_callback_friend_status( + Tox_Dispatch *dispatch, tox_events_friend_status_cb *callback); +void tox_events_callback_friend_status_message( + Tox_Dispatch *dispatch, tox_events_friend_status_message_cb *callback); +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); + +#ifdef __cplusplus +} +#endif + +#endif // C_TOXCORE_TOXCORE_TOX_DISPATCH_H diff --git a/toxcore/tox_events.c b/toxcore/tox_events.c new file mode 100644 index 00000000..703aaf5e --- /dev/null +++ b/toxcore/tox_events.c @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2022 The TokTok team. + */ + +#include "tox_events.h" + +#include +#include + +#include "ccompat.h" +#include "events/events_alloc.h" +#include "tox.h" + + +/***************************************************** + * + * :: Set up event handlers. + * + *****************************************************/ + + +void tox_events_init(Tox *tox) +{ + tox_callback_conference_connected(tox, tox_events_handle_conference_connected); + tox_callback_conference_invite(tox, tox_events_handle_conference_invite); + tox_callback_conference_message(tox, tox_events_handle_conference_message); + tox_callback_conference_peer_list_changed(tox, tox_events_handle_conference_peer_list_changed); + tox_callback_conference_peer_name(tox, tox_events_handle_conference_peer_name); + tox_callback_conference_title(tox, tox_events_handle_conference_title); + tox_callback_file_chunk_request(tox, tox_events_handle_file_chunk_request); + tox_callback_file_recv_chunk(tox, tox_events_handle_file_recv_chunk); + tox_callback_file_recv_control(tox, tox_events_handle_file_recv_control); + tox_callback_file_recv(tox, tox_events_handle_file_recv); + tox_callback_friend_connection_status(tox, tox_events_handle_friend_connection_status); + tox_callback_friend_lossless_packet(tox, tox_events_handle_friend_lossless_packet); + tox_callback_friend_lossy_packet(tox, tox_events_handle_friend_lossy_packet); + tox_callback_friend_message(tox, tox_events_handle_friend_message); + tox_callback_friend_name(tox, tox_events_handle_friend_name); + tox_callback_friend_read_receipt(tox, tox_events_handle_friend_read_receipt); + tox_callback_friend_request(tox, tox_events_handle_friend_request); + tox_callback_friend_status_message(tox, tox_events_handle_friend_status_message); + 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_Events *tox_events_iterate(Tox *tox, Tox_Err_Events_Iterate *error) +{ + Tox_Events_State state = {TOX_ERR_EVENTS_ITERATE_OK}; + tox_iterate(tox, &state); + + if (error != nullptr) { + *error = state.error; + } + + return state.events; +} diff --git a/toxcore/tox_events.h b/toxcore/tox_events.h new file mode 100644 index 00000000..2d65e612 --- /dev/null +++ b/toxcore/tox_events.h @@ -0,0 +1,313 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2022 The TokTok team. + */ + +#ifndef C_TOXCORE_TOXCORE_TOX_EVENTS_H +#define C_TOXCORE_TOXCORE_TOX_EVENTS_H + +#include "tox.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct Tox_Event_Conference_Connected Tox_Event_Conference_Connected; +uint32_t tox_event_conference_connected_get_conference_number( + const Tox_Event_Conference_Connected *conference_connected); + +typedef struct Tox_Event_Conference_Invite Tox_Event_Conference_Invite; +const uint8_t *tox_event_conference_invite_get_cookie( + const Tox_Event_Conference_Invite *conference_invite); +size_t tox_event_conference_invite_get_cookie_length( + const Tox_Event_Conference_Invite *conference_invite); +Tox_Conference_Type tox_event_conference_invite_get_type( + const Tox_Event_Conference_Invite *conference_invite); +uint32_t tox_event_conference_invite_get_friend_number( + const Tox_Event_Conference_Invite *conference_invite); + +typedef struct Tox_Event_Conference_Message Tox_Event_Conference_Message; +const uint8_t *tox_event_conference_message_get_message( + const Tox_Event_Conference_Message *conference_message); +size_t tox_event_conference_message_get_message_length( + const Tox_Event_Conference_Message *conference_message); +Tox_Message_Type tox_event_conference_message_get_type( + const Tox_Event_Conference_Message *conference_message); +uint32_t tox_event_conference_message_get_conference_number( + const Tox_Event_Conference_Message *conference_message); +uint32_t tox_event_conference_message_get_peer_number( + const Tox_Event_Conference_Message *conference_message); + +typedef struct Tox_Event_Conference_Peer_List_Changed Tox_Event_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); + +typedef struct Tox_Event_Conference_Peer_Name Tox_Event_Conference_Peer_Name; +const uint8_t *tox_event_conference_peer_name_get_name( + const Tox_Event_Conference_Peer_Name *conference_peer_name); +size_t tox_event_conference_peer_name_get_name_length( + 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); +uint32_t tox_event_conference_peer_name_get_peer_number( + const Tox_Event_Conference_Peer_Name *conference_peer_name); + +typedef struct Tox_Event_Conference_Title Tox_Event_Conference_Title; +const uint8_t *tox_event_conference_title_get_title( + const Tox_Event_Conference_Title *conference_title); +size_t tox_event_conference_title_get_title_length( + const Tox_Event_Conference_Title *conference_title); +uint32_t tox_event_conference_title_get_conference_number( + const Tox_Event_Conference_Title *conference_title); +uint32_t tox_event_conference_title_get_peer_number( + const Tox_Event_Conference_Title *conference_title); + +typedef struct Tox_Event_File_Chunk_Request Tox_Event_File_Chunk_Request; +size_t tox_event_file_chunk_request_get_length( + const Tox_Event_File_Chunk_Request *file_chunk_request); +uint32_t tox_event_file_chunk_request_get_file_number( + const Tox_Event_File_Chunk_Request *file_chunk_request); +uint32_t tox_event_file_chunk_request_get_friend_number( + const Tox_Event_File_Chunk_Request *file_chunk_request); +uint64_t tox_event_file_chunk_request_get_position( + const Tox_Event_File_Chunk_Request *file_chunk_request); + +typedef struct Tox_Event_File_Recv Tox_Event_File_Recv; +const uint8_t *tox_event_file_recv_get_filename( + const Tox_Event_File_Recv *file_recv); +size_t tox_event_file_recv_get_filename_length( + const Tox_Event_File_Recv *file_recv); +uint32_t tox_event_file_recv_get_file_number( + const Tox_Event_File_Recv *file_recv); +uint32_t tox_event_file_recv_get_file_size( + const Tox_Event_File_Recv *file_recv); +uint32_t tox_event_file_recv_get_friend_number( + const Tox_Event_File_Recv *file_recv); +uint32_t tox_event_file_recv_get_kind( + const Tox_Event_File_Recv *file_recv); + +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); +size_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_file_number( + const Tox_Event_File_Recv_Chunk *file_recv_chunk); +uint32_t tox_event_file_recv_chunk_get_friend_number( + const Tox_Event_File_Recv_Chunk *file_recv_chunk); +uint32_t tox_event_file_recv_chunk_get_position( + const Tox_Event_File_Recv_Chunk *file_recv_chunk); + +typedef struct Tox_Event_File_Recv_Control Tox_Event_File_Recv_Control; +Tox_File_Control tox_event_file_recv_control_get_control( + const Tox_Event_File_Recv_Control *file_recv_control); +uint32_t tox_event_file_recv_control_get_file_number( + const Tox_Event_File_Recv_Control *file_recv_control); +uint32_t tox_event_file_recv_control_get_friend_number( + const Tox_Event_File_Recv_Control *file_recv_control); + +typedef struct Tox_Event_Friend_Connection_Status Tox_Event_Friend_Connection_Status; +Tox_Connection tox_event_friend_connection_status_get_connection_status( + 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); + +typedef struct Tox_Event_Friend_Lossless_Packet Tox_Event_Friend_Lossless_Packet; +const uint8_t *tox_event_friend_lossless_packet_get_data( + const Tox_Event_Friend_Lossless_Packet *friend_lossless_packet); +size_t tox_event_friend_lossless_packet_get_data_length( + 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); + +typedef struct Tox_Event_Friend_Lossy_Packet Tox_Event_Friend_Lossy_Packet; +const uint8_t *tox_event_friend_lossy_packet_get_data( + const Tox_Event_Friend_Lossy_Packet *friend_lossy_packet); +size_t tox_event_friend_lossy_packet_get_data_length( + const Tox_Event_Friend_Lossy_Packet *friend_lossy_packet); +uint32_t tox_event_friend_lossy_packet_get_friend_number( + const Tox_Event_Friend_Lossy_Packet *friend_lossy_packet); + +typedef struct Tox_Event_Friend_Message Tox_Event_Friend_Message; +uint32_t tox_event_friend_message_get_friend_number( + const Tox_Event_Friend_Message *friend_message); +Tox_Message_Type tox_event_friend_message_get_type( + const Tox_Event_Friend_Message *friend_message); +size_t tox_event_friend_message_get_message_length( + const Tox_Event_Friend_Message *friend_message); +const uint8_t *tox_event_friend_message_get_message( + const Tox_Event_Friend_Message *friend_message); + +typedef struct Tox_Event_Friend_Name Tox_Event_Friend_Name; +const uint8_t *tox_event_friend_name_get_name( + const Tox_Event_Friend_Name *friend_name); +size_t tox_event_friend_name_get_name_length( + const Tox_Event_Friend_Name *friend_name); +uint32_t tox_event_friend_name_get_friend_number( + const Tox_Event_Friend_Name *friend_name); + +typedef struct Tox_Event_Friend_Read_Receipt Tox_Event_Friend_Read_Receipt; +uint32_t tox_event_friend_read_receipt_get_friend_number( + const Tox_Event_Friend_Read_Receipt *friend_read_receipt); +uint32_t tox_event_friend_read_receipt_get_message_id( + const Tox_Event_Friend_Read_Receipt *friend_read_receipt); + +typedef struct Tox_Event_Friend_Request Tox_Event_Friend_Request; +const uint8_t *tox_event_friend_request_get_message( + const Tox_Event_Friend_Request *friend_request); +const uint8_t *tox_event_friend_request_get_public_key( + const Tox_Event_Friend_Request *friend_request); +size_t tox_event_friend_request_get_message_length( + const Tox_Event_Friend_Request *friend_request); + +typedef struct Tox_Event_Friend_Status Tox_Event_Friend_Status; +Tox_User_Status tox_event_friend_status_get_connection_status( + const Tox_Event_Friend_Status *friend_status); +uint32_t tox_event_friend_status_get_friend_number( + const Tox_Event_Friend_Status *friend_status); + +typedef struct Tox_Event_Friend_Status_Message Tox_Event_Friend_Status_Message; +const uint8_t *tox_event_friend_status_message_get_status_message( + const Tox_Event_Friend_Status_Message *friend_status_message); +size_t tox_event_friend_status_message_get_status_message_length( + const Tox_Event_Friend_Status_Message *friend_status_message); +uint32_t tox_event_friend_status_message_get_friend_number( + const Tox_Event_Friend_Status_Message *friend_status_message); + +typedef struct Tox_Event_Friend_Typing Tox_Event_Friend_Typing; +bool tox_event_friend_typing_get_typing( + const Tox_Event_Friend_Typing *friend_typing); +uint32_t tox_event_friend_typing_get_friend_number( + const Tox_Event_Friend_Typing *friend_typing); + +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); + + +/** + * Container object for all Tox core events. + * + * This is an immutable object once created. + */ +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); + +/** + * Initialise the events recording system. + * + * All callbacks will be set to handlers inside the events recording system. + * After this function returns, no user-defined event handlers will be + * invoked. If the client sets their own handlers after calling this function, + * the events associated with that handler will not be recorded. + */ +void tox_events_init(Tox *tox); + +typedef enum Tox_Err_Events_Iterate { + /** + * The function returned successfully. + */ + TOX_ERR_EVENTS_ITERATE_OK, + + /** + * The function failed to allocate enough memory to store the events. + * + * Some events may still be stored if the return value is NULL. The events + * object will always be valid (or NULL) but if this error code is set, + * the function may have missed some events. + */ + TOX_ERR_EVENTS_ITERATE_MALLOC, +} Tox_Err_Events_Iterate; + +/** + * Run a single `tox_iterate` iteration and record all the events. + * + * If allocation of the top level events object fails, this returns NULL. + * Otherwise it returns an object with the recorded events in it. If an + * allocation fails while recording events, some events may be dropped. + * + * The result must be freed using `tox_events_free`. + * + * @param tox The Tox instance to iterate on. + * @param error An error code. Will be set to OK on success. + * + * @returns the recorded events structure. + */ +Tox_Events *tox_events_iterate(Tox *tox, Tox_Err_Events_Iterate *error); + +/** + * Frees all memory associated with the events structure. + * + * All pointers into this object and its sub-objects, including byte buffers, + * will be invalid once this function returns. + */ +void tox_events_free(Tox_Events *events); + +#ifdef __cplusplus +} +#endif + +#endif // C_TOXCORE_TOXCORE_TOX_EVENTS_H