Coverage Report

Created: 2026-10-24 08:16

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