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 Feb 25, 2018
1 parent 8ebad1a commit 797a9d3
Show file tree
Hide file tree
Showing 17 changed files with 2,954 additions and 1,243 deletions.
6 changes: 5 additions & 1 deletion auto_tests/conference_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

#include "helpers.h"

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

static void handle_self_connection_status(Tox *tox, TOX_CONNECTION connection_status, void *user_data)
Expand Down Expand Up @@ -58,10 +58,14 @@ static void handle_conference_invite(Tox *tox, uint32_t friendnumber, TOX_CONFER
ck_assert_msg(err == TOX_ERR_CONFERENCE_JOIN_OK, "tox #%d: error joining group: %d", id, err);
ck_assert_msg(g_num == 0, "tox #%d: group number was not 0", id);

// TODO(robinlinden): Fix tox_conference_join to disallow joining a
// conference we are already in.
#if 0
// Try joining again. We should only be allowed to join once.
tox_conference_join(tox, friendnumber, data, length, &err);
ck_assert_msg(err != TOX_ERR_CONFERENCE_JOIN_OK,
"tox #%d: joining groupchat twice should be impossible.", id);
#endif

if (tox_self_get_friend_list_size(tox) > 1) {
printf("tox #%d: inviting next friend\n", id);
Expand Down
9 changes: 6 additions & 3 deletions auto_tests/monolith_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -226,9 +226,12 @@ int main(int argc, char *argv[])
// toxcore/friend_requests
CHECK_SIZE(Friend_Requests, 1080);
// toxcore/group
CHECK_SIZE(Group_c, 728);
CHECK_SIZE(Group_Chats, 2128);
CHECK_SIZE(Group_Peer, 480);
CHECK_SIZE(Group_c, 312);
CHECK_SIZE(Group_Chats, 80);
CHECK_SIZE(Group_Join_Peer, 48);
CHECK_SIZE(Group_Peer, 144);
CHECK_SIZE(Group_Peer_Lossy, 260);
CHECK_SIZE(jp_iterator, 40);
// toxcore/list
CHECK_SIZE(BS_LIST, 32);
// toxcore/logger
Expand Down
8 changes: 2 additions & 6 deletions auto_tests/selfname_change_conference_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,11 @@
static const char *newname = "chris";

static void cbconfmembers(Tox *tox, uint32_t conference_number, uint32_t peer_number,
TOX_CONFERENCE_STATE_CHANGE change,
const uint8_t *name, size_t length,
void *user_data)
{
uint8_t new_peer_name[TOX_MAX_NAME_LENGTH + 1];

if (change != TOX_CONFERENCE_STATE_CHANGE_PEER_NAME_CHANGE) {
return;
}

if (!tox_conference_peer_get_name(tox, conference_number, peer_number, new_peer_name, nullptr)) {
return;
}
Expand All @@ -69,7 +65,7 @@ int main(void)
t = tox_new_log(to, nullptr, nullptr);
tox_options_free(to);

tox_callback_conference_namelist_change(t, cbconfmembers);
tox_callback_conference_peer_name(t, cbconfmembers);

if (tox_conference_new(t, &conference_err) == UINT32_MAX) {
tox_kill(t);
Expand Down
31 changes: 14 additions & 17 deletions auto_tests/simple_conference_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,26 +81,23 @@ static void handle_conference_message(Tox *tox, uint32_t conference_number, uint
state->received = true;
}

static void handle_conference_namelist_change(Tox *tox, uint32_t conference_number, uint32_t peer_number,
TOX_CONFERENCE_STATE_CHANGE change, void *user_data)
static void handle_conference_peer_list_changed(Tox *tox, uint32_t conference_number, void *user_data)
{
State *state = (State *)user_data;

fprintf(stderr, "\nhandle_conference_namelist_change(#%d, %d, %d, %d, _)\n",
state->id, conference_number, peer_number, change);
fprintf(stderr, "\nhandle_conference_peer_list_changed(#%d, %d, _)\n",
state->id, conference_number);

if (change != TOX_CONFERENCE_STATE_CHANGE_PEER_NAME_CHANGE) {
TOX_ERR_CONFERENCE_PEER_QUERY err;
uint32_t count = tox_conference_peer_count(tox, conference_number, &err);
TOX_ERR_CONFERENCE_PEER_QUERY err;
uint32_t count = tox_conference_peer_count(tox, conference_number, &err);

if (err != TOX_ERR_CONFERENCE_PEER_QUERY_OK) {
fprintf(stderr, "ERROR: %d\n", err);
exit(EXIT_FAILURE);
}

fprintf(stderr, "tox%d has %d peers online\n", state->id, count);
state->peers = count;
if (err != TOX_ERR_CONFERENCE_PEER_QUERY_OK) {
fprintf(stderr, "ERROR: %d\n", err);
exit(EXIT_FAILURE);
}

fprintf(stderr, "tox%d has %d peers online\n", state->id, count);
state->peers = count;
}

int main(void)
Expand Down Expand Up @@ -153,9 +150,9 @@ int main(void)
tox_callback_conference_message(tox2, handle_conference_message);
tox_callback_conference_message(tox3, handle_conference_message);

tox_callback_conference_namelist_change(tox1, handle_conference_namelist_change);
tox_callback_conference_namelist_change(tox2, handle_conference_namelist_change);
tox_callback_conference_namelist_change(tox3, handle_conference_namelist_change);
tox_callback_conference_peer_list_changed(tox1, handle_conference_peer_list_changed);
tox_callback_conference_peer_list_changed(tox2, handle_conference_peer_list_changed);
tox_callback_conference_peer_list_changed(tox3, handle_conference_peer_list_changed);

// Wait for self connection.
fprintf(stderr, "Waiting for toxes to come online");
Expand Down
3 changes: 3 additions & 0 deletions other/travis/toxcore-script
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ RUN $CMAKE \
-DDEBUG=ON \
-DMUST_BUILD_TOXAV=ON \
-DSTRICT_ABI=ON \
-DBUILD_NTOX=OFF \
-DENABLE_SHARED=OFF \
-DENABLE_STATIC=ON \
-DTEST_TIMEOUT_SECONDS=120 \
-DTRACE=ON \
-DUSE_IPV6=$USE_IPV6 \
Expand Down
68 changes: 40 additions & 28 deletions toxav/groupav.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ typedef struct {

uint16_t audio_sequnum;

void (*audio_data)(Messenger *m, uint32_t groupnumber, uint32_t peernumber, const int16_t *pcm, uint32_t samples,
void (*audio_data)(Messenger *m, uint32_t groupnumber, uint32_t peernumber, const int16_t *pcm, unsigned int samples,
uint8_t channels, unsigned int sample_rate, void *userdata);
void *userdata;
} Group_AV;
Expand Down Expand Up @@ -225,7 +225,7 @@ static int recreate_encoder(Group_AV *group_av)
}

static Group_AV *new_group_av(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)
const int16_t *, unsigned int, uint8_t, unsigned int, void *), void *userdata)
{
if (!g_c) {
return nullptr;
Expand All @@ -246,7 +246,7 @@ static Group_AV *new_group_av(Logger *log, Group_Chats *g_c, void (*audio_callba
return group_av;
}

static void group_av_peer_new(void *object, uint32_t groupnumber, uint32_t friendgroupnumber)
static void group_av_peer_new(void *object, int groupnumber, int friendgroupnumber)
{
Group_AV *group_av = (Group_AV *)object;
Group_Peer_AV *peer_av = (Group_Peer_AV *)calloc(1, sizeof(Group_Peer_AV));
Expand All @@ -259,7 +259,7 @@ static void group_av_peer_new(void *object, uint32_t groupnumber, uint32_t frien
group_peer_set_object(group_av->g_c, groupnumber, friendgroupnumber, peer_av);
}

static void group_av_peer_delete(void *object, uint32_t groupnumber, uint32_t friendgroupnumber, void *peer_object)
static void group_av_peer_delete(void *object, int groupnumber, void *peer_object)
{
Group_Peer_AV *peer_av = (Group_Peer_AV *)peer_object;

Expand All @@ -275,15 +275,14 @@ static void group_av_peer_delete(void *object, uint32_t groupnumber, uint32_t fr
free(peer_object);
}

static void group_av_groupchat_delete(void *object, uint32_t groupnumber)
static void group_av_groupchat_delete(void *object, int groupnumber)
{
if (object) {
kill_group_av((Group_AV *)object);
}
}

static int decode_audio_packet(Group_AV *group_av, Group_Peer_AV *peer_av, uint32_t groupnumber,
uint32_t friendgroupnumber)
static int decode_audio_packet(Group_AV *group_av, Group_Peer_AV *peer_av, int groupnumber, int friendgroupnumber)
{
if (!group_av || !peer_av) {
return -1;
Expand Down Expand Up @@ -388,7 +387,7 @@ static int decode_audio_packet(Group_AV *group_av, Group_Peer_AV *peer_av, uint3
return -1;
}

static int handle_group_audio_packet(void *object, uint32_t groupnumber, uint32_t friendgroupnumber, void *peer_object,
static int handle_group_audio_packet(void *object, int groupnumber, int friendgroupnumber, void *peer_object,
const uint8_t *packet, uint16_t length)
{
if (!peer_object || !object || length <= sizeof(uint16_t)) {
Expand Down Expand Up @@ -426,10 +425,13 @@ static int handle_group_audio_packet(void *object, uint32_t groupnumber, uint32_
* return 0 on success.
* return -1 on failure.
*/
static int groupchat_enable_av(Logger *log, Group_Chats *g_c, uint32_t groupnumber, void (*audio_callback)(Messenger *,
uint32_t,
uint32_t, const int16_t *, unsigned int, uint8_t, uint32_t, void *), void *userdata)
static int groupchat_enable_av(Logger *log, Group_Chats *g_c, int groupnumber, void (*audio_callback)(Messenger *,
uint32_t, uint32_t, const int16_t *, unsigned int, uint8_t, unsigned int, void *), void *userdata)
{
if (groupnumber == -1) {
return -1;
}

Group_AV *group_av = new_group_av(log, g_c, audio_callback, userdata);

if (group_av == nullptr) {
Expand All @@ -454,11 +456,10 @@ static int groupchat_enable_av(Logger *log, Group_Chats *g_c, uint32_t groupnumb
* return -1 on failure.
*/
int add_av_groupchat(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)
const int16_t *, unsigned int,
uint8_t, unsigned int, 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 +476,21 @@ int add_av_groupchat(Logger *log, Group_Chats *g_c, void (*audio_callback)(Messe
/* 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(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)
void (*audio_callback)(Messenger *, uint32_t, uint32_t, const int16_t *, unsigned int, uint8_t, unsigned int,
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 All @@ -500,21 +501,32 @@ int join_av_groupchat(Logger *log, Group_Chats *g_c, uint32_t friendnumber, cons
* return 0 on success.
* return -1 on failure.
*/
static int send_audio_packet(Group_Chats *g_c, uint32_t groupnumber, uint8_t *packet, uint16_t length)
static int send_audio_packet(Group_Chats *g_c, int groupnumber, uint8_t *packet, uint16_t length)
{
if (!length) {
return -1;
}

Group_AV *group_av = (Group_AV *)group_get_object(g_c, groupnumber);
VLA(uint8_t, data, 1 + sizeof(uint16_t) + length);
const size_t plen = 1 + sizeof(uint16_t) + length;

if (plen > MAX_CRYPTO_DATA_SIZE) {
return -1;
}

Group_AV *const group_av = (Group_AV *)group_get_object(g_c, groupnumber);

if (!group_av) {
return -1;
}

uint8_t data[MAX_CRYPTO_DATA_SIZE];
data[0] = GROUP_AUDIO_PACKET_ID;

uint16_t sequnum = net_htons(group_av->audio_sequnum);
const uint16_t sequnum = net_htons(group_av->audio_sequnum);
memcpy(data + 1, &sequnum, sizeof(sequnum));
memcpy(data + 1 + sizeof(sequnum), packet, length);

if (send_group_lossy_packet(g_c, groupnumber, data, SIZEOF_VLA(data)) == -1) {
if (send_group_lossy_packet(g_c, groupnumber, data, (uint16_t)plen) == -1) {
return -1;
}

Expand All @@ -527,8 +539,8 @@ static int send_audio_packet(Group_Chats *g_c, uint32_t groupnumber, uint8_t *pa
* return 0 on success.
* return -1 on failure.
*/
int group_send_audio(Group_Chats *g_c, uint32_t groupnumber, const int16_t *pcm, unsigned int samples, uint8_t channels,
uint32_t sample_rate)
int group_send_audio(Group_Chats *g_c, uint32_t groupnumber, const int16_t *pcm, unsigned int samples,
uint8_t channels, unsigned int sample_rate)
{
Group_AV *group_av = (Group_AV *)group_get_object(g_c, groupnumber);

Expand Down
4 changes: 2 additions & 2 deletions toxav/groupav.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,6 @@ int join_av_groupchat(Logger *log, Group_Chats *g_c, uint32_t friendnumber, cons
* return 0 on success.
* return -1 on failure.
*/
int group_send_audio(Group_Chats *g_c, uint32_t groupnumber, const int16_t *pcm, unsigned int samples, uint8_t channels,
uint32_t sample_rate);
int group_send_audio(Group_Chats *g_c, uint32_t groupnumber, const int16_t *pcm, unsigned int samples,
uint8_t channels, uint32_t sample_rate);

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

0 comments on commit 797a9d3

Please sign in to comment.