• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

TokTok / c-toxcore / 7017

pending completion
7017

Pull #217

travis-ci

web-flow
Fix for state module refactoring.
Pull Request #217: ARCHIVED: New group chats (no new development here, no WIP, see #1162)

3718 of 3718 new or added lines in 10 files covered. (100.0%)

11481 of 15235 relevant lines covered (75.36%)

351764.03 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

55.29
/toxcore/tox.c
1
/*
2
 * The Tox public API.
3
 */
4

5
/*
6
 * Copyright © 2016-2018 The TokTok team.
7
 * Copyright © 2013 Tox project.
8
 *
9
 * This file is part of Tox, the free peer to peer instant messenger.
10
 *
11
 * Tox is free software: you can redistribute it and/or modify
12
 * it under the terms of the GNU General Public License as published by
13
 * the Free Software Foundation, either version 3 of the License, or
14
 * (at your option) any later version.
15
 *
16
 * Tox is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
 * GNU General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU General Public License
22
 * along with Tox.  If not, see <http://www.gnu.org/licenses/>.
23
 */
24
#ifdef HAVE_CONFIG_H
25
#include "config.h"
26
#endif
27

28
#ifndef _XOPEN_SOURCE
29
#define _XOPEN_SOURCE 600
30
#endif
31

32
#include "tox.h"
33

34
#include <assert.h>
35
#include <stdio.h>
36
#include <stdlib.h>
37
#include <string.h>
38

39
#include "Messenger.h"
40
#include "group.h"
41
#include "group_chats.h"
42
#include "group_moderation.h"
43
#include "logger.h"
44
#include "mono_time.h"
45

46
#include "../toxencryptsave/defines.h"
47

48
#define SET_ERROR_PARAMETER(param, x) do { if (param) { *param = x; } } while (0)
49

50
#if TOX_HASH_LENGTH != CRYPTO_SHA256_SIZE
51
#error "TOX_HASH_LENGTH is assumed to be equal to CRYPTO_SHA256_SIZE"
52
#endif
53

54
#if FILE_ID_LENGTH != CRYPTO_SYMMETRIC_KEY_SIZE
55
#error "FILE_ID_LENGTH is assumed to be equal to CRYPTO_SYMMETRIC_KEY_SIZE"
56
#endif
57

58
#if TOX_FILE_ID_LENGTH != CRYPTO_SYMMETRIC_KEY_SIZE
59
#error "TOX_FILE_ID_LENGTH is assumed to be equal to CRYPTO_SYMMETRIC_KEY_SIZE"
60
#endif
61

62
#if TOX_FILE_ID_LENGTH != TOX_HASH_LENGTH
63
#error "TOX_FILE_ID_LENGTH is assumed to be equal to TOX_HASH_LENGTH"
64
#endif
65

66
#if TOX_PUBLIC_KEY_SIZE != CRYPTO_PUBLIC_KEY_SIZE
67
#error "TOX_PUBLIC_KEY_SIZE is assumed to be equal to CRYPTO_PUBLIC_KEY_SIZE"
68
#endif
69

70
#if TOX_SECRET_KEY_SIZE != CRYPTO_SECRET_KEY_SIZE
71
#error "TOX_SECRET_KEY_SIZE is assumed to be equal to CRYPTO_SECRET_KEY_SIZE"
72
#endif
73

74
#if TOX_MAX_NAME_LENGTH != MAX_NAME_LENGTH
75
#error "TOX_MAX_NAME_LENGTH is assumed to be equal to MAX_NAME_LENGTH"
76
#endif
77

78
#if TOX_MAX_STATUS_MESSAGE_LENGTH != MAX_STATUSMESSAGE_LENGTH
79
#error "TOX_MAX_STATUS_MESSAGE_LENGTH is assumed to be equal to MAX_STATUSMESSAGE_LENGTH"
80
#endif
81

82
struct Tox {
83
    Messenger *m;
84
    Mono_Time *mono_time;
85
    void *non_const_user_data;
86

87
    tox_self_connection_status_cb *self_connection_status_callback;
88
    tox_friend_name_cb *friend_name_callback;
89
    tox_friend_status_message_cb *friend_status_message_callback;
90
    tox_friend_status_cb *friend_status_callback;
91
    tox_friend_connection_status_cb *friend_connection_status_callback;
92
    tox_friend_typing_cb *friend_typing_callback;
93
    tox_friend_read_receipt_cb *friend_read_receipt_callback;
94
    tox_friend_request_cb *friend_request_callback;
95
    tox_friend_message_cb *friend_message_callback;
96
    tox_file_recv_control_cb *file_recv_control_callback;
97
    tox_file_chunk_request_cb *file_chunk_request_callback;
98
    tox_file_recv_cb *file_recv_callback;
99
    tox_file_recv_chunk_cb *file_recv_chunk_callback;
100
    tox_conference_invite_cb *conference_invite_callback;
101
    tox_conference_connected_cb *conference_connected_callback;
102
    tox_conference_message_cb *conference_message_callback;
103
    tox_conference_title_cb *conference_title_callback;
104
    tox_conference_peer_name_cb *conference_peer_name_callback;
105
    tox_conference_peer_list_changed_cb *conference_peer_list_changed_callback;
106
    tox_friend_lossy_packet_cb *friend_lossy_packet_callback;
107
    tox_friend_lossless_packet_cb *friend_lossless_packet_callback;
108
    tox_group_peer_name_cb *group_peer_name_callback;
109
    tox_group_peer_status_cb *group_peer_status_callback;
110
    tox_group_topic_cb *group_topic_callback;
111
    tox_group_privacy_state_cb *group_privacy_state_callback;
112
    tox_group_peer_limit_cb *group_peer_limit_callback;
113
    tox_group_password_cb *group_password_callback;
114
    tox_group_message_cb *group_message_callback;
115
    tox_group_private_message_cb *group_private_message_callback;
116
    tox_group_custom_packet_cb *group_custom_packet_callback;
117
    tox_group_invite_cb *group_invite_callback;
118
    tox_group_peer_join_cb *group_peer_join_callback;
119
    tox_group_peer_exit_cb *group_peer_exit_callback;
120
    tox_group_self_join_cb *group_self_join_callback;
121
    tox_group_join_fail_cb *group_join_fail_callback;
122
    tox_group_moderation_cb *group_moderation_callback;
123
};
124

125
struct Tox_Userdata {
126
    Tox *tox;
127
    void *user_data;
128
};
129

130
static void tox_self_connection_status_handler(Messenger *m, unsigned int connection_status, void *user_data)
241✔
131
{
132
    struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
241✔
133

134
    if (tox_data->tox->self_connection_status_callback != nullptr) {
241✔
135
        tox_data->tox->self_connection_status_callback(tox_data->tox, (Tox_Connection)connection_status, tox_data->user_data);
22✔
136
    }
137
}
241✔
138

139
static void tox_friend_name_handler(Messenger *m, uint32_t friend_number, const uint8_t *name, size_t length,
450✔
140
                                    void *user_data)
141
{
142
    struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
450✔
143

144
    if (tox_data->tox->friend_name_callback != nullptr) {
450✔
145
        tox_data->tox->friend_name_callback(tox_data->tox, friend_number, name, length, tox_data->user_data);
2✔
146
    }
147
}
450✔
148

149
static void tox_friend_status_message_handler(Messenger *m, uint32_t friend_number, const uint8_t *message,
414✔
150
        size_t length, void *user_data)
151
{
152
    struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
414✔
153

154
    if (tox_data->tox->friend_status_message_callback != nullptr) {
414✔
155
        tox_data->tox->friend_status_message_callback(tox_data->tox, friend_number, message, length, tox_data->user_data);
2✔
156
    }
157
}
414✔
158

159
static void tox_friend_status_handler(Messenger *m, uint32_t friend_number, unsigned int status, void *user_data)
413✔
160
{
161
    struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
413✔
162

163
    if (tox_data->tox->friend_status_callback != nullptr) {
413✔
164
        tox_data->tox->friend_status_callback(tox_data->tox, friend_number, (Tox_User_Status)status, tox_data->user_data);
×
165
    }
166
}
413✔
167

168
static void tox_friend_connection_status_handler(Messenger *m, uint32_t friend_number, unsigned int connection_status,
458✔
169
        void *user_data)
170
{
171
    struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
458✔
172

173
    if (tox_data->tox->friend_connection_status_callback != nullptr) {
458✔
174
        tox_data->tox->friend_connection_status_callback(tox_data->tox, friend_number, (Tox_Connection)connection_status,
48✔
175
                tox_data->user_data);
176
    }
177
}
458✔
178

179
static void tox_friend_typing_handler(Messenger *m, uint32_t friend_number, bool is_typing, void *user_data)
415✔
180
{
181
    struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
415✔
182

183
    if (tox_data->tox->friend_typing_callback != nullptr) {
415✔
184
        tox_data->tox->friend_typing_callback(tox_data->tox, friend_number, is_typing, tox_data->user_data);
2✔
185
    }
186
}
415✔
187

188
static void tox_friend_read_receipt_handler(Messenger *m, uint32_t friend_number, uint32_t message_id, void *user_data)
34,297✔
189
{
190
    struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
34,297✔
191

192
    if (tox_data->tox->friend_read_receipt_callback != nullptr) {
34,297✔
193
        tox_data->tox->friend_read_receipt_callback(tox_data->tox, friend_number, message_id, tox_data->user_data);
×
194
    }
195
}
34,297✔
196

197
static void tox_friend_request_handler(Messenger *m, const uint8_t *public_key, const uint8_t *message, size_t length,
157✔
198
                                       void *user_data)
199
{
200
    struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
157✔
201

202
    if (tox_data->tox->friend_request_callback != nullptr) {
157✔
203
        tox_data->tox->friend_request_callback(tox_data->tox, public_key, message, length, tox_data->user_data);
157✔
204
    }
205
}
157✔
206

207
static void tox_friend_message_handler(Messenger *m, uint32_t friend_number, unsigned int type, const uint8_t *message,
34,298✔
208
                                       size_t length, void *user_data)
209
{
210
    struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
34,298✔
211

212
    if (tox_data->tox->friend_message_callback != nullptr) {
34,298✔
213
        tox_data->tox->friend_message_callback(tox_data->tox, friend_number, (Tox_Message_Type)type, message, length,
34,298✔
214
                                               tox_data->user_data);
215
    }
216
}
34,298✔
217

218
static void tox_file_recv_control_handler(Messenger *m, uint32_t friend_number, uint32_t file_number,
3✔
219
        unsigned int control, void *user_data)
220
{
221
    struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
3✔
222

223
    if (tox_data->tox->file_recv_control_callback != nullptr) {
3✔
224
        tox_data->tox->file_recv_control_callback(tox_data->tox, friend_number, file_number, (Tox_File_Control)control,
3✔
225
                tox_data->user_data);
226
    }
227
}
3✔
228

229
static void tox_file_chunk_request_handler(Messenger *m, uint32_t friend_number, uint32_t file_number,
76,559✔
230
        uint64_t position, size_t length, void *user_data)
231
{
232
    struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
76,559✔
233

234
    if (tox_data->tox->file_chunk_request_callback != nullptr) {
76,559✔
235
        tox_data->tox->file_chunk_request_callback(tox_data->tox, friend_number, file_number, position, length,
76,559✔
236
                tox_data->user_data);
237
    }
238
}
76,559✔
239

240
static void tox_file_recv_handler(Messenger *m, uint32_t friend_number, uint32_t file_number, uint32_t kind,
3✔
241
                                  uint64_t file_size, const uint8_t *filename, size_t filename_length, void *user_data)
242
{
243
    struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
3✔
244

245
    if (tox_data->tox->file_recv_callback != nullptr) {
3✔
246
        tox_data->tox->file_recv_callback(tox_data->tox, friend_number, file_number, kind, file_size, filename, filename_length,
3✔
247
                                          tox_data->user_data);
248
    }
249
}
3✔
250

251
static void tox_file_recv_chunk_handler(Messenger *m, uint32_t friend_number, uint32_t file_number, uint64_t position,
76,559✔
252
                                        const uint8_t *data, size_t length, void *user_data)
253
{
254
    struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
76,559✔
255

256
    if (tox_data->tox->file_recv_chunk_callback != nullptr) {
76,559✔
257
        tox_data->tox->file_recv_chunk_callback(tox_data->tox, friend_number, file_number, position, data, length,
76,559✔
258
                                                tox_data->user_data);
259
    }
260
}
76,559✔
261

262
static void tox_conference_invite_handler(Messenger *m, uint32_t friend_number, int type, const uint8_t *cookie,
19✔
263
        size_t length, void *user_data)
264
{
265
    struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
19✔
266

267
    if (tox_data->tox->conference_invite_callback != nullptr) {
19✔
268
        tox_data->tox->conference_invite_callback(tox_data->tox, friend_number, (Tox_Conference_Type)type, cookie, length,
19✔
269
                tox_data->user_data);
270
    }
271
}
19✔
272

273
static void tox_conference_connected_handler(Messenger *m, uint32_t conference_number, void *user_data)
19✔
274
{
275
    struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
19✔
276

277
    if (tox_data->tox->conference_connected_callback != nullptr) {
19✔
278
        tox_data->tox->conference_connected_callback(tox_data->tox, conference_number, tox_data->user_data);
17✔
279
    }
280
}
19✔
281

282
static void tox_conference_message_handler(Messenger *m, uint32_t conference_number, uint32_t peer_number, int type,
18✔
283
        const uint8_t *message, size_t length, void *user_data)
284
{
285
    struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
18✔
286

287
    if (tox_data->tox->conference_message_callback != nullptr) {
18✔
288
        tox_data->tox->conference_message_callback(tox_data->tox, conference_number, peer_number, (Tox_Message_Type)type,
18✔
289
                message, length, tox_data->user_data);
290
    }
291
}
18✔
292

293
static void tox_conference_title_handler(Messenger *m, uint32_t conference_number, uint32_t peer_number,
15✔
294
        const uint8_t *title, size_t length, void *user_data)
295
{
296
    struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
15✔
297

298
    if (tox_data->tox->conference_title_callback != nullptr) {
15✔
299
        tox_data->tox->conference_title_callback(tox_data->tox, conference_number, peer_number, title, length,
×
300
                tox_data->user_data);
301
    }
302
}
15✔
303

304
static void tox_conference_peer_name_handler(Messenger *m, uint32_t conference_number, uint32_t peer_number,
257✔
305
        const uint8_t *name, size_t length, void *user_data)
306
{
307
    struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
257✔
308

309
    if (tox_data->tox->conference_peer_name_callback != nullptr) {
257✔
310
        tox_data->tox->conference_peer_name_callback(tox_data->tox, conference_number, peer_number, name, length,
×
311
                tox_data->user_data);
312
    }
313
}
257✔
314

315
static void tox_conference_peer_list_changed_handler(Messenger *m, uint32_t conference_number, void *user_data)
608✔
316
{
317
    struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
608✔
318

319
    if (tox_data->tox->conference_peer_list_changed_callback != nullptr) {
608✔
320
        tox_data->tox->conference_peer_list_changed_callback(tox_data->tox, conference_number, tox_data->user_data);
12✔
321
    }
322
}
608✔
323

324
static void tox_friend_lossy_packet_handler(Messenger *m, uint32_t friend_number, const uint8_t *data, size_t length,
1✔
325
        void *user_data)
326
{
327
    struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
1✔
328

329
    if (tox_data->tox->friend_lossy_packet_callback != nullptr) {
1✔
330
        tox_data->tox->friend_lossy_packet_callback(tox_data->tox, friend_number, data, length, tox_data->user_data);
1✔
331
    }
332
}
1✔
333

334
static void tox_friend_lossless_packet_handler(Messenger *m, uint32_t friend_number, const uint8_t *data, size_t length,
1✔
335
        void *user_data)
336
{
337
    struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
1✔
338

339
    if (tox_data->tox->friend_lossless_packet_callback != nullptr) {
1✔
340
        tox_data->tox->friend_lossless_packet_callback(tox_data->tox, friend_number, data, length, tox_data->user_data);
1✔
341
    }
342
}
1✔
343

344
#ifndef VANILLA_NACL
345
static void tox_group_peer_name_handler(Messenger *m, uint32_t groupnumber, uint32_t peer_id, const uint8_t *name,
346
                                        size_t length, void *user_data)
347
{
348
    puts(__func__);
×
349
    Tox *tox = (Tox *)user_data;
×
350

351
    if (tox->group_peer_name_callback != nullptr) {
×
352
        tox->group_peer_name_callback(tox, groupnumber, peer_id, name, length, tox->non_const_user_data);
×
353
    }
354
}
355

356
static void tox_group_peer_status_handler(Messenger *m, uint32_t groupnumber, uint32_t peer_id, unsigned int status,
357
        void *user_data)
358
{
359
    puts(__func__);
×
360
    Tox *tox = (Tox *)user_data;
×
361

362
    if (tox->group_peer_status_callback != nullptr) {
×
363
        tox->group_peer_status_callback(tox, groupnumber, peer_id, (Tox_User_Status)status, tox->non_const_user_data);
×
364
    }
365
}
366

367
static void tox_group_topic_handler(Messenger *m, uint32_t groupnumber, uint32_t peer_id, const uint8_t *topic,
3✔
368
                                    size_t length, void *user_data)
369
{
370
    puts(__func__);
3✔
371
    Tox *tox = (Tox *)user_data;
3✔
372

373
    if (tox->group_topic_callback != nullptr) {
3✔
374
        tox->group_topic_callback(tox, groupnumber, peer_id, topic, length, tox->non_const_user_data);
×
375
    }
376
}
3✔
377

378
static void tox_group_privacy_state_handler(Messenger *m, uint32_t groupnumber, unsigned int privacy_state,
3✔
379
        void *user_data)
380
{
381
    puts(__func__);
3✔
382
    Tox *tox = (Tox *)user_data;
3✔
383

384
    if (tox->group_privacy_state_callback != nullptr) {
3✔
385
        tox->group_privacy_state_callback(tox, groupnumber, (Tox_Group_Privacy_State)privacy_state, tox->non_const_user_data);
×
386
    }
387
}
3✔
388

389
static void tox_group_peer_limit_handler(Messenger *m, uint32_t groupnumber, uint32_t peer_limit, void *user_data)
3✔
390
{
391
    puts(__func__);
3✔
392
    Tox *tox = (Tox *)user_data;
3✔
393

394
    if (tox->group_peer_limit_callback != nullptr) {
3✔
395
        tox->group_peer_limit_callback(tox, groupnumber, peer_limit, tox->non_const_user_data);
×
396
    }
397
}
3✔
398

399
static void tox_group_password_handler(Messenger *m, uint32_t groupnumber, const uint8_t *password, size_t length,
3✔
400
                                       void *user_data)
401
{
402
    puts(__func__);
3✔
403
    Tox *tox = (Tox *)user_data;
3✔
404

405
    if (tox->group_password_callback != nullptr) {
3✔
406
        tox->group_password_callback(tox, groupnumber, password, length, tox->non_const_user_data);
×
407
    }
408
}
3✔
409

410
static void tox_group_message_handler(Messenger *m, uint32_t groupnumber, uint32_t peer_id, unsigned int type,
2✔
411
                                      const uint8_t *message, size_t length, void *user_data)
412
{
413
    puts(__func__);
2✔
414
    Tox *tox = (Tox *)user_data;
2✔
415

416
    if (tox->group_message_callback != nullptr) {
2✔
417
        tox->group_message_callback(tox, groupnumber, peer_id, (Tox_Message_Type)type, message, length,
2✔
418
                                    tox->non_const_user_data);
419
    }
420
}
2✔
421

422
static void tox_group_private_message_handler(Messenger *m, uint32_t groupnumber, uint32_t peer_id,
423
        const uint8_t *message, size_t length, void *user_data)
424
{
425
    puts(__func__);
×
426
    Tox *tox = (Tox *)user_data;
×
427

428
    if (tox->group_private_message_callback != nullptr) {
×
429
        tox->group_private_message_callback(tox, groupnumber, peer_id, message, length, tox->non_const_user_data);
×
430
    }
431
}
432

433
static void tox_group_custom_packet_handler(Messenger *m, uint32_t groupnumber, uint32_t peer_id, const uint8_t *data,
434
        size_t length, void *user_data)
435
{
436
    puts(__func__);
×
437
    Tox *tox = (Tox *)user_data;
×
438

439
    if (tox->group_custom_packet_callback != nullptr) {
×
440
        tox->group_custom_packet_callback(tox, groupnumber, peer_id, data, length, tox->non_const_user_data);
×
441
    }
442
}
443

444
static void tox_group_invite_handler(Messenger *m, uint32_t friend_number, const uint8_t *invite_data, size_t length,
1✔
445
                                     void *user_data)
446
{
447
    puts(__func__);
1✔
448
    Tox *tox = (Tox *)user_data;
1✔
449

450
    if (tox->group_invite_callback != nullptr) {
1✔
451
        tox->group_invite_callback(tox, friend_number, invite_data, length, tox->non_const_user_data);
1✔
452
    }
453
}
1✔
454

455
static void tox_group_peer_join_handler(Messenger *m, uint32_t groupnumber, uint32_t peer_id, void *user_data)
10✔
456
{
457
    puts(__func__);
10✔
458
    Tox *tox = (Tox *)user_data;
10✔
459

460
    if (tox->group_peer_join_callback != nullptr) {
10✔
461
        tox->group_peer_join_callback(tox, groupnumber, peer_id, tox->non_const_user_data);
2✔
462
    }
463
}
10✔
464

465
static void tox_group_peer_exit_handler(Messenger *m, uint32_t groupnumber, uint32_t peer_id,
466
                                        const uint8_t *part_message, size_t length, void *user_data)
467
{
468
    puts(__func__);
×
469
    Tox *tox = (Tox *)user_data;
×
470

471
    if (tox->group_peer_exit_callback != nullptr) {
×
472
        tox->group_peer_exit_callback(tox, groupnumber, peer_id, part_message, length, tox->non_const_user_data);
×
473
    }
474
}
475

476
static void tox_group_self_join_handler(Messenger *m, uint32_t groupnumber, void *user_data)
5✔
477
{
478
    puts(__func__);
5✔
479
    Tox *tox = (Tox *)user_data;
5✔
480

481
    if (tox->group_self_join_callback != nullptr) {
5✔
482
        tox->group_self_join_callback(tox, groupnumber, tox->non_const_user_data);
×
483
    }
484
}
5✔
485

486
static void tox_group_join_fail_handler(Messenger *m, uint32_t groupnumber, unsigned int fail_type, void *user_data)
487
{
488
    puts(__func__);
×
489
    Tox *tox = (Tox *)user_data;
×
490

491
    if (tox->group_join_fail_callback != nullptr) {
×
492
        tox->group_join_fail_callback(tox, groupnumber, (Tox_Group_Join_Fail)fail_type, tox->non_const_user_data);
×
493
    }
494
}
495

496
static void tox_group_moderation_handler(Messenger *m, uint32_t groupnumber, uint32_t source_peer_number,
497
        uint32_t target_peer_number, unsigned int mod_type, void *user_data)
498
{
499
    puts(__func__);
×
500
    Tox *tox = (Tox *)user_data;
×
501

502
    if (tox->group_moderation_callback != nullptr) {
×
503
        tox->group_moderation_callback(tox, groupnumber, source_peer_number, target_peer_number, (Tox_Group_Mod_Event)mod_type,
×
504
                                       tox->non_const_user_data);
505
    }
506
}
507
#endif
508

509
bool tox_version_is_compatible(uint32_t major, uint32_t minor, uint32_t patch)
×
510
{
511
    return TOX_VERSION_IS_API_COMPATIBLE(major, minor, patch);
×
512
}
513

514
static State_Load_Status state_load_callback(void *outer, const uint8_t *data, uint32_t length, uint16_t type)
130✔
515
{
516
    Tox *tox = (Tox *)outer;
130✔
517
    State_Load_Status status = STATE_LOAD_STATUS_CONTINUE;
130✔
518

519
    if (messenger_load_state_section(tox->m, data, length, type, &status)
130✔
520
            || conferences_load_state_section(tox->m->conferences_object, data, length, type, &status)) {
23✔
521
        return status;
118✔
522
    }
523

524
    if (type == STATE_TYPE_END) {
12✔
525
        if (length != 0) {
12✔
526
            return STATE_LOAD_STATUS_ERROR;
527
        }
528

529
        return STATE_LOAD_STATUS_END;
12✔
530
    }
531

532
    LOGGER_ERROR(tox->m->log, "Load state: contains unrecognized part (len %u, type %u)\n",
×
533
                 length, type);
534

535
    return STATE_LOAD_STATUS_CONTINUE;
×
536
}
537

538
/* Load tox from data of size length. */
539
static int tox_load(Tox *tox, const uint8_t *data, uint32_t length)
12✔
540
{
541
    uint32_t data32[2];
542
    uint32_t cookie_len = sizeof(data32);
12✔
543

544
    if (length < cookie_len) {
12✔
545
        return -1;
546
    }
547

548
    memcpy(data32, data, sizeof(uint32_t));
549
    lendian_bytes_to_host32(data32 + 1, data + sizeof(uint32_t));
12✔
550

551
    if (data32[0] != 0 || data32[1] != STATE_COOKIE_GLOBAL) {
12✔
552
        return -1;
553
    }
554

555
    return state_load(tox->m->log, state_load_callback, tox, data + cookie_len,
12✔
556
                      length - cookie_len, STATE_COOKIE_TYPE);
557
}
558

559

560
Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)
267✔
561
{
562
    Tox *tox = (Tox *)calloc(1, sizeof(Tox));
267✔
563

564
    if (tox == nullptr) {
267✔
565
        SET_ERROR_PARAMETER(error, TOX_ERR_NEW_MALLOC);
×
566
        return nullptr;
567
    }
568

569
    Messenger_Options m_options = {0};
267✔
570

571
    bool load_savedata_sk = false, load_savedata_tox = false;
267✔
572

573
    struct Tox_Options *default_options = nullptr;
267✔
574

575
    if (options == nullptr) {
267✔
576
        Tox_Err_Options_New err;
577
        default_options = tox_options_new(&err);
×
578

579
        switch (err) {
×
580
            case TOX_ERR_OPTIONS_NEW_OK:
581
                break;
582

583
            case TOX_ERR_OPTIONS_NEW_MALLOC:
584
                SET_ERROR_PARAMETER(error, TOX_ERR_NEW_MALLOC);
×
585
                free(tox);
×
586
                return nullptr;
×
587
        }
588
    }
589

590
    const struct Tox_Options *const opts = options != nullptr ? options : default_options;
267✔
591
    assert(opts != nullptr);
267✔
592

593
    if (tox_options_get_savedata_type(opts) != TOX_SAVEDATA_TYPE_NONE) {
267✔
594
        if (tox_options_get_savedata_data(opts) == nullptr || tox_options_get_savedata_length(opts) == 0) {
14✔
595
            SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_BAD_FORMAT);
×
596
            tox_options_free(default_options);
×
597
            free(tox);
×
598
            return nullptr;
×
599
        }
600
    }
601

602
    if (tox_options_get_savedata_type(opts) == TOX_SAVEDATA_TYPE_SECRET_KEY) {
267✔
603
        if (tox_options_get_savedata_length(opts) != TOX_SECRET_KEY_SIZE) {
1✔
604
            SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_BAD_FORMAT);
×
605
            tox_options_free(default_options);
×
606
            free(tox);
×
607
            return nullptr;
×
608
        }
609

610
        load_savedata_sk = true;
611
    } else if (tox_options_get_savedata_type(opts) == TOX_SAVEDATA_TYPE_TOX_SAVE) {
266✔
612
        if (tox_options_get_savedata_length(opts) < TOX_ENC_SAVE_MAGIC_LENGTH) {
13✔
613
            SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_BAD_FORMAT);
×
614
            tox_options_free(default_options);
×
615
            free(tox);
×
616
            return nullptr;
×
617
        }
618

619
        if (crypto_memcmp(tox_options_get_savedata_data(opts), TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) == 0) {
13✔
620
            SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_ENCRYPTED);
1✔
621
            tox_options_free(default_options);
1✔
622
            free(tox);
1✔
623
            return nullptr;
1✔
624
        }
625

626
        load_savedata_tox = true;
627
    }
628

629
    m_options.ipv6enabled = tox_options_get_ipv6_enabled(opts);
266✔
630
    m_options.udp_disabled = !tox_options_get_udp_enabled(opts);
266✔
631
    m_options.port_range[0] = tox_options_get_start_port(opts);
266✔
632
    m_options.port_range[1] = tox_options_get_end_port(opts);
266✔
633
    m_options.tcp_server_port = tox_options_get_tcp_port(opts);
266✔
634
    m_options.hole_punching_enabled = tox_options_get_hole_punching_enabled(opts);
266✔
635
    m_options.local_discovery_enabled = tox_options_get_local_discovery_enabled(opts);
266✔
636

637
    m_options.log_callback = (logger_cb *)tox_options_get_log_callback(opts);
266✔
638
    m_options.log_context = tox;
266✔
639
    m_options.log_user_data = tox_options_get_log_user_data(opts);
266✔
640

641
    switch (tox_options_get_proxy_type(opts)) {
266✔
642
        case TOX_PROXY_TYPE_HTTP:
643
            m_options.proxy_info.proxy_type = TCP_PROXY_HTTP;
×
644
            break;
×
645

646
        case TOX_PROXY_TYPE_SOCKS5:
647
            m_options.proxy_info.proxy_type = TCP_PROXY_SOCKS5;
2✔
648
            break;
2✔
649

650
        case TOX_PROXY_TYPE_NONE:
651
            m_options.proxy_info.proxy_type = TCP_PROXY_NONE;
264✔
652
            break;
264✔
653

654
        default:
655
            SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PROXY_BAD_TYPE);
×
656
            tox_options_free(default_options);
×
657
            free(tox);
×
658
            return nullptr;
×
659
    }
660

661
    if (m_options.proxy_info.proxy_type != TCP_PROXY_NONE) {
266✔
662
        if (tox_options_get_proxy_port(opts) == 0) {
2✔
663
            SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PROXY_BAD_PORT);
×
664
            tox_options_free(default_options);
×
665
            free(tox);
×
666
            return nullptr;
×
667
        }
668

669
        ip_init(&m_options.proxy_info.ip_port.ip, m_options.ipv6enabled);
2✔
670

671
        if (m_options.ipv6enabled) {
2✔
672
            m_options.proxy_info.ip_port.ip.family = net_family_unspec;
2✔
673
        }
674

675
        if (addr_resolve_or_parse_ip(tox_options_get_proxy_host(opts), &m_options.proxy_info.ip_port.ip, nullptr) == 0) {
2✔
676
            SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PROXY_BAD_HOST);
×
677
            // TODO(irungentoo): TOX_ERR_NEW_PROXY_NOT_FOUND if domain.
678
            tox_options_free(default_options);
×
679
            free(tox);
×
680
            return nullptr;
×
681
        }
682

683
        m_options.proxy_info.ip_port.port = net_htons(tox_options_get_proxy_port(opts));
2✔
684
    }
685

686
    tox->mono_time = mono_time_new();
266✔
687

688
    if (tox->mono_time == nullptr) {
266✔
689
        SET_ERROR_PARAMETER(error, TOX_ERR_NEW_MALLOC);
×
690
        tox_options_free(default_options);
×
691
        free(tox);
×
692
        return nullptr;
×
693
    }
694

695
    unsigned int m_error;
696
    Messenger *const m = new_messenger(tox->mono_time, &m_options, &m_error);
266✔
697
    tox->m = m;
266✔
698

699
    // TODO(iphydf): Clarify this code, check for NULL before new_groupchats, so
700
    // new_groupchats can assume m is non-NULL.
701
    if (!new_groupchats(tox->mono_time, m)) {
266✔
702
        kill_messenger(m);
×
703

704
        if (m_error == MESSENGER_ERROR_PORT) {
×
705
            SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PORT_ALLOC);
×
706
        } else if (m_error == MESSENGER_ERROR_TCP_SERVER) {
×
707
            SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PORT_ALLOC);
×
708
        } else {
709
            SET_ERROR_PARAMETER(error, TOX_ERR_NEW_MALLOC);
×
710
        }
711

712
        mono_time_free(tox->mono_time);
×
713
        tox_options_free(default_options);
×
714
        free(tox);
×
715
        return nullptr;
×
716
    }
717

718
    if (load_savedata_tox
266✔
719
            && tox_load(tox, tox_options_get_savedata_data(opts), tox_options_get_savedata_length(opts)) == -1) {
12✔
720
        SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_BAD_FORMAT);
×
721
    } else if (load_savedata_sk) {
266✔
722
        load_secret_key(m->net_crypto, tox_options_get_savedata_data(opts));
1✔
723
        SET_ERROR_PARAMETER(error, TOX_ERR_NEW_OK);
1✔
724
    } else {
725
        SET_ERROR_PARAMETER(error, TOX_ERR_NEW_OK);
265✔
726
    }
727

728
    m_callback_namechange(m, tox_friend_name_handler);
266✔
729
    m_callback_core_connection(m, tox_self_connection_status_handler);
266✔
730
    m_callback_statusmessage(m, tox_friend_status_message_handler);
266✔
731
    m_callback_userstatus(m, tox_friend_status_handler);
266✔
732
    m_callback_connectionstatus(m, tox_friend_connection_status_handler);
266✔
733
    m_callback_typingchange(m, tox_friend_typing_handler);
266✔
734
    m_callback_read_receipt(m, tox_friend_read_receipt_handler);
266✔
735
    m_callback_friendrequest(m, tox_friend_request_handler);
266✔
736
    m_callback_friendmessage(m, tox_friend_message_handler);
266✔
737
    callback_file_control(m, tox_file_recv_control_handler);
266✔
738
    callback_file_reqchunk(m, tox_file_chunk_request_handler);
266✔
739
    callback_file_sendrequest(m, tox_file_recv_handler);
266✔
740
    callback_file_data(m, tox_file_recv_chunk_handler);
266✔
741
    g_callback_group_invite(m->conferences_object, tox_conference_invite_handler);
266✔
742
    g_callback_group_connected(m->conferences_object, tox_conference_connected_handler);
266✔
743
    g_callback_group_message(m->conferences_object, tox_conference_message_handler);
266✔
744
    g_callback_group_title(m->conferences_object, tox_conference_title_handler);
266✔
745
    g_callback_peer_name(m->conferences_object, tox_conference_peer_name_handler);
266✔
746
    g_callback_peer_list_changed(m->conferences_object, tox_conference_peer_list_changed_handler);
266✔
747
    custom_lossy_packet_registerhandler(m, tox_friend_lossy_packet_handler);
266✔
748
    custom_lossless_packet_registerhandler(m, tox_friend_lossless_packet_handler);
266✔
749

750
#ifndef VANILLA_NACL
751
    m_callback_group_invite(m, tox_group_invite_handler, tox);
266✔
752
    gc_callback_message(m, tox_group_message_handler, tox);
266✔
753
    gc_callback_private_message(m, tox_group_private_message_handler, tox);
266✔
754
    gc_callback_custom_packet(m, tox_group_custom_packet_handler, tox);
266✔
755
    gc_callback_moderation(m, tox_group_moderation_handler, tox);
266✔
756
    gc_callback_nick_change(m, tox_group_peer_name_handler, tox);
266✔
757
    gc_callback_status_change(m, tox_group_peer_status_handler, tox);
266✔
758
    gc_callback_topic_change(m, tox_group_topic_handler, tox);
266✔
759
    gc_callback_privacy_state(m, tox_group_privacy_state_handler, tox);
266✔
760
    gc_callback_peer_limit(m, tox_group_peer_limit_handler, tox);
266✔
761
    gc_callback_password(m, tox_group_password_handler, tox);
266✔
762
    gc_callback_peer_join(m, tox_group_peer_join_handler, tox);
266✔
763
    gc_callback_peer_exit(m, tox_group_peer_exit_handler, tox);
266✔
764
    gc_callback_self_join(m, tox_group_self_join_handler, tox);
266✔
765
    gc_callback_rejected(m, tox_group_join_fail_handler, tox);
266✔
766
#endif
767

768
    tox_options_free(default_options);
266✔
769
    return tox;
266✔
770
}
771

772
void tox_kill(Tox *tox)
261✔
773
{
774
    if (tox == nullptr) {
261✔
775
        return;
261✔
776
    }
777

778
    Messenger *m = tox->m;
261✔
779
    LOGGER_ASSERT(m->log, m->msi_packet == nullptr, "Attempted to kill tox while toxav is still alive");
261✔
780
    kill_groupchats(m->conferences_object);
261✔
781
    kill_messenger(m);
261✔
782
    mono_time_free(tox->mono_time);
261✔
783
    free(tox);
261✔
784
}
785

786
static uint32_t end_size(void)
787
{
788
    return 2 * sizeof(uint32_t);
789
}
790

791
static void end_save(uint8_t *data)
792
{
793
    state_write_section_header(data, STATE_COOKIE_TYPE, 0, STATE_TYPE_END);
13✔
794
}
795

796
size_t tox_get_savedata_size(const Tox *tox)
26✔
797
{
798
    const Messenger *m = tox->m;
26✔
799
    return 2 * sizeof(uint32_t)
26✔
800
           + messenger_size(m)
26✔
801
           + conferences_size(m->conferences_object)
26✔
802
           + end_size();
803
}
804

805
void tox_get_savedata(const Tox *tox, uint8_t *savedata)
13✔
806
{
807
    if (savedata == nullptr) {
13✔
808
        return;
13✔
809
    }
810

811
    memset(savedata, 0, tox_get_savedata_size(tox));
13✔
812

813
    const uint32_t size32 = sizeof(uint32_t);
13✔
814

815
    // write cookie
816
    memset(savedata, 0, size32);
13✔
817
    savedata += size32;
13✔
818
    host_to_lendian_bytes32(savedata, STATE_COOKIE_GLOBAL);
13✔
819
    savedata += size32;
13✔
820

821
    const Messenger *m = tox->m;
13✔
822
    savedata = messenger_save(m, savedata);
13✔
823
    savedata = conferences_save(m->conferences_object, savedata);
13✔
824
    end_save(savedata);
825
}
826

827
bool tox_bootstrap(Tox *tox, const char *host, uint16_t port, const uint8_t *public_key, Tox_Err_Bootstrap *error)
182✔
828
{
829
    if (!host || !public_key) {
182✔
830
        SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_NULL);
×
831
        return 0;
832
    }
833

834
    if (port == 0) {
182✔
835
        SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_PORT);
×
836
        return 0;
837
    }
838

839
    IP_Port *root;
840

841
    int32_t count = net_getipport(host, &root, TOX_SOCK_DGRAM);
182✔
842

843
    if (count == -1) {
182✔
844
        net_freeipport(root);
×
845
        SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_HOST);
×
846
        return 0;
847
    }
848

849
    unsigned int i;
850

851
    for (i = 0; i < count; ++i) {
182✔
852
        root[i].port = net_htons(port);
182✔
853

854
        Messenger *m = tox->m;
182✔
855
        onion_add_bs_path_node(m->onion_c, root[i], public_key);
182✔
856
        dht_bootstrap(m->dht, root[i], public_key);
182✔
857
    }
858

859
    net_freeipport(root);
182✔
860

861
    if (count) {
182✔
862
        SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_OK);
182✔
863
        return 1;
864
    }
865

866
    SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_HOST);
×
867
    return 0;
868
}
869

870
bool tox_add_tcp_relay(Tox *tox, const char *host, uint16_t port, const uint8_t *public_key,
84✔
871
                       Tox_Err_Bootstrap *error)
872
{
873
    if (!host || !public_key) {
84✔
874
        SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_NULL);
×
875
        return 0;
876
    }
877

878
    if (port == 0) {
84✔
879
        SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_PORT);
×
880
        return 0;
881
    }
882

883
    IP_Port *root;
884

885
    int32_t count = net_getipport(host, &root, TOX_SOCK_STREAM);
84✔
886

887
    if (count == -1) {
84✔
888
        net_freeipport(root);
×
889
        SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_HOST);
×
890
        return 0;
891
    }
892

893
    unsigned int i;
894

895
    for (i = 0; i < count; ++i) {
84✔
896
        root[i].port = net_htons(port);
84✔
897

898
        Messenger *m = tox->m;
84✔
899
        add_tcp_relay(m->net_crypto, root[i], public_key);
84✔
900
    }
901

902
    net_freeipport(root);
84✔
903

904
    if (count) {
84✔
905
        SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_OK);
84✔
906
        return 1;
907
    }
908

909
    SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_HOST);
×
910
    return 0;
911
}
912

913
Tox_Connection tox_self_get_connection_status(const Tox *tox)
4,629✔
914
{
915
    const Messenger *m = tox->m;
4,629✔
916

917
    unsigned int ret = onion_connection_status(m->onion_c);
4,629✔
918

919
    if (ret == 2) {
4,629✔
920
        return TOX_CONNECTION_UDP;
921
    }
922

923
    if (ret == 1) {
3,673✔
924
        return TOX_CONNECTION_TCP;
925
    }
926

927
    return TOX_CONNECTION_NONE;
3,621✔
928
}
929

930

931
void tox_callback_self_connection_status(Tox *tox, tox_self_connection_status_cb *callback)
20✔
932
{
933
    tox->self_connection_status_callback = callback;
20✔
934
}
20✔
935

936
uint32_t tox_iteration_interval(const Tox *tox)
27,776✔
937
{
938
    const Messenger *m = tox->m;
27,776✔
939
    return messenger_run_interval(m);
27,776✔
940
}
941

942
void tox_iterate(Tox *tox, void *user_data)
69,604✔
943
{
944
    mono_time_update(tox->mono_time);
69,604✔
945

946
    Messenger *m = tox->m;
69,604✔
947
    struct Tox_Userdata tox_data = { tox, user_data };
69,604✔
948
    tox->non_const_user_data = user_data;
69,604✔
949
    do_messenger(m, &tox_data);
69,604✔
950
    do_groupchats(m->conferences_object, &tox_data);
69,604✔
951
}
69,604✔
952

953
void tox_self_get_address(const Tox *tox, uint8_t *address)
167✔
954
{
955
    if (address) {
167✔
956
        const Messenger *m = tox->m;
167✔
957
        getaddress(m, address);
167✔
958
    }
959
}
167✔
960

961
void tox_self_set_nospam(Tox *tox, uint32_t nospam)
×
962
{
963
    Messenger *m = tox->m;
×
964
    set_nospam(m->fr, net_htonl(nospam));
×
965
}
966

967
uint32_t tox_self_get_nospam(const Tox *tox)
1✔
968
{
969
    const Messenger *m = tox->m;
1✔
970
    return net_ntohl(get_nospam(m->fr));
1✔
971
}
972

973
void tox_self_get_public_key(const Tox *tox, uint8_t *public_key)
69✔
974
{
975
    const Messenger *m = tox->m;
69✔
976

977
    if (public_key) {
69✔
978
        memcpy(public_key, nc_get_self_public_key(m->net_crypto), CRYPTO_PUBLIC_KEY_SIZE);
69✔
979
    }
980
}
69✔
981

982
void tox_self_get_secret_key(const Tox *tox, uint8_t *secret_key)
1✔
983
{
984
    const Messenger *m = tox->m;
1✔
985

986
    if (secret_key) {
1✔
987
        memcpy(secret_key, nc_get_self_secret_key(m->net_crypto), CRYPTO_SECRET_KEY_SIZE);
1✔
988
    }
989
}
1✔
990

991
bool tox_self_set_name(Tox *tox, const uint8_t *name, size_t length, Tox_Err_Set_Info *error)
31✔
992
{
993
    if (!name && length != 0) {
31✔
994
        SET_ERROR_PARAMETER(error, TOX_ERR_SET_INFO_NULL);
×
995
        return 0;
996
    }
997

998
    Messenger *m = tox->m;
31✔
999

1000
    if (setname(m, name, length) == 0) {
31✔
1001
        // TODO(irungentoo): function to set different per group names?
1002
        send_name_all_groups(m->conferences_object);
31✔
1003
        SET_ERROR_PARAMETER(error, TOX_ERR_SET_INFO_OK);
31✔
1004
        return 1;
1005
    }
1006

1007
    SET_ERROR_PARAMETER(error, TOX_ERR_SET_INFO_TOO_LONG);
×
1008
    return 0;
1009
}
1010

1011
size_t tox_self_get_name_size(const Tox *tox)
4✔
1012
{
1013
    const Messenger *m = tox->m;
4✔
1014
    return m_get_self_name_size(m);
4✔
1015
}
1016

1017
void tox_self_get_name(const Tox *tox, uint8_t *name)
5✔
1018
{
1019
    if (name) {
5✔
1020
        const Messenger *m = tox->m;
5✔
1021
        getself_name(m, name);
5✔
1022
    }
1023
}
5✔
1024

1025
bool tox_self_set_status_message(Tox *tox, const uint8_t *status_message, size_t length, Tox_Err_Set_Info *error)
4✔
1026
{
1027
    if (!status_message && length != 0) {
4✔
1028
        SET_ERROR_PARAMETER(error, TOX_ERR_SET_INFO_NULL);
×
1029
        return 0;
1030
    }
1031

1032
    Messenger *m = tox->m;
4✔
1033

1034
    if (m_set_statusmessage(m, status_message, length) == 0) {
4✔
1035
        SET_ERROR_PARAMETER(error, TOX_ERR_SET_INFO_OK);
4✔
1036
        return 1;
1037
    }
1038

1039
    SET_ERROR_PARAMETER(error, TOX_ERR_SET_INFO_TOO_LONG);
×
1040
    return 0;
1041
}
1042

1043
size_t tox_self_get_status_message_size(const Tox *tox)
3✔
1044
{
1045
    const Messenger *m = tox->m;
3✔
1046
    return m_get_self_statusmessage_size(m);
3✔
1047
}
1048

1049
void tox_self_get_status_message(const Tox *tox, uint8_t *status_message)
3✔
1050
{
1051
    if (status_message) {
3✔
1052
        const Messenger *m = tox->m;
3✔
1053
        m_copy_self_statusmessage(m, status_message);
3✔
1054
    }
1055
}
3✔
1056

1057
void tox_self_set_status(Tox *tox, Tox_User_Status status)
×
1058
{
1059
    Messenger *m = tox->m;
×
1060
    m_set_userstatus(m, status);
×
1061
}
1062

1063
Tox_User_Status tox_self_get_status(const Tox *tox)
×
1064
{
1065
    const Messenger *m = tox->m;
×
1066
    const uint8_t status = m_get_self_userstatus(m);
×
1067
    return (Tox_User_Status)status;
×
1068
}
1069

1070
static void set_friend_error(const Logger *log, int32_t ret, Tox_Err_Friend_Add *error)
9✔
1071
{
1072
    switch (ret) {
9✔
1073
        case FAERR_TOOLONG:
1074
            SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_TOO_LONG);
1✔
1075
            break;
1076

1077
        case FAERR_NOMESSAGE:
1078
            SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_NO_MESSAGE);
1✔
1079
            break;
1080

1081
        case FAERR_OWNKEY:
1082
            SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_OWN_KEY);
1✔
1083
            break;
1084

1085
        case FAERR_ALREADYSENT:
1086
            SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_ALREADY_SENT);
5✔
1087
            break;
1088

1089
        case FAERR_BADCHECKSUM:
1090
            SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_BAD_CHECKSUM);
1✔
1091
            break;
1092

1093
        case FAERR_SETNEWNOSPAM:
1094
            SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_SET_NEW_NOSPAM);
×
1095
            break;
1096

1097
        case FAERR_NOMEM:
1098
            SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_MALLOC);
×
1099
            break;
1100

1101
        default:
1102
            /* can't happen */
1103
            LOGGER_FATAL(log, "impossible: unknown friend-add error");
×
1104
            break;
1105
    }
1106
}
9✔
1107

1108
uint32_t tox_friend_add(Tox *tox, const uint8_t *address, const uint8_t *message, size_t length,
169✔
1109
                        Tox_Err_Friend_Add *error)
1110
{
1111
    if (!address || !message) {
169✔
1112
        SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_NULL);
1✔
1113
        return UINT32_MAX;
1114
    }
1115

1116
    Messenger *m = tox->m;
168✔
1117
    int32_t ret = m_addfriend(m, address, message, length);
168✔
1118

1119
    if (ret >= 0) {
168✔
1120
        SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_OK);
159✔
1121
        return ret;
159✔
1122
    }
1123

1124
    set_friend_error(m->log, ret, error);
9✔
1125
    return UINT32_MAX;
9✔
1126
}
1127

1128
uint32_t tox_friend_add_norequest(Tox *tox, const uint8_t *public_key, Tox_Err_Friend_Add *error)
225✔
1129
{
1130
    if (!public_key) {
225✔
1131
        SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_NULL);
×
1132
        return UINT32_MAX;
1133
    }
1134

1135
    Messenger *m = tox->m;
225✔
1136
    int32_t ret = m_addfriend_norequest(m, public_key);
225✔
1137

1138
    if (ret >= 0) {
225✔
1139
        SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_OK);
225✔
1140
        return ret;
225✔
1141
    }
1142

1143
    set_friend_error(m->log, ret, error);
×
1144
    return UINT32_MAX;
×
1145
}
1146

1147
bool tox_friend_delete(Tox *tox, uint32_t friend_number, Tox_Err_Friend_Delete *error)
×
1148
{
1149
    Messenger *m = tox->m;
×
1150
    int ret = m_delfriend(m, friend_number);
×
1151

1152
    // TODO(irungentoo): handle if realloc fails?
1153
    if (ret == -1) {
×
1154
        SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_DELETE_FRIEND_NOT_FOUND);
×
1155
        return 0;
1156
    }
1157

1158
    SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_DELETE_OK);
×
1159
    return 1;
1160
}
1161

1162
uint32_t tox_friend_by_public_key(const Tox *tox, const uint8_t *public_key, Tox_Err_Friend_By_Public_Key *error)
×
1163
{
1164
    if (!public_key) {
×
1165
        SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_BY_PUBLIC_KEY_NULL);
×
1166
        return UINT32_MAX;
1167
    }
1168

1169
    const Messenger *m = tox->m;
×
1170
    int32_t ret = getfriend_id(m, public_key);
×
1171

1172
    if (ret == -1) {
×
1173
        SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_BY_PUBLIC_KEY_NOT_FOUND);
×
1174
        return UINT32_MAX;
1175
    }
1176

1177
    SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_BY_PUBLIC_KEY_OK);
×
1178
    return ret;
×
1179
}
1180

1181
bool tox_friend_get_public_key(const Tox *tox, uint32_t friend_number, uint8_t *public_key,
2✔
1182
                               Tox_Err_Friend_Get_Public_Key *error)
1183
{
1184
    if (!public_key) {
2✔
1185
        return 0;
1186
    }
1187

1188
    const Messenger *m = tox->m;
2✔
1189

1190
    if (get_real_pk(m, friend_number, public_key) == -1) {
2✔
1191
        SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_GET_PUBLIC_KEY_FRIEND_NOT_FOUND);
×
1192
        return 0;
1193
    }
1194

1195
    SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_GET_PUBLIC_KEY_OK);
2✔
1196
    return 1;
1197
}
1198

1199
bool tox_friend_exists(const Tox *tox, uint32_t friend_number)
×
1200
{
1201
    const Messenger *m = tox->m;
×
1202
    return m_friend_exists(m, friend_number);
×
1203
}
1204

1205
uint64_t tox_friend_get_last_online(const Tox *tox, uint32_t friend_number, Tox_Err_Friend_Get_Last_Online *error)
×
1206
{
1207
    const Messenger *m = tox->m;
×
1208
    uint64_t timestamp = m_get_last_online(m, friend_number);
×
1209

1210
    if (timestamp == UINT64_MAX) {
×
1211
        SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_GET_LAST_ONLINE_FRIEND_NOT_FOUND);
×
1212
        return UINT64_MAX;
1213
    }
1214

1215
    SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_GET_LAST_ONLINE_OK);
×
1216
    return timestamp;
×
1217
}
1218

1219
size_t tox_self_get_friend_list_size(const Tox *tox)
47,005✔
1220
{
1221
    const Messenger *m = tox->m;
47,005✔
1222
    return count_friendlist(m);
47,005✔
1223
}
1224

1225
void tox_self_get_friend_list(const Tox *tox, uint32_t *friend_list)
×
1226
{
1227
    if (friend_list) {
×
1228
        const Messenger *m = tox->m;
×
1229
        // TODO(irungentoo): size parameter?
1230
        copy_friendlist(m, friend_list, tox_self_get_friend_list_size(tox));
×
1231
    }
1232
}
1233

1234
size_t tox_friend_get_name_size(const Tox *tox, uint32_t friend_number, Tox_Err_Friend_Query *error)
1✔
1235
{
1236
    const Messenger *m = tox->m;
1✔
1237
    int ret = m_get_name_size(m, friend_number);
1✔
1238

1239
    if (ret == -1) {
1✔
1240
        SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND);
×
1241
        return SIZE_MAX;
1242
    }
1243

1244
    SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_OK);
1✔
1245
    return ret;
1✔
1246
}
1247

1248
bool tox_friend_get_name(const Tox *tox, uint32_t friend_number, uint8_t *name, Tox_Err_Friend_Query *error)
2✔
1249
{
1250
    if (!name) {
2✔
1251
        SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_NULL);
×
1252
        return 0;
1253
    }
1254

1255
    const Messenger *m = tox->m;
2✔
1256
    int ret = getname(m, friend_number, name);
2✔
1257

1258
    if (ret == -1) {
2✔
1259
        SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND);
×
1260
        return 0;
1261
    }
1262

1263
    SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_OK);
2✔
1264
    return 1;
1265
}
1266

1267
void tox_callback_friend_name(Tox *tox, tox_friend_name_cb *callback)
2✔
1268
{
1269
    tox->friend_name_callback = callback;
2✔
1270
}
2✔
1271

1272
size_t tox_friend_get_status_message_size(const Tox *tox, uint32_t friend_number, Tox_Err_Friend_Query *error)
1✔
1273
{
1274
    const Messenger *m = tox->m;
1✔
1275
    int ret = m_get_statusmessage_size(m, friend_number);
1✔
1276

1277
    if (ret == -1) {
1✔
1278
        SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND);
×
1279
        return SIZE_MAX;
1280
    }
1281

1282
    SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_OK);
1✔
1283
    return ret;
1✔
1284
}
1285

1286
bool tox_friend_get_status_message(const Tox *tox, uint32_t friend_number, uint8_t *status_message,
2✔
1287
                                   Tox_Err_Friend_Query *error)
1288
{
1289
    if (!status_message) {
2✔
1290
        SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_NULL);
×
1291
        return false;
1292
    }
1293

1294
    const Messenger *const m = tox->m;
2✔
1295
    const int size = m_get_statusmessage_size(m, friend_number);
2✔
1296

1297
    if (size == -1) {
2✔
1298
        SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND);
×
1299
        return false;
1300
    }
1301

1302
    const int ret = m_copy_statusmessage(m, friend_number, status_message, size);
2✔
1303
    LOGGER_ASSERT(m->log, ret == size, "concurrency problem: friend status message changed");
2✔
1304

1305
    SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_OK);
2✔
1306
    return ret == size;
2✔
1307
}
1308

1309
void tox_callback_friend_status_message(Tox *tox, tox_friend_status_message_cb *callback)
2✔
1310
{
1311
    tox->friend_status_message_callback = callback;
2✔
1312
}
2✔
1313

1314
Tox_User_Status tox_friend_get_status(const Tox *tox, uint32_t friend_number, Tox_Err_Friend_Query *error)
×
1315
{
1316
    const Messenger *m = tox->m;
×
1317

1318
    int ret = m_get_userstatus(m, friend_number);
×
1319

1320
    if (ret == USERSTATUS_INVALID) {
×
1321
        SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND);
×
1322
        return (Tox_User_Status)(TOX_USER_STATUS_BUSY + 1);
1323
    }
1324

1325
    SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_OK);
×
1326
    return (Tox_User_Status)ret;
×
1327
}
1328

1329
void tox_callback_friend_status(Tox *tox, tox_friend_status_cb *callback)
×
1330
{
1331
    tox->friend_status_callback = callback;
×
1332
}
1333

1334
Tox_Connection tox_friend_get_connection_status(const Tox *tox, uint32_t friend_number, Tox_Err_Friend_Query *error)
26,355✔
1335
{
1336
    const Messenger *m = tox->m;
26,355✔
1337

1338
    int ret = m_get_friend_connectionstatus(m, friend_number);
26,355✔
1339

1340
    if (ret == -1) {
26,355✔
1341
        SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND);
464✔
1342
        return TOX_CONNECTION_NONE;
1343
    }
1344

1345
    SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_OK);
25,891✔
1346
    return (Tox_Connection)ret;
25,891✔
1347
}
1348

1349
void tox_callback_friend_connection_status(Tox *tox, tox_friend_connection_status_cb *callback)
19✔
1350
{
1351
    tox->friend_connection_status_callback = callback;
19✔
1352
}
19✔
1353

1354
bool tox_friend_get_typing(const Tox *tox, uint32_t friend_number, Tox_Err_Friend_Query *error)
2✔
1355
{
1356
    const Messenger *m = tox->m;
2✔
1357
    int ret = m_get_istyping(m, friend_number);
2✔
1358

1359
    if (ret == -1) {
2✔
1360
        SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND);
×
1361
        return 0;
1362
    }
1363

1364
    SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_OK);
2✔
1365
    return !!ret;
2✔
1366
}
1367

1368
void tox_callback_friend_typing(Tox *tox, tox_friend_typing_cb *callback)
1✔
1369
{
1370
    tox->friend_typing_callback = callback;
1✔
1371
}
1✔
1372

1373
bool tox_self_set_typing(Tox *tox, uint32_t friend_number, bool typing, Tox_Err_Set_Typing *error)
2✔
1374
{
1375
    Messenger *m = tox->m;
2✔
1376

1377
    if (m_set_usertyping(m, friend_number, typing) == -1) {
2✔
1378
        SET_ERROR_PARAMETER(error, TOX_ERR_SET_TYPING_FRIEND_NOT_FOUND);
×
1379
        return 0;
1380
    }
1381

1382
    SET_ERROR_PARAMETER(error, TOX_ERR_SET_TYPING_OK);
2✔
1383
    return 1;
1384
}
1385

1386
static void set_message_error(const Logger *log, int ret, Tox_Err_Friend_Send_Message *error)
105,540✔
1387
{
1388
    switch (ret) {
105,540✔
1389
        case 0:
1390
            SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_SEND_MESSAGE_OK);
98,300✔
1391
            break;
1392

1393
        case -1:
1394
            SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_SEND_MESSAGE_FRIEND_NOT_FOUND);
×
1395
            break;
1396

1397
        case -2:
1398
            SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_SEND_MESSAGE_TOO_LONG);
1✔
1399
            break;
1400

1401
        case -3:
1402
            SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_SEND_MESSAGE_FRIEND_NOT_CONNECTED);
×
1403
            break;
1404

1405
        case -4:
1406
            SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_SEND_MESSAGE_SENDQ);
7,239✔
1407
            break;
1408

1409
        case -5:
1410
            LOGGER_FATAL(log, "impossible: Messenger and Tox disagree on message types");
×
1411
            break;
1412

1413
        default:
1414
            /* can't happen */
1415
            LOGGER_FATAL(log, "impossible: unknown send-message error: %d", ret);
×
1416
            break;
1417
    }
1418
}
105,540✔
1419

1420
uint32_t tox_friend_send_message(Tox *tox, uint32_t friend_number, Tox_Message_Type type, const uint8_t *message,
105,540✔
1421
                                 size_t length, Tox_Err_Friend_Send_Message *error)
1422
{
1423
    if (!message) {
105,540✔
1424
        SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_SEND_MESSAGE_NULL);
×
1425
        return 0;
1426
    }
1427

1428
    if (!length) {
105,540✔
1429
        SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_SEND_MESSAGE_EMPTY);
×
1430
        return 0;
1431
    }
1432

1433
    Messenger *m = tox->m;
105,540✔
1434
    uint32_t message_id = 0;
105,540✔
1435
    set_message_error(m->log, m_send_message_generic(m, friend_number, type, message, length, &message_id), error);
105,540✔
1436
    return message_id;
105,540✔
1437
}
1438

1439
void tox_callback_friend_read_receipt(Tox *tox, tox_friend_read_receipt_cb *callback)
×
1440
{
1441
    tox->friend_read_receipt_callback = callback;
×
1442
}
1443

1444
void tox_callback_friend_request(Tox *tox, tox_friend_request_cb *callback)
176✔
1445
{
1446
    tox->friend_request_callback = callback;
176✔
1447
}
176✔
1448

1449
void tox_callback_friend_message(Tox *tox, tox_friend_message_cb *callback)
2✔
1450
{
1451
    tox->friend_message_callback = callback;
2✔
1452
}
2✔
1453

1454
bool tox_hash(uint8_t *hash, const uint8_t *data, size_t length)
×
1455
{
1456
    if (!hash || (length && !data)) {
×
1457
        return 0;
1458
    }
1459

1460
    crypto_sha256(hash, data, length);
×
1461
    return 1;
×
1462
}
1463

1464
bool tox_file_control(Tox *tox, uint32_t friend_number, uint32_t file_number, Tox_File_Control control,
3✔
1465
                      Tox_Err_File_Control *error)
1466
{
1467
    Messenger *m = tox->m;
3✔
1468
    int ret = file_control(m, friend_number, file_number, control);
3✔
1469

1470
    if (ret == 0) {
3✔
1471
        SET_ERROR_PARAMETER(error, TOX_ERR_FILE_CONTROL_OK);
3✔
1472
        return 1;
1473
    }
1474

1475
    switch (ret) {
×
1476
        case -1:
1477
            SET_ERROR_PARAMETER(error, TOX_ERR_FILE_CONTROL_FRIEND_NOT_FOUND);
×
1478
            return 0;
1479

1480
        case -2:
1481
            SET_ERROR_PARAMETER(error, TOX_ERR_FILE_CONTROL_FRIEND_NOT_CONNECTED);
×
1482
            return 0;
1483

1484
        case -3:
1485
            SET_ERROR_PARAMETER(error, TOX_ERR_FILE_CONTROL_NOT_FOUND);
×
1486
            return 0;
1487

1488
        case -4:
1489
            /* can't happen */
1490
            return 0;
1491

1492
        case -5:
1493
            SET_ERROR_PARAMETER(error, TOX_ERR_FILE_CONTROL_ALREADY_PAUSED);
×
1494
            return 0;
1495

1496
        case -6:
1497
            SET_ERROR_PARAMETER(error, TOX_ERR_FILE_CONTROL_DENIED);
×
1498
            return 0;
1499

1500
        case -7:
1501
            SET_ERROR_PARAMETER(error, TOX_ERR_FILE_CONTROL_NOT_PAUSED);
×
1502
            return 0;
1503

1504
        case -8:
1505
            SET_ERROR_PARAMETER(error, TOX_ERR_FILE_CONTROL_SENDQ);
×
1506
            return 0;
1507
    }
1508

1509
    /* can't happen */
1510
    return 0;
1511
}
1512

1513
bool tox_file_seek(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position,
5✔
1514
                   Tox_Err_File_Seek *error)
1515
{
1516
    Messenger *m = tox->m;
5✔
1517
    int ret = file_seek(m, friend_number, file_number, position);
5✔
1518

1519
    if (ret == 0) {
5✔
1520
        SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_OK);
2✔
1521
        return 1;
1522
    }
1523

1524
    switch (ret) {
3✔
1525
        case -1:
1526
            SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_FRIEND_NOT_FOUND);
×
1527
            return 0;
1528

1529
        case -2:
1530
            SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_FRIEND_NOT_CONNECTED);
×
1531
            return 0;
1532

1533
        case -3:
1534
            SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_NOT_FOUND);
×
1535
            return 0;
1536

1537
        case -4: // fall-through
1538
        case -5:
1539
            SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_DENIED);
3✔
1540
            return 0;
1541

1542
        case -6:
1543
            SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_INVALID_POSITION);
×
1544
            return 0;
1545

1546
        case -8:
1547
            SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_SENDQ);
×
1548
            return 0;
1549
    }
1550

1551
    /* can't happen */
1552
    return 0;
1553
}
1554

1555
void tox_callback_file_recv_control(Tox *tox, tox_file_recv_control_cb *callback)
6✔
1556
{
1557
    tox->file_recv_control_callback = callback;
6✔
1558
}
6✔
1559

1560
bool tox_file_get_file_id(const Tox *tox, uint32_t friend_number, uint32_t file_number, uint8_t *file_id,
12✔
1561
                          Tox_Err_File_Get *error)
1562
{
1563
    if (!file_id) {
12✔
1564
        SET_ERROR_PARAMETER(error, TOX_ERR_FILE_GET_NULL);
×
1565
        return 0;
1566
    }
1567

1568
    const Messenger *m = tox->m;
12✔
1569
    int ret = file_get_id(m, friend_number, file_number, file_id);
12✔
1570

1571
    if (ret == 0) {
12✔
1572
        SET_ERROR_PARAMETER(error, TOX_ERR_FILE_GET_OK);
6✔
1573
        return 1;
1574
    }
1575

1576
    if (ret == -1) {
6✔
1577
        SET_ERROR_PARAMETER(error, TOX_ERR_FILE_GET_FRIEND_NOT_FOUND);
3✔
1578
    } else {
1579
        SET_ERROR_PARAMETER(error, TOX_ERR_FILE_GET_NOT_FOUND);
3✔
1580
    }
1581

1582
    return 0;
1583
}
1584

1585
uint32_t tox_file_send(Tox *tox, uint32_t friend_number, uint32_t kind, uint64_t file_size, const uint8_t *file_id,
3✔
1586
                       const uint8_t *filename, size_t filename_length, Tox_Err_File_Send *error)
1587
{
1588
    if (filename_length && !filename) {
3✔
1589
        SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_NULL);
×
1590
        return UINT32_MAX;
1591
    }
1592

1593
    uint8_t f_id[FILE_ID_LENGTH];
1594

1595
    if (!file_id) {
3✔
1596
        /* Tox keys are 32 bytes like FILE_ID_LENGTH. */
1597
        new_symmetric_key(f_id);
3✔
1598
        file_id = f_id;
3✔
1599
    }
1600

1601
    Messenger *m = tox->m;
3✔
1602
    long int file_num = new_filesender(m, friend_number, kind, file_size, file_id, filename, filename_length);
3✔
1603

1604
    if (file_num >= 0) {
3✔
1605
        SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_OK);
3✔
1606
        return file_num;
3✔
1607
    }
1608

1609
    switch (file_num) {
×
1610
        case -1:
1611
            SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_FRIEND_NOT_FOUND);
×
1612
            return UINT32_MAX;
1613

1614
        case -2:
1615
            SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_NAME_TOO_LONG);
×
1616
            return UINT32_MAX;
1617

1618
        case -3:
1619
            SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_TOO_MANY);
×
1620
            return UINT32_MAX;
1621

1622
        case -4:
1623
            SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_FRIEND_NOT_CONNECTED);
×
1624
            return UINT32_MAX;
1625
    }
1626

1627
    /* can't happen */
1628
    return UINT32_MAX;
1629
}
1630

1631
bool tox_file_send_chunk(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position, const uint8_t *data,
76,556✔
1632
                         size_t length, Tox_Err_File_Send_Chunk *error)
1633
{
1634
    Messenger *m = tox->m;
76,556✔
1635
    int ret = file_data(m, friend_number, file_number, position, data, length);
76,556✔
1636

1637
    if (ret == 0) {
76,556✔
1638
        SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_OK);
76,556✔
1639
        return 1;
1640
    }
1641

1642
    switch (ret) {
×
1643
        case -1:
1644
            SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_FRIEND_NOT_FOUND);
×
1645
            return 0;
1646

1647
        case -2:
1648
            SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_FRIEND_NOT_CONNECTED);
×
1649
            return 0;
1650

1651
        case -3:
1652
            SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_NOT_FOUND);
×
1653
            return 0;
1654

1655
        case -4:
1656
            SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_NOT_TRANSFERRING);
×
1657
            return 0;
1658

1659
        case -5:
1660
            SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_INVALID_LENGTH);
×
1661
            return 0;
1662

1663
        case -6:
1664
            SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_SENDQ);
×
1665
            return 0;
1666

1667
        case -7:
1668
            SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_WRONG_POSITION);
×
1669
            return 0;
1670
    }
1671

1672
    /* can't happen */
1673
    return 0;
1674
}
1675

1676
void tox_callback_file_chunk_request(Tox *tox, tox_file_chunk_request_cb *callback)
3✔
1677
{
1678
    tox->file_chunk_request_callback = callback;
3✔
1679
}
3✔
1680

1681
void tox_callback_file_recv(Tox *tox, tox_file_recv_cb *callback)
3✔
1682
{
1683
    tox->file_recv_callback = callback;
3✔
1684
}
3✔
1685

1686
void tox_callback_file_recv_chunk(Tox *tox, tox_file_recv_chunk_cb *callback)
3✔
1687
{
1688
    tox->file_recv_chunk_callback = callback;
3✔
1689
}
3✔
1690

1691
void tox_callback_conference_invite(Tox *tox, tox_conference_invite_cb *callback)
23✔
1692
{
1693
    tox->conference_invite_callback = callback;
23✔
1694
}
23✔
1695

1696
void tox_callback_conference_connected(Tox *tox, tox_conference_connected_cb *callback)
19✔
1697
{
1698
    tox->conference_connected_callback = callback;
19✔
1699
}
19✔
1700

1701
void tox_callback_conference_message(Tox *tox, tox_conference_message_cb *callback)
19✔
1702
{
1703
    tox->conference_message_callback = callback;
19✔
1704
}
19✔
1705

1706
void tox_callback_conference_title(Tox *tox, tox_conference_title_cb *callback)
×
1707
{
1708
    tox->conference_title_callback = callback;
×
1709
}
1710

1711
void tox_callback_conference_peer_name(Tox *tox, tox_conference_peer_name_cb *callback)
×
1712
{
1713
    tox->conference_peer_name_callback = callback;
×
1714
}
1715

1716
void tox_callback_conference_peer_list_changed(Tox *tox, tox_conference_peer_list_changed_cb *callback)
5✔
1717
{
1718
    tox->conference_peer_list_changed_callback = callback;
5✔
1719
}
5✔
1720

1721
uint32_t tox_conference_new(Tox *tox, Tox_Err_Conference_New *error)
6✔
1722
{
1723
    Messenger *m = tox->m;
6✔
1724
    int ret = add_groupchat(m->conferences_object, GROUPCHAT_TYPE_TEXT);
6✔
1725

1726
    if (ret == -1) {
6✔
1727
        SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_NEW_INIT);
×
1728
        return UINT32_MAX;
1729
    }
1730

1731
    SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_NEW_OK);
6✔
1732
    return ret;
6✔
1733
}
1734

1735
bool tox_conference_delete(Tox *tox, uint32_t conference_number, Tox_Err_Conference_Delete *error)
16✔
1736
{
1737
    Messenger *m = tox->m;
16✔
1738
    group_leave(m->conferences_object, conference_number);
16✔
1739
    int ret = del_groupchat(m->conferences_object, conference_number);
16✔
1740

1741
    if (ret == -1) {
16✔
1742
        SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_DELETE_CONFERENCE_NOT_FOUND);
×
1743
        return false;
1744
    }
1745

1746
    SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_DELETE_OK);
16✔
1747
    return true;
1748
}
1749

1750
uint32_t tox_conference_peer_count(const Tox *tox, uint32_t conference_number, Tox_Err_Conference_Peer_Query *error)
1,002✔
1751
{
1752
    const Messenger *m = tox->m;
1,002✔
1753
    int ret = group_number_peers(m->conferences_object, conference_number);
1,002✔
1754

1755
    if (ret == -1) {
1,002✔
1756
        SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND);
×
1757
        return UINT32_MAX;
1758
    }
1759

1760
    SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_OK);
1,002✔
1761
    return ret;
1,002✔
1762
}
1763

1764
size_t tox_conference_peer_get_name_size(const Tox *tox, uint32_t conference_number, uint32_t peer_number,
321✔
1765
        Tox_Err_Conference_Peer_Query *error)
1766
{
1767
    const Messenger *m = tox->m;
321✔
1768
    int ret = group_peername_size(m->conferences_object, conference_number, peer_number);
321✔
1769

1770
    switch (ret) {
321✔
1771
        case -1:
1772
            SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND);
×
1773
            return -1;
1774

1775
        case -2:
1776
            SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_PEER_NOT_FOUND);
×
1777
            return -1;
1778
    }
1779

1780
    SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_OK);
321✔
1781
    return ret;
321✔
1782
}
1783

1784
bool tox_conference_peer_get_name(const Tox *tox, uint32_t conference_number, uint32_t peer_number, uint8_t *name,
65✔
1785
                                  Tox_Err_Conference_Peer_Query *error)
1786
{
1787
    const Messenger *m = tox->m;
65✔
1788
    int ret = group_peername(m->conferences_object, conference_number, peer_number, name);
65✔
1789

1790
    switch (ret) {
65✔
1791
        case -1:
1792
            SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND);
×
1793
            return false;
1794

1795
        case -2:
1796
            SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_PEER_NOT_FOUND);
×
1797
            return false;
1798
    }
1799

1800
    SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_OK);
65✔
1801
    return true;
1802
}
1803

1804
bool tox_conference_peer_get_public_key(const Tox *tox, uint32_t conference_number, uint32_t peer_number,
×
1805
                                        uint8_t *public_key, Tox_Err_Conference_Peer_Query *error)
1806
{
1807
    const Messenger *m = tox->m;
×
1808
    int ret = group_peer_pubkey(m->conferences_object, conference_number, peer_number, public_key);
×
1809

1810
    switch (ret) {
×
1811
        case -1:
1812
            SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND);
×
1813
            return false;
1814

1815
        case -2:
1816
            SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_PEER_NOT_FOUND);
×
1817
            return false;
1818
    }
1819

1820
    SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_OK);
×
1821
    return true;
1822
}
1823

1824
bool tox_conference_peer_number_is_ours(const Tox *tox, uint32_t conference_number, uint32_t peer_number,
×
1825
                                        Tox_Err_Conference_Peer_Query *error)
1826
{
1827
    const Messenger *m = tox->m;
×
1828
    int ret = group_peernumber_is_ours(m->conferences_object, conference_number, peer_number);
×
1829

1830
    switch (ret) {
×
1831
        case -1:
1832
            SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND);
×
1833
            return false;
1834

1835
        case -2:
1836
            SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_PEER_NOT_FOUND);
×
1837
            return false;
1838

1839
        case -3:
1840
            SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_NO_CONNECTION);
×
1841
            return false;
1842
    }
1843

1844
    SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_OK);
×
1845
    return ret;
×
1846
}
1847

1848
bool tox_conference_invite(Tox *tox, uint32_t friend_number, uint32_t conference_number,
20✔
1849
                           Tox_Err_Conference_Invite *error)
1850
{
1851
    Messenger *m = tox->m;
20✔
1852
    int ret = invite_friend(m->conferences_object, friend_number, conference_number);
20✔
1853

1854
    switch (ret) {
20✔
1855
        case -1:
1856
            SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_INVITE_CONFERENCE_NOT_FOUND);
×
1857
            return false;
1858

1859
        case -2:
1860
            SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_INVITE_FAIL_SEND);
×
1861
            return false;
1862

1863
        case -3:
1864
            SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_INVITE_NO_CONNECTION);
×
1865
            return false;
1866
    }
1867

1868
    SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_INVITE_OK);
20✔
1869
    return true;
1870
}
1871

1872
uint32_t tox_conference_join(Tox *tox, uint32_t friend_number, const uint8_t *cookie, size_t length,
34✔
1873
                             Tox_Err_Conference_Join *error)
1874
{
1875
    Messenger *m = tox->m;
34✔
1876
    int ret = join_groupchat(m->conferences_object, friend_number, GROUPCHAT_TYPE_TEXT, cookie, length);
34✔
1877

1878
    switch (ret) {
34✔
1879
        case -1:
1880
            SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_JOIN_INVALID_LENGTH);
×
1881
            return UINT32_MAX;
1882

1883
        case -2:
1884
            SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_JOIN_WRONG_TYPE);
×
1885
            return UINT32_MAX;
1886

1887
        case -3:
1888
            SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_JOIN_FRIEND_NOT_FOUND);
×
1889
            return UINT32_MAX;
1890

1891
        case -4:
1892
            SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_JOIN_DUPLICATE);
15✔
1893
            return UINT32_MAX;
1894

1895
        case -5:
1896
            SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_JOIN_INIT_FAIL);
×
1897
            return UINT32_MAX;
1898

1899
        case -6:
1900
            SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_JOIN_FAIL_SEND);
×
1901
            return UINT32_MAX;
1902
    }
1903

1904
    SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_JOIN_OK);
19✔
1905
    return ret;
19✔
1906
}
1907

1908
bool tox_conference_send_message(Tox *tox, uint32_t conference_number, Tox_Message_Type type, const uint8_t *message,
2✔
1909
                                 size_t length, Tox_Err_Conference_Send_Message *error)
1910
{
1911
    Messenger *m = tox->m;
2✔
1912
    int ret = 0;
2✔
1913

1914
    if (type == TOX_MESSAGE_TYPE_NORMAL) {
2✔
1915
        ret = group_message_send(m->conferences_object, conference_number, message, length);
2✔
1916
    } else {
1917
        ret = group_action_send(m->conferences_object, conference_number, message, length);
×
1918
    }
1919

1920
    switch (ret) {
2✔
1921
        case -1:
1922
            SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_SEND_MESSAGE_CONFERENCE_NOT_FOUND);
×
1923
            return false;
1924

1925
        case -2:
1926
            SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_SEND_MESSAGE_TOO_LONG);
×
1927
            return false;
1928

1929
        case -3:
1930
            SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_SEND_MESSAGE_NO_CONNECTION);
×
1931
            return false;
1932

1933
        case -4:
1934
            SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_SEND_MESSAGE_FAIL_SEND);
×
1935
            return false;
1936
    }
1937

1938
    SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_SEND_MESSAGE_OK);
2✔
1939
    return true;
1940
}
1941

1942
size_t tox_conference_get_title_size(const Tox *tox, uint32_t conference_number, Tox_Err_Conference_Title *error)
16✔
1943
{
1944
    const Messenger *m = tox->m;
16✔
1945
    int ret = group_title_get_size(m->conferences_object, conference_number);
16✔
1946

1947
    switch (ret) {
16✔
1948
        case -1:
1949
            SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_CONFERENCE_NOT_FOUND);
×
1950
            return -1;
1951

1952
        case -2:
1953
            SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_INVALID_LENGTH);
×
1954
            return -1;
1955
    }
1956

1957
    SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_OK);
16✔
1958
    return ret;
16✔
1959
}
1960

1961
bool tox_conference_get_title(const Tox *tox, uint32_t conference_number, uint8_t *title,
16✔
1962
                              Tox_Err_Conference_Title *error)
1963
{
1964
    const Messenger *m = tox->m;
16✔
1965
    int ret = group_title_get(m->conferences_object, conference_number, title);
16✔
1966

1967
    switch (ret) {
16✔
1968
        case -1:
1969
            SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_CONFERENCE_NOT_FOUND);
×
1970
            return false;
1971

1972
        case -2:
1973
            SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_INVALID_LENGTH);
×
1974
            return false;
1975
    }
1976

1977
    SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_OK);
16✔
1978
    return true;
1979
}
1980

1981
bool tox_conference_set_title(Tox *tox, uint32_t conference_number, const uint8_t *title, size_t length,
1✔
1982
                              Tox_Err_Conference_Title *error)
1983
{
1984
    Messenger *m = tox->m;
1✔
1985
    int ret = group_title_send(m->conferences_object, conference_number, title, length);
1✔
1986

1987
    switch (ret) {
1✔
1988
        case -1:
1989
            SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_CONFERENCE_NOT_FOUND);
×
1990
            return false;
1991

1992
        case -2:
1993
            SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_INVALID_LENGTH);
×
1994
            return false;
1995

1996
        case -3:
1997
            SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_FAIL_SEND);
×
1998
            return false;
1999
    }
2000

2001
    SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_OK);
1✔
2002
    return true;
2003
}
2004

2005
size_t tox_conference_get_chatlist_size(const Tox *tox)
66✔
2006
{
2007
    const Messenger *m = tox->m;
66✔
2008
    return count_chatlist(m->conferences_object);
66✔
2009
}
2010

2011
void tox_conference_get_chatlist(const Tox *tox, uint32_t *chatlist)
×
2012
{
2013
    const Messenger *m = tox->m;
×
2014
    size_t list_size = tox_conference_get_chatlist_size(tox);
×
2015
    copy_chatlist(m->conferences_object, chatlist, list_size);
×
2016
}
2017

2018
Tox_Conference_Type tox_conference_get_type(const Tox *tox, uint32_t conference_number,
×
2019
        Tox_Err_Conference_Get_Type *error)
2020
{
2021
    const Messenger *m = tox->m;
×
2022
    int ret = group_get_type(m->conferences_object, conference_number);
×
2023

2024
    if (ret == -1) {
×
2025
        SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_GET_TYPE_CONFERENCE_NOT_FOUND);
×
2026
        return (Tox_Conference_Type)ret;
×
2027
    }
2028

2029
    SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_GET_TYPE_OK);
×
2030
    return (Tox_Conference_Type)ret;
×
2031
}
2032

2033
bool tox_conference_get_id(const Tox *tox, uint32_t conference_number, uint8_t *id /* TOX_CONFERENCE_ID_SIZE bytes */)
×
2034
{
2035
    return conference_get_id(tox->m->conferences_object, conference_number, id);
×
2036
}
2037

2038
// TODO(iphydf): Delete in 0.3.0.
2039
bool tox_conference_get_uid(const Tox *tox, uint32_t conference_number, uint8_t *uid /* TOX_CONFERENCE_ID_SIZE bytes */)
×
2040
{
2041
    return tox_conference_get_id(tox, conference_number, uid);
×
2042
}
2043

2044
uint32_t tox_conference_by_id(const Tox *tox, const uint8_t *id, Tox_Err_Conference_By_Id *error)
×
2045
{
2046
    if (!id) {
×
2047
        SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_BY_ID_NULL);
×
2048
        return UINT32_MAX;
2049
    }
2050

2051
    int32_t ret = conference_by_id(tox->m->conferences_object, id);
×
2052

2053
    if (ret == -1) {
×
2054
        SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_BY_ID_NOT_FOUND);
×
2055
        return UINT32_MAX;
2056
    }
2057

2058
    SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_BY_ID_OK);
×
2059
    return ret;
×
2060
}
2061

2062
// TODO(iphydf): Delete in 0.3.0.
2063
uint32_t tox_conference_by_uid(const Tox *tox, const uint8_t *uid, Tox_Err_Conference_By_Uid *error)
×
2064
{
2065
    Tox_Err_Conference_By_Id id_error;
2066
    const uint32_t res = tox_conference_by_id(tox, uid, &id_error);
×
2067

2068
    switch (id_error) {
×
2069
        case TOX_ERR_CONFERENCE_BY_ID_OK:
2070
            SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_BY_UID_OK);
×
2071
            break;
2072

2073
        case TOX_ERR_CONFERENCE_BY_ID_NULL:
2074
            SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_BY_UID_NULL);
×
2075
            break;
2076

2077
        case TOX_ERR_CONFERENCE_BY_ID_NOT_FOUND:
2078
            SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_BY_UID_NOT_FOUND);
×
2079
            break;
2080
    }
2081

2082
    return res;
×
2083
}
2084

2085
static void set_custom_packet_error(int ret, Tox_Err_Friend_Custom_Packet *error)
4✔
2086
{
2087
    switch (ret) {
4✔
2088
        case 0:
2089
            SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_OK);
2✔
2090
            break;
2091

2092
        case -1:
2093
            SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_FRIEND_NOT_FOUND);
×
2094
            break;
2095

2096
        case -2:
2097
            SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_TOO_LONG);
2✔
2098
            break;
2099

2100
        case -3:
2101
            SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_INVALID);
×
2102
            break;
2103

2104
        case -4:
2105
            SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_FRIEND_NOT_CONNECTED);
×
2106
            break;
2107

2108
        case -5:
2109
            SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_SENDQ);
×
2110
            break;
2111
    }
2112
}
4✔
2113

2114
bool tox_friend_send_lossy_packet(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length,
2✔
2115
                                  Tox_Err_Friend_Custom_Packet *error)
2116
{
2117
    if (!data) {
2✔
2118
        SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_NULL);
×
2119
        return 0;
2120
    }
2121

2122
    Messenger *m = tox->m;
2✔
2123

2124
    if (length == 0) {
2✔
2125
        SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_EMPTY);
×
2126
        return 0;
2127
    }
2128

2129
    // TODO(oxij): this feels ugly, this is needed only because m_send_custom_lossy_packet in Messenger.c
2130
    // sends both AV and custom packets despite its name and this API hides those AV packets
2131
    if (data[0] <= PACKET_ID_RANGE_LOSSY_AV_END) {
2✔
2132
        SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_INVALID);
×
2133
        return 0;
2134
    }
2135

2136
    int ret = m_send_custom_lossy_packet(m, friend_number, data, length);
2✔
2137

2138
    set_custom_packet_error(ret, error);
2✔
2139

2140
    if (ret == 0) {
2✔
2141
        return 1;
2142
    }
2143

2144
    return 0;
1✔
2145
}
2146

2147
void tox_callback_friend_lossy_packet(Tox *tox, tox_friend_lossy_packet_cb *callback)
1✔
2148
{
2149
    tox->friend_lossy_packet_callback = callback;
1✔
2150
}
1✔
2151

2152
bool tox_friend_send_lossless_packet(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length,
2✔
2153
                                     Tox_Err_Friend_Custom_Packet *error)
2154
{
2155
    if (!data) {
2✔
2156
        SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_NULL);
×
2157
        return 0;
2158
    }
2159

2160
    Messenger *m = tox->m;
2✔
2161

2162
    if (length == 0) {
2✔
2163
        SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_EMPTY);
×
2164
        return 0;
2165
    }
2166

2167
    int ret = send_custom_lossless_packet(m, friend_number, data, length);
2✔
2168

2169
    set_custom_packet_error(ret, error);
2✔
2170

2171
    if (ret == 0) {
2✔
2172
        return 1;
2173
    }
2174

2175
    return 0;
1✔
2176
}
2177

2178
void tox_callback_friend_lossless_packet(Tox *tox, tox_friend_lossless_packet_cb *callback)
1✔
2179
{
2180
    tox->friend_lossless_packet_callback = callback;
1✔
2181
}
1✔
2182

2183
void tox_self_get_dht_id(const Tox *tox, uint8_t *dht_id)
196✔
2184
{
2185
    if (dht_id) {
196✔
2186
        const Messenger *m = tox->m;
196✔
2187
        memcpy(dht_id, dht_get_self_public_key(m->dht), CRYPTO_PUBLIC_KEY_SIZE);
196✔
2188
    }
2189
}
196✔
2190

2191
uint16_t tox_self_get_udp_port(const Tox *tox, Tox_Err_Get_Port *error)
156✔
2192
{
2193
    const Messenger *m = tox->m;
156✔
2194
    uint16_t port = net_htons(net_port(m->net));
156✔
2195

2196
    if (port) {
156✔
2197
        SET_ERROR_PARAMETER(error, TOX_ERR_GET_PORT_OK);
156✔
2198
    } else {
2199
        SET_ERROR_PARAMETER(error, TOX_ERR_GET_PORT_NOT_BOUND);
×
2200
    }
2201

2202
    return port;
156✔
2203
}
2204

2205
uint16_t tox_self_get_tcp_port(const Tox *tox, Tox_Err_Get_Port *error)
×
2206
{
2207
    const Messenger *m = tox->m;
×
2208

2209
    if (m->tcp_server) {
×
2210
        SET_ERROR_PARAMETER(error, TOX_ERR_GET_PORT_OK);
×
2211
        return m->options.tcp_server_port;
×
2212
    }
2213

2214
    SET_ERROR_PARAMETER(error, TOX_ERR_GET_PORT_NOT_BOUND);
×
2215
    return 0;
2216
}
2217

2218
/**************** GROUPCHAT FUNCTIONS *****************/
2219

2220
#ifndef VANILLA_NACL
2221
void tox_callback_group_invite(Tox *tox, tox_group_invite_cb *function, void *userdata)
2✔
2222
{
2223
    assert(userdata == nullptr);
2✔
2224
    tox->group_invite_callback = function;
2✔
2225
}
2✔
2226

2227
void tox_callback_group_message(Tox *tox, tox_group_message_cb *function, void *userdata)
2✔
2228
{
2229
    assert(userdata == nullptr);
2✔
2230
    tox->group_message_callback = function;
2✔
2231
}
2✔
2232

2233
void tox_callback_group_private_message(Tox *tox, tox_group_private_message_cb *function, void *userdata)
×
2234
{
2235
    assert(userdata == nullptr);
×
2236
    tox->group_private_message_callback = function;
×
2237
}
2238

2239
void tox_callback_group_custom_packet(Tox *tox, tox_group_custom_packet_cb *function, void *userdata)
×
2240
{
2241
    assert(userdata == nullptr);
×
2242
    tox->group_custom_packet_callback = function;
×
2243
}
2244

2245
void tox_callback_group_moderation(Tox *tox, tox_group_moderation_cb *function, void *userdata)
×
2246
{
2247
    assert(userdata == nullptr);
×
2248
    tox->group_moderation_callback = function;
×
2249
}
2250

2251
void tox_callback_group_peer_name(Tox *tox, tox_group_peer_name_cb *function, void *userdata)
×
2252
{
2253
    assert(userdata == nullptr);
×
2254
    tox->group_peer_name_callback = function;
×
2255
}
2256

2257
void tox_callback_group_peer_status(Tox *tox, tox_group_peer_status_cb *function, void *userdata)
×
2258
{
2259
    assert(userdata == nullptr);
×
2260
    tox->group_peer_status_callback = function;
×
2261
}
2262

2263
void tox_callback_group_topic(Tox *tox, tox_group_topic_cb *function, void *userdata)
×
2264
{
2265
    assert(userdata == nullptr);
×
2266
    tox->group_topic_callback = function;
×
2267
}
2268

2269
void tox_callback_group_privacy_state(Tox *tox, tox_group_privacy_state_cb *function, void *user_data)
×
2270
{
2271
    assert(user_data == nullptr);
×
2272
    tox->group_privacy_state_callback = function;
×
2273
}
2274

2275
void tox_callback_group_peer_limit(Tox *tox, tox_group_peer_limit_cb *function, void *user_data)
×
2276
{
2277
    assert(user_data == nullptr);
×
2278
    tox->group_peer_limit_callback = function;
×
2279
}
2280

2281
void tox_callback_group_password(Tox *tox, tox_group_password_cb *function, void *user_data)
×
2282
{
2283
    assert(user_data == nullptr);
×
2284
    tox->group_password_callback = function;
×
2285
}
2286

2287
void tox_callback_group_peer_join(Tox *tox, tox_group_peer_join_cb *function, void *userdata)
2✔
2288
{
2289
    assert(userdata == nullptr);
2✔
2290
    tox->group_peer_join_callback = function;
2✔
2291
}
2✔
2292

2293
void tox_callback_group_peer_exit(Tox *tox, tox_group_peer_exit_cb *function, void *userdata)
×
2294
{
2295
    assert(userdata == nullptr);
×
2296
    tox->group_peer_exit_callback = function;
×
2297
}
2298

2299
void tox_callback_group_self_join(Tox *tox, tox_group_self_join_cb *function, void *userdata)
×
2300
{
2301
    assert(userdata == nullptr);
×
2302
    tox->group_self_join_callback = function;
×
2303
}
2304

2305
void tox_callback_group_join_fail(Tox *tox, tox_group_join_fail_cb *function, void *userdata)
2✔
2306
{
2307
    assert(userdata == nullptr);
2✔
2308
    tox->group_join_fail_callback = function;
2✔
2309
}
2✔
2310

2311
uint32_t tox_group_new(Tox *tox, Tox_Group_Privacy_State privacy_state, const uint8_t *group_name, size_t length,
3✔
2312
                       Tox_Err_Group_New *error)
2313
{
2314
    Messenger *m = tox->m;
3✔
2315
    int ret = gc_group_add(m->group_handler, privacy_state, group_name, length);
3✔
2316

2317
    if (ret >= 0) {
3✔
2318
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_NEW_OK);
3✔
2319
        return ret;
3✔
2320
    }
2321

2322
    switch (ret) {
×
2323
        case -1:
2324
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_NEW_TOO_LONG);
×
2325
            return UINT32_MAX;
2326

2327
        case -2:
2328
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_NEW_EMPTY);
×
2329
            return UINT32_MAX;
2330

2331
        case -3:
2332
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_NEW_PRIVACY);
×
2333
            return UINT32_MAX;
2334

2335
        case -4:
2336
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_NEW_INIT);
×
2337
            return UINT32_MAX;
2338

2339
        case -5:
2340
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_NEW_STATE);
×
2341
            return UINT32_MAX;
2342

2343
        case -6:
2344
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_NEW_ANNOUNCE);
×
2345
            return UINT32_MAX;
2346
    }
2347

2348
    /* can't happen */
2349
    return UINT32_MAX;
2350
}
2351

2352
uint32_t tox_group_join(Tox *tox, const uint8_t *chat_id, const uint8_t *password, size_t length,
4✔
2353
                        Tox_Err_Group_Join *error)
2354
{
2355
    Messenger *m = tox->m;
4✔
2356
    int ret = gc_group_join(m->group_handler, chat_id, password, length);
4✔
2357

2358
    if (ret >= 0) {
4✔
2359
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_JOIN_OK);
4✔
2360
        return ret;
4✔
2361
    }
2362

2363
    switch (ret) {
×
2364
        case -1:
2365
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_JOIN_INIT);
×
2366
            return UINT32_MAX;
2367

2368
        case -2:
2369
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_JOIN_BAD_CHAT_ID);
×
2370
            return UINT32_MAX;
2371

2372
        case -3:
2373
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_JOIN_TOO_LONG);
×
2374
            return UINT32_MAX;
2375
    }
2376

2377
    /* can't happen */
2378
    return UINT32_MAX;
2379
}
2380

2381
bool tox_group_reconnect(Tox *tox, uint32_t groupnumber, Tox_Err_Group_Reconnect *error)
×
2382
{
2383
    Messenger *m = tox->m;
×
2384
    GC_Chat *chat = gc_get_group(m->group_handler, groupnumber);
×
2385

2386
    if (chat == nullptr) {
×
2387
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_RECONNECT_GROUP_NOT_FOUND);
×
2388
        return 0;
2389
    }
2390

2391
    gc_rejoin_group(m->group_handler, chat);
×
2392
    SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_RECONNECT_OK);
×
2393
    return 1;
2394
}
2395

2396
bool tox_group_leave(Tox *tox, uint32_t groupnumber, const uint8_t *partmessage, size_t length,
×
2397
                     Tox_Err_Group_Leave *error)
2398
{
2399
    Messenger *m = tox->m;
×
2400
    GC_Chat *chat = gc_get_group(m->group_handler, groupnumber);
×
2401

2402
    if (chat == nullptr) {
×
2403
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_LEAVE_GROUP_NOT_FOUND);
×
2404
        return 0;
2405
    }
2406

2407
    int ret = gc_group_exit(m->group_handler, chat, partmessage, length);
×
2408

2409
    switch (ret) {
×
2410
        case 0:
2411
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_LEAVE_OK);
×
2412
            return 1;
2413

2414
        case -1:
2415
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_LEAVE_TOO_LONG);
×
2416
            return 0;
2417

2418
        case -2:
2419
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_LEAVE_FAIL_SEND);
×
2420
            return 1;   /* the group was still successfully deleted */
2421

2422
        case -3:
2423
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_LEAVE_DELETE_FAIL);
×
2424
            return 0;
2425
    }
2426

2427
    /* can't happen */
2428
    return 0;
2429
}
2430

2431
bool tox_group_self_set_name(Tox *tox, uint32_t groupnumber, const uint8_t *name, size_t length,
×
2432
                             Tox_Err_Group_Self_Name_Set *error)
2433
{
2434
    Messenger *m = tox->m;
×
2435
    int ret = gc_set_self_nick(m, groupnumber, name, length);
×
2436

2437
    switch (ret) {
×
2438
        case 0:
2439
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SELF_NAME_SET_OK);
×
2440
            return 1;
2441

2442
        case -1:
2443
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SELF_NAME_SET_GROUP_NOT_FOUND);
×
2444
            return 0;
2445

2446
        case -2:
2447
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SELF_NAME_SET_TOO_LONG);
×
2448
            return 0;
2449

2450
        case -3:
2451
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SELF_NAME_SET_INVALID);
×
2452
            return 0;
2453

2454
        case -4:
2455
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SELF_NAME_SET_TAKEN);
×
2456
            return 0;
2457

2458
        case -5:
2459
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SELF_NAME_SET_FAIL_SEND);
×
2460
            return 0;
2461
    }
2462

2463
    /* can't happen */
2464
    return 0;
2465
}
2466

2467
size_t tox_group_self_get_name_size(const Tox *tox, uint32_t groupnumber, Tox_Err_Group_Self_Query *error)
×
2468
{
2469
    const Messenger *m = tox->m;
×
2470
    const GC_Chat *chat = gc_get_group(m->group_handler, groupnumber);
×
2471

2472
    if (chat == nullptr) {
×
2473
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SELF_QUERY_GROUP_NOT_FOUND);
×
2474
        return -1;
2475
    }
2476

2477
    SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SELF_QUERY_OK);
×
2478
    return gc_get_self_nick_size(chat);
×
2479
}
2480

2481
bool tox_group_self_get_name(const Tox *tox, uint32_t groupnumber, uint8_t *name, Tox_Err_Group_Self_Query *error)
×
2482
{
2483
    const Messenger *m = tox->m;
×
2484
    const GC_Chat *chat = gc_get_group(m->group_handler, groupnumber);
×
2485

2486
    if (chat == nullptr) {
×
2487
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SELF_QUERY_GROUP_NOT_FOUND);
×
2488
        return 0;
2489
    }
2490

2491
    SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SELF_QUERY_OK);
×
2492
    gc_get_self_nick(chat, name);
×
2493
    return 1;
×
2494
}
2495

2496
bool tox_group_self_set_status(Tox *tox, uint32_t groupnumber, Tox_User_Status status,
×
2497
                               Tox_Err_Group_Self_Status_Set *error)
2498
{
2499
    Messenger *m = tox->m;
×
2500
    int ret = gc_set_self_status(m, groupnumber, status);
×
2501

2502
    switch (ret) {
×
2503
        case 0:
2504
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SELF_STATUS_SET_OK);
×
2505
            return 1;
2506

2507
        case -1:
2508
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SELF_STATUS_SET_GROUP_NOT_FOUND);
×
2509
            return 0;
2510

2511
        case -2:
2512
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SELF_STATUS_SET_INVALID);
×
2513
            return 0;
2514

2515
        case -3:
2516
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SELF_STATUS_SET_FAIL_SEND);
×
2517
            return 0;
2518
    }
2519

2520
    /* can't happen */
2521
    return 0;
2522
}
2523

2524
Tox_User_Status tox_group_self_get_status(const Tox *tox, uint32_t groupnumber, Tox_Err_Group_Self_Query *error)
×
2525
{
2526
    const Messenger *m = tox->m;
×
2527
    const GC_Chat *chat = gc_get_group(m->group_handler, groupnumber);
×
2528

2529
    if (chat == nullptr) {
×
2530
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SELF_QUERY_GROUP_NOT_FOUND);
×
2531
        return (Tox_User_Status) - 1;
2532
    }
2533

2534
    SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SELF_QUERY_OK);
×
2535
    uint8_t status = gc_get_self_status(chat);
×
2536
    return (Tox_User_Status)status;
×
2537
}
2538

2539
Tox_Group_Role tox_group_self_get_role(const Tox *tox, uint32_t groupnumber, Tox_Err_Group_Self_Query *error)
×
2540
{
2541
    const Messenger *m = tox->m;
×
2542
    const GC_Chat *chat = gc_get_group(m->group_handler, groupnumber);
×
2543

2544
    if (chat == nullptr) {
×
2545
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SELF_QUERY_GROUP_NOT_FOUND);
×
2546
        return (Tox_Group_Role) - 1;
2547
    }
2548

2549
    SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SELF_QUERY_OK);
×
2550
    uint8_t role = gc_get_self_role(chat);
×
2551
    return (Tox_Group_Role)role;
×
2552
}
2553

2554
uint32_t tox_group_self_get_peer_id(const Tox *tox, uint32_t groupnumber, Tox_Err_Group_Self_Query *error)
×
2555
{
2556
    const Messenger *m = tox->m;
×
2557
    const GC_Chat *chat = gc_get_group(m->group_handler, groupnumber);
×
2558

2559
    if (chat == nullptr) {
×
2560
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SELF_QUERY_GROUP_NOT_FOUND);
×
2561
        return -1;
2562
    }
2563

2564
    SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SELF_QUERY_OK);
×
2565
    return gc_get_self_peer_id(chat);
×
2566
}
2567

2568
bool tox_group_self_get_public_key(const Tox *tox, uint32_t groupnumber, uint8_t *public_key,
×
2569
                                   Tox_Err_Group_Self_Query *error)
2570
{
2571
    const Messenger *m = tox->m;
×
2572
    const GC_Chat *chat = gc_get_group(m->group_handler, groupnumber);
×
2573

2574
    if (chat == nullptr) {
×
2575
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SELF_QUERY_GROUP_NOT_FOUND);
×
2576
        return 0;
2577
    }
2578

2579
    SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SELF_QUERY_OK);
×
2580
    gc_get_self_public_key(chat, public_key);
×
2581
    return 1;
×
2582
}
2583

2584
size_t tox_group_peer_get_name_size(const Tox *tox, uint32_t groupnumber, uint32_t peer_id,
×
2585
                                    Tox_Err_Group_Peer_Query *error)
2586
{
2587
    const Messenger *m = tox->m;
×
2588
    const GC_Chat *chat = gc_get_group(m->group_handler, groupnumber);
×
2589

2590
    if (chat == nullptr) {
×
2591
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_PEER_QUERY_GROUP_NOT_FOUND);
×
2592
        return -1;
2593
    }
2594

2595
    int ret = gc_get_peer_nick_size(chat, peer_id);
×
2596

2597
    if (ret == -1) {
×
2598
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_PEER_QUERY_PEER_NOT_FOUND);
×
2599
        return -1;
2600
    } else {
2601
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_PEER_QUERY_OK);
×
2602
        return ret;
×
2603
    }
2604
}
2605

2606
bool tox_group_peer_get_name(const Tox *tox, uint32_t groupnumber, uint32_t peer_id, uint8_t *name,
×
2607
                             Tox_Err_Group_Peer_Query *error)
2608
{
2609
    const Messenger *m = tox->m;
×
2610
    const GC_Chat *chat = gc_get_group(m->group_handler, groupnumber);
×
2611

2612
    if (chat == nullptr) {
×
2613
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_PEER_QUERY_GROUP_NOT_FOUND);
×
2614
        return 0;
2615
    }
2616

2617
    int ret = gc_get_peer_nick(chat, peer_id, name);
×
2618

2619
    if (ret == -1) {
×
2620
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_PEER_QUERY_PEER_NOT_FOUND);
×
2621
        return 0;
2622
    }
2623

2624
    SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_PEER_QUERY_OK);
×
2625
    return 1;
2626
}
2627

2628
Tox_User_Status tox_group_peer_get_status(const Tox *tox, uint32_t groupnumber, uint32_t peer_id,
×
2629
        Tox_Err_Group_Peer_Query *error)
2630
{
2631
    const Messenger *m = tox->m;
×
2632
    const GC_Chat *chat = gc_get_group(m->group_handler, groupnumber);
×
2633

2634
    if (chat == nullptr) {
×
2635
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_PEER_QUERY_GROUP_NOT_FOUND);
×
2636
        return (Tox_User_Status) - 1;
2637
    }
2638

2639
    uint8_t ret = gc_get_status(chat, peer_id);
×
2640

2641
    if (ret == (uint8_t) - 1) {
×
2642
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_PEER_QUERY_PEER_NOT_FOUND);
×
2643
        return (Tox_User_Status) - 1;
2644
    }
2645

2646
    SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_PEER_QUERY_OK);
×
2647
    return (Tox_User_Status)ret;
×
2648
}
2649

2650
Tox_Group_Role tox_group_peer_get_role(const Tox *tox, uint32_t groupnumber, uint32_t peer_id,
×
2651
                                       Tox_Err_Group_Peer_Query *error)
2652
{
2653
    const Messenger *m = tox->m;
×
2654
    const GC_Chat *chat = gc_get_group(m->group_handler, groupnumber);
×
2655

2656
    if (chat == nullptr) {
×
2657
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_PEER_QUERY_GROUP_NOT_FOUND);
×
2658
        return (Tox_Group_Role) - 1;
2659
    }
2660

2661
    uint8_t ret = gc_get_role(chat, peer_id);
×
2662

2663
    if (ret == (uint8_t) - 1) {
×
2664
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_PEER_QUERY_PEER_NOT_FOUND);
×
2665
        return (Tox_Group_Role) - 1;
2666
    }
2667

2668
    SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_PEER_QUERY_OK);
×
2669
    return (Tox_Group_Role)ret;
×
2670
}
2671

2672
bool tox_group_peer_get_public_key(const Tox *tox, uint32_t groupnumber, uint32_t peer_id, uint8_t *public_key,
×
2673
                                   Tox_Err_Group_Peer_Query *error)
2674
{
2675
    const Messenger *m = tox->m;
×
2676
    const GC_Chat *chat = gc_get_group(m->group_handler, groupnumber);
×
2677

2678
    if (chat == nullptr) {
×
2679
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_PEER_QUERY_GROUP_NOT_FOUND);
×
2680
        return 0;
2681
    }
2682

2683
    int ret = gc_get_peer_public_key(chat, peer_id, public_key);
×
2684

2685
    if (ret == -1) {
×
2686
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_PEER_QUERY_PEER_NOT_FOUND);
×
2687
        return 0;
2688
    }
2689

2690
    SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_PEER_QUERY_OK);
×
2691
    return 1;
2692
}
2693

2694
bool tox_group_set_topic(Tox *tox, uint32_t groupnumber, const uint8_t *topic, size_t length,
2✔
2695
                         Tox_Err_Group_Topic_Set *error)
2696
{
2697
    Messenger *m = tox->m;
2✔
2698
    GC_Chat *chat = gc_get_group(m->group_handler, groupnumber);
2✔
2699

2700
    if (chat == nullptr) {
2✔
2701
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_TOPIC_SET_GROUP_NOT_FOUND);
×
2702
        return 0;
2703
    }
2704

2705
    int ret = gc_set_topic(chat, topic, length);
2✔
2706

2707
    switch (ret) {
2✔
2708
        case 0:
2709
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_TOPIC_SET_OK);
2✔
2710
            return 1;
2711

2712
        case -1:
2713
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_TOPIC_SET_TOO_LONG);
×
2714
            return 0;
2715

2716
        case -2:
2717
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_TOPIC_SET_PERMISSIONS);
×
2718
            return 0;
2719

2720
        case -3:
2721
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_TOPIC_SET_FAIL_CREATE);
×
2722
            return 0;
2723

2724
        case -4:
2725
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_TOPIC_SET_FAIL_SEND);
×
2726
            return 0;
2727
    }
2728

2729
    /* can't happen */
2730
    return 0;
2731
}
2732

2733
size_t tox_group_get_topic_size(const Tox *tox, uint32_t groupnumber, Tox_Err_Group_State_Queries *error)
8✔
2734
{
2735
    const Messenger *m = tox->m;
8✔
2736
    const GC_Chat *chat = gc_get_group(m->group_handler, groupnumber);
8✔
2737

2738
    if (chat == nullptr) {
8✔
2739
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_GROUP_NOT_FOUND);
×
2740
        return -1;
2741
    }
2742

2743
    SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_OK);
8✔
2744
    return gc_get_topic_size(chat);
8✔
2745
}
2746

2747
bool tox_group_get_topic(const Tox *tox, uint32_t groupnumber, uint8_t *topic, Tox_Err_Group_State_Queries *error)
8✔
2748
{
2749
    const Messenger *m = tox->m;
8✔
2750
    const GC_Chat *chat = gc_get_group(m->group_handler, groupnumber);
8✔
2751

2752
    if (chat == nullptr) {
8✔
2753
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_GROUP_NOT_FOUND);
×
2754
        return 0;
2755
    }
2756

2757
    gc_get_topic(chat, topic);
8✔
2758
    SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_OK);
8✔
2759
    return 1;
2760
}
2761

2762
size_t tox_group_get_name_size(const Tox *tox, uint32_t groupnumber, Tox_Err_Group_State_Queries *error)
8✔
2763
{
2764
    const Messenger *m = tox->m;
8✔
2765
    const GC_Chat *chat = gc_get_group(m->group_handler, groupnumber);
8✔
2766

2767
    if (chat == nullptr) {
8✔
2768
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_GROUP_NOT_FOUND);
×
2769
        return -1;
2770
    }
2771

2772
    SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_OK);
8✔
2773
    return gc_get_group_name_size(chat);
8✔
2774
}
2775

2776
bool tox_group_get_name(const Tox *tox, uint32_t groupnumber, uint8_t *groupname, Tox_Err_Group_State_Queries *error)
8✔
2777
{
2778
    const Messenger *m = tox->m;
8✔
2779
    const GC_Chat *chat = gc_get_group(m->group_handler, groupnumber);
8✔
2780

2781
    if (chat == nullptr) {
8✔
2782
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_GROUP_NOT_FOUND);
×
2783
        return 0;
2784
    }
2785

2786
    gc_get_group_name(chat, groupname);
8✔
2787
    SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_OK);
8✔
2788
    return 1;
2789
}
2790

2791
bool tox_group_get_chat_id(const Tox *tox, uint32_t groupnumber, uint8_t *chat_id, Tox_Err_Group_State_Queries *error)
2✔
2792
{
2793
    const Messenger *m = tox->m;
2✔
2794
    const GC_Chat *chat = gc_get_group(m->group_handler, groupnumber);
2✔
2795

2796
    if (chat == nullptr) {
2✔
2797
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_GROUP_NOT_FOUND);
×
2798
        return 0;
2799
    }
2800

2801
    SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_OK);
2✔
2802
    gc_get_chat_id(chat, chat_id);
2✔
2803
    return 1;
2✔
2804
}
2805

2806
uint32_t tox_group_get_number_groups(const Tox *tox)
×
2807
{
2808
    const Messenger *m = tox->m;
×
2809
    return gc_count_groups(m->group_handler);
×
2810
}
2811

2812
Tox_Group_Privacy_State tox_group_get_privacy_state(const Tox *tox, uint32_t groupnumber,
8✔
2813
        Tox_Err_Group_State_Queries *error)
2814
{
2815
    const Messenger *m = tox->m;
8✔
2816
    const GC_Chat *chat = gc_get_group(m->group_handler, groupnumber);
8✔
2817

2818
    if (chat == nullptr) {
8✔
2819
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_GROUP_NOT_FOUND);
×
2820
        return (Tox_Group_Privacy_State) - 1;
2821
    }
2822

2823
    SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_OK);
8✔
2824
    uint8_t state = gc_get_privacy_state(chat);
8✔
2825
    return (Tox_Group_Privacy_State)state;
8✔
2826
}
2827

2828
uint32_t tox_group_get_peer_limit(const Tox *tox, uint32_t groupnumber, Tox_Err_Group_State_Queries *error)
24✔
2829
{
2830
    const Messenger *m = tox->m;
24✔
2831
    const GC_Chat *chat = gc_get_group(m->group_handler, groupnumber);
24✔
2832

2833
    if (chat == nullptr) {
24✔
2834
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_GROUP_NOT_FOUND);
×
2835
        return -1;
2836
    }
2837

2838
    SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_OK);
24✔
2839
    return gc_get_max_peers(chat);
24✔
2840
}
2841

2842
size_t tox_group_get_password_size(const Tox *tox, uint32_t groupnumber, Tox_Err_Group_State_Queries *error)
8✔
2843
{
2844
    const Messenger *m = tox->m;
8✔
2845
    const GC_Chat *chat = gc_get_group(m->group_handler, groupnumber);
8✔
2846

2847
    if (chat == nullptr) {
8✔
2848
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_GROUP_NOT_FOUND);
×
2849
        return -1;
2850
    }
2851

2852
    SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_OK);
8✔
2853
    return gc_get_password_size(chat);
8✔
2854
}
2855

2856
bool tox_group_get_password(const Tox *tox, uint32_t groupnumber, uint8_t *password, Tox_Err_Group_State_Queries *error)
4✔
2857
{
2858
    const Messenger *m = tox->m;
4✔
2859
    const GC_Chat *chat = gc_get_group(m->group_handler, groupnumber);
4✔
2860

2861
    if (chat == nullptr) {
4✔
2862
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_GROUP_NOT_FOUND);
×
2863
        return 0;
2864
    }
2865

2866
    SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_OK);
4✔
2867
    gc_get_password(chat, password);
4✔
2868
    return 1;
4✔
2869
}
2870

2871
bool tox_group_send_message(Tox *tox, uint32_t groupnumber, Tox_Message_Type type, const uint8_t *message,
2✔
2872
                            size_t length, Tox_Err_Group_Send_Message *error)
2873
{
2874
    const Messenger *m = tox->m;
2✔
2875
    GC_Chat *chat = gc_get_group(m->group_handler, groupnumber);
2✔
2876

2877
    if (chat == nullptr) {
2✔
2878
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_MESSAGE_GROUP_NOT_FOUND);
×
2879
        return 0;
2880
    }
2881

2882
    int ret = gc_send_message(chat, message, length, type);
2✔
2883

2884
    switch (ret) {
2✔
2885
        case 0:
2886
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_MESSAGE_OK);
2✔
2887
            return 1;
2888

2889
        case -1:
2890
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_MESSAGE_TOO_LONG);
×
2891
            return 0;
2892

2893
        case -2:
2894
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_MESSAGE_EMPTY);
×
2895
            return 0;
2896

2897
        case -3:
2898
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_MESSAGE_BAD_TYPE);
×
2899
            return 0;
2900

2901
        case -4:
2902
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_MESSAGE_PERMISSIONS);
×
2903
            return 0;
2904

2905
        case -5:
2906
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_MESSAGE_FAIL_SEND);
×
2907
            return 0;
2908
    }
2909

2910
    /* can't happen */
2911
    return 0;
2912
}
2913

2914
bool tox_group_send_private_message(Tox *tox, uint32_t groupnumber, uint32_t peer_id, const uint8_t *message,
×
2915
                                    size_t length, Tox_Err_Group_Send_Private_Message *error)
2916
{
2917
    const Messenger *m = tox->m;
×
2918
    GC_Chat *chat = gc_get_group(m->group_handler, groupnumber);
×
2919

2920
    if (chat == nullptr) {
×
2921
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_GROUP_NOT_FOUND);
×
2922
        return 0;
2923
    }
2924

2925
    int ret = gc_send_private_message(chat, peer_id, message, length);
×
2926

2927
    switch (ret) {
×
2928
        case 0:
2929
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_OK);
×
2930
            return 1;
2931

2932
        case -1:
2933
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_TOO_LONG);
×
2934
            return 0;
2935

2936
        case -2:
2937
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_EMPTY);
×
2938
            return 0;
2939

2940
        case -3:
2941
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_PEER_NOT_FOUND);
×
2942
            return 0;
2943

2944
        case -4:
2945
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_PERMISSIONS);
×
2946
            return 0;
2947

2948
        case -5:
2949
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_FAIL_SEND);
×
2950
            return 0;
2951
    }
2952

2953
    /* can't happen */
2954
    return 0;
2955
}
2956

2957
bool tox_group_send_custom_packet(Tox *tox, uint32_t groupnumber, bool lossless, const uint8_t *data,
×
2958
                                  size_t length, Tox_Err_Group_Send_Custom_Packet *error)
2959
{
2960
    const Messenger *m = tox->m;
×
2961
    GC_Chat *chat = gc_get_group(m->group_handler, groupnumber);
×
2962

2963
    if (chat == nullptr) {
×
2964
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_CUSTOM_PACKET_GROUP_NOT_FOUND);
×
2965
        return 0;
2966
    }
2967

2968
    int ret = gc_send_custom_packet(chat, lossless, data, length);
×
2969

2970
    switch (ret) {
×
2971
        case 0:
2972
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_CUSTOM_PACKET_OK);
×
2973
            return 1;
2974

2975
        case -1:
2976
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_CUSTOM_PACKET_TOO_LONG);
×
2977
            return 0;
2978

2979
        case -2:
2980
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_CUSTOM_PACKET_EMPTY);
×
2981
            return 0;
2982

2983
        case -3:
2984
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_CUSTOM_PACKET_PERMISSIONS);
×
2985
            return 0;
2986
    }
2987

2988
    /* can't happen */
2989
    return 0;
2990
}
2991

2992
bool tox_group_invite_friend(Tox *tox, uint32_t groupnumber, uint32_t friend_number, Tox_Err_Group_Invite_Friend *error)
1✔
2993
{
2994
    Messenger *m = tox->m;
1✔
2995
    GC_Chat *chat = gc_get_group(m->group_handler, groupnumber);
1✔
2996

2997
    if (chat == nullptr) {
1✔
2998
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_INVITE_FRIEND_GROUP_NOT_FOUND);
×
2999
        return 0;
3000
    }
3001

3002
    if (friend_not_valid(m, friend_number)) {
1✔
3003
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_INVITE_FRIEND_FRIEND_NOT_FOUND);
×
3004
        return 0;
3005
    }
3006

3007
    int ret = gc_invite_friend(m->group_handler, chat, friend_number,
1✔
3008
                               send_group_invite_packet);
3009

3010
    switch (ret) {
1✔
3011
        case 0:
3012
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_INVITE_FRIEND_OK);
1✔
3013
            return 1;
3014

3015
        case -1:
3016
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_INVITE_FRIEND_FRIEND_NOT_FOUND);
×
3017
            return 0;
3018

3019
        case -2:
3020
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_INVITE_FRIEND_INVITE_FAIL);
×
3021
            return 0;
3022

3023
        case -3:
3024
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_INVITE_FRIEND_FAIL_SEND);
×
3025
            return 0;
3026
    }
3027

3028
    /* can't happen */
3029
    return 0;
3030
}
3031

3032
uint32_t tox_group_invite_accept(Tox *tox, const uint8_t *invite_data, size_t length, const uint8_t *password,
1✔
3033
                                 size_t password_length, Tox_Err_Group_Invite_Accept *error)
3034
{
3035
    Messenger *m = tox->m;
1✔
3036
    int ret = gc_accept_invite(m->group_handler, invite_data, length, password, password_length);
1✔
3037

3038
    if (ret >= 0) {
1✔
3039
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_INVITE_ACCEPT_OK);
1✔
3040
        return ret;
1✔
3041
    }
3042

3043
    switch (ret) {
×
3044
        case -1:
3045
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_INVITE_ACCEPT_BAD_INVITE);
×
3046
            return UINT32_MAX;
3047

3048
        case -2:
3049
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_INVITE_ACCEPT_INIT_FAILED);
×
3050
            return UINT32_MAX;
3051

3052
        case -3:
3053
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_INVITE_ACCEPT_TOO_LONG);
×
3054
            return UINT32_MAX;
3055
    }
3056

3057
    /* can't happen */
3058
    return UINT32_MAX;
3059
}
3060

3061
bool tox_group_founder_set_password(Tox *tox, uint32_t groupnumber, const uint8_t *password, size_t length,
2✔
3062
                                    Tox_Err_Group_Founder_Set_Password *error)
3063
{
3064
    Messenger *m = tox->m;
2✔
3065
    GC_Chat *chat = gc_get_group(m->group_handler, groupnumber);
2✔
3066

3067
    if (chat == nullptr) {
2✔
3068
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_GROUP_NOT_FOUND);
×
3069
        return 0;
3070
    }
3071

3072
    int ret = gc_founder_set_password(chat, password, length);
2✔
3073

3074
    switch (ret) {
2✔
3075
        case 0:
3076
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_OK);
2✔
3077
            return 1;
3078

3079
        case -1:
3080
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_PERMISSIONS);
×
3081
            return 0;
3082

3083
        case -2:
3084
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_TOO_LONG);
×
3085
            return 0;
3086

3087
        case -3:
3088
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_FAIL_SEND);
×
3089
            return 0;
3090
    }
3091

3092
    /* can't happen */
3093
    return 0;
3094
}
3095

3096
bool tox_group_founder_set_privacy_state(Tox *tox, uint32_t groupnumber, Tox_Group_Privacy_State privacy_state,
2✔
3097
        Tox_Err_Group_Founder_Set_Privacy_State *error)
3098
{
3099
    Messenger *m = tox->m;
2✔
3100
    int ret = gc_founder_set_privacy_state(m, groupnumber, privacy_state);
2✔
3101

3102
    switch (ret) {
2✔
3103
        case 0:
3104
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_OK);
2✔
3105
            return 1;
3106

3107
        case -1:
3108
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_GROUP_NOT_FOUND);
×
3109
            return 0;
3110

3111
        case -2:
3112
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_INVALID);
×
3113
            return 0;
3114

3115
        case -3:
3116
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_PERMISSIONS);
×
3117
            return 0;
3118

3119
        case -4:
3120
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_FAIL_SET);
×
3121
            return 0;
3122

3123
        case -5:
3124
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_FAIL_SEND);
×
3125
            return 0;
3126
    }
3127

3128
    /* can't happen */
3129
    return 0;
3130
}
3131

3132
bool tox_group_founder_set_peer_limit(Tox *tox, uint32_t groupnumber, uint32_t maxpeers,
2✔
3133
                                      Tox_Err_Group_Founder_Set_Peer_Limit *error)
3134
{
3135
    Messenger *m = tox->m;
2✔
3136
    GC_Chat *chat = gc_get_group(m->group_handler, groupnumber);
2✔
3137

3138
    if (chat == nullptr) {
2✔
3139
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_GROUP_NOT_FOUND);
×
3140
        return 0;
3141
    }
3142

3143
    int ret = gc_founder_set_max_peers(chat, groupnumber, maxpeers);
2✔
3144

3145
    switch (ret) {
2✔
3146
        case 0:
3147
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_OK);
2✔
3148
            return 1;
3149

3150
        case -1:
3151
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_PERMISSIONS);
×
3152
            return 0;
3153

3154
        case -2:
3155
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_FAIL_SET);
×
3156
            return 0;
3157

3158
        case -3:
3159
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_FAIL_SEND);
×
3160
            return 0;
3161
    }
3162

3163
    /* can't happen */
3164
    return 0;
3165
}
3166

3167
bool tox_group_toggle_ignore(Tox *tox, uint32_t groupnumber, uint32_t peer_id, bool ignore,
×
3168
                             Tox_Err_Group_Toggle_Ignore *error)
3169
{
3170
    Messenger *m = tox->m;
×
3171
    GC_Chat *chat = gc_get_group(m->group_handler, groupnumber);
×
3172

3173
    if (chat == nullptr) {
×
3174
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_TOGGLE_IGNORE_GROUP_NOT_FOUND);
×
3175
        return 0;
3176
    }
3177

3178
    int ret = gc_toggle_ignore(chat, peer_id, ignore);
×
3179

3180
    if (ret == -1) {
×
3181
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_TOGGLE_IGNORE_PEER_NOT_FOUND);
×
3182
        return 0;
3183
    } else {
3184
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_TOGGLE_IGNORE_OK);
×
3185
        return 1;
3186
    }
3187
}
3188

3189
bool tox_group_mod_set_role(Tox *tox, uint32_t groupnumber, uint32_t peer_id, Tox_Group_Role role,
×
3190
                            Tox_Err_Group_Mod_Set_Role *error)
3191
{
3192
    Messenger *m = tox->m;
×
3193
    int ret = gc_set_peer_role(m, groupnumber, peer_id, role);
×
3194

3195
    switch (ret) {
×
3196
        case 0:
3197
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_MOD_SET_ROLE_OK);
×
3198
            return 1;
3199

3200
        case -1:
3201
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_MOD_SET_ROLE_GROUP_NOT_FOUND);
×
3202
            return 0;
3203

3204
        case -2:
3205
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_MOD_SET_ROLE_PEER_NOT_FOUND);
×
3206
            return 0;
3207

3208
        case -3:
3209
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_MOD_SET_ROLE_PERMISSIONS);
×
3210
            return 0;
3211

3212
        case -4:
3213
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_MOD_SET_ROLE_ASSIGNMENT);
×
3214
            return 0;
3215

3216
        case -5:
3217
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_MOD_SET_ROLE_FAIL_ACTION);
×
3218
            return 0;
3219
    }
3220

3221
    /* can't happen */
3222
    return 0;
3223
}
3224

3225
bool tox_group_mod_remove_peer(Tox *tox, uint32_t groupnumber, uint32_t peer_id, bool set_ban,
×
3226
                               Tox_Err_Group_Mod_Remove_Peer *error)
3227
{
3228
    Messenger *m = tox->m;
×
3229
    int ret = gc_remove_peer(m, groupnumber, peer_id, set_ban);
×
3230

3231
    switch (ret) {
×
3232
        case 0:
3233
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_MOD_REMOVE_PEER_OK);
×
3234
            return 1;
3235

3236
        case -1:
3237
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_MOD_REMOVE_PEER_GROUP_NOT_FOUND);
×
3238
            return 0;
3239

3240
        case -2:
3241
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_MOD_REMOVE_PEER_PEER_NOT_FOUND);
×
3242
            return 0;
3243

3244
        case -3:
3245
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_MOD_REMOVE_PEER_PERMISSIONS);
×
3246
            return 0;
3247

3248
        case -4:
3249
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_MOD_REMOVE_PEER_FAIL_ACTION);
×
3250
            return 0;
3251

3252
        case -5:
3253
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_MOD_REMOVE_PEER_FAIL_SEND);
×
3254
            return 0;
3255
    }
3256

3257
    /* can't happen */
3258
    return 0;
3259
}
3260

3261
bool tox_group_mod_remove_ban(Tox *tox, uint32_t groupnumber, uint32_t ban_id, Tox_Err_Group_Mod_Remove_Ban *error)
×
3262
{
3263
    Messenger *m = tox->m;
×
3264
    GC_Chat *chat = gc_get_group(m->group_handler, groupnumber);
×
3265

3266
    if (chat == nullptr) {
×
3267
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_MOD_REMOVE_BAN_GROUP_NOT_FOUND);
×
3268
        return 0;
3269
    }
3270

3271
    int ret = gc_remove_ban(chat, ban_id);
×
3272

3273
    switch (ret) {
×
3274
        case 0:
3275
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_MOD_REMOVE_BAN_OK);
×
3276
            return 1;
3277

3278
        case -1:
3279
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_MOD_REMOVE_BAN_PERMISSIONS);
×
3280
            return 0;
3281

3282
        case -2:
3283
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_MOD_REMOVE_BAN_FAIL_ACTION);
×
3284
            return 0;
3285

3286
        case -3:
3287
            SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_MOD_REMOVE_BAN_FAIL_SEND);
×
3288
            return 0;
3289
    }
3290

3291
    /* can't happen */
3292
    return 0;
3293
}
3294

3295
size_t tox_group_ban_get_list_size(const Tox *tox, uint32_t groupnumber, Tox_Err_Group_Ban_Query *error)
×
3296
{
3297
    const Messenger *m = tox->m;
×
3298
    const GC_Chat *chat = gc_get_group(m->group_handler, groupnumber);
×
3299

3300
    if (chat == nullptr) {
×
3301
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_BAN_QUERY_GROUP_NOT_FOUND);
×
3302
        return -1;
3303
    }
3304

3305
    SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_BAN_QUERY_OK);
×
3306
    return sanctions_list_num_banned(chat);
×
3307
}
3308

3309
bool tox_group_ban_get_list(const Tox *tox, uint32_t groupnumber, uint32_t *list, Tox_Err_Group_Ban_Query *error)
×
3310
{
3311
    const Messenger *m = tox->m;
×
3312
    const GC_Chat *chat = gc_get_group(m->group_handler, groupnumber);
×
3313

3314
    if (chat == nullptr) {
×
3315
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_BAN_QUERY_GROUP_NOT_FOUND);
×
3316
        return 0;
3317
    }
3318

3319
    sanctions_list_get_ban_list(chat, list);
×
3320
    SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_BAN_QUERY_OK);
×
3321
    return 1;
3322
}
3323

3324
size_t tox_group_ban_get_name_size(const Tox *tox, uint32_t groupnumber, uint32_t ban_id,
×
3325
                                   Tox_Err_Group_Ban_Query *error)
3326
{
3327
    const Messenger *m = tox->m;
×
3328
    const GC_Chat *chat = gc_get_group(m->group_handler, groupnumber);
×
3329

3330
    if (chat == nullptr) {
×
3331
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_BAN_QUERY_GROUP_NOT_FOUND);
×
3332
        return -1;
3333
    }
3334

3335
    uint16_t ret = sanctions_list_get_ban_nick_length(chat, ban_id);
×
3336

3337
    if (ret == 0) {
×
3338
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_BAN_QUERY_BAD_ID);
×
3339
        return -1;
3340
    }
3341

3342
    SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_BAN_QUERY_OK);
×
3343
    return ret;
×
3344
}
3345

3346
bool tox_group_ban_get_name(const Tox *tox, uint32_t groupnumber, uint32_t ban_id, uint8_t *name,
×
3347
                            Tox_Err_Group_Ban_Query *error)
3348
{
3349
    const Messenger *m = tox->m;
×
3350
    const GC_Chat *chat = gc_get_group(m->group_handler, groupnumber);
×
3351

3352
    if (chat == nullptr) {
×
3353
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_BAN_QUERY_GROUP_NOT_FOUND);
×
3354
        return 0;
3355
    }
3356

3357
    int ret = sanctions_list_get_ban_nick(chat, ban_id, name);
×
3358

3359
    if (ret == -1) {
×
3360
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_BAN_QUERY_BAD_ID);
×
3361
        return 0;
3362
    }
3363

3364
    SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_BAN_QUERY_OK);
×
3365
    return 1;
3366
}
3367

3368
uint64_t tox_group_ban_get_time_set(const Tox *tox, uint32_t groupnumber, uint32_t ban_id,
×
3369
                                    Tox_Err_Group_Ban_Query *error)
3370
{
3371
    const Messenger *m = tox->m;
×
3372
    const GC_Chat *chat = gc_get_group(m->group_handler, groupnumber);
×
3373

3374
    if (chat == nullptr) {
×
3375
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_BAN_QUERY_GROUP_NOT_FOUND);
×
3376
        return -1;
3377
    }
3378

3379
    uint64_t ret = sanctions_list_get_ban_time_set(chat, ban_id);
×
3380

3381
    if (ret == 0) {
×
3382
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_BAN_QUERY_BAD_ID);
×
3383
        return -1;
3384
    }
3385

3386
    SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_BAN_QUERY_OK);
×
3387
    return ret;
×
3388
}
3389
#endif /* VANILLA_NACL */
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2024 Coveralls, Inc