summaryrefslogtreecommitdiff
path: root/protocols/Tox/libtox/src/toxcore/events
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2022-07-24 16:44:24 +0300
committerGeorge Hazan <ghazan@miranda.im>2022-07-24 16:44:24 +0300
commite55d071e5485a937efd427d159b76c208cccdcce (patch)
tree48d09dc5cf1df2581fd6471b5ccf1560015fa3a4 /protocols/Tox/libtox/src/toxcore/events
parentf36629f67153bc500c828cf51de31988122a1024 (diff)
fixes #3118 (Update toxcore to 0.2.18)
Diffstat (limited to 'protocols/Tox/libtox/src/toxcore/events')
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/conference_connected.c190
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/conference_invite.c249
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/conference_message.c266
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/conference_peer_list_changed.c195
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/conference_peer_name.c250
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/conference_title.c248
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/events_alloc.c64
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/events_alloc.h216
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/file_chunk_request.c243
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/file_recv.c282
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/file_recv_chunk.c265
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/file_recv_control.c228
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/friend_connection_status.c215
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/friend_lossless_packet.c233
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/friend_lossy_packet.c232
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/friend_message.c248
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/friend_name.c231
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/friend_read_receipt.c210
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/friend_request.c232
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/friend_status.c211
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/friend_status_message.c234
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/friend_typing.c208
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/self_connection_status.c190
23 files changed, 5140 insertions, 0 deletions
diff --git a/protocols/Tox/libtox/src/toxcore/events/conference_connected.c b/protocols/Tox/libtox/src/toxcore/events/conference_connected.c
new file mode 100644
index 0000000000..ce278755e1
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/events/conference_connected.c
@@ -0,0 +1,190 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2022 The TokTok team.
+ */
+
+#include "events_alloc.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../bin_pack.h"
+#include "../bin_unpack.h"
+#include "../ccompat.h"
+#include "../tox.h"
+#include "../tox_events.h"
+
+
+/*****************************************************
+ *
+ * :: struct and accessors
+ *
+ *****************************************************/
+
+
+struct Tox_Event_Conference_Connected {
+ uint32_t conference_number;
+};
+
+non_null()
+static void tox_event_conference_connected_construct(Tox_Event_Conference_Connected *conference_connected)
+{
+ *conference_connected = (Tox_Event_Conference_Connected) {
+ 0
+ };
+}
+non_null()
+static void tox_event_conference_connected_destruct(Tox_Event_Conference_Connected *conference_connected)
+{
+ return;
+}
+
+non_null()
+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;
+}
+
+non_null()
+static bool tox_event_conference_connected_pack(
+ const Tox_Event_Conference_Connected *event, Bin_Pack *bp)
+{
+ assert(event != nullptr);
+ return bin_pack_array(bp, 2)
+ && bin_pack_u32(bp, TOX_EVENT_CONFERENCE_CONNECTED)
+ && bin_pack_u32(bp, event->conference_number);
+}
+
+non_null()
+static bool tox_event_conference_connected_unpack(
+ Tox_Event_Conference_Connected *event, Bin_Unpack *bu)
+{
+ assert(event != nullptr);
+ return bin_unpack_u32(bu, &event->conference_number);
+}
+
+
+/*****************************************************
+ *
+ * :: add/clear/get
+ *
+ *****************************************************/
+
+
+non_null()
+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)
+{
+ if (events == nullptr) {
+ return 0;
+ }
+
+ 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];
+}
+
+bool tox_events_pack_conference_connected(const Tox_Events *events, Bin_Pack *bp)
+{
+ const uint32_t size = tox_events_get_conference_connected_size(events);
+
+ for (uint32_t i = 0; i < size; ++i) {
+ if (!tox_event_conference_connected_pack(tox_events_get_conference_connected(events, i), bp)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool tox_events_unpack_conference_connected(Tox_Events *events, Bin_Unpack *bu)
+{
+ Tox_Event_Conference_Connected *event = tox_events_add_conference_connected(events);
+
+ if (event == nullptr) {
+ return false;
+ }
+
+ return tox_event_conference_connected_unpack(event, bu);
+}
+
+
+
+/*****************************************************
+ *
+ * :: 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);
+
+ if (state->events == nullptr) {
+ return;
+ }
+
+ 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/protocols/Tox/libtox/src/toxcore/events/conference_invite.c b/protocols/Tox/libtox/src/toxcore/events/conference_invite.c
new file mode 100644
index 0000000000..1d88f41d76
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/events/conference_invite.c
@@ -0,0 +1,249 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2022 The TokTok team.
+ */
+
+#include "events_alloc.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../bin_pack.h"
+#include "../bin_unpack.h"
+#include "../ccompat.h"
+#include "../tox.h"
+#include "../tox_events.h"
+#include "../tox_unpack.h"
+
+
+/*****************************************************
+ *
+ * :: struct and accessors
+ *
+ *****************************************************/
+
+
+struct Tox_Event_Conference_Invite {
+ uint32_t friend_number;
+ Tox_Conference_Type type;
+ uint8_t *cookie;
+ uint32_t cookie_length;
+};
+
+non_null()
+static void tox_event_conference_invite_construct(Tox_Event_Conference_Invite *conference_invite)
+{
+ *conference_invite = (Tox_Event_Conference_Invite) {
+ 0
+ };
+}
+non_null()
+static void tox_event_conference_invite_destruct(Tox_Event_Conference_Invite *conference_invite)
+{
+ free(conference_invite->cookie);
+}
+
+non_null()
+static void tox_event_conference_invite_set_friend_number(Tox_Event_Conference_Invite *conference_invite,
+ uint32_t friend_number)
+{
+ 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;
+}
+
+non_null()
+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;
+}
+
+non_null()
+static bool tox_event_conference_invite_set_cookie(Tox_Event_Conference_Invite *conference_invite,
+ const uint8_t *cookie, uint32_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;
+}
+uint32_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;
+}
+
+non_null()
+static bool tox_event_conference_invite_pack(
+ const Tox_Event_Conference_Invite *event, Bin_Pack *bp)
+{
+ assert(event != nullptr);
+ return bin_pack_array(bp, 2)
+ && bin_pack_u32(bp, TOX_EVENT_CONFERENCE_INVITE)
+ && bin_pack_array(bp, 3)
+ && bin_pack_u32(bp, event->friend_number)
+ && bin_pack_u32(bp, event->type)
+ && bin_pack_bin(bp, event->cookie, event->cookie_length);
+}
+
+non_null()
+static bool tox_event_conference_invite_unpack(
+ Tox_Event_Conference_Invite *event, Bin_Unpack *bu)
+{
+ assert(event != nullptr);
+ if (!bin_unpack_array_fixed(bu, 3)) {
+ return false;
+ }
+
+ return bin_unpack_u32(bu, &event->friend_number)
+ && tox_unpack_conference_type(bu, &event->type)
+ && bin_unpack_bin(bu, &event->cookie, &event->cookie_length);
+}
+
+
+/*****************************************************
+ *
+ * :: add/clear/get
+ *
+ *****************************************************/
+
+
+non_null()
+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)
+{
+ if (events == nullptr) {
+ return 0;
+ }
+
+ 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];
+}
+
+bool tox_events_pack_conference_invite(const Tox_Events *events, Bin_Pack *bp)
+{
+ const uint32_t size = tox_events_get_conference_invite_size(events);
+
+ for (uint32_t i = 0; i < size; ++i) {
+ if (!tox_event_conference_invite_pack(tox_events_get_conference_invite(events, i), bp)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool tox_events_unpack_conference_invite(Tox_Events *events, Bin_Unpack *bu)
+{
+ Tox_Event_Conference_Invite *event = tox_events_add_conference_invite(events);
+
+ if (event == nullptr) {
+ return false;
+ }
+
+ return tox_event_conference_invite_unpack(event, bu);
+}
+
+
+/*****************************************************
+ *
+ * :: 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);
+
+ if (state->events == nullptr) {
+ return;
+ }
+
+ 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/protocols/Tox/libtox/src/toxcore/events/conference_message.c b/protocols/Tox/libtox/src/toxcore/events/conference_message.c
new file mode 100644
index 0000000000..bc9a19b738
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/events/conference_message.c
@@ -0,0 +1,266 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2022 The TokTok team.
+ */
+
+#include "events_alloc.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../bin_pack.h"
+#include "../bin_unpack.h"
+#include "../ccompat.h"
+#include "../tox.h"
+#include "../tox_events.h"
+#include "../tox_unpack.h"
+
+
+/*****************************************************
+ *
+ * :: struct and accessors
+ *
+ *****************************************************/
+
+
+struct Tox_Event_Conference_Message {
+ uint32_t conference_number;
+ uint32_t peer_number;
+ Tox_Message_Type type;
+ uint8_t *message;
+ uint32_t message_length;
+};
+
+non_null()
+static void tox_event_conference_message_construct(Tox_Event_Conference_Message *conference_message)
+{
+ *conference_message = (Tox_Event_Conference_Message) {
+ 0
+ };
+}
+non_null()
+static void tox_event_conference_message_destruct(Tox_Event_Conference_Message *conference_message)
+{
+ free(conference_message->message);
+}
+
+non_null()
+static void tox_event_conference_message_set_conference_number(Tox_Event_Conference_Message *conference_message,
+ uint32_t conference_number)
+{
+ 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;
+}
+
+non_null()
+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;
+}
+
+non_null()
+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;
+}
+
+non_null()
+static bool tox_event_conference_message_set_message(Tox_Event_Conference_Message *conference_message,
+ const uint8_t *message, uint32_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;
+}
+uint32_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;
+}
+
+non_null()
+static bool tox_event_conference_message_pack(
+ const Tox_Event_Conference_Message *event, Bin_Pack *bp)
+{
+ assert(event != nullptr);
+ return bin_pack_array(bp, 2)
+ && bin_pack_u32(bp, TOX_EVENT_CONFERENCE_MESSAGE)
+ && bin_pack_array(bp, 4)
+ && bin_pack_u32(bp, event->conference_number)
+ && bin_pack_u32(bp, event->peer_number)
+ && bin_pack_u32(bp, event->type)
+ && bin_pack_bin(bp, event->message, event->message_length);
+}
+
+non_null()
+static bool tox_event_conference_message_unpack(
+ Tox_Event_Conference_Message *event, Bin_Unpack *bu)
+{
+ assert(event != nullptr);
+ if (!bin_unpack_array_fixed(bu, 4)) {
+ return false;
+ }
+
+ return bin_unpack_u32(bu, &event->conference_number)
+ && bin_unpack_u32(bu, &event->peer_number)
+ && tox_unpack_message_type(bu, &event->type)
+ && bin_unpack_bin(bu, &event->message, &event->message_length);
+}
+
+
+/*****************************************************
+ *
+ * :: add/clear/get
+ *
+ *****************************************************/
+
+
+non_null()
+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)
+{
+ if (events == nullptr) {
+ return 0;
+ }
+
+ 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];
+}
+
+bool tox_events_pack_conference_message(const Tox_Events *events, Bin_Pack *bp)
+{
+ const uint32_t size = tox_events_get_conference_message_size(events);
+
+ for (uint32_t i = 0; i < size; ++i) {
+ if (!tox_event_conference_message_pack(tox_events_get_conference_message(events, i), bp)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool tox_events_unpack_conference_message(Tox_Events *events, Bin_Unpack *bu)
+{
+ Tox_Event_Conference_Message *event = tox_events_add_conference_message(events);
+
+ if (event == nullptr) {
+ return false;
+ }
+
+ return tox_event_conference_message_unpack(event, bu);
+}
+
+
+/*****************************************************
+ *
+ * :: 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);
+
+ if (state->events == nullptr) {
+ return;
+ }
+
+ 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/protocols/Tox/libtox/src/toxcore/events/conference_peer_list_changed.c b/protocols/Tox/libtox/src/toxcore/events/conference_peer_list_changed.c
new file mode 100644
index 0000000000..b6aaa3bf7a
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/events/conference_peer_list_changed.c
@@ -0,0 +1,195 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2022 The TokTok team.
+ */
+
+#include "events_alloc.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../bin_pack.h"
+#include "../bin_unpack.h"
+#include "../ccompat.h"
+#include "../tox.h"
+#include "../tox_events.h"
+
+
+/*****************************************************
+ *
+ * :: struct and accessors
+ *
+ *****************************************************/
+
+
+struct Tox_Event_Conference_Peer_List_Changed {
+ uint32_t conference_number;
+};
+
+non_null()
+static void tox_event_conference_peer_list_changed_construct(Tox_Event_Conference_Peer_List_Changed
+ *conference_peer_list_changed)
+{
+ *conference_peer_list_changed = (Tox_Event_Conference_Peer_List_Changed) {
+ 0
+ };
+}
+non_null()
+static void tox_event_conference_peer_list_changed_destruct(Tox_Event_Conference_Peer_List_Changed
+ *conference_peer_list_changed)
+{
+ return;
+}
+
+non_null()
+static void tox_event_conference_peer_list_changed_set_conference_number(Tox_Event_Conference_Peer_List_Changed
+ *conference_peer_list_changed, uint32_t conference_number)
+{
+ 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;
+}
+
+non_null()
+static bool tox_event_conference_peer_list_changed_pack(
+ const Tox_Event_Conference_Peer_List_Changed *event, Bin_Pack *bp)
+{
+ assert(event != nullptr);
+ return bin_pack_array(bp, 2)
+ && bin_pack_u32(bp, TOX_EVENT_CONFERENCE_PEER_LIST_CHANGED)
+ && bin_pack_u32(bp, event->conference_number);
+}
+
+non_null()
+static bool tox_event_conference_peer_list_changed_unpack(
+ Tox_Event_Conference_Peer_List_Changed *event, Bin_Unpack *bu)
+{
+ assert(event != nullptr);
+ return bin_unpack_u32(bu, &event->conference_number);
+}
+
+
+/*****************************************************
+ *
+ * :: add/clear/get
+ *
+ *****************************************************/
+
+
+non_null()
+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)
+{
+ if (events == nullptr) {
+ return 0;
+ }
+
+ 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];
+}
+
+bool tox_events_pack_conference_peer_list_changed(const Tox_Events *events, Bin_Pack *bp)
+{
+ const uint32_t size = tox_events_get_conference_peer_list_changed_size(events);
+
+ for (uint32_t i = 0; i < size; ++i) {
+ if (!tox_event_conference_peer_list_changed_pack(tox_events_get_conference_peer_list_changed(events, i), bp)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool tox_events_unpack_conference_peer_list_changed(Tox_Events *events, Bin_Unpack *bu)
+{
+ Tox_Event_Conference_Peer_List_Changed *event = tox_events_add_conference_peer_list_changed(events);
+
+ if (event == nullptr) {
+ return false;
+ }
+
+ return tox_event_conference_peer_list_changed_unpack(event, bu);
+}
+
+
+/*****************************************************
+ *
+ * :: 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);
+
+ if (state->events == nullptr) {
+ return;
+ }
+
+ 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/protocols/Tox/libtox/src/toxcore/events/conference_peer_name.c b/protocols/Tox/libtox/src/toxcore/events/conference_peer_name.c
new file mode 100644
index 0000000000..4d3f285eee
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/events/conference_peer_name.c
@@ -0,0 +1,250 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2022 The TokTok team.
+ */
+
+#include "events_alloc.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../bin_pack.h"
+#include "../bin_unpack.h"
+#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;
+ uint32_t name_length;
+};
+
+non_null()
+static void tox_event_conference_peer_name_construct(Tox_Event_Conference_Peer_Name *conference_peer_name)
+{
+ *conference_peer_name = (Tox_Event_Conference_Peer_Name) {
+ 0
+ };
+}
+non_null()
+static void tox_event_conference_peer_name_destruct(Tox_Event_Conference_Peer_Name *conference_peer_name)
+{
+ free(conference_peer_name->name);
+}
+
+non_null()
+static void tox_event_conference_peer_name_set_conference_number(Tox_Event_Conference_Peer_Name *conference_peer_name,
+ uint32_t conference_number)
+{
+ assert(conference_peer_name != nullptr);
+ conference_peer_name->conference_number = conference_number;
+}
+uint32_t tox_event_conference_peer_name_get_conference_number(const Tox_Event_Conference_Peer_Name
+ *conference_peer_name)
+{
+ assert(conference_peer_name != nullptr);
+ return conference_peer_name->conference_number;
+}
+
+non_null()
+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;
+}
+
+non_null()
+static bool tox_event_conference_peer_name_set_name(Tox_Event_Conference_Peer_Name *conference_peer_name,
+ const uint8_t *name, uint32_t name_length)
+{
+ 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;
+}
+uint32_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;
+}
+
+non_null()
+static bool tox_event_conference_peer_name_pack(
+ const Tox_Event_Conference_Peer_Name *event, Bin_Pack *bp)
+{
+ assert(event != nullptr);
+ return bin_pack_array(bp, 2)
+ && bin_pack_u32(bp, TOX_EVENT_CONFERENCE_PEER_NAME)
+ && bin_pack_array(bp, 3)
+ && bin_pack_u32(bp, event->conference_number)
+ && bin_pack_u32(bp, event->peer_number)
+ && bin_pack_bin(bp, event->name, event->name_length);
+}
+
+non_null()
+static bool tox_event_conference_peer_name_unpack(
+ Tox_Event_Conference_Peer_Name *event, Bin_Unpack *bu)
+{
+ assert(event != nullptr);
+ if (!bin_unpack_array_fixed(bu, 3)) {
+ return false;
+ }
+
+ return bin_unpack_u32(bu, &event->conference_number)
+ && bin_unpack_u32(bu, &event->peer_number)
+ && bin_unpack_bin(bu, &event->name, &event->name_length);
+}
+
+
+/*****************************************************
+ *
+ * :: add/clear/get
+ *
+ *****************************************************/
+
+
+non_null()
+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)
+{
+ if (events == nullptr) {
+ return 0;
+ }
+
+ 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];
+}
+
+bool tox_events_pack_conference_peer_name(const Tox_Events *events, Bin_Pack *bp)
+{
+ const uint32_t size = tox_events_get_conference_peer_name_size(events);
+
+ for (uint32_t i = 0; i < size; ++i) {
+ if (!tox_event_conference_peer_name_pack(tox_events_get_conference_peer_name(events, i), bp)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool tox_events_unpack_conference_peer_name(Tox_Events *events, Bin_Unpack *bu)
+{
+ Tox_Event_Conference_Peer_Name *event = tox_events_add_conference_peer_name(events);
+
+ if (event == nullptr) {
+ return false;
+ }
+
+ return tox_event_conference_peer_name_unpack(event, bu);
+}
+
+
+/*****************************************************
+ *
+ * :: 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);
+
+ if (state->events == nullptr) {
+ return;
+ }
+
+ 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/protocols/Tox/libtox/src/toxcore/events/conference_title.c b/protocols/Tox/libtox/src/toxcore/events/conference_title.c
new file mode 100644
index 0000000000..1866966e9f
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/events/conference_title.c
@@ -0,0 +1,248 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2022 The TokTok team.
+ */
+
+#include "events_alloc.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../bin_pack.h"
+#include "../bin_unpack.h"
+#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;
+ uint32_t title_length;
+};
+
+non_null()
+static void tox_event_conference_title_construct(Tox_Event_Conference_Title *conference_title)
+{
+ *conference_title = (Tox_Event_Conference_Title) {
+ 0
+ };
+}
+non_null()
+static void tox_event_conference_title_destruct(Tox_Event_Conference_Title *conference_title)
+{
+ free(conference_title->title);
+}
+
+non_null()
+static void tox_event_conference_title_set_conference_number(Tox_Event_Conference_Title *conference_title,
+ uint32_t conference_number)
+{
+ 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;
+}
+
+non_null()
+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;
+}
+
+non_null()
+static bool tox_event_conference_title_set_title(Tox_Event_Conference_Title *conference_title, const uint8_t *title,
+ uint32_t title_length)
+{
+ assert(conference_title != nullptr);
+
+ 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;
+}
+uint32_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;
+}
+
+non_null()
+static bool tox_event_conference_title_pack(
+ const Tox_Event_Conference_Title *event, Bin_Pack *bp)
+{
+ assert(event != nullptr);
+ return bin_pack_array(bp, 2)
+ && bin_pack_u32(bp, TOX_EVENT_CONFERENCE_TITLE)
+ && bin_pack_array(bp, 3)
+ && bin_pack_u32(bp, event->conference_number)
+ && bin_pack_u32(bp, event->peer_number)
+ && bin_pack_bin(bp, event->title, event->title_length);
+}
+
+non_null()
+static bool tox_event_conference_title_unpack(
+ Tox_Event_Conference_Title *event, Bin_Unpack *bu)
+{
+ assert(event != nullptr);
+ if (!bin_unpack_array_fixed(bu, 3)) {
+ return false;
+ }
+
+ return bin_unpack_u32(bu, &event->conference_number)
+ && bin_unpack_u32(bu, &event->peer_number)
+ && bin_unpack_bin(bu, &event->title, &event->title_length);
+}
+
+
+/*****************************************************
+ *
+ * :: add/clear/get
+ *
+ *****************************************************/
+
+
+non_null()
+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)
+{
+ if (events == nullptr) {
+ return 0;
+ }
+
+ 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];
+}
+
+bool tox_events_pack_conference_title(const Tox_Events *events, Bin_Pack *bp)
+{
+ const uint32_t size = tox_events_get_conference_title_size(events);
+
+ for (uint32_t i = 0; i < size; ++i) {
+ if (!tox_event_conference_title_pack(tox_events_get_conference_title(events, i), bp)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool tox_events_unpack_conference_title(Tox_Events *events, Bin_Unpack *bu)
+{
+ Tox_Event_Conference_Title *event = tox_events_add_conference_title(events);
+
+ if (event == nullptr) {
+ return false;
+ }
+
+ return tox_event_conference_title_unpack(event, bu);
+}
+
+
+/*****************************************************
+ *
+ * :: 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);
+
+ if (state->events == nullptr) {
+ return;
+ }
+
+ 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/protocols/Tox/libtox/src/toxcore/events/events_alloc.c b/protocols/Tox/libtox/src/toxcore/events/events_alloc.c
new file mode 100644
index 0000000000..f661c5c039
--- /dev/null
+++ b/protocols/Tox/libtox/src/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 <assert.h>
+#include <stdlib.h>
+
+#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/protocols/Tox/libtox/src/toxcore/events/events_alloc.h b/protocols/Tox/libtox/src/toxcore/events/events_alloc.h
new file mode 100644
index 0000000000..6c5a7abd4f
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/events/events_alloc.h
@@ -0,0 +1,216 @@
+/* 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 "../attributes.h"
+#include "../bin_pack.h"
+#include "../bin_unpack.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;
+
+// non_null()
+typedef void tox_events_clear_cb(Tox_Events *events);
+
+tox_events_clear_cb tox_events_clear_conference_connected;
+tox_events_clear_cb tox_events_clear_conference_invite;
+tox_events_clear_cb tox_events_clear_conference_message;
+tox_events_clear_cb tox_events_clear_conference_peer_list_changed;
+tox_events_clear_cb tox_events_clear_conference_peer_name;
+tox_events_clear_cb tox_events_clear_conference_title;
+tox_events_clear_cb tox_events_clear_file_chunk_request;
+tox_events_clear_cb tox_events_clear_file_recv_chunk;
+tox_events_clear_cb tox_events_clear_file_recv_control;
+tox_events_clear_cb tox_events_clear_file_recv;
+tox_events_clear_cb tox_events_clear_friend_connection_status;
+tox_events_clear_cb tox_events_clear_friend_lossless_packet;
+tox_events_clear_cb tox_events_clear_friend_lossy_packet;
+tox_events_clear_cb tox_events_clear_friend_message;
+tox_events_clear_cb tox_events_clear_friend_name;
+tox_events_clear_cb tox_events_clear_friend_read_receipt;
+tox_events_clear_cb tox_events_clear_friend_request;
+tox_events_clear_cb tox_events_clear_friend_status_message;
+tox_events_clear_cb tox_events_clear_friend_status;
+tox_events_clear_cb tox_events_clear_friend_typing;
+tox_events_clear_cb tox_events_clear_self_connection_status;
+
+// non_null()
+typedef bool tox_events_pack_cb(const Tox_Events *events, Bin_Pack *bp);
+
+tox_events_pack_cb tox_events_pack_conference_connected;
+tox_events_pack_cb tox_events_pack_conference_invite;
+tox_events_pack_cb tox_events_pack_conference_message;
+tox_events_pack_cb tox_events_pack_conference_peer_list_changed;
+tox_events_pack_cb tox_events_pack_conference_peer_name;
+tox_events_pack_cb tox_events_pack_conference_title;
+tox_events_pack_cb tox_events_pack_file_chunk_request;
+tox_events_pack_cb tox_events_pack_file_recv_chunk;
+tox_events_pack_cb tox_events_pack_file_recv_control;
+tox_events_pack_cb tox_events_pack_file_recv;
+tox_events_pack_cb tox_events_pack_friend_connection_status;
+tox_events_pack_cb tox_events_pack_friend_lossless_packet;
+tox_events_pack_cb tox_events_pack_friend_lossy_packet;
+tox_events_pack_cb tox_events_pack_friend_message;
+tox_events_pack_cb tox_events_pack_friend_name;
+tox_events_pack_cb tox_events_pack_friend_read_receipt;
+tox_events_pack_cb tox_events_pack_friend_request;
+tox_events_pack_cb tox_events_pack_friend_status_message;
+tox_events_pack_cb tox_events_pack_friend_status;
+tox_events_pack_cb tox_events_pack_friend_typing;
+tox_events_pack_cb tox_events_pack_self_connection_status;
+
+tox_events_pack_cb tox_events_pack;
+
+// non_null()
+typedef bool tox_events_unpack_cb(Tox_Events *events, Bin_Unpack *bu);
+
+tox_events_unpack_cb tox_events_unpack_conference_connected;
+tox_events_unpack_cb tox_events_unpack_conference_invite;
+tox_events_unpack_cb tox_events_unpack_conference_message;
+tox_events_unpack_cb tox_events_unpack_conference_peer_list_changed;
+tox_events_unpack_cb tox_events_unpack_conference_peer_name;
+tox_events_unpack_cb tox_events_unpack_conference_title;
+tox_events_unpack_cb tox_events_unpack_file_chunk_request;
+tox_events_unpack_cb tox_events_unpack_file_recv_chunk;
+tox_events_unpack_cb tox_events_unpack_file_recv_control;
+tox_events_unpack_cb tox_events_unpack_file_recv;
+tox_events_unpack_cb tox_events_unpack_friend_connection_status;
+tox_events_unpack_cb tox_events_unpack_friend_lossless_packet;
+tox_events_unpack_cb tox_events_unpack_friend_lossy_packet;
+tox_events_unpack_cb tox_events_unpack_friend_message;
+tox_events_unpack_cb tox_events_unpack_friend_name;
+tox_events_unpack_cb tox_events_unpack_friend_read_receipt;
+tox_events_unpack_cb tox_events_unpack_friend_request;
+tox_events_unpack_cb tox_events_unpack_friend_status_message;
+tox_events_unpack_cb tox_events_unpack_friend_status;
+tox_events_unpack_cb tox_events_unpack_friend_typing;
+tox_events_unpack_cb tox_events_unpack_self_connection_status;
+
+tox_events_unpack_cb tox_events_unpack;
+
+non_null()
+Tox_Events_State *tox_events_alloc(void *user_data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // C_TOXCORE_TOXCORE_TOX_EVENTS_INTERNAL_H
diff --git a/protocols/Tox/libtox/src/toxcore/events/file_chunk_request.c b/protocols/Tox/libtox/src/toxcore/events/file_chunk_request.c
new file mode 100644
index 0000000000..f5a9421f58
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/events/file_chunk_request.c
@@ -0,0 +1,243 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2022 The TokTok team.
+ */
+
+#include "events_alloc.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../bin_pack.h"
+#include "../bin_unpack.h"
+#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;
+ uint16_t length;
+};
+
+non_null()
+static void tox_event_file_chunk_request_construct(Tox_Event_File_Chunk_Request *file_chunk_request)
+{
+ *file_chunk_request = (Tox_Event_File_Chunk_Request) {
+ 0
+ };
+}
+non_null()
+static void tox_event_file_chunk_request_destruct(Tox_Event_File_Chunk_Request *file_chunk_request)
+{
+ return;
+}
+
+non_null()
+static void tox_event_file_chunk_request_set_friend_number(Tox_Event_File_Chunk_Request *file_chunk_request,
+ uint32_t friend_number)
+{
+ 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;
+}
+
+non_null()
+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;
+}
+
+non_null()
+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;
+}
+
+non_null()
+static void tox_event_file_chunk_request_set_length(Tox_Event_File_Chunk_Request *file_chunk_request, uint16_t length)
+{
+ assert(file_chunk_request != nullptr);
+ file_chunk_request->length = length;
+}
+uint16_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;
+}
+
+non_null()
+static bool tox_event_file_chunk_request_pack(
+ const Tox_Event_File_Chunk_Request *event, Bin_Pack *bp)
+{
+ assert(event != nullptr);
+ return bin_pack_array(bp, 2)
+ && bin_pack_u32(bp, TOX_EVENT_FILE_CHUNK_REQUEST)
+ && bin_pack_array(bp, 4)
+ && bin_pack_u32(bp, event->friend_number)
+ && bin_pack_u32(bp, event->file_number)
+ && bin_pack_u64(bp, event->position)
+ && bin_pack_u16(bp, event->length);
+}
+
+non_null()
+static bool tox_event_file_chunk_request_unpack(
+ Tox_Event_File_Chunk_Request *event, Bin_Unpack *bu)
+{
+ assert(event != nullptr);
+ if (!bin_unpack_array_fixed(bu, 4)) {
+ return false;
+ }
+
+ return bin_unpack_u32(bu, &event->friend_number)
+ && bin_unpack_u32(bu, &event->file_number)
+ && bin_unpack_u64(bu, &event->position)
+ && bin_unpack_u16(bu, &event->length);
+}
+
+
+/*****************************************************
+ *
+ * :: add/clear/get
+ *
+ *****************************************************/
+
+
+non_null()
+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)
+{
+ if (events == nullptr) {
+ return 0;
+ }
+
+ 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];
+}
+
+bool tox_events_pack_file_chunk_request(const Tox_Events *events, Bin_Pack *bp)
+{
+ const uint32_t size = tox_events_get_file_chunk_request_size(events);
+
+ for (uint32_t i = 0; i < size; ++i) {
+ if (!tox_event_file_chunk_request_pack(tox_events_get_file_chunk_request(events, i), bp)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool tox_events_unpack_file_chunk_request(Tox_Events *events, Bin_Unpack *bu)
+{
+ Tox_Event_File_Chunk_Request *event = tox_events_add_file_chunk_request(events);
+
+ if (event == nullptr) {
+ return false;
+ }
+
+ return tox_event_file_chunk_request_unpack(event, bu);
+}
+
+
+/*****************************************************
+ *
+ * :: 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);
+
+ if (state->events == nullptr) {
+ return;
+ }
+
+ 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/protocols/Tox/libtox/src/toxcore/events/file_recv.c b/protocols/Tox/libtox/src/toxcore/events/file_recv.c
new file mode 100644
index 0000000000..a907b3fdbe
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/events/file_recv.c
@@ -0,0 +1,282 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2022 The TokTok team.
+ */
+
+#include "events_alloc.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../bin_pack.h"
+#include "../bin_unpack.h"
+#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;
+ uint32_t filename_length;
+};
+
+non_null()
+static void tox_event_file_recv_construct(Tox_Event_File_Recv *file_recv)
+{
+ *file_recv = (Tox_Event_File_Recv) {
+ 0
+ };
+}
+non_null()
+static void tox_event_file_recv_destruct(Tox_Event_File_Recv *file_recv)
+{
+ free(file_recv->filename);
+}
+
+non_null()
+static void tox_event_file_recv_set_friend_number(Tox_Event_File_Recv *file_recv,
+ uint32_t friend_number)
+{
+ 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;
+}
+
+non_null()
+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;
+}
+
+non_null()
+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;
+}
+
+non_null()
+static void tox_event_file_recv_set_file_size(Tox_Event_File_Recv *file_recv,
+ uint64_t file_size)
+{
+ assert(file_recv != nullptr);
+ file_recv->file_size = file_size;
+}
+uint64_t tox_event_file_recv_get_file_size(const Tox_Event_File_Recv *file_recv)
+{
+ assert(file_recv != nullptr);
+ return file_recv->file_size;
+}
+
+non_null()
+static bool tox_event_file_recv_set_filename(Tox_Event_File_Recv *file_recv, const uint8_t *filename,
+ uint32_t filename_length)
+{
+ 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;
+}
+uint32_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;
+}
+
+non_null()
+static bool tox_event_file_recv_pack(
+ const Tox_Event_File_Recv *event, Bin_Pack *bp)
+{
+ assert(event != nullptr);
+ return bin_pack_array(bp, 2)
+ && bin_pack_u32(bp, TOX_EVENT_FILE_RECV)
+ && bin_pack_array(bp, 5)
+ && bin_pack_u32(bp, event->friend_number)
+ && bin_pack_u32(bp, event->file_number)
+ && bin_pack_u32(bp, event->kind)
+ && bin_pack_u64(bp, event->file_size)
+ && bin_pack_bin(bp, event->filename, event->filename_length);
+}
+
+non_null()
+static bool tox_event_file_recv_unpack(
+ Tox_Event_File_Recv *event, Bin_Unpack *bu)
+{
+ assert(event != nullptr);
+ if (!bin_unpack_array_fixed(bu, 5)) {
+ return false;
+ }
+
+ return bin_unpack_u32(bu, &event->friend_number)
+ && bin_unpack_u32(bu, &event->file_number)
+ && bin_unpack_u32(bu, &event->kind)
+ && bin_unpack_u64(bu, &event->file_size)
+ && bin_unpack_bin(bu, &event->filename, &event->filename_length);
+}
+
+
+/*****************************************************
+ *
+ * :: add/clear/get
+ *
+ *****************************************************/
+
+
+non_null()
+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)
+{
+ if (events == nullptr) {
+ return 0;
+ }
+
+ 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];
+}
+
+bool tox_events_pack_file_recv(const Tox_Events *events, Bin_Pack *bp)
+{
+ const uint32_t size = tox_events_get_file_recv_size(events);
+
+ for (uint32_t i = 0; i < size; ++i) {
+ if (!tox_event_file_recv_pack(tox_events_get_file_recv(events, i), bp)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool tox_events_unpack_file_recv(Tox_Events *events, Bin_Unpack *bu)
+{
+ Tox_Event_File_Recv *event = tox_events_add_file_recv(events);
+
+ if (event == nullptr) {
+ return false;
+ }
+
+ return tox_event_file_recv_unpack(event, bu);
+}
+
+
+/*****************************************************
+ *
+ * :: 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);
+
+ if (state->events == nullptr) {
+ return;
+ }
+
+ 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/protocols/Tox/libtox/src/toxcore/events/file_recv_chunk.c b/protocols/Tox/libtox/src/toxcore/events/file_recv_chunk.c
new file mode 100644
index 0000000000..0fe7784465
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/events/file_recv_chunk.c
@@ -0,0 +1,265 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2022 The TokTok team.
+ */
+
+#include "events_alloc.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../bin_pack.h"
+#include "../bin_unpack.h"
+#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;
+ uint32_t data_length;
+};
+
+non_null()
+static void tox_event_file_recv_chunk_construct(Tox_Event_File_Recv_Chunk *file_recv_chunk)
+{
+ *file_recv_chunk = (Tox_Event_File_Recv_Chunk) {
+ 0
+ };
+}
+non_null()
+static void tox_event_file_recv_chunk_destruct(Tox_Event_File_Recv_Chunk *file_recv_chunk)
+{
+ free(file_recv_chunk->data);
+}
+
+non_null()
+static void tox_event_file_recv_chunk_set_friend_number(Tox_Event_File_Recv_Chunk *file_recv_chunk,
+ uint32_t friend_number)
+{
+ 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;
+}
+
+non_null()
+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;
+}
+
+non_null()
+static void tox_event_file_recv_chunk_set_position(Tox_Event_File_Recv_Chunk *file_recv_chunk,
+ uint64_t position)
+{
+ assert(file_recv_chunk != nullptr);
+ file_recv_chunk->position = position;
+}
+uint64_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;
+}
+
+non_null()
+static bool tox_event_file_recv_chunk_set_data(Tox_Event_File_Recv_Chunk *file_recv_chunk, const uint8_t *data,
+ uint32_t data_length)
+{
+ 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;
+}
+uint32_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;
+}
+
+non_null()
+static bool tox_event_file_recv_chunk_pack(
+ const Tox_Event_File_Recv_Chunk *event, Bin_Pack *bp)
+{
+ assert(event != nullptr);
+ return bin_pack_array(bp, 2)
+ && bin_pack_u32(bp, TOX_EVENT_FILE_RECV_CHUNK)
+ && bin_pack_array(bp, 4)
+ && bin_pack_u32(bp, event->friend_number)
+ && bin_pack_u32(bp, event->file_number)
+ && bin_pack_u64(bp, event->position)
+ && bin_pack_bin(bp, event->data, event->data_length);
+}
+
+non_null()
+static bool tox_event_file_recv_chunk_unpack(
+ Tox_Event_File_Recv_Chunk *event, Bin_Unpack *bu)
+{
+ assert(event != nullptr);
+ if (!bin_unpack_array_fixed(bu, 4)) {
+ return false;
+ }
+
+ return bin_unpack_u32(bu, &event->friend_number)
+ && bin_unpack_u32(bu, &event->file_number)
+ && bin_unpack_u64(bu, &event->position)
+ && bin_unpack_bin(bu, &event->data, &event->data_length);
+}
+
+
+/*****************************************************
+ *
+ * :: add/clear/get
+ *
+ *****************************************************/
+
+
+non_null()
+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)
+{
+ if (events == nullptr) {
+ return 0;
+ }
+
+ 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];
+}
+
+bool tox_events_pack_file_recv_chunk(const Tox_Events *events, Bin_Pack *bp)
+{
+ const uint32_t size = tox_events_get_file_recv_chunk_size(events);
+
+ for (uint32_t i = 0; i < size; ++i) {
+ if (!tox_event_file_recv_chunk_pack(tox_events_get_file_recv_chunk(events, i), bp)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool tox_events_unpack_file_recv_chunk(Tox_Events *events, Bin_Unpack *bu)
+{
+ Tox_Event_File_Recv_Chunk *event = tox_events_add_file_recv_chunk(events);
+
+ if (event == nullptr) {
+ return false;
+ }
+
+ return tox_event_file_recv_chunk_unpack(event, bu);
+}
+
+
+/*****************************************************
+ *
+ * :: 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);
+
+ if (state->events == nullptr) {
+ return;
+ }
+
+ 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/protocols/Tox/libtox/src/toxcore/events/file_recv_control.c b/protocols/Tox/libtox/src/toxcore/events/file_recv_control.c
new file mode 100644
index 0000000000..af04b33dce
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/events/file_recv_control.c
@@ -0,0 +1,228 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2022 The TokTok team.
+ */
+
+#include "events_alloc.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../bin_pack.h"
+#include "../bin_unpack.h"
+#include "../ccompat.h"
+#include "../tox.h"
+#include "../tox_events.h"
+#include "../tox_unpack.h"
+
+
+/*****************************************************
+ *
+ * :: struct and accessors
+ *
+ *****************************************************/
+
+
+struct Tox_Event_File_Recv_Control {
+ uint32_t friend_number;
+ uint32_t file_number;
+ Tox_File_Control control;
+};
+
+non_null()
+static void tox_event_file_recv_control_construct(Tox_Event_File_Recv_Control *file_recv_control)
+{
+ *file_recv_control = (Tox_Event_File_Recv_Control) {
+ 0
+ };
+}
+non_null()
+static void tox_event_file_recv_control_destruct(Tox_Event_File_Recv_Control *file_recv_control)
+{
+ return;
+}
+
+non_null()
+static void tox_event_file_recv_control_set_friend_number(Tox_Event_File_Recv_Control *file_recv_control,
+ uint32_t friend_number)
+{
+ 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;
+}
+
+non_null()
+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;
+}
+
+non_null()
+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;
+}
+
+non_null()
+static bool tox_event_file_recv_control_pack(
+ const Tox_Event_File_Recv_Control *event, Bin_Pack *bp)
+{
+ assert(event != nullptr);
+ return bin_pack_array(bp, 2)
+ && bin_pack_u32(bp, TOX_EVENT_FILE_RECV_CONTROL)
+ && bin_pack_array(bp, 3)
+ && bin_pack_u32(bp, event->friend_number)
+ && bin_pack_u32(bp, event->file_number)
+ && bin_pack_u32(bp, event->control);
+}
+
+non_null()
+static bool tox_event_file_recv_control_unpack(
+ Tox_Event_File_Recv_Control *event, Bin_Unpack *bu)
+{
+ assert(event != nullptr);
+ if (!bin_unpack_array_fixed(bu, 3)) {
+ return false;
+ }
+
+ return bin_unpack_u32(bu, &event->friend_number)
+ && bin_unpack_u32(bu, &event->file_number)
+ && tox_unpack_file_control(bu, &event->control);
+}
+
+
+/*****************************************************
+ *
+ * :: add/clear/get
+ *
+ *****************************************************/
+
+
+non_null()
+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)
+{
+ if (events == nullptr) {
+ return 0;
+ }
+
+ 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];
+}
+
+bool tox_events_pack_file_recv_control(const Tox_Events *events, Bin_Pack *bp)
+{
+ const uint32_t size = tox_events_get_file_recv_control_size(events);
+
+ for (uint32_t i = 0; i < size; ++i) {
+ if (!tox_event_file_recv_control_pack(tox_events_get_file_recv_control(events, i), bp)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool tox_events_unpack_file_recv_control(Tox_Events *events, Bin_Unpack *bu)
+{
+ Tox_Event_File_Recv_Control *event = tox_events_add_file_recv_control(events);
+
+ if (event == nullptr) {
+ return false;
+ }
+
+ return tox_event_file_recv_control_unpack(event, bu);
+}
+
+
+/*****************************************************
+ *
+ * :: 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);
+
+ if (state->events == nullptr) {
+ return;
+ }
+
+ 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/protocols/Tox/libtox/src/toxcore/events/friend_connection_status.c b/protocols/Tox/libtox/src/toxcore/events/friend_connection_status.c
new file mode 100644
index 0000000000..3d325ef29f
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/events/friend_connection_status.c
@@ -0,0 +1,215 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2022 The TokTok team.
+ */
+
+#include "events_alloc.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../bin_pack.h"
+#include "../bin_unpack.h"
+#include "../ccompat.h"
+#include "../tox.h"
+#include "../tox_events.h"
+#include "../tox_unpack.h"
+
+
+/*****************************************************
+ *
+ * :: struct and accessors
+ *
+ *****************************************************/
+
+
+struct Tox_Event_Friend_Connection_Status {
+ uint32_t friend_number;
+ Tox_Connection connection_status;
+};
+
+non_null()
+static void tox_event_friend_connection_status_construct(Tox_Event_Friend_Connection_Status *friend_connection_status)
+{
+ *friend_connection_status = (Tox_Event_Friend_Connection_Status) {
+ 0
+ };
+}
+non_null()
+static void tox_event_friend_connection_status_destruct(Tox_Event_Friend_Connection_Status *friend_connection_status)
+{
+ return;
+}
+
+non_null()
+static void tox_event_friend_connection_status_set_friend_number(Tox_Event_Friend_Connection_Status
+ *friend_connection_status, uint32_t friend_number)
+{
+ 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;
+}
+
+non_null()
+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;
+}
+
+non_null()
+static bool tox_event_friend_connection_status_pack(
+ const Tox_Event_Friend_Connection_Status *event, Bin_Pack *bp)
+{
+ assert(event != nullptr);
+ return bin_pack_array(bp, 2)
+ && bin_pack_u32(bp, TOX_EVENT_FRIEND_CONNECTION_STATUS)
+ && bin_pack_array(bp, 2)
+ && bin_pack_u32(bp, event->friend_number)
+ && bin_pack_u32(bp, event->connection_status);
+}
+
+non_null()
+static bool tox_event_friend_connection_status_unpack(
+ Tox_Event_Friend_Connection_Status *event, Bin_Unpack *bu)
+{
+ assert(event != nullptr);
+ if (!bin_unpack_array_fixed(bu, 2)) {
+ return false;
+ }
+
+ return bin_unpack_u32(bu, &event->friend_number)
+ && tox_unpack_connection(bu, &event->connection_status);
+}
+
+
+/*****************************************************
+ *
+ * :: add/clear/get
+ *
+ *****************************************************/
+
+
+non_null()
+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)
+{
+ if (events == nullptr) {
+ return 0;
+ }
+
+ 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];
+}
+
+bool tox_events_pack_friend_connection_status(const Tox_Events *events, Bin_Pack *bp)
+{
+ const uint32_t size = tox_events_get_friend_connection_status_size(events);
+
+ for (uint32_t i = 0; i < size; ++i) {
+ if (!tox_event_friend_connection_status_pack(tox_events_get_friend_connection_status(events, i), bp)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool tox_events_unpack_friend_connection_status(Tox_Events *events, Bin_Unpack *bu)
+{
+ Tox_Event_Friend_Connection_Status *event = tox_events_add_friend_connection_status(events);
+
+ if (event == nullptr) {
+ return false;
+ }
+
+ return tox_event_friend_connection_status_unpack(event, bu);
+}
+
+
+/*****************************************************
+ *
+ * :: 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);
+
+ if (state->events == nullptr) {
+ return;
+ }
+
+ 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/protocols/Tox/libtox/src/toxcore/events/friend_lossless_packet.c b/protocols/Tox/libtox/src/toxcore/events/friend_lossless_packet.c
new file mode 100644
index 0000000000..944abd46c7
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/events/friend_lossless_packet.c
@@ -0,0 +1,233 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2022 The TokTok team.
+ */
+
+#include "events_alloc.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../bin_pack.h"
+#include "../bin_unpack.h"
+#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;
+ uint32_t data_length;
+};
+
+non_null()
+static void tox_event_friend_lossless_packet_construct(Tox_Event_Friend_Lossless_Packet *friend_lossless_packet)
+{
+ *friend_lossless_packet = (Tox_Event_Friend_Lossless_Packet) {
+ 0
+ };
+}
+non_null()
+static void tox_event_friend_lossless_packet_destruct(Tox_Event_Friend_Lossless_Packet *friend_lossless_packet)
+{
+ free(friend_lossless_packet->data);
+}
+
+non_null()
+static void tox_event_friend_lossless_packet_set_friend_number(Tox_Event_Friend_Lossless_Packet *friend_lossless_packet,
+ uint32_t friend_number)
+{
+ assert(friend_lossless_packet != nullptr);
+ friend_lossless_packet->friend_number = friend_number;
+}
+uint32_t tox_event_friend_lossless_packet_get_friend_number(const Tox_Event_Friend_Lossless_Packet
+ *friend_lossless_packet)
+{
+ assert(friend_lossless_packet != nullptr);
+ return friend_lossless_packet->friend_number;
+}
+
+non_null()
+static bool tox_event_friend_lossless_packet_set_data(Tox_Event_Friend_Lossless_Packet *friend_lossless_packet,
+ const uint8_t *data, uint32_t data_length)
+{
+ 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;
+}
+uint32_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;
+}
+
+non_null()
+static bool tox_event_friend_lossless_packet_pack(
+ const Tox_Event_Friend_Lossless_Packet *event, Bin_Pack *bp)
+{
+ assert(event != nullptr);
+ return bin_pack_array(bp, 2)
+ && bin_pack_u32(bp, TOX_EVENT_FRIEND_LOSSLESS_PACKET)
+ && bin_pack_array(bp, 2)
+ && bin_pack_u32(bp, event->friend_number)
+ && bin_pack_bin(bp, event->data, event->data_length);
+}
+
+non_null()
+static bool tox_event_friend_lossless_packet_unpack(
+ Tox_Event_Friend_Lossless_Packet *event, Bin_Unpack *bu)
+{
+ assert(event != nullptr);
+ if (!bin_unpack_array_fixed(bu, 2)) {
+ return false;
+ }
+
+ return bin_unpack_u32(bu, &event->friend_number)
+ && bin_unpack_bin(bu, &event->data, &event->data_length);
+}
+
+
+/*****************************************************
+ *
+ * :: add/clear/get
+ *
+ *****************************************************/
+
+
+non_null()
+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)
+{
+ if (events == nullptr) {
+ return 0;
+ }
+
+ 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];
+}
+
+bool tox_events_pack_friend_lossless_packet(const Tox_Events *events, Bin_Pack *bp)
+{
+ const uint32_t size = tox_events_get_friend_lossless_packet_size(events);
+
+ for (uint32_t i = 0; i < size; ++i) {
+ if (!tox_event_friend_lossless_packet_pack(tox_events_get_friend_lossless_packet(events, i), bp)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool tox_events_unpack_friend_lossless_packet(Tox_Events *events, Bin_Unpack *bu)
+{
+ Tox_Event_Friend_Lossless_Packet *event = tox_events_add_friend_lossless_packet(events);
+
+ if (event == nullptr) {
+ return false;
+ }
+
+ return tox_event_friend_lossless_packet_unpack(event, bu);
+}
+
+
+/*****************************************************
+ *
+ * :: 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);
+
+ if (state->events == nullptr) {
+ return;
+ }
+
+ 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/protocols/Tox/libtox/src/toxcore/events/friend_lossy_packet.c b/protocols/Tox/libtox/src/toxcore/events/friend_lossy_packet.c
new file mode 100644
index 0000000000..a787fce0cf
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/events/friend_lossy_packet.c
@@ -0,0 +1,232 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2022 The TokTok team.
+ */
+
+#include "events_alloc.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../bin_pack.h"
+#include "../bin_unpack.h"
+#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;
+ uint32_t data_length;
+};
+
+non_null()
+static void tox_event_friend_lossy_packet_construct(Tox_Event_Friend_Lossy_Packet *friend_lossy_packet)
+{
+ *friend_lossy_packet = (Tox_Event_Friend_Lossy_Packet) {
+ 0
+ };
+}
+non_null()
+static void tox_event_friend_lossy_packet_destruct(Tox_Event_Friend_Lossy_Packet *friend_lossy_packet)
+{
+ free(friend_lossy_packet->data);
+}
+
+non_null()
+static void tox_event_friend_lossy_packet_set_friend_number(Tox_Event_Friend_Lossy_Packet *friend_lossy_packet,
+ uint32_t friend_number)
+{
+ 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;
+}
+
+non_null()
+static bool tox_event_friend_lossy_packet_set_data(Tox_Event_Friend_Lossy_Packet *friend_lossy_packet,
+ const uint8_t *data, uint32_t data_length)
+{
+ 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;
+}
+uint32_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;
+}
+
+non_null()
+static bool tox_event_friend_lossy_packet_pack(
+ const Tox_Event_Friend_Lossy_Packet *event, Bin_Pack *bp)
+{
+ assert(event != nullptr);
+ return bin_pack_array(bp, 2)
+ && bin_pack_u32(bp, TOX_EVENT_FRIEND_LOSSY_PACKET)
+ && bin_pack_array(bp, 2)
+ && bin_pack_u32(bp, event->friend_number)
+ && bin_pack_bin(bp, event->data, event->data_length);
+}
+
+non_null()
+static bool tox_event_friend_lossy_packet_unpack(
+ Tox_Event_Friend_Lossy_Packet *event, Bin_Unpack *bu)
+{
+ assert(event != nullptr);
+ if (!bin_unpack_array_fixed(bu, 2)) {
+ return false;
+ }
+
+ return bin_unpack_u32(bu, &event->friend_number)
+ && bin_unpack_bin(bu, &event->data, &event->data_length);
+}
+
+
+/*****************************************************
+ *
+ * :: add/clear/get
+ *
+ *****************************************************/
+
+
+non_null()
+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)
+{
+ if (events == nullptr) {
+ return 0;
+ }
+
+ 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];
+}
+
+bool tox_events_pack_friend_lossy_packet(const Tox_Events *events, Bin_Pack *bp)
+{
+ const uint32_t size = tox_events_get_friend_lossy_packet_size(events);
+
+ for (uint32_t i = 0; i < size; ++i) {
+ if (!tox_event_friend_lossy_packet_pack(tox_events_get_friend_lossy_packet(events, i), bp)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool tox_events_unpack_friend_lossy_packet(Tox_Events *events, Bin_Unpack *bu)
+{
+ Tox_Event_Friend_Lossy_Packet *event = tox_events_add_friend_lossy_packet(events);
+
+ if (event == nullptr) {
+ return false;
+ }
+
+ return tox_event_friend_lossy_packet_unpack(event, bu);
+}
+
+
+/*****************************************************
+ *
+ * :: 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);
+
+ if (state->events == nullptr) {
+ return;
+ }
+
+ 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/protocols/Tox/libtox/src/toxcore/events/friend_message.c b/protocols/Tox/libtox/src/toxcore/events/friend_message.c
new file mode 100644
index 0000000000..8fa6a19e34
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/events/friend_message.c
@@ -0,0 +1,248 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2022 The TokTok team.
+ */
+
+#include "events_alloc.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../bin_pack.h"
+#include "../bin_unpack.h"
+#include "../ccompat.h"
+#include "../tox.h"
+#include "../tox_events.h"
+#include "../tox_unpack.h"
+
+
+/*****************************************************
+ *
+ * :: struct and accessors
+ *
+ *****************************************************/
+
+
+struct Tox_Event_Friend_Message {
+ uint32_t friend_number;
+ Tox_Message_Type type;
+ uint8_t *message;
+ uint32_t message_length;
+};
+
+non_null()
+static void tox_event_friend_message_construct(Tox_Event_Friend_Message *friend_message)
+{
+ *friend_message = (Tox_Event_Friend_Message) {
+ 0
+ };
+}
+non_null()
+static void tox_event_friend_message_destruct(Tox_Event_Friend_Message *friend_message)
+{
+ free(friend_message->message);
+}
+
+non_null()
+static void tox_event_friend_message_set_friend_number(Tox_Event_Friend_Message *friend_message,
+ uint32_t friend_number)
+{
+ 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;
+}
+
+non_null()
+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;
+}
+
+non_null()
+static bool tox_event_friend_message_set_message(Tox_Event_Friend_Message *friend_message, const uint8_t *message,
+ uint32_t message_length)
+{
+ assert(friend_message != nullptr);
+
+ 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;
+}
+uint32_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;
+}
+
+non_null()
+static bool tox_event_friend_message_pack(
+ const Tox_Event_Friend_Message *event, Bin_Pack *bp)
+{
+ assert(event != nullptr);
+ return bin_pack_array(bp, 2)
+ && bin_pack_u32(bp, TOX_EVENT_FRIEND_MESSAGE)
+ && bin_pack_array(bp, 3)
+ && bin_pack_u32(bp, event->friend_number)
+ && bin_pack_u32(bp, event->type)
+ && bin_pack_bin(bp, event->message, event->message_length);
+}
+
+non_null()
+static bool tox_event_friend_message_unpack(
+ Tox_Event_Friend_Message *event, Bin_Unpack *bu)
+{
+ assert(event != nullptr);
+ if (!bin_unpack_array_fixed(bu, 3)) {
+ return false;
+ }
+
+ return bin_unpack_u32(bu, &event->friend_number)
+ && tox_unpack_message_type(bu, &event->type)
+ && bin_unpack_bin(bu, &event->message, &event->message_length);
+}
+
+
+/*****************************************************
+ *
+ * :: add/clear/get
+ *
+ *****************************************************/
+
+
+non_null()
+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)
+{
+ if (events == nullptr) {
+ return 0;
+ }
+
+ 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];
+}
+
+bool tox_events_pack_friend_message(const Tox_Events *events, Bin_Pack *bp)
+{
+ const uint32_t size = tox_events_get_friend_message_size(events);
+
+ for (uint32_t i = 0; i < size; ++i) {
+ if (!tox_event_friend_message_pack(tox_events_get_friend_message(events, i), bp)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool tox_events_unpack_friend_message(Tox_Events *events, Bin_Unpack *bu)
+{
+ Tox_Event_Friend_Message *event = tox_events_add_friend_message(events);
+
+ if (event == nullptr) {
+ return false;
+ }
+
+ return tox_event_friend_message_unpack(event, bu);
+}
+
+
+/*****************************************************
+ *
+ * :: 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);
+
+ if (state->events == nullptr) {
+ return;
+ }
+
+ 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/protocols/Tox/libtox/src/toxcore/events/friend_name.c b/protocols/Tox/libtox/src/toxcore/events/friend_name.c
new file mode 100644
index 0000000000..123918386a
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/events/friend_name.c
@@ -0,0 +1,231 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2022 The TokTok team.
+ */
+
+#include "events_alloc.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../bin_pack.h"
+#include "../bin_unpack.h"
+#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;
+ uint32_t name_length;
+};
+
+non_null()
+static void tox_event_friend_name_construct(Tox_Event_Friend_Name *friend_name)
+{
+ *friend_name = (Tox_Event_Friend_Name) {
+ 0
+ };
+}
+non_null()
+static void tox_event_friend_name_destruct(Tox_Event_Friend_Name *friend_name)
+{
+ free(friend_name->name);
+}
+
+non_null()
+static void tox_event_friend_name_set_friend_number(Tox_Event_Friend_Name *friend_name,
+ uint32_t friend_number)
+{
+ 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;
+}
+
+non_null()
+static bool tox_event_friend_name_set_name(Tox_Event_Friend_Name *friend_name, const uint8_t *name,
+ uint32_t name_length)
+{
+ assert(friend_name != nullptr);
+
+ 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;
+}
+uint32_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;
+}
+
+non_null()
+static bool tox_event_friend_name_pack(
+ const Tox_Event_Friend_Name *event, Bin_Pack *bp)
+{
+ assert(event != nullptr);
+ return bin_pack_array(bp, 2)
+ && bin_pack_u32(bp, TOX_EVENT_FRIEND_NAME)
+ && bin_pack_array(bp, 2)
+ && bin_pack_u32(bp, event->friend_number)
+ && bin_pack_bin(bp, event->name, event->name_length);
+}
+
+non_null()
+static bool tox_event_friend_name_unpack(
+ Tox_Event_Friend_Name *event, Bin_Unpack *bu)
+{
+ assert(event != nullptr);
+ if (!bin_unpack_array_fixed(bu, 2)) {
+ return false;
+ }
+
+ return bin_unpack_u32(bu, &event->friend_number)
+ && bin_unpack_bin(bu, &event->name, &event->name_length);
+}
+
+
+/*****************************************************
+ *
+ * :: add/clear/get
+ *
+ *****************************************************/
+
+
+non_null()
+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)
+{
+ if (events == nullptr) {
+ return 0;
+ }
+
+ 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];
+}
+
+bool tox_events_pack_friend_name(const Tox_Events *events, Bin_Pack *bp)
+{
+ const uint32_t size = tox_events_get_friend_name_size(events);
+
+ for (uint32_t i = 0; i < size; ++i) {
+ if (!tox_event_friend_name_pack(tox_events_get_friend_name(events, i), bp)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool tox_events_unpack_friend_name(Tox_Events *events, Bin_Unpack *bu)
+{
+ Tox_Event_Friend_Name *event = tox_events_add_friend_name(events);
+
+ if (event == nullptr) {
+ return false;
+ }
+
+ return tox_event_friend_name_unpack(event, bu);
+}
+
+
+/*****************************************************
+ *
+ * :: 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);
+
+ if (state->events == nullptr) {
+ return;
+ }
+
+ 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/protocols/Tox/libtox/src/toxcore/events/friend_read_receipt.c b/protocols/Tox/libtox/src/toxcore/events/friend_read_receipt.c
new file mode 100644
index 0000000000..1485b67cca
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/events/friend_read_receipt.c
@@ -0,0 +1,210 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2022 The TokTok team.
+ */
+
+#include "events_alloc.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../bin_pack.h"
+#include "../bin_unpack.h"
+#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;
+};
+
+non_null()
+static void tox_event_friend_read_receipt_construct(Tox_Event_Friend_Read_Receipt *friend_read_receipt)
+{
+ *friend_read_receipt = (Tox_Event_Friend_Read_Receipt) {
+ 0
+ };
+}
+non_null()
+static void tox_event_friend_read_receipt_destruct(Tox_Event_Friend_Read_Receipt *friend_read_receipt)
+{
+ return;
+}
+
+non_null()
+static void tox_event_friend_read_receipt_set_friend_number(Tox_Event_Friend_Read_Receipt *friend_read_receipt,
+ uint32_t friend_number)
+{
+ 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;
+}
+
+non_null()
+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;
+}
+
+non_null()
+static bool tox_event_friend_read_receipt_pack(
+ const Tox_Event_Friend_Read_Receipt *event, Bin_Pack *bp)
+{
+ assert(event != nullptr);
+ return bin_pack_array(bp, 2)
+ && bin_pack_u32(bp, TOX_EVENT_FRIEND_READ_RECEIPT)
+ && bin_pack_array(bp, 2)
+ && bin_pack_u32(bp, event->friend_number)
+ && bin_pack_u32(bp, event->message_id);
+}
+
+non_null()
+static bool tox_event_friend_read_receipt_unpack(
+ Tox_Event_Friend_Read_Receipt *event, Bin_Unpack *bu)
+{
+ assert(event != nullptr);
+ if (!bin_unpack_array_fixed(bu, 2)) {
+ return false;
+ }
+
+ return bin_unpack_u32(bu, &event->friend_number)
+ && bin_unpack_u32(bu, &event->message_id);
+}
+
+
+/*****************************************************
+ *
+ * :: add/clear/get
+ *
+ *****************************************************/
+
+
+non_null()
+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)
+{
+ if (events == nullptr) {
+ return 0;
+ }
+
+ 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];
+}
+
+bool tox_events_pack_friend_read_receipt(const Tox_Events *events, Bin_Pack *bp)
+{
+ const uint32_t size = tox_events_get_friend_read_receipt_size(events);
+
+ for (uint32_t i = 0; i < size; ++i) {
+ if (!tox_event_friend_read_receipt_pack(tox_events_get_friend_read_receipt(events, i), bp)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool tox_events_unpack_friend_read_receipt(Tox_Events *events, Bin_Unpack *bu)
+{
+ Tox_Event_Friend_Read_Receipt *event = tox_events_add_friend_read_receipt(events);
+
+ if (event == nullptr) {
+ return false;
+ }
+
+ return tox_event_friend_read_receipt_unpack(event, bu);
+}
+
+
+/*****************************************************
+ *
+ * :: 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);
+
+ if (state->events == nullptr) {
+ return;
+ }
+
+ 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/protocols/Tox/libtox/src/toxcore/events/friend_request.c b/protocols/Tox/libtox/src/toxcore/events/friend_request.c
new file mode 100644
index 0000000000..3366f54fe4
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/events/friend_request.c
@@ -0,0 +1,232 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2022 The TokTok team.
+ */
+
+#include "events_alloc.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../bin_pack.h"
+#include "../bin_unpack.h"
+#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;
+ uint32_t message_length;
+};
+
+non_null()
+static void tox_event_friend_request_construct(Tox_Event_Friend_Request *friend_request)
+{
+ *friend_request = (Tox_Event_Friend_Request) {
+ 0
+ };
+}
+non_null()
+static void tox_event_friend_request_destruct(Tox_Event_Friend_Request *friend_request)
+{
+ free(friend_request->message);
+}
+
+non_null()
+static bool tox_event_friend_request_set_public_key(Tox_Event_Friend_Request *friend_request, const uint8_t *public_key)
+{
+ assert(friend_request != nullptr);
+
+ 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;
+}
+
+non_null()
+static bool tox_event_friend_request_set_message(Tox_Event_Friend_Request *friend_request, const uint8_t *message,
+ uint32_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;
+}
+uint32_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;
+}
+
+non_null()
+static bool tox_event_friend_request_pack(
+ const Tox_Event_Friend_Request *event, Bin_Pack *bp)
+{
+ assert(event != nullptr);
+ return bin_pack_array(bp, 2)
+ && bin_pack_u32(bp, TOX_EVENT_FRIEND_REQUEST)
+ && bin_pack_array(bp, 2)
+ && bin_pack_bin(bp, event->public_key, TOX_PUBLIC_KEY_SIZE)
+ && bin_pack_bin(bp, event->message, event->message_length);
+}
+
+non_null()
+static bool tox_event_friend_request_unpack(
+ Tox_Event_Friend_Request *event, Bin_Unpack *bu)
+{
+ assert(event != nullptr);
+ if (!bin_unpack_array_fixed(bu, 2)) {
+ return false;
+ }
+
+ return bin_unpack_bin_fixed(bu, event->public_key, TOX_PUBLIC_KEY_SIZE)
+ && bin_unpack_bin(bu, &event->message, &event->message_length);
+}
+
+
+/*****************************************************
+ *
+ * :: add/clear/get
+ *
+ *****************************************************/
+
+
+non_null()
+static Tox_Event_Friend_Request *tox_events_add_friend_request(Tox_Events *events)
+{
+ 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)
+{
+ if (events == nullptr) {
+ return 0;
+ }
+
+ 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];
+}
+
+bool tox_events_pack_friend_request(const Tox_Events *events, Bin_Pack *bp)
+{
+ const uint32_t size = tox_events_get_friend_request_size(events);
+
+ for (uint32_t i = 0; i < size; ++i) {
+ if (!tox_event_friend_request_pack(tox_events_get_friend_request(events, i), bp)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool tox_events_unpack_friend_request(Tox_Events *events, Bin_Unpack *bu)
+{
+ Tox_Event_Friend_Request *event = tox_events_add_friend_request(events);
+
+ if (event == nullptr) {
+ return false;
+ }
+
+ return tox_event_friend_request_unpack(event, bu);
+}
+
+
+/*****************************************************
+ *
+ * :: 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);
+
+ if (state->events == nullptr) {
+ return;
+ }
+
+ 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/protocols/Tox/libtox/src/toxcore/events/friend_status.c b/protocols/Tox/libtox/src/toxcore/events/friend_status.c
new file mode 100644
index 0000000000..c6eabdaa47
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/events/friend_status.c
@@ -0,0 +1,211 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2022 The TokTok team.
+ */
+
+#include "events_alloc.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include "../bin_unpack.h"
+
+#include "../bin_pack.h"
+#include "../ccompat.h"
+#include "../tox.h"
+#include "../tox_events.h"
+#include "../tox_unpack.h"
+
+
+/*****************************************************
+ *
+ * :: struct and accessors
+ *
+ *****************************************************/
+
+
+struct Tox_Event_Friend_Status {
+ uint32_t friend_number;
+ Tox_User_Status status;
+};
+
+non_null()
+static void tox_event_friend_status_construct(Tox_Event_Friend_Status *friend_status)
+{
+ *friend_status = (Tox_Event_Friend_Status) {
+ 0
+ };
+}
+non_null()
+static void tox_event_friend_status_destruct(Tox_Event_Friend_Status *friend_status)
+{
+ return;
+}
+
+non_null()
+static void tox_event_friend_status_set_friend_number(Tox_Event_Friend_Status *friend_status,
+ uint32_t friend_number)
+{
+ 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;
+}
+
+non_null()
+static void tox_event_friend_status_set_status(Tox_Event_Friend_Status *friend_status,
+ Tox_User_Status status)
+{
+ assert(friend_status != nullptr);
+ friend_status->status = status;
+}
+Tox_User_Status tox_event_friend_status_get_status(const Tox_Event_Friend_Status *friend_status)
+{
+ assert(friend_status != nullptr);
+ return friend_status->status;
+}
+
+non_null()
+static bool tox_event_friend_status_pack(
+ const Tox_Event_Friend_Status *event, Bin_Pack *bp)
+{
+ assert(event != nullptr);
+ return bin_pack_array(bp, 2)
+ && bin_pack_u32(bp, TOX_EVENT_FRIEND_STATUS)
+ && bin_pack_array(bp, 2)
+ && bin_pack_u32(bp, event->friend_number)
+ && bin_pack_u32(bp, event->status);
+}
+
+non_null()
+static bool tox_event_friend_status_unpack(
+ Tox_Event_Friend_Status *event, Bin_Unpack *bu)
+{
+ assert(event != nullptr);
+ if (!bin_unpack_array_fixed(bu, 2)) {
+ return false;
+ }
+
+ return bin_unpack_u32(bu, &event->friend_number)
+ && tox_unpack_user_status(bu, &event->status);
+}
+
+
+/*****************************************************
+ *
+ * :: add/clear/get
+ *
+ *****************************************************/
+
+
+non_null()
+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)
+{
+ if (events == nullptr) {
+ return 0;
+ }
+
+ 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];
+}
+
+bool tox_events_pack_friend_status(const Tox_Events *events, Bin_Pack *bp)
+{
+ const uint32_t size = tox_events_get_friend_status_size(events);
+
+ for (uint32_t i = 0; i < size; ++i) {
+ if (!tox_event_friend_status_pack(tox_events_get_friend_status(events, i), bp)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool tox_events_unpack_friend_status(Tox_Events *events, Bin_Unpack *bu)
+{
+ Tox_Event_Friend_Status *event = tox_events_add_friend_status(events);
+
+ if (event == nullptr) {
+ return false;
+ }
+
+ return tox_event_friend_status_unpack(event, bu);
+}
+
+
+/*****************************************************
+ *
+ * :: event handler
+ *
+ *****************************************************/
+
+
+void tox_events_handle_friend_status(Tox *tox, uint32_t friend_number, Tox_User_Status status,
+ void *user_data)
+{
+ Tox_Events_State *state = tox_events_alloc(user_data);
+ assert(state != nullptr);
+
+ if (state->events == nullptr) {
+ return;
+ }
+
+ Tox_Event_Friend_Status *friend_status = tox_events_add_friend_status(state->events);
+
+ 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_status(friend_status, status);
+}
diff --git a/protocols/Tox/libtox/src/toxcore/events/friend_status_message.c b/protocols/Tox/libtox/src/toxcore/events/friend_status_message.c
new file mode 100644
index 0000000000..91fa88e321
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/events/friend_status_message.c
@@ -0,0 +1,234 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2022 The TokTok team.
+ */
+
+#include "events_alloc.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../bin_pack.h"
+#include "../bin_unpack.h"
+#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 *message;
+ uint32_t message_length;
+};
+
+non_null()
+static void tox_event_friend_status_message_construct(Tox_Event_Friend_Status_Message *friend_status_message)
+{
+ *friend_status_message = (Tox_Event_Friend_Status_Message) {
+ 0
+ };
+}
+non_null()
+static void tox_event_friend_status_message_destruct(Tox_Event_Friend_Status_Message *friend_status_message)
+{
+ free(friend_status_message->message);
+}
+
+non_null()
+static void tox_event_friend_status_message_set_friend_number(Tox_Event_Friend_Status_Message *friend_status_message,
+ uint32_t friend_number)
+{
+ 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;
+}
+
+non_null()
+static bool tox_event_friend_status_message_set_message(Tox_Event_Friend_Status_Message *friend_status_message,
+ const uint8_t *message, uint32_t message_length)
+{
+ assert(friend_status_message != nullptr);
+
+ if (friend_status_message->message != nullptr) {
+ free(friend_status_message->message);
+ friend_status_message->message = nullptr;
+ friend_status_message->message_length = 0;
+ }
+
+ friend_status_message->message = (uint8_t *)malloc(message_length);
+
+ if (friend_status_message->message == nullptr) {
+ return false;
+ }
+
+ memcpy(friend_status_message->message, message, message_length);
+ friend_status_message->message_length = message_length;
+ return true;
+}
+uint32_t tox_event_friend_status_message_get_message_length(const Tox_Event_Friend_Status_Message
+ *friend_status_message)
+{
+ assert(friend_status_message != nullptr);
+ return friend_status_message->message_length;
+}
+const uint8_t *tox_event_friend_status_message_get_message(const Tox_Event_Friend_Status_Message
+ *friend_status_message)
+{
+ assert(friend_status_message != nullptr);
+ return friend_status_message->message;
+}
+
+non_null()
+static bool tox_event_friend_status_message_pack(
+ const Tox_Event_Friend_Status_Message *event, Bin_Pack *bp)
+{
+ assert(event != nullptr);
+ return bin_pack_array(bp, 2)
+ && bin_pack_u32(bp, TOX_EVENT_FRIEND_STATUS_MESSAGE)
+ && bin_pack_array(bp, 2)
+ && bin_pack_u32(bp, event->friend_number)
+ && bin_pack_bin(bp, event->message, event->message_length);
+}
+
+non_null()
+static bool tox_event_friend_status_message_unpack(
+ Tox_Event_Friend_Status_Message *event, Bin_Unpack *bu)
+{
+ assert(event != nullptr);
+ if (!bin_unpack_array_fixed(bu, 2)) {
+ return false;
+ }
+
+ return bin_unpack_u32(bu, &event->friend_number)
+ && bin_unpack_bin(bu, &event->message, &event->message_length);
+}
+
+
+/*****************************************************
+ *
+ * :: add/clear/get
+ *
+ *****************************************************/
+
+
+non_null()
+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)
+{
+ if (events == nullptr) {
+ return 0;
+ }
+
+ 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];
+}
+
+bool tox_events_pack_friend_status_message(const Tox_Events *events, Bin_Pack *bp)
+{
+ const uint32_t size = tox_events_get_friend_status_message_size(events);
+
+ for (uint32_t i = 0; i < size; ++i) {
+ if (!tox_event_friend_status_message_pack(tox_events_get_friend_status_message(events, i), bp)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool tox_events_unpack_friend_status_message(Tox_Events *events, Bin_Unpack *bu)
+{
+ Tox_Event_Friend_Status_Message *event = tox_events_add_friend_status_message(events);
+
+ if (event == nullptr) {
+ return false;
+ }
+
+ return tox_event_friend_status_message_unpack(event, bu);
+}
+
+
+/*****************************************************
+ *
+ * :: event handler
+ *
+ *****************************************************/
+
+
+void tox_events_handle_friend_status_message(Tox *tox, uint32_t friend_number, const uint8_t *message,
+ size_t length, void *user_data)
+{
+ Tox_Events_State *state = tox_events_alloc(user_data);
+ assert(state != nullptr);
+
+ if (state->events == nullptr) {
+ return;
+ }
+
+ Tox_Event_Friend_Status_Message *friend_status_message = tox_events_add_friend_status_message(state->events);
+
+ 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_message(friend_status_message, message, length);
+}
diff --git a/protocols/Tox/libtox/src/toxcore/events/friend_typing.c b/protocols/Tox/libtox/src/toxcore/events/friend_typing.c
new file mode 100644
index 0000000000..83c4dbac63
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/events/friend_typing.c
@@ -0,0 +1,208 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2022 The TokTok team.
+ */
+
+#include "events_alloc.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../bin_pack.h"
+#include "../bin_unpack.h"
+#include "../ccompat.h"
+#include "../tox.h"
+#include "../tox_events.h"
+
+
+/*****************************************************
+ *
+ * :: struct and accessors
+ *
+ *****************************************************/
+
+
+struct Tox_Event_Friend_Typing {
+ uint32_t friend_number;
+ bool typing;
+};
+
+non_null()
+static void tox_event_friend_typing_construct(Tox_Event_Friend_Typing *friend_typing)
+{
+ *friend_typing = (Tox_Event_Friend_Typing) {
+ 0
+ };
+}
+non_null()
+static void tox_event_friend_typing_destruct(Tox_Event_Friend_Typing *friend_typing)
+{
+ return;
+}
+
+non_null()
+static void tox_event_friend_typing_set_friend_number(Tox_Event_Friend_Typing *friend_typing,
+ uint32_t friend_number)
+{
+ 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;
+}
+
+non_null()
+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;
+}
+
+non_null()
+static bool tox_event_friend_typing_pack(
+ const Tox_Event_Friend_Typing *event, Bin_Pack *bp)
+{
+ assert(event != nullptr);
+ return bin_pack_array(bp, 2)
+ && bin_pack_u32(bp, TOX_EVENT_FRIEND_TYPING)
+ && bin_pack_array(bp, 2)
+ && bin_pack_u32(bp, event->friend_number)
+ && bin_pack_bool(bp, event->typing);
+}
+
+non_null()
+static bool tox_event_friend_typing_unpack(
+ Tox_Event_Friend_Typing *event, Bin_Unpack *bu)
+{
+ assert(event != nullptr);
+ if (!bin_unpack_array_fixed(bu, 2)) {
+ return false;
+ }
+
+ return bin_unpack_u32(bu, &event->friend_number)
+ && bin_unpack_bool(bu, &event->typing);
+}
+
+
+/*****************************************************
+ *
+ * :: add/clear/get
+ *
+ *****************************************************/
+
+
+non_null()
+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)
+{
+ if (events == nullptr) {
+ return 0;
+ }
+
+ 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];
+}
+
+bool tox_events_pack_friend_typing(const Tox_Events *events, Bin_Pack *bp)
+{
+ const uint32_t size = tox_events_get_friend_typing_size(events);
+
+ for (uint32_t i = 0; i < size; ++i) {
+ if (!tox_event_friend_typing_pack(tox_events_get_friend_typing(events, i), bp)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool tox_events_unpack_friend_typing(Tox_Events *events, Bin_Unpack *bu)
+{
+ Tox_Event_Friend_Typing *event = tox_events_add_friend_typing(events);
+
+ if (event == nullptr) {
+ return false;
+ }
+
+ return tox_event_friend_typing_unpack(event, bu);
+}
+
+
+/*****************************************************
+ *
+ * :: 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);
+
+ if (state->events == nullptr) {
+ return;
+ }
+
+ 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/protocols/Tox/libtox/src/toxcore/events/self_connection_status.c b/protocols/Tox/libtox/src/toxcore/events/self_connection_status.c
new file mode 100644
index 0000000000..0e381de7fa
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/events/self_connection_status.c
@@ -0,0 +1,190 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2022 The TokTok team.
+ */
+
+#include "events_alloc.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../bin_pack.h"
+#include "../bin_unpack.h"
+#include "../ccompat.h"
+#include "../tox.h"
+#include "../tox_events.h"
+#include "../tox_unpack.h"
+
+
+/*****************************************************
+ *
+ * :: struct and accessors
+ *
+ *****************************************************/
+
+
+struct Tox_Event_Self_Connection_Status {
+ Tox_Connection connection_status;
+};
+
+non_null()
+static void tox_event_self_connection_status_construct(Tox_Event_Self_Connection_Status *self_connection_status)
+{
+ *self_connection_status = (Tox_Event_Self_Connection_Status) {
+ TOX_CONNECTION_NONE
+ };
+}
+non_null()
+static void tox_event_self_connection_status_destruct(Tox_Event_Self_Connection_Status *self_connection_status)
+{
+ return;
+}
+
+non_null()
+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;
+}
+
+non_null()
+static bool tox_event_self_connection_status_pack(
+ const Tox_Event_Self_Connection_Status *event, Bin_Pack *bp)
+{
+ assert(event != nullptr);
+ return bin_pack_array(bp, 2)
+ && bin_pack_u32(bp, TOX_EVENT_SELF_CONNECTION_STATUS)
+ && bin_pack_u32(bp, event->connection_status);
+}
+
+non_null()
+static bool tox_event_self_connection_status_unpack(
+ Tox_Event_Self_Connection_Status *event, Bin_Unpack *bu)
+{
+ assert(event != nullptr);
+ return tox_unpack_connection(bu, &event->connection_status);
+}
+
+
+/*****************************************************
+ *
+ * :: add/clear/get
+ *
+ *****************************************************/
+
+
+non_null()
+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)
+{
+ if (events == nullptr) {
+ return 0;
+ }
+
+ 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];
+}
+
+bool tox_events_pack_self_connection_status(const Tox_Events *events, Bin_Pack *bp)
+{
+ const uint32_t size = tox_events_get_self_connection_status_size(events);
+
+ for (uint32_t i = 0; i < size; ++i) {
+ if (!tox_event_self_connection_status_pack(tox_events_get_self_connection_status(events, i), bp)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool tox_events_unpack_self_connection_status(Tox_Events *events, Bin_Unpack *bu)
+{
+ Tox_Event_Self_Connection_Status *event = tox_events_add_self_connection_status(events);
+
+ if (event == nullptr) {
+ return false;
+ }
+
+ return tox_event_self_connection_status_unpack(event, bu);
+}
+
+
+/*****************************************************
+ *
+ * :: 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);
+
+ if (state->events == nullptr) {
+ return;
+ }
+
+ 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);
+}