diff options
-rw-r--r-- | auto_tests/conference_test.c | 22 | ||||
-rw-r--r-- | toxcore/group.c | 100 | ||||
-rw-r--r-- | toxcore/group.h | 13 | ||||
-rw-r--r-- | toxcore/tox.api.h | 12 | ||||
-rw-r--r-- | toxcore/tox.c | 16 | ||||
-rw-r--r-- | toxcore/tox.h | 22 |
6 files changed, 178 insertions, 7 deletions
diff --git a/auto_tests/conference_test.c b/auto_tests/conference_test.c index 5f08b823..ec88c82a 100644 --- a/auto_tests/conference_test.c +++ b/auto_tests/conference_test.c | |||
@@ -10,6 +10,8 @@ | |||
10 | #include <time.h> | 10 | #include <time.h> |
11 | #include <stdint.h> | 11 | #include <stdint.h> |
12 | 12 | ||
13 | #include "../toxcore/util.h" | ||
14 | |||
13 | #include "check_compat.h" | 15 | #include "check_compat.h" |
14 | 16 | ||
15 | #define NUM_GROUP_TOX 16 | 17 | #define NUM_GROUP_TOX 16 |
@@ -199,6 +201,18 @@ static void run_conference_tests(Tox **toxes, State *state) | |||
199 | * fails due to disconnections too short to trigger freezing */ | 201 | * fails due to disconnections too short to trigger freezing */ |
200 | const bool check_name_change_propagation = false; | 202 | const bool check_name_change_propagation = false; |
201 | 203 | ||
204 | /* each peer should freeze at least its two friends, but freezing more | ||
205 | * should not be necessary */ | ||
206 | const uint32_t max_frozen = max_u32(2, NUM_DISCONNECT / 2); | ||
207 | printf("restricting number of frozen peers to %u\n", max_frozen); | ||
208 | |||
209 | for (uint16_t i = 0; i < NUM_GROUP_TOX; ++i) { | ||
210 | Tox_Err_Conference_Set_Max_Offline err; | ||
211 | tox_conference_set_max_offline(toxes[i], 0, max_frozen, &err); | ||
212 | ck_assert_msg(err == TOX_ERR_CONFERENCE_SET_MAX_OFFLINE_OK, | ||
213 | "tox #%u failed to set max offline: err = %d", state[i].index, err); | ||
214 | } | ||
215 | |||
202 | printf("letting random toxes timeout\n"); | 216 | printf("letting random toxes timeout\n"); |
203 | bool disconnected[NUM_GROUP_TOX] = {0}; | 217 | bool disconnected[NUM_GROUP_TOX] = {0}; |
204 | bool restarting[NUM_GROUP_TOX] = {0}; | 218 | bool restarting[NUM_GROUP_TOX] = {0}; |
@@ -243,6 +257,7 @@ static void run_conference_tests(Tox **toxes, State *state) | |||
243 | free(save[i]); | 257 | free(save[i]); |
244 | 258 | ||
245 | set_mono_time_callback(toxes[i], &state[i]); | 259 | set_mono_time_callback(toxes[i], &state[i]); |
260 | tox_conference_set_max_offline(toxes[i], 0, max_frozen, nullptr); | ||
246 | } | 261 | } |
247 | } | 262 | } |
248 | 263 | ||
@@ -256,6 +271,13 @@ static void run_conference_tests(Tox **toxes, State *state) | |||
256 | } | 271 | } |
257 | } | 272 | } |
258 | 273 | ||
274 | for (uint16_t i = 0; i < NUM_GROUP_TOX; ++i) { | ||
275 | const uint32_t num_frozen = tox_conference_offline_peer_count(toxes[i], 0, nullptr); | ||
276 | ck_assert_msg(num_frozen <= max_frozen, | ||
277 | "tox #%u has too many offline peers: %u\n", | ||
278 | state[i].index, num_frozen); | ||
279 | } | ||
280 | |||
259 | printf("reconnecting toxes\n"); | 281 | printf("reconnecting toxes\n"); |
260 | 282 | ||
261 | do { | 283 | do { |
diff --git a/toxcore/group.c b/toxcore/group.c index 20ee5459..f6f8c704 100644 --- a/toxcore/group.c +++ b/toxcore/group.c | |||
@@ -118,6 +118,8 @@ static bool realloc_conferences(Group_Chats *g_c, uint16_t num) | |||
118 | static void setup_conference(Group_c *g) | 118 | static void setup_conference(Group_c *g) |
119 | { | 119 | { |
120 | memset(g, 0, sizeof(Group_c)); | 120 | memset(g, 0, sizeof(Group_c)); |
121 | |||
122 | g->maxfrozen = MAX_FROZEN_DEFAULT; | ||
121 | } | 123 | } |
122 | 124 | ||
123 | /* Create a new empty groupchat connection. | 125 | /* Create a new empty groupchat connection. |
@@ -644,8 +646,8 @@ static int addpeer(Group_Chats *g_c, uint32_t groupnumber, const uint8_t *real_p | |||
644 | id_copy(g->group[g->numpeers].temp_pk, temp_pk); | 646 | id_copy(g->group[g->numpeers].temp_pk, temp_pk); |
645 | g->group[g->numpeers].temp_pk_updated = true; | 647 | g->group[g->numpeers].temp_pk_updated = true; |
646 | g->group[g->numpeers].peer_number = peer_number; | 648 | g->group[g->numpeers].peer_number = peer_number; |
647 | |||
648 | g->group[g->numpeers].last_active = mono_time_get(g_c->mono_time); | 649 | g->group[g->numpeers].last_active = mono_time_get(g_c->mono_time); |
650 | g->group[g->numpeers].is_friend = (getfriend_id(g_c->m, real_pk) != -1); | ||
649 | ++g->numpeers; | 651 | ++g->numpeers; |
650 | 652 | ||
651 | add_to_closest(g_c, groupnumber, real_pk, temp_pk); | 653 | add_to_closest(g_c, groupnumber, real_pk, temp_pk); |
@@ -752,6 +754,56 @@ static int delpeer(Group_Chats *g_c, uint32_t groupnumber, int peer_index, void | |||
752 | return 0; | 754 | return 0; |
753 | } | 755 | } |
754 | 756 | ||
757 | static int cmp_u64(uint64_t a, uint64_t b) | ||
758 | { | ||
759 | return (a > b) - (a < b); | ||
760 | } | ||
761 | |||
762 | /* Order peers with friends first and with more recently active earlier */ | ||
763 | static int cmp_frozen(const void *a, const void *b) | ||
764 | { | ||
765 | const Group_Peer *pa = (const Group_Peer *) a; | ||
766 | const Group_Peer *pb = (const Group_Peer *) b; | ||
767 | |||
768 | if (pa->is_friend ^ pb->is_friend) { | ||
769 | return pa->is_friend ? -1 : 1; | ||
770 | } | ||
771 | |||
772 | return cmp_u64(pb->last_active, pa->last_active); | ||
773 | } | ||
774 | |||
775 | /* Delete frozen peers as necessary to ensure at most g->maxfrozen remain. | ||
776 | * | ||
777 | * return true if any frozen peers are removed. | ||
778 | */ | ||
779 | static bool delete_old_frozen(Group_c *g) | ||
780 | { | ||
781 | if (g->numfrozen <= g->maxfrozen) { | ||
782 | return false; | ||
783 | } | ||
784 | |||
785 | if (g->maxfrozen == 0) { | ||
786 | free(g->frozen); | ||
787 | g->frozen = nullptr; | ||
788 | g->numfrozen = 0; | ||
789 | return true; | ||
790 | } | ||
791 | |||
792 | qsort(g->frozen, g->numfrozen, sizeof(Group_Peer), cmp_frozen); | ||
793 | |||
794 | Group_Peer *temp = (Group_Peer *)realloc(g->frozen, sizeof(Group_Peer) * g->maxfrozen); | ||
795 | |||
796 | if (temp == nullptr) { | ||
797 | return false; | ||
798 | } | ||
799 | |||
800 | g->frozen = temp; | ||
801 | |||
802 | g->numfrozen = g->maxfrozen; | ||
803 | |||
804 | return true; | ||
805 | } | ||
806 | |||
755 | static bool try_send_rejoin(Group_Chats *g_c, uint32_t groupnumber, const uint8_t *real_pk); | 807 | static bool try_send_rejoin(Group_Chats *g_c, uint32_t groupnumber, const uint8_t *real_pk); |
756 | 808 | ||
757 | static int freeze_peer(Group_Chats *g_c, uint32_t groupnumber, int peer_index, void *userdata) | 809 | static int freeze_peer(Group_Chats *g_c, uint32_t groupnumber, int peer_index, void *userdata) |
@@ -762,8 +814,6 @@ static int freeze_peer(Group_Chats *g_c, uint32_t groupnumber, int peer_index, v | |||
762 | return -1; | 814 | return -1; |
763 | } | 815 | } |
764 | 816 | ||
765 | try_send_rejoin(g_c, groupnumber, g->group[peer_index].real_pk); | ||
766 | |||
767 | Group_Peer *temp = (Group_Peer *)realloc(g->frozen, sizeof(Group_Peer) * (g->numfrozen + 1)); | 817 | Group_Peer *temp = (Group_Peer *)realloc(g->frozen, sizeof(Group_Peer) * (g->numfrozen + 1)); |
768 | 818 | ||
769 | if (temp == nullptr) { | 819 | if (temp == nullptr) { |
@@ -773,9 +823,18 @@ static int freeze_peer(Group_Chats *g_c, uint32_t groupnumber, int peer_index, v | |||
773 | g->frozen = temp; | 823 | g->frozen = temp; |
774 | g->frozen[g->numfrozen] = g->group[peer_index]; | 824 | g->frozen[g->numfrozen] = g->group[peer_index]; |
775 | g->frozen[g->numfrozen].object = nullptr; | 825 | g->frozen[g->numfrozen].object = nullptr; |
826 | |||
827 | if (delpeer(g_c, groupnumber, peer_index, userdata, true) != 0) { | ||
828 | return -1; | ||
829 | } | ||
830 | |||
831 | try_send_rejoin(g_c, groupnumber, g->frozen[g->numfrozen].real_pk); | ||
832 | |||
776 | ++g->numfrozen; | 833 | ++g->numfrozen; |
777 | 834 | ||
778 | return delpeer(g_c, groupnumber, peer_index, userdata, true); | 835 | delete_old_frozen(g); |
836 | |||
837 | return 0; | ||
779 | } | 838 | } |
780 | 839 | ||
781 | 840 | ||
@@ -1236,6 +1295,24 @@ int group_frozen_last_active(const Group_Chats *g_c, uint32_t groupnumber, int p | |||
1236 | return 0; | 1295 | return 0; |
1237 | } | 1296 | } |
1238 | 1297 | ||
1298 | /* Set maximum number of frozen peers. | ||
1299 | * | ||
1300 | * return 0 on success. | ||
1301 | * return -1 if groupnumber is invalid. | ||
1302 | */ | ||
1303 | int group_set_max_frozen(const Group_Chats *g_c, uint32_t groupnumber, uint32_t maxfrozen) | ||
1304 | { | ||
1305 | Group_c *g = get_group_c(g_c, groupnumber); | ||
1306 | |||
1307 | if (!g) { | ||
1308 | return -1; | ||
1309 | } | ||
1310 | |||
1311 | g->maxfrozen = maxfrozen; | ||
1312 | delete_old_frozen(g); | ||
1313 | return 0; | ||
1314 | } | ||
1315 | |||
1239 | /* List all the (frozen, if frozen is true) peers in the group chat. | 1316 | /* List all the (frozen, if frozen is true) peers in the group chat. |
1240 | * | 1317 | * |
1241 | * Copies the names of the peers to the name[length][MAX_NAME_LENGTH] array. | 1318 | * Copies the names of the peers to the name[length][MAX_NAME_LENGTH] array. |
@@ -3208,10 +3285,12 @@ static State_Load_Status load_conferences(Group_Chats *g_c, const uint8_t *data, | |||
3208 | lendian_bytes_to_host32(&g->numfrozen, data); | 3285 | lendian_bytes_to_host32(&g->numfrozen, data); |
3209 | data += sizeof(uint32_t); | 3286 | data += sizeof(uint32_t); |
3210 | 3287 | ||
3211 | g->frozen = (Group_Peer *)malloc(sizeof(Group_Peer) * g->numfrozen); | 3288 | if (g->numfrozen > 0) { |
3289 | g->frozen = (Group_Peer *)malloc(sizeof(Group_Peer) * g->numfrozen); | ||
3212 | 3290 | ||
3213 | if (g->frozen == nullptr) { | 3291 | if (g->frozen == nullptr) { |
3214 | return STATE_LOAD_STATUS_ERROR; | 3292 | return STATE_LOAD_STATUS_ERROR; |
3293 | } | ||
3215 | } | 3294 | } |
3216 | 3295 | ||
3217 | g->title_len = *data; | 3296 | g->title_len = *data; |
@@ -3252,6 +3331,13 @@ static State_Load_Status load_conferences(Group_Chats *g_c, const uint8_t *data, | |||
3252 | 3331 | ||
3253 | memcpy(peer->nick, data, peer->nick_len); | 3332 | memcpy(peer->nick, data, peer->nick_len); |
3254 | data += peer->nick_len; | 3333 | data += peer->nick_len; |
3334 | |||
3335 | // NOTE: this relies on friends being loaded before conferences. | ||
3336 | peer->is_friend = (getfriend_id(g_c->m, peer->real_pk) != -1); | ||
3337 | } | ||
3338 | |||
3339 | if (g->numfrozen > g->maxfrozen) { | ||
3340 | g->maxfrozen = g->numfrozen; | ||
3255 | } | 3341 | } |
3256 | 3342 | ||
3257 | g->status = GROUPCHAT_STATUS_CONNECTED; | 3343 | g->status = GROUPCHAT_STATUS_CONNECTED; |
diff --git a/toxcore/group.h b/toxcore/group.h index 83015273..884ac8f5 100644 --- a/toxcore/group.h +++ b/toxcore/group.h | |||
@@ -50,6 +50,7 @@ typedef struct Group_Peer { | |||
50 | uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE]; | 50 | uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE]; |
51 | uint8_t temp_pk[CRYPTO_PUBLIC_KEY_SIZE]; | 51 | uint8_t temp_pk[CRYPTO_PUBLIC_KEY_SIZE]; |
52 | bool temp_pk_updated; | 52 | bool temp_pk_updated; |
53 | bool is_friend; | ||
53 | 54 | ||
54 | uint64_t last_active; | 55 | uint64_t last_active; |
55 | 56 | ||
@@ -106,6 +107,9 @@ typedef void peer_on_join_cb(void *object, uint32_t conference_number, uint32_t | |||
106 | typedef void peer_on_leave_cb(void *object, uint32_t conference_number, void *peer_object); | 107 | typedef void peer_on_leave_cb(void *object, uint32_t conference_number, void *peer_object); |
107 | typedef void group_on_delete_cb(void *object, uint32_t conference_number); | 108 | typedef void group_on_delete_cb(void *object, uint32_t conference_number); |
108 | 109 | ||
110 | // maximum number of frozen peers to store; group_set_max_frozen() overrides. | ||
111 | #define MAX_FROZEN_DEFAULT 128 | ||
112 | |||
109 | typedef struct Group_c { | 113 | typedef struct Group_c { |
110 | uint8_t status; | 114 | uint8_t status; |
111 | 115 | ||
@@ -118,6 +122,8 @@ typedef struct Group_c { | |||
118 | Group_Peer *frozen; | 122 | Group_Peer *frozen; |
119 | uint32_t numfrozen; | 123 | uint32_t numfrozen; |
120 | 124 | ||
125 | uint32_t maxfrozen; | ||
126 | |||
121 | /* TODO(zugz) rename close to something more accurate - "connected"? */ | 127 | /* TODO(zugz) rename close to something more accurate - "connected"? */ |
122 | Groupchat_Close close[MAX_GROUP_CONNECTIONS]; | 128 | Groupchat_Close close[MAX_GROUP_CONNECTIONS]; |
123 | 129 | ||
@@ -284,6 +290,13 @@ int group_peername(const Group_Chats *g_c, uint32_t groupnumber, int peernumber, | |||
284 | int group_frozen_last_active(const Group_Chats *g_c, uint32_t groupnumber, int peernumber, | 290 | int group_frozen_last_active(const Group_Chats *g_c, uint32_t groupnumber, int peernumber, |
285 | uint64_t *last_active); | 291 | uint64_t *last_active); |
286 | 292 | ||
293 | /* Set maximum number of frozen peers. | ||
294 | * | ||
295 | * return 0 on success. | ||
296 | * return -1 if groupnumber is invalid. | ||
297 | */ | ||
298 | int group_set_max_frozen(const Group_Chats *g_c, uint32_t groupnumber, uint32_t maxfrozen); | ||
299 | |||
287 | /* invite friendnumber to groupnumber | 300 | /* invite friendnumber to groupnumber |
288 | * | 301 | * |
289 | * return 0 on success. | 302 | * return 0 on success. |
diff --git a/toxcore/tox.api.h b/toxcore/tox.api.h index 2e5c7841..51a6d639 100644 --- a/toxcore/tox.api.h +++ b/toxcore/tox.api.h | |||
@@ -2375,6 +2375,17 @@ namespace conference { | |||
2375 | } | 2375 | } |
2376 | 2376 | ||
2377 | /** | 2377 | /** |
2378 | * Set maximum number of offline peers to store, overriding the default. | ||
2379 | */ | ||
2380 | bool set_max_offline(uint32_t conference_number, uint32_t max_offline_peers) { | ||
2381 | /** | ||
2382 | * The conference number passed did not designate a valid conference. | ||
2383 | */ | ||
2384 | CONFERENCE_NOT_FOUND, | ||
2385 | } | ||
2386 | |||
2387 | |||
2388 | /** | ||
2378 | * Invites a friend to a conference. | 2389 | * Invites a friend to a conference. |
2379 | * | 2390 | * |
2380 | * We must be connected to the conference, meaning that the conference has not | 2391 | * We must be connected to the conference, meaning that the conference has not |
@@ -2806,6 +2817,7 @@ typedef TOX_ERR_FILE_SEND_CHUNK Tox_Err_File_Send_Chunk; | |||
2806 | typedef TOX_ERR_CONFERENCE_NEW Tox_Err_Conference_New; | 2817 | typedef TOX_ERR_CONFERENCE_NEW Tox_Err_Conference_New; |
2807 | typedef TOX_ERR_CONFERENCE_DELETE Tox_Err_Conference_Delete; | 2818 | typedef TOX_ERR_CONFERENCE_DELETE Tox_Err_Conference_Delete; |
2808 | typedef TOX_ERR_CONFERENCE_PEER_QUERY Tox_Err_Conference_Peer_Query; | 2819 | typedef TOX_ERR_CONFERENCE_PEER_QUERY Tox_Err_Conference_Peer_Query; |
2820 | typedef TOX_ERR_CONFERENCE_SET_MAX_OFFLINE Tox_Err_Conference_Set_Max_Offline; | ||
2809 | typedef TOX_ERR_CONFERENCE_BY_ID Tox_Err_Conference_By_Id; | 2821 | typedef TOX_ERR_CONFERENCE_BY_ID Tox_Err_Conference_By_Id; |
2810 | typedef TOX_ERR_CONFERENCE_BY_UID Tox_Err_Conference_By_Uid; | 2822 | typedef TOX_ERR_CONFERENCE_BY_UID Tox_Err_Conference_By_Uid; |
2811 | typedef TOX_ERR_CONFERENCE_INVITE Tox_Err_Conference_Invite; | 2823 | typedef TOX_ERR_CONFERENCE_INVITE Tox_Err_Conference_Invite; |
diff --git a/toxcore/tox.c b/toxcore/tox.c index d59094af..0a575dbf 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c | |||
@@ -1742,6 +1742,22 @@ uint64_t tox_conference_offline_peer_get_last_active(const Tox *tox, uint32_t co | |||
1742 | return last_active; | 1742 | return last_active; |
1743 | } | 1743 | } |
1744 | 1744 | ||
1745 | bool tox_conference_set_max_offline(Tox *tox, uint32_t conference_number, | ||
1746 | uint32_t max_offline_peers, | ||
1747 | Tox_Err_Conference_Set_Max_Offline *error) | ||
1748 | { | ||
1749 | const Messenger *m = tox->m; | ||
1750 | const int ret = group_set_max_frozen(m->conferences_object, conference_number, max_offline_peers); | ||
1751 | |||
1752 | if (ret == -1) { | ||
1753 | SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_SET_MAX_OFFLINE_CONFERENCE_NOT_FOUND); | ||
1754 | return false; | ||
1755 | } | ||
1756 | |||
1757 | SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_SET_MAX_OFFLINE_OK); | ||
1758 | return true; | ||
1759 | } | ||
1760 | |||
1745 | bool tox_conference_invite(Tox *tox, uint32_t friend_number, uint32_t conference_number, | 1761 | bool tox_conference_invite(Tox *tox, uint32_t friend_number, uint32_t conference_number, |
1746 | Tox_Err_Conference_Invite *error) | 1762 | Tox_Err_Conference_Invite *error) |
1747 | { | 1763 | { |
diff --git a/toxcore/tox.h b/toxcore/tox.h index 30ae7187..ad66305f 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h | |||
@@ -2673,6 +2673,27 @@ bool tox_conference_offline_peer_get_public_key(const Tox *tox, uint32_t confere | |||
2673 | uint64_t tox_conference_offline_peer_get_last_active(const Tox *tox, uint32_t conference_number, | 2673 | uint64_t tox_conference_offline_peer_get_last_active(const Tox *tox, uint32_t conference_number, |
2674 | uint32_t offline_peer_number, TOX_ERR_CONFERENCE_PEER_QUERY *error); | 2674 | uint32_t offline_peer_number, TOX_ERR_CONFERENCE_PEER_QUERY *error); |
2675 | 2675 | ||
2676 | typedef enum TOX_ERR_CONFERENCE_SET_MAX_OFFLINE { | ||
2677 | |||
2678 | /** | ||
2679 | * The function returned successfully. | ||
2680 | */ | ||
2681 | TOX_ERR_CONFERENCE_SET_MAX_OFFLINE_OK, | ||
2682 | |||
2683 | /** | ||
2684 | * The conference number passed did not designate a valid conference. | ||
2685 | */ | ||
2686 | TOX_ERR_CONFERENCE_SET_MAX_OFFLINE_CONFERENCE_NOT_FOUND, | ||
2687 | |||
2688 | } TOX_ERR_CONFERENCE_SET_MAX_OFFLINE; | ||
2689 | |||
2690 | |||
2691 | /** | ||
2692 | * Set maximum number of offline peers to store, overriding the default. | ||
2693 | */ | ||
2694 | bool tox_conference_set_max_offline(Tox *tox, uint32_t conference_number, uint32_t max_offline_peers, | ||
2695 | TOX_ERR_CONFERENCE_SET_MAX_OFFLINE *error); | ||
2696 | |||
2676 | typedef enum TOX_ERR_CONFERENCE_INVITE { | 2697 | typedef enum TOX_ERR_CONFERENCE_INVITE { |
2677 | 2698 | ||
2678 | /** | 2699 | /** |
@@ -3191,6 +3212,7 @@ typedef TOX_ERR_FILE_SEND_CHUNK Tox_Err_File_Send_Chunk; | |||
3191 | typedef TOX_ERR_CONFERENCE_NEW Tox_Err_Conference_New; | 3212 | typedef TOX_ERR_CONFERENCE_NEW Tox_Err_Conference_New; |
3192 | typedef TOX_ERR_CONFERENCE_DELETE Tox_Err_Conference_Delete; | 3213 | typedef TOX_ERR_CONFERENCE_DELETE Tox_Err_Conference_Delete; |
3193 | typedef TOX_ERR_CONFERENCE_PEER_QUERY Tox_Err_Conference_Peer_Query; | 3214 | typedef TOX_ERR_CONFERENCE_PEER_QUERY Tox_Err_Conference_Peer_Query; |
3215 | typedef TOX_ERR_CONFERENCE_SET_MAX_OFFLINE Tox_Err_Conference_Set_Max_Offline; | ||
3194 | typedef TOX_ERR_CONFERENCE_BY_ID Tox_Err_Conference_By_Id; | 3216 | typedef TOX_ERR_CONFERENCE_BY_ID Tox_Err_Conference_By_Id; |
3195 | typedef TOX_ERR_CONFERENCE_BY_UID Tox_Err_Conference_By_Uid; | 3217 | typedef TOX_ERR_CONFERENCE_BY_UID Tox_Err_Conference_By_Uid; |
3196 | typedef TOX_ERR_CONFERENCE_INVITE Tox_Err_Conference_Invite; | 3218 | typedef TOX_ERR_CONFERENCE_INVITE Tox_Err_Conference_Invite; |