Coverage Report

Created: 2026-10-24 08:16

/work/toxcore/events/group_invite.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_Group_Invite {
27
    uint32_t friend_number;
28
    uint8_t *_Nullable invite_data;
29
    uint32_t invite_data_length;
30
    uint8_t *_Nullable group_name;
31
    uint32_t group_name_length;
32
};
33
34
static void tox_event_group_invite_set_friend_number(Tox_Event_Group_Invite *_Nonnull group_invite, uint32_t friend_number)
35
3
{
36
3
    assert(group_invite != nullptr);
37
3
    group_invite->friend_number = friend_number;
38
3
}
39
uint32_t tox_event_group_invite_get_friend_number(const Tox_Event_Group_Invite *group_invite)
40
3
{
41
3
    assert(group_invite != nullptr);
42
3
    return group_invite->friend_number;
43
3
}
44
45
static bool tox_event_group_invite_set_invite_data(Tox_Event_Group_Invite *_Nonnull group_invite,
46
        const Memory *_Nonnull mem, const uint8_t *_Nullable invite_data, uint32_t invite_data_length)
47
3
{
48
3
    assert(group_invite != nullptr);
49
3
    if (group_invite->invite_data != nullptr) {
50
0
        mem_delete(mem, group_invite->invite_data);
51
0
        group_invite->invite_data = nullptr;
52
0
        group_invite->invite_data_length = 0;
53
0
    }
54
55
3
    if (invite_data == nullptr) {
56
0
        assert(invite_data_length == 0);
57
0
        return true;
58
0
    }
59
60
3
    if (invite_data_length == 0) {
61
0
        group_invite->invite_data = nullptr;
62
0
        group_invite->invite_data_length = 0;
63
0
        return true;
64
0
    }
65
66
3
    uint8_t *invite_data_copy = (uint8_t *)mem_balloc(mem, invite_data_length);
67
68
3
    if (invite_data_copy == nullptr) {
69
0
        return false;
70
0
    }
71
72
3
    memcpy(invite_data_copy, invite_data, invite_data_length);
73
3
    group_invite->invite_data = invite_data_copy;
74
3
    group_invite->invite_data_length = invite_data_length;
75
3
    return true;
76
3
}
77
uint32_t tox_event_group_invite_get_invite_data_length(const Tox_Event_Group_Invite *group_invite)
78
3
{
79
3
    assert(group_invite != nullptr);
80
3
    return group_invite->invite_data_length;
81
3
}
82
const uint8_t *tox_event_group_invite_get_invite_data(const Tox_Event_Group_Invite *group_invite)
83
3
{
84
3
    assert(group_invite != nullptr);
85
3
    return group_invite->invite_data;
86
3
}
87
88
static bool tox_event_group_invite_set_group_name(Tox_Event_Group_Invite *_Nonnull group_invite,
89
        const Memory *_Nonnull mem, const uint8_t *_Nullable group_name, uint32_t group_name_length)
90
3
{
91
3
    assert(group_invite != nullptr);
92
3
    if (group_invite->group_name != nullptr) {
93
0
        mem_delete(mem, group_invite->group_name);
94
0
        group_invite->group_name = nullptr;
95
0
        group_invite->group_name_length = 0;
96
0
    }
97
98
3
    if (group_name == nullptr) {
99
0
        assert(group_name_length == 0);
100
0
        return true;
101
0
    }
102
103
3
    if (group_name_length == 0) {
104
0
        group_invite->group_name = nullptr;
105
0
        group_invite->group_name_length = 0;
106
0
        return true;
107
0
    }
108
109
3
    uint8_t *group_name_copy = (uint8_t *)mem_balloc(mem, group_name_length);
110
111
3
    if (group_name_copy == nullptr) {
112
0
        return false;
113
0
    }
114
115
3
    memcpy(group_name_copy, group_name, group_name_length);
116
3
    group_invite->group_name = group_name_copy;
117
3
    group_invite->group_name_length = group_name_length;
118
3
    return true;
119
3
}
120
uint32_t tox_event_group_invite_get_group_name_length(const Tox_Event_Group_Invite *group_invite)
121
0
{
122
0
    assert(group_invite != nullptr);
123
0
    return group_invite->group_name_length;
124
0
}
125
const uint8_t *tox_event_group_invite_get_group_name(const Tox_Event_Group_Invite *group_invite)
126
0
{
127
0
    assert(group_invite != nullptr);
128
0
    return group_invite->group_name;
129
0
}
130
131
static void tox_event_group_invite_construct(Tox_Event_Group_Invite *_Nonnull group_invite)
132
25
{
133
25
    *group_invite = (Tox_Event_Group_Invite) {
134
25
        0
135
25
    };
136
25
}
137
static void tox_event_group_invite_destruct(Tox_Event_Group_Invite *_Nonnull group_invite, const Memory *_Nonnull mem)
138
25
{
139
25
    mem_delete(mem, group_invite->invite_data);
140
25
    mem_delete(mem, group_invite->group_name);
141
25
}
142
143
bool tox_event_group_invite_pack(
144
    const Tox_Event_Group_Invite *event, Bin_Pack *bp)
145
22
{
146
22
    return bin_pack_array(bp, 3)
147
22
           && bin_pack_u32(bp, event->friend_number)
148
22
           && bin_pack_bin(bp, event->invite_data, event->invite_data_length)
149
22
           && bin_pack_bin(bp, event->group_name, event->group_name_length);
150
22
}
151
152
static bool tox_event_group_invite_unpack_into(Tox_Event_Group_Invite *_Nonnull event, Bin_Unpack *_Nonnull bu)
153
22
{
154
22
    assert(event != nullptr);
155
22
    if (!bin_unpack_array_fixed(bu, 3, nullptr)) {
156
2
        return false;
157
2
    }
158
159
20
    return bin_unpack_u32(bu, &event->friend_number)
160
20
           && bin_unpack_bin(bu, &event->invite_data, &event->invite_data_length)
161
20
           && bin_unpack_bin(bu, &event->group_name, &event->group_name_length);
162
22
}
163
164
/*****************************************************
165
 *
166
 * :: new/free/add/get/size/unpack
167
 *
168
 *****************************************************/
169
170
const Tox_Event_Group_Invite *tox_event_get_group_invite(const Tox_Event *event)
171
0
{
172
0
    return event->type == TOX_EVENT_GROUP_INVITE ? event->data.group_invite : nullptr;
173
0
}
174
175
Tox_Event_Group_Invite *tox_event_group_invite_new(const Memory *mem)
176
26
{
177
26
    Tox_Event_Group_Invite *const group_invite =
178
26
        (Tox_Event_Group_Invite *)mem_alloc(mem, sizeof(Tox_Event_Group_Invite));
179
180
26
    if (group_invite == nullptr) {
181
1
        return nullptr;
182
1
    }
183
184
25
    tox_event_group_invite_construct(group_invite);
185
25
    return group_invite;
186
26
}
187
188
void tox_event_group_invite_free(Tox_Event_Group_Invite *group_invite, const Memory *mem)
189
26
{
190
26
    if (group_invite != nullptr) {
191
25
        tox_event_group_invite_destruct(group_invite, mem);
192
25
    }
193
26
    mem_delete(mem, group_invite);
194
26
}
195
196
static Tox_Event_Group_Invite *_Nullable tox_events_add_group_invite(Tox_Events *_Nonnull events, const Memory *_Nonnull mem)
197
3
{
198
3
    Tox_Event_Group_Invite *const group_invite = tox_event_group_invite_new(mem);
199
200
3
    if (group_invite == nullptr) {
201
0
        return nullptr;
202
0
    }
203
204
3
    Tox_Event event;
205
3
    event.type = TOX_EVENT_GROUP_INVITE;
206
3
    event.data.group_invite = group_invite;
207
208
3
    if (!tox_events_add(events, &event)) {
209
0
        tox_event_group_invite_free(group_invite, mem);
210
0
        return nullptr;
211
0
    }
212
3
    return group_invite;
213
3
}
214
215
bool tox_event_group_invite_unpack(
216
    Tox_Event_Group_Invite **event, Bin_Unpack *bu, const Memory *mem)
217
23
{
218
23
    assert(event != nullptr);
219
23
    assert(*event == nullptr);
220
23
    *event = tox_event_group_invite_new(mem);
221
222
23
    if (*event == nullptr) {
223
1
        return false;
224
1
    }
225
226
22
    return tox_event_group_invite_unpack_into(*event, bu);
227
23
}
228
229
static Tox_Event_Group_Invite *_Nullable tox_event_group_invite_alloc(Tox_Events_State *_Nonnull state)
230
3
{
231
3
    if (state->events == nullptr) {
232
0
        return nullptr;
233
0
    }
234
235
3
    Tox_Event_Group_Invite *group_invite = tox_events_add_group_invite(state->events, state->mem);
236
237
3
    if (group_invite == nullptr) {
238
0
        state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
239
0
        return nullptr;
240
0
    }
241
242
3
    return group_invite;
243
3
}
244
245
/*****************************************************
246
 *
247
 * :: event handler
248
 *
249
 *****************************************************/
250
251
void tox_events_handle_group_invite(
252
    Tox *_Nonnull tox,
253
    uint32_t friend_number,
254
    const uint8_t *_Nullable invite_data, size_t invite_data_length,
255
    const uint8_t *_Nullable group_name, size_t group_name_length,
256
    void *_Nullable user_data)
257
3
{
258
3
    Tox_Events_State *state = tox_events_alloc(user_data);
259
3
    Tox_Event_Group_Invite *group_invite = tox_event_group_invite_alloc(state);
260
261
3
    if (group_invite == nullptr) {
262
0
        return;
263
0
    }
264
265
3
    tox_event_group_invite_set_friend_number(group_invite, friend_number);
266
3
    if (!tox_event_group_invite_set_invite_data(group_invite, state->mem, invite_data, invite_data_length)) {
267
0
        tox_event_group_invite_free(group_invite, state->mem);
268
0
        state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
269
0
        return;
270
0
    }
271
3
    if (!tox_event_group_invite_set_group_name(group_invite, state->mem, group_name, group_name_length)) {
272
0
        tox_event_group_invite_free(group_invite, state->mem);
273
0
        state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
274
0
        return;
275
0
    }
276
3
}
277
278
void tox_events_handle_group_invite_dispatch(Tox *tox, const Tox_Event_Group_Invite *event, void *user_data)
279
0
{
280
0
    if (tox->group_invite_callback == nullptr) {
281
0
        return;
282
0
    }
283
284
0
    tox_unlock(tox);
285
0
    tox->group_invite_callback(tox, event->friend_number, event->invite_data, event->invite_data_length, event->group_name, event->group_name_length, user_data);
286
0
    tox_lock(tox);
287
0
}