Skip to content

Commit fc06506

Browse files
committed
fix: Allow peers to reconnect to group chats using a password
This commit deprecates the tox_group_reconnect groupchat API function and modifies the tox_group_join function to automatically reconnect to groups when it's called with a chat_id that designates a group that it's already a member of. This allows clients to implement group rejoin functionality that lets peers rejoin/reconnect to groups with a passed password argument, which may be necessary if the group password changes while a peer is offline. This fixes the bug described in #2806.
1 parent 11ab1d2 commit fc06506

File tree

5 files changed

+67
-43
lines changed

5 files changed

+67
-43
lines changed

auto_tests/group_general_test.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -392,9 +392,9 @@ static void group_announce_test(AutoTox *autotoxes)
392392
ck_assert(s_err == TOX_ERR_GROUP_SELF_STATUS_SET_OK);
393393

394394
fprintf(stderr, "Peer 0 reconnecting...\n");
395-
Tox_Err_Group_Reconnect r_err;
396-
tox_group_reconnect(tox0, groupnumber, &r_err);
397-
ck_assert(r_err == TOX_ERR_GROUP_RECONNECT_OK);
395+
Tox_Err_Group_Join err_rejoin;
396+
tox_group_join(tox0, chat_id, (const uint8_t *)PEER0_NICK, PEER0_NICK_LEN, nullptr, 0, &err_rejoin);
397+
ck_assert(err_rejoin == TOX_ERR_GROUP_JOIN_OK);
398398

399399
while (state1->peer_joined_count != 2 && state0->self_joined_count == 2) {
400400
iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);

toxcore/group_chats.c

Lines changed: 55 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -7733,10 +7733,52 @@ int gc_group_add(GC_Session *c, Group_Privacy_State privacy_state,
77337733
return group_number;
77347734
}
77357735

7736+
int gc_rejoin_group(GC_Session *c, GC_Chat *chat, const uint8_t *passwd, uint16_t passwd_len)
7737+
{
7738+
if (c == nullptr) {
7739+
LOGGER_ERROR(chat->log, "NULL group session pointer.");
7740+
return -1;
7741+
}
7742+
7743+
if (passwd != nullptr && passwd_len > 0) {
7744+
if (!set_gc_password_local(chat, passwd, passwd_len)) {
7745+
LOGGER_WARNING(chat->log, "Failed to set new password during reconnect.");
7746+
}
7747+
}
7748+
7749+
chat->time_connected = 0;
7750+
7751+
if (group_can_handle_packets(chat)) {
7752+
send_gc_self_exit(chat, nullptr, 0);
7753+
}
7754+
7755+
for (uint32_t i = 1; i < chat->numpeers; ++i) {
7756+
GC_Connection *gconn = get_gc_connection(chat, i);
7757+
assert(gconn != nullptr);
7758+
7759+
gcc_mark_for_deletion(gconn, chat->tcp_conn, GC_EXIT_TYPE_SELF_DISCONNECTED, nullptr, 0);
7760+
}
7761+
7762+
if (is_public_chat(chat)) {
7763+
kill_group_friend_connection(c, chat);
7764+
7765+
if (!m_create_group_connection(c->messenger, chat)) {
7766+
LOGGER_WARNING(chat->log, "Failed to create new messenger connection for group");
7767+
return -1;
7768+
}
7769+
7770+
chat->update_self_announces = true;
7771+
}
7772+
7773+
chat->connection_state = CS_CONNECTING;
7774+
7775+
return 0;
7776+
}
7777+
77367778
int gc_group_join(GC_Session *c, const uint8_t *chat_id, const uint8_t *nick, size_t nick_length, const uint8_t *passwd,
77377779
uint16_t passwd_len)
77387780
{
7739-
if (chat_id == nullptr || group_exists(c, chat_id) || getfriend_id(c->messenger, chat_id) != -1) {
7781+
if (chat_id == nullptr) {
77407782
return -2;
77417783
}
77427784

@@ -7748,6 +7790,18 @@ int gc_group_join(GC_Session *c, const uint8_t *chat_id, const uint8_t *nick, si
77487790
return -4;
77497791
}
77507792

7793+
GC_Chat *existing_group = gc_get_group_by_public_key(c, chat_id);
7794+
7795+
// If we're already in the group we try to reconnect to it
7796+
if (existing_group != nullptr) {
7797+
const int ret = gc_rejoin_group(c, existing_group, passwd, passwd_len);
7798+
return ret != 0 ? -6 : ret;
7799+
}
7800+
7801+
if (getfriend_id(c->messenger, chat_id) != -1) {
7802+
return -2;
7803+
}
7804+
77517805
const int group_number = create_new_group(c, nick, nick_length, false, GI_PUBLIC);
77527806

77537807
if (group_number == -1) {
@@ -7806,41 +7860,6 @@ bool gc_disconnect_from_group(const GC_Session *c, GC_Chat *chat)
78067860
return true;
78077861
}
78087862

7809-
int gc_rejoin_group(GC_Session *c, GC_Chat *chat)
7810-
{
7811-
if (c == nullptr || chat == nullptr) {
7812-
return -1;
7813-
}
7814-
7815-
chat->time_connected = 0;
7816-
7817-
if (group_can_handle_packets(chat)) {
7818-
send_gc_self_exit(chat, nullptr, 0);
7819-
}
7820-
7821-
for (uint32_t i = 1; i < chat->numpeers; ++i) {
7822-
GC_Connection *gconn = get_gc_connection(chat, i);
7823-
assert(gconn != nullptr);
7824-
7825-
gcc_mark_for_deletion(gconn, chat->tcp_conn, GC_EXIT_TYPE_SELF_DISCONNECTED, nullptr, 0);
7826-
}
7827-
7828-
if (is_public_chat(chat)) {
7829-
kill_group_friend_connection(c, chat);
7830-
7831-
if (!m_create_group_connection(c->messenger, chat)) {
7832-
LOGGER_WARNING(chat->log, "Failed to create new messenger connection for group");
7833-
return -2;
7834-
}
7835-
7836-
chat->update_self_announces = true;
7837-
}
7838-
7839-
chat->connection_state = CS_CONNECTING;
7840-
7841-
return 0;
7842-
}
7843-
78447863
bool group_not_added(const GC_Session *c, const uint8_t *chat_id, uint32_t length)
78457864
{
78467865
if (length < CHAT_ID_SIZE) {

toxcore/group_chats.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -676,8 +676,8 @@ bool gc_disconnect_from_group(const GC_Session *c, GC_Chat *chat);
676676
* Returns -1 if the group handler object or chat object is null.
677677
* Returns -2 if the Messenger friend connection fails to initialize.
678678
*/
679-
non_null()
680-
int gc_rejoin_group(GC_Session *c, GC_Chat *chat);
679+
non_null(1, 2) nullable(3)
680+
int gc_rejoin_group(GC_Session *c, GC_Chat *chat, const uint8_t *passwd, uint16_t passwd_len);
681681

682682
/** @brief Joins a group using the invite data received in a friend's group invite.
683683
*

toxcore/tox.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3249,7 +3249,7 @@ bool tox_group_reconnect(Tox *tox, uint32_t group_number, Tox_Err_Group_Reconnec
32493249
return false;
32503250
}
32513251

3252-
const int ret = gc_rejoin_group(tox->m->group_handler, chat);
3252+
const int ret = gc_rejoin_group(tox->m->group_handler, chat, nullptr, 0);
32533253
tox_unlock(tox);
32543254

32553255
switch (ret) {

toxcore/tox.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3717,12 +3717,15 @@ typedef enum Tox_Err_Group_Join {
37173717
const char *tox_err_group_join_to_string(Tox_Err_Group_Join value);
37183718

37193719
/**
3720-
* Joins a group chat with specified Chat ID.
3720+
* Joins a group chat with specified Chat ID or reconnects to an existing group.
37213721
*
37223722
* This function creates a new group chat object, adds it to the chats array,
37233723
* and sends a DHT announcement to find peers in the group associated with
37243724
* chat_id. Once a peer has been found a join attempt will be initiated.
37253725
*
3726+
* If a group with the specified Chat ID already exists, this function will attempt
3727+
* to reconnect to the group.
3728+
*
37263729
* @param chat_id The Chat ID of the group you wish to join. This must be
37273730
* TOX_GROUP_CHAT_ID_SIZE bytes.
37283731
* @param password The password required to join the group. Set to NULL if no
@@ -3827,6 +3830,8 @@ const char *tox_err_group_reconnect_to_string(Tox_Err_Group_Reconnect value);
38273830
* @param group_number The group number of the group we wish to reconnect to.
38283831
*
38293832
* @return true on success.
3833+
*
3834+
* @deprecated Use `tox_group_join` instead.
38303835
*/
38313836
bool tox_group_reconnect(Tox *tox, Tox_Group_Number group_number, Tox_Err_Group_Reconnect *error);
38323837

0 commit comments

Comments
 (0)