Coverage Report

Created: 2025-10-08 19:34

/work/toxcore/tox_private.c
Line
Count
Source (jump to first uncovered line)
1
/* SPDX-License-Identifier: GPL-3.0-or-later
2
 * Copyright © 2016-2025 The TokTok team.
3
 * Copyright © 2013 Tox project.
4
 */
5
6
/**
7
 * The Tox private API (for tests).
8
 */
9
#include "tox_private.h"
10
11
#include <assert.h>
12
13
#include "DHT.h"
14
#include "Messenger.h"
15
#include "TCP_server.h"
16
#include "ccompat.h"
17
#include "crypto_core.h"
18
#include "group_chats.h"
19
#include "group_common.h"
20
#include "logger.h"
21
#include "mem.h"
22
#include "net_crypto.h"
23
#include "net_profile.h"
24
#include "network.h"
25
#include "os_memory.h"
26
#include "os_random.h"
27
#include "tox.h"
28
#include "tox_struct.h"  // IWYU pragma: keep
29
30
#define SET_ERROR_PARAMETER(param, x) \
31
27.0k
    do {                              \
32
27.0k
        if (param != nullptr) {       \
33
12
            *param = x;               \
34
12
        }                             \
35
27.0k
    } while (0)
36
37
Tox_System tox_default_system(void)
38
3.20k
{
39
3.20k
    const Tox_System sys = {
40
3.20k
        nullptr,  // mono_time_callback
41
3.20k
        nullptr,  // mono_time_user_data
42
3.20k
        os_random(),
43
3.20k
        os_network(),
44
3.20k
        os_memory(),
45
3.20k
    };
46
3.20k
    return sys;
47
3.20k
}
48
49
void tox_lock(const Tox *tox)
50
944k
{
51
944k
    if (tox->mutex != nullptr) {
52
5.36k
        pthread_mutex_lock(tox->mutex);
53
5.36k
    }
54
944k
}
55
56
void tox_unlock(const Tox *tox)
57
944k
{
58
944k
    if (tox->mutex != nullptr) {
59
5.36k
        pthread_mutex_unlock(tox->mutex);
60
5.36k
    }
61
944k
}
62
63
void tox_callback_friend_lossy_packet_per_pktid(Tox *tox, tox_friend_lossy_packet_cb *callback, uint8_t pktid)
64
84
{
65
84
    assert(tox != nullptr);
66
67
84
    if (pktid >= PACKET_ID_RANGE_LOSSY_START && pktid <= PACKET_ID_RANGE_LOSSY_END) {
68
84
        tox->friend_lossy_packet_callback_per_pktid[pktid] = callback;
69
84
    }
70
84
}
71
72
void tox_callback_friend_lossless_packet_per_pktid(Tox *tox, tox_friend_lossless_packet_cb *callback, uint8_t pktid)
73
12
{
74
12
    assert(tox != nullptr);
75
76
12
    if ((pktid >= PACKET_ID_RANGE_LOSSLESS_CUSTOM_START && pktid <= PACKET_ID_RANGE_LOSSLESS_CUSTOM_END)
77
12
            || pktid == PACKET_ID_MSI) {
78
12
        tox->friend_lossless_packet_callback_per_pktid[pktid] = callback;
79
12
    }
80
12
}
81
82
void tox_set_av_object(Tox *tox, void *object)
83
12
{
84
12
    assert(tox != nullptr);
85
12
    tox_lock(tox);
86
12
    tox->toxav_object = object;
87
12
    tox_unlock(tox);
88
12
}
89
90
void *tox_get_av_object(const Tox *tox)
91
304
{
92
304
    assert(tox != nullptr);
93
304
    tox_lock(tox);
94
304
    void *object = tox->toxav_object;
95
304
    tox_unlock(tox);
96
304
    return object;
97
304
}
98
99
void tox_callback_dht_nodes_response(Tox *tox, tox_dht_nodes_response_cb *callback)
100
1.21k
{
101
1.21k
    assert(tox != nullptr);
102
1.21k
    tox->dht_nodes_response_callback = callback;
103
1.21k
}
104
105
bool tox_dht_send_nodes_request(const Tox *tox, const uint8_t *public_key, const char *ip, uint16_t port,
106
                                const uint8_t *target_public_key, Tox_Err_Dht_Send_Nodes_Request *error)
107
27.0k
{
108
27.0k
    assert(tox != nullptr);
109
110
27.0k
    tox_lock(tox);
111
112
27.0k
    if (tox->m->options.udp_disabled) {
113
0
        SET_ERROR_PARAMETER(error, TOX_ERR_DHT_SEND_NODES_REQUEST_UDP_DISABLED);
114
0
        tox_unlock(tox);
115
0
        return false;
116
0
    }
117
118
27.0k
    if (public_key == nullptr || ip == nullptr || target_public_key == nullptr) {
119
0
        SET_ERROR_PARAMETER(error, TOX_ERR_DHT_SEND_NODES_REQUEST_NULL);
120
0
        tox_unlock(tox);
121
0
        return false;
122
0
    }
123
124
27.0k
    if (port == 0) {
125
0
        SET_ERROR_PARAMETER(error, TOX_ERR_DHT_SEND_NODES_REQUEST_BAD_PORT);
126
0
        tox_unlock(tox);
127
0
        return false;
128
0
    }
129
130
27.0k
    IP_Port *root;
131
132
27.0k
    const int32_t count = net_getipport(tox->sys.ns, tox->sys.mem, ip, &root, TOX_SOCK_DGRAM, tox->m->options.dns_enabled);
133
134
27.0k
    if (count < 1) {
135
0
        SET_ERROR_PARAMETER(error, TOX_ERR_DHT_SEND_NODES_REQUEST_BAD_IP);
136
0
        net_freeipport(tox->sys.mem, root);
137
0
        tox_unlock(tox);
138
0
        return false;
139
0
    }
140
141
27.0k
    bool success = false;
142
143
54.0k
    for (int32_t i = 0; i < count; ++i) {
144
27.0k
        root[i].port = net_htons(port);
145
146
27.0k
        if (dht_send_nodes_request(tox->m->dht, &root[i], public_key, target_public_key)) {
147
26.1k
            success = true;
148
26.1k
        }
149
27.0k
    }
150
151
27.0k
    tox_unlock(tox);
152
153
27.0k
    net_freeipport(tox->sys.mem, root);
154
155
27.0k
    if (!success) {
156
900
        SET_ERROR_PARAMETER(error, TOX_ERR_DHT_SEND_NODES_REQUEST_FAIL);
157
900
        return false;
158
900
    }
159
160
26.1k
    SET_ERROR_PARAMETER(error, TOX_ERR_DHT_SEND_NODES_REQUEST_OK);
161
162
26.1k
    return true;
163
27.0k
}
164
165
uint16_t tox_dht_get_num_closelist(const Tox *tox)
166
30
{
167
30
    tox_lock(tox);
168
30
    const uint16_t num_total = dht_get_num_closelist(tox->m->dht);
169
30
    tox_unlock(tox);
170
171
30
    return num_total;
172
30
}
173
174
uint16_t tox_dht_get_num_closelist_announce_capable(const Tox *tox)
175
30
{
176
30
    tox_lock(tox);
177
30
    const uint16_t num_cap = dht_get_num_closelist_announce_capable(tox->m->dht);
178
30
    tox_unlock(tox);
179
180
30
    return num_cap;
181
30
}
182
183
size_t tox_group_peer_get_ip_address_size(const Tox *tox, uint32_t group_number, uint32_t peer_id,
184
        Tox_Err_Group_Peer_Query *error)
185
6
{
186
6
    assert(tox != nullptr);
187
188
6
    tox_lock(tox);
189
6
    const GC_Chat *chat = gc_get_group(tox->m->group_handler, group_number);
190
191
6
    if (chat == nullptr) {
192
0
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_PEER_QUERY_GROUP_NOT_FOUND);
193
0
        tox_unlock(tox);
194
0
        return -1;
195
0
    }
196
197
6
    const int ret = gc_get_peer_ip_address_size(chat, gc_peer_id_from_int(peer_id));
198
6
    tox_unlock(tox);
199
200
6
    if (ret == -1) {
201
0
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_PEER_QUERY_PEER_NOT_FOUND);
202
0
        return -1;
203
6
    } else {
204
6
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_PEER_QUERY_OK);
205
6
        return ret;
206
6
    }
207
6
}
208
209
bool tox_group_peer_get_ip_address(const Tox *tox, uint32_t group_number, uint32_t peer_id, uint8_t *ip_addr,
210
                                   Tox_Err_Group_Peer_Query *error)
211
6
{
212
6
    assert(tox != nullptr);
213
214
6
    tox_lock(tox);
215
6
    const GC_Chat *chat = gc_get_group(tox->m->group_handler, group_number);
216
217
6
    if (chat == nullptr) {
218
0
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_PEER_QUERY_GROUP_NOT_FOUND);
219
0
        tox_unlock(tox);
220
0
        return false;
221
0
    }
222
223
6
    const int ret = gc_get_peer_ip_address(chat, gc_peer_id_from_int(peer_id), ip_addr);
224
6
    tox_unlock(tox);
225
226
6
    if (ret == -1) {
227
0
        SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_PEER_QUERY_PEER_NOT_FOUND);
228
0
        return false;
229
0
    }
230
231
6
    SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_PEER_QUERY_OK);
232
6
    return true;
233
6
}
234
235
uint64_t tox_netprof_get_packet_id_count(const Tox *tox, Tox_Netprof_Packet_Type type, uint8_t id,
236
        Tox_Netprof_Direction direction)
237
511
{
238
511
    assert(tox != nullptr);
239
240
511
    tox_lock(tox);
241
242
511
    const Net_Profile *tcp_c_profile = tox->m->tcp_np;
243
511
    const Net_Profile *tcp_s_profile = tcp_server_get_net_profile(tox->m->tcp_server);
244
245
511
    const Packet_Direction dir = (Packet_Direction) direction;
246
247
511
    uint64_t count = 0;
248
249
511
    switch (type) {
250
0
        case TOX_NETPROF_PACKET_TYPE_TCP_CLIENT: {
251
0
            count = netprof_get_packet_count_id(tcp_c_profile, id, dir);
252
0
            break;
253
0
        }
254
255
0
        case TOX_NETPROF_PACKET_TYPE_TCP_SERVER: {
256
0
            count = netprof_get_packet_count_id(tcp_s_profile, id, dir);
257
0
            break;
258
0
        }
259
260
0
        case TOX_NETPROF_PACKET_TYPE_TCP: {
261
0
            const uint64_t tcp_c_count = netprof_get_packet_count_id(tcp_c_profile, id, dir);
262
0
            const uint64_t tcp_s_count = netprof_get_packet_count_id(tcp_s_profile, id, dir);
263
0
            count = tcp_c_count + tcp_s_count;
264
0
            break;
265
0
        }
266
267
511
        case TOX_NETPROF_PACKET_TYPE_UDP: {
268
511
            const Net_Profile *udp_profile = net_get_net_profile(tox->m->net);
269
511
            count = netprof_get_packet_count_id(udp_profile, id, dir);
270
511
            break;
271
0
        }
272
273
0
        default: {
274
0
            LOGGER_ERROR(tox->m->log, "invalid packet type: %u", type);
275
0
            break;
276
0
        }
277
511
    }
278
279
511
    tox_unlock(tox);
280
281
511
    return count;
282
511
}
283
284
uint64_t tox_netprof_get_packet_total_count(const Tox *tox, Tox_Netprof_Packet_Type type,
285
        Tox_Netprof_Direction direction)
286
4
{
287
4
    assert(tox != nullptr);
288
289
4
    tox_lock(tox);
290
291
4
    const Net_Profile *tcp_c_profile = tox->m->tcp_np;
292
4
    const Net_Profile *tcp_s_profile = tcp_server_get_net_profile(tox->m->tcp_server);
293
294
4
    const Packet_Direction dir = (Packet_Direction) direction;
295
296
4
    uint64_t count = 0;
297
298
4
    switch (type) {
299
0
        case TOX_NETPROF_PACKET_TYPE_TCP_CLIENT: {
300
0
            count = netprof_get_packet_count_total(tcp_c_profile, dir);
301
0
            break;
302
0
        }
303
304
0
        case TOX_NETPROF_PACKET_TYPE_TCP_SERVER: {
305
0
            count = netprof_get_packet_count_total(tcp_s_profile, dir);
306
0
            break;
307
0
        }
308
309
2
        case TOX_NETPROF_PACKET_TYPE_TCP: {
310
2
            const uint64_t tcp_c_count = netprof_get_packet_count_total(tcp_c_profile, dir);
311
2
            const uint64_t tcp_s_count = netprof_get_packet_count_total(tcp_s_profile, dir);
312
2
            count = tcp_c_count + tcp_s_count;
313
2
            break;
314
0
        }
315
316
2
        case TOX_NETPROF_PACKET_TYPE_UDP: {
317
2
            const Net_Profile *udp_profile = net_get_net_profile(tox->m->net);
318
2
            count = netprof_get_packet_count_total(udp_profile, dir);
319
2
            break;
320
0
        }
321
322
0
        default: {
323
0
            LOGGER_ERROR(tox->m->log, "invalid packet type: %u", type);
324
0
            break;
325
0
        }
326
4
    }
327
328
4
    tox_unlock(tox);
329
330
4
    return count;
331
4
}
332
333
uint64_t tox_netprof_get_packet_id_bytes(const Tox *tox, Tox_Netprof_Packet_Type type, uint8_t id,
334
        Tox_Netprof_Direction direction)
335
513
{
336
513
    assert(tox != nullptr);
337
338
513
    tox_lock(tox);
339
340
513
    const Net_Profile *tcp_c_profile = tox->m->tcp_np;
341
513
    const Net_Profile *tcp_s_profile = tcp_server_get_net_profile(tox->m->tcp_server);
342
343
513
    const Packet_Direction dir = (Packet_Direction) direction;
344
345
513
    uint64_t bytes = 0;
346
347
513
    switch (type) {
348
0
        case TOX_NETPROF_PACKET_TYPE_TCP_CLIENT: {
349
0
            bytes = netprof_get_bytes_id(tcp_c_profile, id, dir);
350
0
            break;
351
0
        }
352
353
0
        case TOX_NETPROF_PACKET_TYPE_TCP_SERVER: {
354
0
            bytes = netprof_get_bytes_id(tcp_s_profile, id, dir);
355
0
            break;
356
0
        }
357
358
0
        case TOX_NETPROF_PACKET_TYPE_TCP: {
359
0
            const uint64_t tcp_c_bytes = netprof_get_bytes_id(tcp_c_profile, id, dir);
360
0
            const uint64_t tcp_s_bytes = netprof_get_bytes_id(tcp_s_profile, id, dir);
361
0
            bytes = tcp_c_bytes + tcp_s_bytes;
362
0
            break;
363
0
        }
364
365
513
        case TOX_NETPROF_PACKET_TYPE_UDP: {
366
513
            const Net_Profile *udp_profile = net_get_net_profile(tox->m->net);
367
513
            bytes = netprof_get_bytes_id(udp_profile, id, dir);
368
513
            break;
369
0
        }
370
371
0
        default: {
372
0
            LOGGER_ERROR(tox->m->log, "invalid packet type: %u", type);
373
0
            break;
374
0
        }
375
513
    }
376
377
513
    tox_unlock(tox);
378
379
513
    return bytes;
380
513
}
381
382
uint64_t tox_netprof_get_packet_total_bytes(const Tox *tox, Tox_Netprof_Packet_Type type,
383
        Tox_Netprof_Direction direction)
384
4
{
385
4
    assert(tox != nullptr);
386
387
4
    tox_lock(tox);
388
389
4
    const Net_Profile *tcp_c_profile = tox->m->tcp_np;
390
4
    const Net_Profile *tcp_s_profile = tcp_server_get_net_profile(tox->m->tcp_server);
391
392
4
    const Packet_Direction dir = (Packet_Direction) direction;
393
394
4
    uint64_t bytes = 0;
395
396
4
    switch (type) {
397
0
        case TOX_NETPROF_PACKET_TYPE_TCP_CLIENT: {
398
0
            bytes = netprof_get_bytes_total(tcp_c_profile, dir);
399
0
            break;
400
0
        }
401
402
0
        case TOX_NETPROF_PACKET_TYPE_TCP_SERVER: {
403
0
            bytes = netprof_get_bytes_total(tcp_s_profile, dir);
404
0
            break;
405
0
        }
406
407
2
        case TOX_NETPROF_PACKET_TYPE_TCP: {
408
2
            const uint64_t tcp_c_bytes = netprof_get_bytes_total(tcp_c_profile, dir);
409
2
            const uint64_t tcp_s_bytes = netprof_get_bytes_total(tcp_s_profile, dir);
410
2
            bytes = tcp_c_bytes + tcp_s_bytes;
411
2
            break;
412
0
        }
413
414
2
        case TOX_NETPROF_PACKET_TYPE_UDP: {
415
2
            const Net_Profile *udp_profile = net_get_net_profile(tox->m->net);
416
2
            bytes = netprof_get_bytes_total(udp_profile, dir);
417
2
            break;
418
0
        }
419
420
0
        default: {
421
0
            LOGGER_ERROR(tox->m->log, "invalid packet type: %u", type);
422
0
            break;
423
0
        }
424
4
    }
425
426
4
    tox_unlock(tox);
427
428
4
    return bytes;
429
4
}