Coverage Report

Created: 2026-10-24 08:16

/work/toxcore/events/file_recv.c
Line
Count
Source (jump to first uncovered line)
1
/* SPDX-License-Identifier: GPL-3.0-or-later
2
 * Copyright © 2023-2026 The TokTok team.
3
 */
4
5
#include "events_alloc.h"
6
7
#include <assert.h>
8
#include <string.h>
9
10
#include "../attributes.h"
11
#include "../bin_pack.h"
12
#include "../bin_unpack.h"
13
#include "../ccompat.h"
14
#include "../mem.h"
15
#include "../tox.h"
16
#include "../tox_event.h"
17
#include "../tox_events.h"
18
#include "../tox_struct.h"
19
20
/*****************************************************
21
 *
22
 * :: struct and accessors
23
 *
24
 *****************************************************/
25
26
struct Tox_Event_File_Recv {
27
    uint32_t friend_number;
28
    uint32_t file_number;
29
    uint32_t kind;
30
    uint64_t file_size;
31
    uint8_t *_Nullable filename;
32
    uint32_t filename_length;
33
};
34
35
static void tox_event_file_recv_set_friend_number(Tox_Event_File_Recv *_Nonnull file_recv, uint32_t friend_number)
36
4
{
37
4
    assert(file_recv != nullptr);
38
4
    file_recv->friend_number = friend_number;
39
4
}
40
uint32_t tox_event_file_recv_get_friend_number(const Tox_Event_File_Recv *file_recv)
41
3
{
42
3
    assert(file_recv != nullptr);
43
3
    return file_recv->friend_number;
44
3
}
45
46
static void tox_event_file_recv_set_file_number(Tox_Event_File_Recv *_Nonnull file_recv, uint32_t file_number)
47
4
{
48
4
    assert(file_recv != nullptr);
49
4
    file_recv->file_number = file_number;
50
4
}
51
uint32_t tox_event_file_recv_get_file_number(const Tox_Event_File_Recv *file_recv)
52
4
{
53
4
    assert(file_recv != nullptr);
54
4
    return file_recv->file_number;
55
4
}
56
57
static void tox_event_file_recv_set_kind(Tox_Event_File_Recv *_Nonnull file_recv, uint32_t kind)
58
4
{
59
4
    assert(file_recv != nullptr);
60
4
    file_recv->kind = kind;
61
4
}
62
uint32_t tox_event_file_recv_get_kind(const Tox_Event_File_Recv *file_recv)
63
1
{
64
1
    assert(file_recv != nullptr);
65
1
    return file_recv->kind;
66
1
}
67
68
static void tox_event_file_recv_set_file_size(Tox_Event_File_Recv *_Nonnull file_recv, uint64_t file_size)
69
4
{
70
4
    assert(file_recv != nullptr);
71
4
    file_recv->file_size = file_size;
72
4
}
73
uint64_t tox_event_file_recv_get_file_size(const Tox_Event_File_Recv *file_recv)
74
1
{
75
1
    assert(file_recv != nullptr);
76
1
    return file_recv->file_size;
77
1
}
78
79
static bool tox_event_file_recv_set_filename(Tox_Event_File_Recv *_Nonnull file_recv,
80
        const Memory *_Nonnull mem, const uint8_t *_Nullable filename, uint32_t filename_length)
81
4
{
82
4
    assert(file_recv != nullptr);
83
4
    if (file_recv->filename != nullptr) {
84
0
        mem_delete(mem, file_recv->filename);
85
0
        file_recv->filename = nullptr;
86
0
        file_recv->filename_length = 0;
87
0
    }
88
89
4
    if (filename == nullptr) {
90
0
        assert(filename_length == 0);
91
0
        return true;
92
0
    }
93
94
4
    if (filename_length == 0) {
95
0
        file_recv->filename = nullptr;
96
0
        file_recv->filename_length = 0;
97
0
        return true;
98
0
    }
99
100
4
    uint8_t *filename_copy = (uint8_t *)mem_balloc(mem, filename_length);
101
102
4
    if (filename_copy == nullptr) {
103
0
        return false;
104
0
    }
105
106
4
    memcpy(filename_copy, filename, filename_length);
107
4
    file_recv->filename = filename_copy;
108
4
    file_recv->filename_length = filename_length;
109
4
    return true;
110
4
}
111
uint32_t tox_event_file_recv_get_filename_length(const Tox_Event_File_Recv *file_recv)
112
0
{
113
0
    assert(file_recv != nullptr);
114
0
    return file_recv->filename_length;
115
0
}
116
const uint8_t *tox_event_file_recv_get_filename(const Tox_Event_File_Recv *file_recv)
117
0
{
118
0
    assert(file_recv != nullptr);
119
0
    return file_recv->filename;
120
0
}
121
122
static void tox_event_file_recv_construct(Tox_Event_File_Recv *_Nonnull file_recv)
123
36
{
124
36
    *file_recv = (Tox_Event_File_Recv) {
125
36
        0
126
36
    };
127
36
}
128
static void tox_event_file_recv_destruct(Tox_Event_File_Recv *_Nonnull file_recv, const Memory *_Nonnull mem)
129
36
{
130
36
    mem_delete(mem, file_recv->filename);
131
36
}
132
133
bool tox_event_file_recv_pack(
134
    const Tox_Event_File_Recv *event, Bin_Pack *bp)
135
38
{
136
38
    return bin_pack_array(bp, 5)
137
38
           && bin_pack_u32(bp, event->friend_number)
138
38
           && bin_pack_u32(bp, event->file_number)
139
38
           && bin_pack_u32(bp, event->kind)
140
38
           && bin_pack_u64(bp, event->file_size)
141
38
           && bin_pack_bin(bp, event->filename, event->filename_length);
142
38
}
143
144
static bool tox_event_file_recv_unpack_into(Tox_Event_File_Recv *_Nonnull event, Bin_Unpack *_Nonnull bu)
145
32
{
146
32
    assert(event != nullptr);
147
32
    if (!bin_unpack_array_fixed(bu, 5, nullptr)) {
148
2
        return false;
149
2
    }
150
151
30
    return bin_unpack_u32(bu, &event->friend_number)
152
30
           && bin_unpack_u32(bu, &event->file_number)
153
30
           && bin_unpack_u32(bu, &event->kind)
154
30
           && bin_unpack_u64(bu, &event->file_size)
155
30
           && bin_unpack_bin(bu, &event->filename, &event->filename_length);
156
32
}
157
158
/*****************************************************
159
 *
160
 * :: new/free/add/get/size/unpack
161
 *
162
 *****************************************************/
163
164
const Tox_Event_File_Recv *tox_event_get_file_recv(const Tox_Event *event)
165
0
{
166
0
    return event->type == TOX_EVENT_FILE_RECV ? event->data.file_recv : nullptr;
167
0
}
168
169
Tox_Event_File_Recv *tox_event_file_recv_new(const Memory *mem)
170
37
{
171
37
    Tox_Event_File_Recv *const file_recv =
172
37
        (Tox_Event_File_Recv *)mem_alloc(mem, sizeof(Tox_Event_File_Recv));
173
174
37
    if (file_recv == nullptr) {
175
1
        return nullptr;
176
1
    }
177
178
36
    tox_event_file_recv_construct(file_recv);
179
36
    return file_recv;
180
37
}
181
182
void tox_event_file_recv_free(Tox_Event_File_Recv *file_recv, const Memory *mem)
183
37
{
184
37
    if (file_recv != nullptr) {
185
36
        tox_event_file_recv_destruct(file_recv, mem);
186
36
    }
187
37
    mem_delete(mem, file_recv);
188
37
}
189
190
static Tox_Event_File_Recv *_Nullable tox_events_add_file_recv(Tox_Events *_Nonnull events, const Memory *_Nonnull mem)
191
4
{
192
4
    Tox_Event_File_Recv *const file_recv = tox_event_file_recv_new(mem);
193
194
4
    if (file_recv == nullptr) {
195
0
        return nullptr;
196
0
    }
197
198
4
    Tox_Event event;
199
4
    event.type = TOX_EVENT_FILE_RECV;
200
4
    event.data.file_recv = file_recv;
201
202
4
    if (!tox_events_add(events, &event)) {
203
0
        tox_event_file_recv_free(file_recv, mem);
204
0
        return nullptr;
205
0
    }
206
4
    return file_recv;
207
4
}
208
209
bool tox_event_file_recv_unpack(
210
    Tox_Event_File_Recv **event, Bin_Unpack *bu, const Memory *mem)
211
33
{
212
33
    assert(event != nullptr);
213
33
    assert(*event == nullptr);
214
33
    *event = tox_event_file_recv_new(mem);
215
216
33
    if (*event == nullptr) {
217
1
        return false;
218
1
    }
219
220
32
    return tox_event_file_recv_unpack_into(*event, bu);
221
33
}
222
223
static Tox_Event_File_Recv *_Nullable tox_event_file_recv_alloc(Tox_Events_State *_Nonnull state)
224
4
{
225
4
    if (state->events == nullptr) {
226
0
        return nullptr;
227
0
    }
228
229
4
    Tox_Event_File_Recv *file_recv = tox_events_add_file_recv(state->events, state->mem);
230
231
4
    if (file_recv == nullptr) {
232
0
        state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
233
0
        return nullptr;
234
0
    }
235
236
4
    return file_recv;
237
4
}
238
239
/*****************************************************
240
 *
241
 * :: event handler
242
 *
243
 *****************************************************/
244
245
void tox_events_handle_file_recv(
246
    Tox *_Nonnull tox,
247
    uint32_t friend_number,
248
    uint32_t file_number,
249
    uint32_t kind,
250
    uint64_t file_size,
251
    const uint8_t *_Nullable filename, size_t filename_length,
252
    void *_Nullable user_data)
253
4
{
254
4
    Tox_Events_State *state = tox_events_alloc(user_data);
255
4
    Tox_Event_File_Recv *file_recv = tox_event_file_recv_alloc(state);
256
257
4
    if (file_recv == nullptr) {
258
0
        return;
259
0
    }
260
261
4
    tox_event_file_recv_set_friend_number(file_recv, friend_number);
262
4
    tox_event_file_recv_set_file_number(file_recv, file_number);
263
4
    tox_event_file_recv_set_kind(file_recv, kind);
264
4
    tox_event_file_recv_set_file_size(file_recv, file_size);
265
4
    if (!tox_event_file_recv_set_filename(file_recv, state->mem, filename, filename_length)) {
266
0
        tox_event_file_recv_free(file_recv, state->mem);
267
0
        state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
268
0
        return;
269
0
    }
270
4
}
271
272
void tox_events_handle_file_recv_dispatch(Tox *tox, const Tox_Event_File_Recv *event, void *user_data)
273
0
{
274
0
    if (tox->file_recv_callback == nullptr) {
275
0
        return;
276
0
    }
277
278
0
    tox_unlock(tox);
279
0
    tox->file_recv_callback(tox, event->friend_number, event->file_number, event->kind, event->file_size, event->filename, event->filename_length, user_data);
280
0
    tox_lock(tox);
281
0
}