Skip to content

Commit

Permalink
Make conferences persistent across restarts and reconnects.
Browse files Browse the repository at this point in the history
This is not new groupchats. This is just upgrade to old groupchats with
some advantages:
- Groupchats are now saved into tox_save.
- Clients can get groupchat unique id to save message log.
- Auto restore groupchats after restart even your friend uses
  non-upgraded version.
  • Loading branch information
isotoxin authored and iphydf committed Jul 28, 2018
1 parent 1f27fcb commit bf2f3c0
Show file tree
Hide file tree
Showing 13 changed files with 2,776 additions and 1,071 deletions.
2 changes: 1 addition & 1 deletion auto_tests/conference_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
#include "../toxcore/util.h"
#include "check_compat.h"

#define NUM_GROUP_TOX 5
#define NUM_GROUP_TOX 16
#define GROUP_MESSAGE "Install Gentoo"

static void handle_self_connection_status(
Expand Down
15 changes: 15 additions & 0 deletions conference-stress-test
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/usr/bin/make -f

RESULTS := $(foreach i,$(shell seq 0 10),$(shell printf "results/%02d.log" $i))

.SILENT:
run: $(RESULTS)

results/%.log: auto_conference_test
echo "TEST $< > $@"
mkdir -p $(@D)
./auto_conference_test > $@ 2>&1

.PHONY: auto_conference_test
auto_conference_test:
$(MAKE) $@
10 changes: 5 additions & 5 deletions toxav/groupav.c
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,7 @@ static int groupchat_enable_av(const Logger *log, Group_Chats *g_c, uint32_t gro
int add_av_groupchat(const Logger *log, Group_Chats *g_c, void (*audio_callback)(Messenger *, uint32_t, uint32_t,
const int16_t *, unsigned int, uint8_t, uint32_t, void *), void *userdata)
{
int groupnumber = add_groupchat(g_c, GROUPCHAT_TYPE_AV);
int groupnumber = add_groupchat(g_c, GROUPCHAT_TYPE_AV, nullptr);

if (groupnumber == -1) {
return -1;
Expand All @@ -475,21 +475,21 @@ int add_av_groupchat(const Logger *log, Group_Chats *g_c, void (*audio_callback)
/* Join a AV group (you need to have been invited first.)
*
* returns group number on success
* returns -1 on failure.
* returns -1 .. -6 on failure (see join_groupchat)
*/
int join_av_groupchat(const Logger *log, Group_Chats *g_c, uint32_t friendnumber, const uint8_t *data, uint16_t length,
void (*audio_callback)(Messenger *, uint32_t, uint32_t, const int16_t *, unsigned int, uint8_t, uint32_t, void *),
void *userdata)
{
int groupnumber = join_groupchat(g_c, friendnumber, GROUPCHAT_TYPE_AV, data, length);

if (groupnumber == -1) {
return -1;
if (groupnumber < 0) {
return groupnumber;
}

if (groupchat_enable_av(log, g_c, groupnumber, audio_callback, userdata) == -1) {
del_groupchat(g_c, groupnumber);
return -1;
return -5; /* initialization failed */
}

return groupnumber;
Expand Down
2 changes: 1 addition & 1 deletion toxav/toxav.api.h
Original file line number Diff line number Diff line change
Expand Up @@ -622,7 +622,7 @@ int toxav_add_av_groupchat(Tox *tox, void (*audio_callback)(void *, uint32_t, ui
/* Join a AV group (you need to have been invited first.)
*
* returns group number on success
* returns -1 on failure.
* returns < 0 on failure.
*
* Audio data callback format (same as the one for toxav_add_av_groupchat()):
* audio_callback(Tox *tox, uint32_t groupnumber, uint32_t peernumber, const int16_t *pcm, unsigned int samples, uint8_t channels, uint32_t sample_rate, void *userdata)
Expand Down
2 changes: 1 addition & 1 deletion toxav/toxav.h
Original file line number Diff line number Diff line change
Expand Up @@ -751,7 +751,7 @@ int toxav_add_av_groupchat(Tox *tox, void (*audio_callback)(void *, uint32_t, ui
/* Join a AV group (you need to have been invited first.)
*
* returns group number on success
* returns -1 on failure.
* returns < 0 on failure.
*
* Audio data callback format (same as the one for toxav_add_av_groupchat()):
* audio_callback(Tox *tox, uint32_t groupnumber, uint32_t peernumber, const int16_t *pcm, unsigned int samples, uint8_t channels, uint32_t sample_rate, void *userdata)
Expand Down
2 changes: 1 addition & 1 deletion toxav/toxav_old.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ int toxav_add_av_groupchat(Tox *tox, void (*audio_callback)(void *, uint32_t, ui
/* Join a AV group (you need to have been invited first.)
*
* returns group number on success
* returns -1 on failure.
* returns < 0 on failure.
*
* Audio data callback format (same as the one for toxav_add_av_groupchat()):
* audio_callback(Tox *tox, int groupnumber, int peernumber, const int16_t *pcm, unsigned int samples, uint8_t channels, unsigned int sample_rate, void *userdata)
Expand Down
50 changes: 49 additions & 1 deletion toxcore/Messenger.c
Original file line number Diff line number Diff line change
Expand Up @@ -2749,6 +2749,7 @@ void do_messenger(Messenger *m, void *userdata)
#define MESSENGER_STATE_TYPE_STATUS 6
#define MESSENGER_STATE_TYPE_TCP_RELAY 10
#define MESSENGER_STATE_TYPE_PATH_NODE 11
#define MESSENGER_STATE_TYPE_CONFERENCES 100
#define MESSENGER_STATE_TYPE_END 255

#define SAVED_FRIEND_REQUEST_SIZE 1024
Expand Down Expand Up @@ -2966,6 +2967,32 @@ static int friends_list_load(Messenger *m, const uint8_t *data, uint32_t length)
return num;
}

// Empty definitions of the conference load/save functions. These are set if the
// groups module is loaded. In tox_new, the group module is initialised, so
// public API users will never see calls to these functions.
static uint32_t saved_conferences_size_default(const Messenger *m)
{
return 0;
}
static void conferences_save_default(const Messenger *m, uint8_t *data)
{
return;
}
static int conferences_load_default(Messenger *m, const uint8_t *data, uint32_t length)
{
return 0;
}

// HACK HACK HACK to make conferences load/save work.
// TODO(robinlinden): Refactor this.
//!TOKSTYLE-
// Invalid in TokTok style, because we don't allow global mutable state.
saved_conferences_size_cb *saved_conferences_size_ptr = saved_conferences_size_default;
conferences_save_cb *conferences_save_ptr = conferences_save_default;
conferences_load_cb *conferences_load_ptr = conferences_load_default;
//!TOKSTYLE+


/* return size of the messenger data (for saving) */
uint32_t messenger_size(const Messenger *m)
{
Expand All @@ -2979,6 +3006,7 @@ uint32_t messenger_size(const Messenger *m)
+ sizesubhead + 1 // status
+ sizesubhead + NUM_SAVED_TCP_RELAYS * packed_node_size(net_family_tcp_ipv6) // TCP relays
+ sizesubhead + NUM_SAVED_PATH_NODES * packed_node_size(net_family_tcp_ipv6) // saved path nodes
+ sizesubhead + saved_conferences_size_ptr(m) // old group chats
+ sizesubhead;
}

Expand Down Expand Up @@ -3070,6 +3098,12 @@ void messenger_save(const Messenger *m, uint8_t *data)
data += len;
}

len = saved_conferences_size_ptr(m);
type = MESSENGER_STATE_TYPE_CONFERENCES;
data = messenger_save_subheader(data, len, type);
conferences_save_ptr(m, data);
data += len;

messenger_save_subheader(data, 0, MESSENGER_STATE_TYPE_END);
}

Expand Down Expand Up @@ -3148,6 +3182,20 @@ static State_Load_Status messenger_load_state_callback(void *outer, const uint8_
break;
}

case MESSENGER_STATE_TYPE_CONFERENCES: {
int err = conferences_load_ptr(m, data, length);

/* No need to do something special if err < 0
* err < 0 just means that conferences data was damaged
* and skipped
*/
if (err < 0) {
LOGGER_ERROR(m->log, "conference savedata was corrupted");
}

break;
}

case MESSENGER_STATE_TYPE_END: {
if (length != 0) {
return STATE_LOAD_STATUS_ERROR;
Expand All @@ -3157,7 +3205,7 @@ static State_Load_Status messenger_load_state_callback(void *outer, const uint8_
}

default:
LOGGER_ERROR(m->log, "Load state: contains unrecognized part (len %u, type %u)\n",
LOGGER_ERROR(m->log, "Load state: contains unrecognized part (len %u, type %u)",
length, type);
break;
}
Expand Down
10 changes: 10 additions & 0 deletions toxcore/Messenger.h
Original file line number Diff line number Diff line change
Expand Up @@ -781,4 +781,14 @@ uint32_t count_friendlist(const Messenger *m);
* of out_list will be truncated to list_size. */
uint32_t copy_friendlist(const Messenger *m, uint32_t *out_list, uint32_t list_size);

typedef uint32_t saved_conferences_size_cb(const Messenger *m);
typedef void conferences_save_cb(const Messenger *m, uint8_t *data);
typedef int conferences_load_cb(Messenger *m, const uint8_t *data, uint32_t length);

// HACK HACK HACK to make conferences load/save work.
// TODO(robinlinden): Refactor this.
extern saved_conferences_size_cb *saved_conferences_size_ptr;
extern conferences_save_cb *conferences_save_ptr;
extern conferences_load_cb *conferences_load_ptr;

#endif
Loading

0 comments on commit bf2f3c0

Please sign in to comment.