From 7b1db6adc1d4244aa1ed02b51609d20fba13b90e Mon Sep 17 00:00:00 2001 From: jfreegman Date: Thu, 7 Mar 2024 10:25:39 -0500 Subject: [PATCH] feat: add message IDs to private group messages --- auto_tests/group_message_test.c | 28 +++++++++++++------- other/event_tooling/generate_event_c.cpp | 1 + toxcore/events/group_private_message.c | 27 +++++++++++++++---- toxcore/group_chats.c | 31 ++++++++++++++++------ toxcore/group_chats.h | 4 +-- toxcore/group_common.h | 2 +- toxcore/tox.c | 33 ++++++++++++------------ toxcore/tox.h | 4 +-- toxcore/tox_events.h | 2 ++ 9 files changed, 89 insertions(+), 43 deletions(-) diff --git a/auto_tests/group_message_test.c b/auto_tests/group_message_test.c index a8ed299bb9..435fbc83a7 100644 --- a/auto_tests/group_message_test.c +++ b/auto_tests/group_message_test.c @@ -274,7 +274,6 @@ static void group_message_handler(const Tox_Event_Group_Message *event, void *us State *state = (State *)autotox->state; state->message_received = true; - state->pseudo_msg_id = pseudo_msg_id; } @@ -288,6 +287,7 @@ static void group_private_message_handler(const Tox_Event_Group_Private_Message const Tox_Message_Type type = tox_event_group_private_message_get_type(event); const uint8_t *message = tox_event_group_private_message_get_message(event); const size_t length = tox_event_group_private_message_get_message_length(event); + const uint32_t pseudo_msg_id = tox_event_group_private_message_get_message_id(event); ck_assert_msg(length == TEST_PRIVATE_MESSAGE_LEN, "Failed to receive message. Invalid length: %zu\n", length); @@ -320,7 +320,7 @@ static void group_private_message_handler(const Tox_Event_Group_Private_Message ck_assert(s_err == TOX_ERR_GROUP_SELF_QUERY_OK); ck_assert(memcmp(self_name, PEER1_NICK, self_name_len) == 0); - printf("%s sent private action to %s: %s\n", peer_name, self_name, message_buf); + printf("%s sent private action to %s:(id: %u) %s\n", peer_name, self_name, pseudo_msg_id, message_buf); ck_assert(memcmp(message_buf, TEST_PRIVATE_MESSAGE, length) == 0); ck_assert(type == TOX_MESSAGE_TYPE_ACTION); @@ -328,6 +328,7 @@ static void group_private_message_handler(const Tox_Event_Group_Private_Message State *state = (State *)autotox->state; state->private_message_received = true; + state->pseudo_msg_id = pseudo_msg_id; } static void group_message_handler_lossless_test(const Tox_Event_Group_Message *event, void *user_data) @@ -435,7 +436,8 @@ static void group_message_test(AutoTox *autotoxes) } } - ck_assert_msg(state0->pseudo_msg_id == state1->pseudo_msg_id, "id0:%u id1:%u", state0->pseudo_msg_id, state1->pseudo_msg_id); + ck_assert_msg(state0->pseudo_msg_id == state1->pseudo_msg_id, "id0:%u id1:%u", + state0->pseudo_msg_id, state1->pseudo_msg_id); // Make sure we're still connected to each friend Tox_Connection conn_1 = tox_friend_get_connection_status(tox0, 0, nullptr); @@ -460,14 +462,23 @@ static void group_message_test(AutoTox *autotoxes) tox_group_set_ignore(tox0, group_number, state0->peer_id, false, &ig_err); ck_assert_msg(ig_err == TOX_ERR_GROUP_SET_IGNORE_OK, "%d", ig_err); - fprintf(stderr, "Sending private message...\n"); + fprintf(stderr, "Sending private action...\n"); - // tox0 sends a private action to tox1 + // tox1 sends a private action to tox0 Tox_Err_Group_Send_Private_Message m_err; - tox_group_send_private_message(tox1, group_number, state1->peer_id, TOX_MESSAGE_TYPE_ACTION, - (const uint8_t *)TEST_PRIVATE_MESSAGE, TEST_PRIVATE_MESSAGE_LEN, &m_err); + state1->pseudo_msg_id = tox_group_send_private_message(tox1, group_number, state1->peer_id, + TOX_MESSAGE_TYPE_ACTION, (const uint8_t *)TEST_PRIVATE_MESSAGE, + TEST_PRIVATE_MESSAGE_LEN, &m_err); + ck_assert_msg(m_err == TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_OK, "%d", m_err); + while (!state0->private_message_received) { + iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL); + } + + ck_assert_msg(state0->pseudo_msg_id == state1->pseudo_msg_id, "id0:%u id1:%u", + state0->pseudo_msg_id, state1->pseudo_msg_id); + fprintf(stderr, "Sending custom packets...\n"); // tox0 sends a lossless and lossy custom packet to tox1 @@ -496,8 +507,7 @@ static void group_message_test(AutoTox *autotoxes) ck_assert_msg(cperr == TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_OK, "%d", cperr); - while (!state0->private_message_received || state0->custom_packets_received < 2 - || state0->custom_private_packets_received < 2) { + while (state0->custom_packets_received < 2 || state0->custom_private_packets_received < 2) { iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL); } diff --git a/other/event_tooling/generate_event_c.cpp b/other/event_tooling/generate_event_c.cpp index 5f624b0192..de5e52ac8e 100644 --- a/other/event_tooling/generate_event_c.cpp +++ b/other/event_tooling/generate_event_c.cpp @@ -757,6 +757,7 @@ int main(int argc, char** argv) { EventTypeTrivial{"uint32_t", "peer_id"}, EventTypeTrivial{"Tox_Message_Type", "type"}, EventTypeByteRange{"message", "message_length", "length"}, // the latter two are ideally the same + EventTypeTrivial{"uint32_t", "message_id"}, } }, { diff --git a/toxcore/events/group_private_message.c b/toxcore/events/group_private_message.c index 648f707880..a9efdd526c 100644 --- a/toxcore/events/group_private_message.c +++ b/toxcore/events/group_private_message.c @@ -30,6 +30,7 @@ struct Tox_Event_Group_Private_Message { Tox_Message_Type type; uint8_t *message; uint32_t message_length; + uint32_t message_id; }; non_null() @@ -110,6 +111,19 @@ const uint8_t *tox_event_group_private_message_get_message(const Tox_Event_Group return group_private_message->message; } +non_null() +static void tox_event_group_private_message_set_message_id(Tox_Event_Group_Private_Message *group_private_message, + uint32_t message_id) +{ + assert(group_private_message != nullptr); + group_private_message->message_id = message_id; +} +uint32_t tox_event_group_private_message_get_message_id(const Tox_Event_Group_Private_Message *group_private_message) +{ + assert(group_private_message != nullptr); + return group_private_message->message_id; +} + non_null() static void tox_event_group_private_message_construct(Tox_Event_Group_Private_Message *group_private_message) { @@ -126,11 +140,12 @@ static void tox_event_group_private_message_destruct(Tox_Event_Group_Private_Mes bool tox_event_group_private_message_pack( const Tox_Event_Group_Private_Message *event, Bin_Pack *bp) { - return bin_pack_array(bp, 4) + return bin_pack_array(bp, 5) && bin_pack_u32(bp, event->group_number) && bin_pack_u32(bp, event->peer_id) && tox_message_type_pack(event->type, bp) - && bin_pack_bin(bp, event->message, event->message_length); + && bin_pack_bin(bp, event->message, event->message_length) + && bin_pack_u32(bp, event->message_id); } non_null() @@ -138,14 +153,15 @@ static bool tox_event_group_private_message_unpack_into( Tox_Event_Group_Private_Message *event, Bin_Unpack *bu) { assert(event != nullptr); - if (!bin_unpack_array_fixed(bu, 4, nullptr)) { + if (!bin_unpack_array_fixed(bu, 5, nullptr)) { return false; } return bin_unpack_u32(bu, &event->group_number) && bin_unpack_u32(bu, &event->peer_id) && tox_message_type_unpack(&event->type, bu) - && bin_unpack_bin(bu, &event->message, &event->message_length); + && bin_unpack_bin(bu, &event->message, &event->message_length) + && bin_unpack_u32(bu, &event->message_id); } /***************************************************** @@ -238,7 +254,7 @@ static Tox_Event_Group_Private_Message *tox_event_group_private_message_alloc(vo *****************************************************/ void tox_events_handle_group_private_message( - Tox *tox, uint32_t group_number, uint32_t peer_id, Tox_Message_Type type, const uint8_t *message, size_t length, + Tox *tox, uint32_t group_number, uint32_t peer_id, Tox_Message_Type type, const uint8_t *message, size_t length, uint32_t message_id, void *user_data) { Tox_Event_Group_Private_Message *group_private_message = tox_event_group_private_message_alloc(user_data); @@ -251,4 +267,5 @@ void tox_events_handle_group_private_message( tox_event_group_private_message_set_peer_id(group_private_message, peer_id); tox_event_group_private_message_set_type(group_private_message, type); tox_event_group_private_message_set_message(group_private_message, message, length); + tox_event_group_private_message_set_message_id(group_private_message, message_id); } diff --git a/toxcore/group_chats.c b/toxcore/group_chats.c index 6bee144836..03077d0806 100644 --- a/toxcore/group_chats.c +++ b/toxcore/group_chats.c @@ -4911,11 +4911,12 @@ int gc_send_message(const GC_Chat *chat, const uint8_t *message, uint16_t length return -5; } + free(message_raw); + if (message_id != nullptr) { *message_id = pseudo_msg_id; } - free(message_raw); return 0; } @@ -4955,7 +4956,7 @@ static int handle_gc_message(const GC_Session *c, const GC_Chat *chat, const GC_ } int gc_send_private_message(const GC_Chat *chat, GC_Peer_Id peer_id, uint8_t type, const uint8_t *message, - uint16_t length) + uint16_t length, uint32_t *message_id) { if (length > MAX_GC_MESSAGE_SIZE) { return -1; @@ -4981,23 +4982,28 @@ int gc_send_private_message(const GC_Chat *chat, GC_Peer_Id peer_id, uint8_t typ return -5; } - uint8_t *message_with_type = (uint8_t *)malloc(length + 1); + const uint16_t raw_length = 1 + length + GC_MESSAGE_PSEUDO_ID_SIZE; + uint8_t *message_with_type = (uint8_t *)malloc(raw_length); if (message_with_type == nullptr) { return -6; } message_with_type[0] = type; - memcpy(message_with_type + 1, message, length); - uint8_t *packet = (uint8_t *)malloc(length + 1 + GC_BROADCAST_ENC_HEADER_SIZE); + const uint32_t pseudo_msg_id = random_u32(chat->rng); + net_pack_u32(message_with_type + 1, pseudo_msg_id); + + memcpy(message_with_type + 1 + GC_MESSAGE_PSEUDO_ID_SIZE, message, length); + + uint8_t *packet = (uint8_t *)malloc(raw_length + GC_BROADCAST_ENC_HEADER_SIZE); if (packet == nullptr) { free(message_with_type); return -6; } - const uint16_t packet_len = make_gc_broadcast_header(message_with_type, length + 1, packet, GM_PRIVATE_MESSAGE); + const uint16_t packet_len = make_gc_broadcast_header(message_with_type, raw_length, packet, GM_PRIVATE_MESSAGE); free(message_with_type); @@ -5008,6 +5014,10 @@ int gc_send_private_message(const GC_Chat *chat, GC_Peer_Id peer_id, uint8_t typ free(packet); + if (message_id != nullptr) { + *message_id = pseudo_msg_id; + } + return 0; } @@ -5020,7 +5030,7 @@ non_null(1, 2, 3, 4) nullable(6) static int handle_gc_private_message(const GC_Session *c, const GC_Chat *chat, const GC_Peer *peer, const uint8_t *data, uint16_t length, void *userdata) { - if (data == nullptr || length > MAX_GC_MESSAGE_SIZE || length <= 1) { + if (data == nullptr || length > MAX_GC_MESSAGE_SIZE || length <= 1 + GC_MESSAGE_PSEUDO_ID_SIZE) { return -1; } @@ -5035,8 +5045,13 @@ static int handle_gc_private_message(const GC_Session *c, const GC_Chat *chat, c return 0; } + uint32_t message_id; + net_unpack_u32(data + 1, &message_id); + if (c->private_message != nullptr) { - c->private_message(c->messenger, chat->group_number, peer->peer_id, message_type, data + 1, length - 1, userdata); + c->private_message(c->messenger, chat->group_number, peer->peer_id, message_type, + data + 1 + GC_MESSAGE_PSEUDO_ID_SIZE, length - 1 - GC_MESSAGE_PSEUDO_ID_SIZE, + message_id, userdata); } return 0; diff --git a/toxcore/group_chats.h b/toxcore/group_chats.h index 6c85e99822..d22ce400e6 100644 --- a/toxcore/group_chats.h +++ b/toxcore/group_chats.h @@ -181,9 +181,9 @@ int gc_send_message(const GC_Chat *chat, const uint8_t *message, uint16_t length * Returns -5 if the sender has the observer role. * Returns -6 if the packet fails to send. */ -non_null() +non_null(1, 4) nullable(6) int gc_send_private_message(const GC_Chat *chat, GC_Peer_Id peer_id, uint8_t type, const uint8_t *message, - uint16_t length); + uint16_t length, uint32_t *message_id); /** @brief Sends a custom packet to the group. If lossless is true, the packet will be lossless. * diff --git a/toxcore/group_common.h b/toxcore/group_common.h index bb1e6f9a64..daa8fe17c8 100644 --- a/toxcore/group_common.h +++ b/toxcore/group_common.h @@ -348,7 +348,7 @@ typedef struct Messenger Messenger; typedef void gc_message_cb(const Messenger *m, uint32_t group_number, GC_Peer_Id peer_id, unsigned int type, const uint8_t *message, size_t length, uint32_t message_id, void *user_data); typedef void gc_private_message_cb(const Messenger *m, uint32_t group_number, GC_Peer_Id peer_id, unsigned int type, - const uint8_t *message, size_t length, void *user_data); + const uint8_t *message, size_t length, uint32_t message_id, void *user_data); typedef void gc_custom_packet_cb(const Messenger *m, uint32_t group_number, GC_Peer_Id peer_id, const uint8_t *data, size_t length, void *user_data); typedef void gc_custom_private_packet_cb(const Messenger *m, uint32_t group_number, GC_Peer_Id peer_id, diff --git a/toxcore/tox.c b/toxcore/tox.c index 706ccb8985..9c414999df 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -536,16 +536,16 @@ static void tox_group_message_handler(const Messenger *m, uint32_t group_number, } } -non_null(1, 5) nullable(7) +non_null(1, 5) nullable(8) static void tox_group_private_message_handler(const Messenger *m, uint32_t group_number, GC_Peer_Id peer_id, - unsigned int type, const uint8_t *message, size_t length, void *user_data) + unsigned int type, const uint8_t *message, size_t length, uint32_t message_id, void *user_data) { struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data; if (tox_data->tox->group_private_message_callback != nullptr) { tox_unlock(tox_data->tox); tox_data->tox->group_private_message_callback(tox_data->tox, group_number, gc_peer_id_to_int(peer_id), (Tox_Message_Type)type, message, - length, tox_data->user_data); + length, message_id, tox_data->user_data); tox_lock(tox_data->tox); } } @@ -3994,8 +3994,8 @@ Tox_Group_Message_Id tox_group_send_message( return -1; } -bool tox_group_send_private_message(const Tox *tox, uint32_t group_number, uint32_t peer_id, Tox_Message_Type type, - const uint8_t *message, size_t length, Tox_Err_Group_Send_Private_Message *error) +Tox_Group_Message_Id tox_group_send_private_message(const Tox *tox, uint32_t group_number, uint32_t peer_id, + Tox_Message_Type type, const uint8_t *message, size_t length, Tox_Err_Group_Send_Private_Message *error) { assert(tox != nullptr); @@ -4005,59 +4005,60 @@ bool tox_group_send_private_message(const Tox *tox, uint32_t group_number, uint3 if (chat == nullptr) { SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_GROUP_NOT_FOUND); tox_unlock(tox); - return false; + return -1; } if (chat->connection_state == CS_DISCONNECTED) { SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_DISCONNECTED); tox_unlock(tox); - return false; + return -1; } - const int ret = gc_send_private_message(chat, gc_peer_id_from_int(peer_id), type, message, length); + uint32_t message_id = 0; + const int ret = gc_send_private_message(chat, gc_peer_id_from_int(peer_id), type, message, length, &message_id); tox_unlock(tox); switch (ret) { case 0: { SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_OK); - return true; + return message_id; } case -1: { SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_TOO_LONG); - return false; + return -1; } case -2: { SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_EMPTY); - return false; + return -1; } case -3: { SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_PEER_NOT_FOUND); - return false; + return -1; } case -4: { SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_BAD_TYPE); - return false; + return -1; } case -5: { SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_PERMISSIONS); - return false; + return -1; } case -6: { SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_FAIL_SEND); - return false; + return -1; } } /* can't happen */ LOGGER_FATAL(tox->m->log, "impossible return value: %d", ret); - return false; + return -1; } bool tox_group_send_custom_packet(const Tox *tox, uint32_t group_number, bool lossless, const uint8_t *data, diff --git a/toxcore/tox.h b/toxcore/tox.h index 9ba9ab366a..79b8c0fae0 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -4575,7 +4575,7 @@ const char *tox_err_group_send_private_message_to_string(Tox_Err_Group_Send_Priv * * @return true on success. */ -bool tox_group_send_private_message( +Tox_Group_Message_Id tox_group_send_private_message( const Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id, Tox_Message_Type type, const uint8_t message[], size_t length, Tox_Err_Group_Send_Private_Message *error); @@ -4753,7 +4753,7 @@ void tox_callback_group_message(Tox *tox, tox_group_message_cb *callback); */ typedef void tox_group_private_message_cb( Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id, Tox_Message_Type type, - const uint8_t message[], size_t length, void *user_data); + const uint8_t message[], size_t length, uint32_t message_id, void *user_data); /** * Set the callback for the `group_private_message` event. Pass NULL to unset. diff --git a/toxcore/tox_events.h b/toxcore/tox_events.h index 3edaa7d06b..73068829e0 100644 --- a/toxcore/tox_events.h +++ b/toxcore/tox_events.h @@ -268,6 +268,8 @@ const uint8_t *tox_event_group_private_message_get_message( const Tox_Event_Group_Private_Message *group_private_message); uint32_t tox_event_group_private_message_get_message_length( const Tox_Event_Group_Private_Message *group_private_message); +uint32_t tox_event_group_private_message_get_message_id( + const Tox_Event_Group_Private_Message *group_private_message); typedef struct Tox_Event_Group_Custom_Packet Tox_Event_Group_Custom_Packet; uint32_t tox_event_group_custom_packet_get_group_number(