summaryrefslogtreecommitdiff
path: root/testing
diff options
context:
space:
mode:
authorCoren[m] <Break@Ocean>2013-09-09 21:31:11 +0200
committerCoren[m] <Break@Ocean>2013-09-09 21:31:11 +0200
commitb91b87f28548261a582c295afa397a6c569089d7 (patch)
tree0dd5cdcd2929812f8600239d11e7fba08afb9dd4 /testing
parent447fdc74ec0794d334d2fa3b5b88091aa582e14a (diff)
parent1f5bfab3278164293dd798ca24ead081c54708da (diff)
Merge branch 'master' into Integration
Diffstat (limited to 'testing')
-rw-r--r--testing/experiment/group_chats.c548
-rw-r--r--testing/experiment/group_chats.h113
-rw-r--r--testing/experiment/group_chats_test.c3
-rw-r--r--testing/experiment/group_chats_test1.c2
4 files changed, 3 insertions, 663 deletions
diff --git a/testing/experiment/group_chats.c b/testing/experiment/group_chats.c
deleted file mode 100644
index 635bba72..00000000
--- a/testing/experiment/group_chats.c
+++ /dev/null
@@ -1,548 +0,0 @@
1/* group_chats.c
2 *
3 * An implementation of massive text only group chats.
4 *
5 *
6 * Copyright (C) 2013 Tox project All Rights Reserved.
7 *
8 * This file is part of Tox.
9 *
10 * Tox is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * Tox is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
22 *
23 */
24
25#include "group_chats.h"
26
27
28#define GROUPCHAT_MAXDATA_LENGTH (MAX_DATA_SIZE - (1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES))
29#define GROUPCHAT_MAXPLAINDATA_LENGTH (GROUPCHAT_MAXDATA_LENGTH - crypto_box_MACBYTES)
30
31#define GROUP_MAX_SENDNODES (GROUP_CLOSE_CONNECTIONS * 2)
32
33typedef struct {
34 uint64_t pingid;
35 //uint8_t client_id[crypto_box_PUBLICKEYBYTES];
36
37} getnodes_data;
38
39typedef struct {
40 uint8_t client_id[crypto_box_PUBLICKEYBYTES];
41 IP_Port ip_port;
42
43} groupchat_nodes;
44
45typedef struct {
46 uint64_t pingid;
47 groupchat_nodes nodes[GROUP_CLOSE_CONNECTIONS];
48 //uint8_t client_id[crypto_box_PUBLICKEYBYTES];
49
50} sendnodes_data;
51
52/* Compares client_id1 and client_id2 with client_id
53 * return 0 if both are same distance
54 * return 1 if client_id1 is closer
55 * return 2 if client_id2 is closer
56 */
57static int id_closest(uint8_t *id, uint8_t *id1, uint8_t *id2)
58{
59 size_t i;
60 uint8_t distance1, distance2;
61
62 for (i = 0; i < CLIENT_ID_SIZE; ++i) {
63
64 distance1 = abs(((int8_t *)id)[i] ^ ((int8_t *)id1)[i]);
65 distance2 = abs(((int8_t *)id)[i] ^ ((int8_t *)id2)[i]);
66
67 if (distance1 < distance2)
68 return 1;
69
70 if (distance1 > distance2)
71 return 2;
72 }
73
74 return 0;
75}
76
77
78/*
79 * check if peer with client_id is in peer array.
80 *
81 * return peer number if peer is in chat.
82 * return -1 if peer is not in chat.
83 *
84 * TODO: make this more efficient.
85 */
86
87static int peer_in_chat(Group_Chat *chat, uint8_t *client_id)
88{
89 uint32_t i;
90
91 for (i = 0; i < chat->numpeers; ++i) {
92 /* Equal */
93 if (memcmp(chat->group[i].client_id, client_id, crypto_box_PUBLICKEYBYTES) == 0)
94 return i;
95 }
96
97 return -1;
98}
99
100#define BAD_NODE_TIMEOUT 30
101
102/*
103 * Check if peer is closer to us that the other peers in the list and if the peer is in the list.
104 * Return the number of peers it is closer to if it is not in the closelist.
105 * Return -1 if the peer is in the closelist.
106 */
107
108static int peer_okping(Group_Chat *chat, uint8_t *client_id)
109{
110 uint32_t i, j = 0;
111 uint64_t temp_time = unix_time();
112
113 if (memcmp(chat->self_public_key, client_id, crypto_box_PUBLICKEYBYTES) == 0)
114 return -1;
115
116 for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) {
117 if (chat->close[i].last_recv + BAD_NODE_TIMEOUT < temp_time) {
118 ++j;
119 continue;
120 }
121
122 /* Equal */
123 if (memcmp(chat->close[i].client_id, client_id, crypto_box_PUBLICKEYBYTES) == 0)
124 return -1;
125
126 if (id_closest(chat->self_public_key, chat->close[i].client_id, client_id) == 2)
127 ++j;
128 }
129
130 return j;
131}
132
133
134
135/* Attempt to add a peer to the close list.
136 * Update last_recv if it is in list.
137 * Attempt to add it to list if it is not.
138 *
139 * Return 0 if success.
140 * Return -1 if peer was not put in list/updated.
141 */
142static int add_closepeer(Group_Chat *chat, uint8_t *client_id, IP_Port ip_port)
143{
144 uint32_t i;
145 uint64_t temp_time = unix_time();
146
147 for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) { /* Check if node is already in list, if it is update its last_recv */
148 if (memcmp(chat->close[i].client_id, client_id, crypto_box_PUBLICKEYBYTES) == 0) {
149 chat->close[i].last_recv = temp_time;
150 return 0;
151 }
152 }
153
154 for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) { /* Try replacing bad nodes first */
155 if (chat->close[i].last_recv + BAD_NODE_TIMEOUT < temp_time) {
156 memcpy(chat->close[i].client_id, client_id, crypto_box_PUBLICKEYBYTES);
157 chat->close[i].ip_port = ip_port;
158 chat->close[i].last_recv = temp_time;
159 return 0;
160 }
161 }
162
163 for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) { /* Replace nodes if given one is closer. */
164 if (id_closest(chat->self_public_key, chat->close[i].client_id, client_id) == 2) {
165 memcpy(chat->close[i].client_id, client_id, crypto_box_PUBLICKEYBYTES);
166 chat->close[i].ip_port = ip_port;
167 chat->close[i].last_recv = temp_time;
168 return 0;
169 }
170 }
171
172 return -1;
173}
174
175static int send_groupchatpacket(Group_Chat *chat, IP_Port ip_port, uint8_t *public_key, uint8_t *data, uint32_t length,
176 uint8_t request_id)
177{
178 if (memcmp(chat->self_public_key, public_key, crypto_box_PUBLICKEYBYTES) == 0)
179 return -1;
180
181 uint8_t packet[MAX_DATA_SIZE];
182 int len = create_request(chat->self_public_key, chat->self_secret_key, packet, public_key, data, length, request_id);
183 packet[0] = 48;
184
185 if (len == -1)
186 return -1;
187
188 if (sendpacket(chat->net->sock, ip_port, packet, len) == len)
189 return 0;
190
191 return -1;
192
193}
194
195/*
196 * Send data to all peers in close peer list.
197 *
198 * return the number of peers the packet was sent to.
199 */
200static uint8_t sendto_allpeers(Group_Chat *chat, uint8_t *data, uint16_t length, uint8_t request_id)
201{
202 uint16_t sent = 0;
203 uint32_t i;
204 uint64_t temp_time = unix_time();
205
206 for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) {
207 if (chat->close[i].ip_port.ip.uint32 != 0 && chat->close[i].last_recv + BAD_NODE_TIMEOUT > temp_time) {
208 if (send_groupchatpacket(chat, chat->close[i].ip_port, chat->close[i].client_id, data, length, request_id) == 0)
209 ++sent;
210 }
211 }
212
213 return sent;
214}
215
216
217/*
218 * Add a peer to the group chat.
219 *
220 * return peernum if success or peer already in chat.
221 * return -1 if error.
222 */
223static int addpeer(Group_Chat *chat, uint8_t *client_id)
224{
225 int peernum = peer_in_chat(chat, client_id);
226
227 if (peernum != -1)
228 return peernum;
229
230 Group_Peer *temp;
231 temp = realloc(chat->group, sizeof(Group_Peer) * (chat->numpeers + 1));
232 memset(&(temp[chat->numpeers]), 0, sizeof(Group_Peer));
233
234 if (temp == NULL)
235 return -1;
236
237 chat->group = temp;
238 memcpy(chat->group[chat->numpeers].client_id, client_id, crypto_box_PUBLICKEYBYTES);
239 ++chat->numpeers;
240 return (chat->numpeers - 1);
241}
242
243/*
244 * Delete a peer to the group chat.
245 *
246 * return 0 if success
247 * return -1 if error.
248 */
249static int delpeer(Group_Chat *chat, uint8_t *client_id)
250{
251 uint32_t i;
252 Group_Peer *temp;
253
254 for (i = 0; i < chat->numpeers; ++i) {
255 /* Equal */
256 if (memcmp(chat->group[i].client_id, client_id, crypto_box_PUBLICKEYBYTES) == 0) {
257 --chat->numpeers;
258
259 if (chat->numpeers != i) {
260 memcpy( chat->group[i].client_id,
261 chat->group[chat->numpeers].client_id,
262 crypto_box_PUBLICKEYBYTES );
263 }
264
265 temp = realloc(chat->group, sizeof(Group_Peer) * (chat->numpeers));
266
267 if (temp == NULL)
268 return -1;
269
270 chat->group = temp;
271 return 0;
272 }
273 }
274
275 return -1;
276}
277/* min time between pings sent to one peer in seconds */
278#define PING_TIMEOUT 5
279static int send_getnodes(Group_Chat *chat, IP_Port ip_port, int peernum)
280{
281 if (peernum < 0 || peernum >= chat->numpeers)
282 return -1;
283
284 uint64_t temp_time = unix_time();
285
286 getnodes_data contents;
287
288 if (chat->group[peernum].last_pinged + PING_TIMEOUT > temp_time)
289 return -1;
290
291 contents.pingid = ((uint64_t)random_int() << 32) + random_int();
292 chat->group[peernum].last_pinged = temp_time;
293 chat->group[peernum].pingid = contents.pingid;
294 return send_groupchatpacket(chat, ip_port, chat->group[peernum].client_id, (uint8_t *)&contents, sizeof(contents), 48);
295}
296
297static int send_sendnodes(Group_Chat *chat, IP_Port ip_port, int peernum, uint64_t pingid)
298{
299 if (peernum < 0 || peernum >= chat->numpeers)
300 return -1;
301
302 sendnodes_data contents;
303 contents.pingid = pingid;
304 uint32_t i, j = 0;
305 uint64_t temp_time = unix_time();
306
307 for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) {
308 if (chat->close[i].last_recv + BAD_NODE_TIMEOUT > temp_time) {
309 memcpy(contents.nodes[j].client_id, chat->close[i].client_id, crypto_box_PUBLICKEYBYTES);
310 contents.nodes[j].ip_port = chat->close[i].ip_port;
311 ++j;
312 }
313 }
314
315 return send_groupchatpacket(chat, ip_port, chat->group[peernum].client_id, (uint8_t *)&contents,
316 sizeof(contents.pingid) + sizeof(groupchat_nodes) * j, 49);
317}
318
319static int handle_getnodes(Group_Chat *chat, IP_Port source, int peernum, uint8_t *data, uint32_t len)
320{
321 if (len != sizeof(getnodes_data))
322 return 1;
323
324 if (peernum < 0 || peernum >= chat->numpeers)
325 return 1;
326
327 getnodes_data contents;
328 memcpy(&contents, data, sizeof(contents));
329 send_sendnodes(chat, source, peernum, contents.pingid);
330
331 if (peer_okping(chat, chat->group[peernum].client_id) > 0)
332 send_getnodes(chat, source, peernum);
333
334 return 0;
335}
336
337static int handle_sendnodes(Group_Chat *chat, IP_Port source, int peernum, uint8_t *data, uint32_t len)
338{
339 if (peernum < 0 || peernum >= chat->numpeers)
340 return 1;
341
342 if (len > sizeof(sendnodes_data) || len < sizeof(uint64_t))
343 return 1;
344
345 if ((len - sizeof(uint64_t)) % sizeof(groupchat_nodes) != 0)
346 return 1;
347
348 if (chat->group[peernum].last_pinged + PING_TIMEOUT < unix_time())
349 return 1;
350
351 sendnodes_data contents;
352 memcpy(&contents, data, len);
353
354 if (contents.pingid != chat->group[peernum].pingid)
355 return 1;
356
357 uint16_t numnodes = (len - sizeof(contents.pingid)) / sizeof(groupchat_nodes);
358 uint32_t i;
359
360 for (i = 0; i < numnodes; ++i) {
361 if (peer_okping(chat, contents.nodes[i].client_id) > 0) {
362 int peern = peer_in_chat(chat, contents.nodes[i].client_id);
363
364 if (peern == -1) { /*NOTE: This is just for testing and will be removed later.*/
365 peern = addpeer(chat, contents.nodes[i].client_id);
366 }
367
368 if (peern == -1)
369 continue;
370
371 send_getnodes(chat, contents.nodes[i].ip_port, peern);
372 }
373 }
374
375 add_closepeer(chat, chat->group[peernum].client_id, source);
376 return 0;
377}
378#define GROUP_DATA_MIN_SIZE (crypto_box_PUBLICKEYBYTES + sizeof(uint32_t) + 1)
379static int handle_data(Group_Chat *chat, uint8_t *data, uint32_t len)
380{
381 if (len < GROUP_DATA_MIN_SIZE)
382 return 1;
383
384//TODO:
385 int peernum = peer_in_chat(chat, data);
386
387 if (peernum == -1) { /*NOTE: This is just for testing and will be removed later.*/
388 peernum = addpeer(chat, data);
389 }
390
391 if (peernum == -1)
392 return 1;
393
394 uint32_t message_num;
395 memcpy(&message_num, data + crypto_box_PUBLICKEYBYTES, sizeof(uint32_t));
396 message_num = ntohl(message_num);
397
398 if (chat->group[peernum].last_message_number == 0) {
399 chat->group[peernum].last_message_number = message_num;
400 } else if (message_num - chat->group[peernum].last_message_number > 64 ||
401 message_num == chat->group[peernum].last_message_number)
402 return 1;
403
404 chat->group[peernum].last_message_number = message_num;
405
406 int handled = 0;
407
408 if (data[crypto_box_PUBLICKEYBYTES + sizeof(message_num)] == 64) {
409 if (chat->group_message != NULL) /* If message is chat message */
410 (*chat->group_message)(chat, peernum, data + GROUP_DATA_MIN_SIZE, len - GROUP_DATA_MIN_SIZE,
411 chat->group_message_userdata);
412
413 handled = 1;
414 }
415
416 if (handled == 1) {
417 sendto_allpeers(chat, data, len, 50);
418 return 0;
419 }
420
421 return 1;
422}
423
424static uint8_t send_data(Group_Chat *chat, uint8_t *data, uint32_t len, uint8_t message_id)
425{
426 if (len + GROUP_DATA_MIN_SIZE > MAX_DATA_SIZE) /*NOTE: not the real maximum len.*/
427 return 1;
428
429 uint8_t packet[MAX_DATA_SIZE];
430 ++chat->message_number;
431
432 if (chat->message_number == 0)
433 chat->message_number = 1;
434
435 uint32_t message_num = htonl(chat->message_number);
436//TODO
437 memcpy(packet, chat->self_public_key, crypto_box_PUBLICKEYBYTES);
438 memcpy(packet + crypto_box_PUBLICKEYBYTES, &message_num, sizeof(message_num));
439 memcpy(packet + GROUP_DATA_MIN_SIZE, data, len);
440 packet[crypto_box_PUBLICKEYBYTES + sizeof(message_num)] = message_id;
441 return sendto_allpeers(chat, packet, len + GROUP_DATA_MIN_SIZE, 50);
442}
443/*
444 * Handle get nodes group packet.
445 *
446 * return 0 if handled correctly.
447 * return 1 if error.
448 */
449
450int handle_groupchatpacket(Group_Chat *chat, IP_Port source, uint8_t *packet, uint32_t length)
451{
452 if (length > MAX_DATA_SIZE)
453 return 1;
454
455 uint8_t public_key[crypto_box_PUBLICKEYBYTES];
456 uint8_t data[MAX_DATA_SIZE];
457 uint8_t number;
458 int len = handle_request(chat->self_public_key, chat->self_secret_key, public_key, data, &number, packet, length);
459
460 if (len <= 0)
461 return 1;
462
463 if (memcmp(chat->self_public_key, public_key, crypto_box_PUBLICKEYBYTES) == 0)
464 return 1;
465
466 int peernum = peer_in_chat(chat, public_key);
467
468 if (peernum == -1)/*NOTE: This is just for testing and will be removed later.*/
469 peernum = addpeer(chat, public_key);
470
471 if (peernum == -1)
472 return 1;
473
474 switch (number) {
475 case 48:
476 return handle_getnodes(chat, source, peernum, data, len);
477
478 case 49:
479 return handle_sendnodes(chat, source, peernum, data, len);
480
481 case 50:
482 return handle_data(chat, data, len);
483
484 default:
485 return 1;
486 }
487
488 return 1;
489}
490
491uint32_t group_sendmessage(Group_Chat *chat, uint8_t *message, uint32_t length)
492{
493 return send_data(chat, message, length, 64); //TODO: better return values?
494}
495
496void callback_groupmessage(Group_Chat *chat, void (*function)(Group_Chat *chat, int, uint8_t *, uint16_t, void *),
497 void *userdata)
498{
499 chat->group_message = function;
500 chat->group_message_userdata = userdata;
501}
502
503Group_Chat *new_groupchat(Networking_Core *net)
504{
505 if (net == 0)
506 return 0;
507
508 Group_Chat *chat = calloc(1, sizeof(Group_Chat));
509 chat->net = net;
510 crypto_box_keypair(chat->self_public_key, chat->self_secret_key);
511 return chat;
512}
513
514#define NODE_PING_INTERVAL 10
515
516static void ping_close(Group_Chat *chat)
517{
518 uint32_t i;
519 uint64_t temp_time = unix_time();
520
521 for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) {
522 if (chat->close[i].last_recv < temp_time + BAD_NODE_TIMEOUT) {
523 int peernum = peer_in_chat(chat, chat->close[i].client_id);
524
525 if (peernum == -1)
526 continue;
527
528 if (chat->group[peernum].last_pinged + NODE_PING_INTERVAL < temp_time)
529 send_getnodes(chat, chat->close[i].ip_port, peernum);
530 }
531 }
532}
533
534void do_groupchat(Group_Chat *chat)
535{
536 ping_close(chat);
537}
538
539void kill_groupchat(Group_Chat *chat)
540{
541 free(chat->group);
542 free(chat);
543}
544
545void chat_bootstrap(Group_Chat *chat, IP_Port ip_port, uint8_t *client_id)
546{
547 send_getnodes(chat, ip_port, addpeer(chat, client_id));
548}
diff --git a/testing/experiment/group_chats.h b/testing/experiment/group_chats.h
deleted file mode 100644
index 42ea3e08..00000000
--- a/testing/experiment/group_chats.h
+++ /dev/null
@@ -1,113 +0,0 @@
1/* group_chats.h
2 *
3 * An implementation of massive text only group chats.
4 *
5 *
6 * Copyright (C) 2013 Tox project All Rights Reserved.
7 *
8 * This file is part of Tox.
9 *
10 * Tox is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * Tox is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
22 *
23 */
24
25#ifndef GROUP_CHATS_H
26#define GROUP_CHATS_H
27
28#include "../../toxcore/net_crypto.h"
29
30#ifdef __cplusplus
31extern "C" {
32#endif
33
34typedef struct {
35 uint8_t client_id[crypto_box_PUBLICKEYBYTES];
36 uint64_t last_recv;
37 uint64_t pingid;
38 uint64_t last_pinged;
39 uint32_t last_message_number;
40} Group_Peer;
41
42typedef struct {
43 uint8_t client_id[crypto_box_PUBLICKEYBYTES];
44 IP_Port ip_port;
45 uint64_t last_recv;
46
47} Group_Close;
48
49#define GROUP_CLOSE_CONNECTIONS 6
50
51typedef struct Group_Chat {
52 Networking_Core *net;
53 uint8_t self_public_key[crypto_box_PUBLICKEYBYTES];
54 uint8_t self_secret_key[crypto_box_SECRETKEYBYTES];
55
56 Group_Peer *group;
57 Group_Close close[GROUP_CLOSE_CONNECTIONS];
58 uint32_t numpeers;
59
60 uint32_t message_number;
61 void (*group_message)(struct Group_Chat *m, int, uint8_t *, uint16_t, void *);
62 void *group_message_userdata;
63
64} Group_Chat;
65
66/*
67 * Set callback function for chat messages.
68 *
69 * format of function is: function(Group_Chat *chat, peer number, message, message length, userdata)
70 */
71
72void callback_groupmessage(Group_Chat *chat, void (*function)(Group_Chat *chat, int, uint8_t *, uint16_t, void *),
73 void *userdata);
74
75/*
76 * Send a message to the group.
77 *
78 */
79uint32_t group_sendmessage(Group_Chat *chat, uint8_t *message, uint32_t length);
80
81/* Create a new group chat.
82 *
83 * Returns a new group chat instance if success.
84 *
85 * Returns a NULL pointer if fail.
86 */
87Group_Chat *new_groupchat(Networking_Core *net);
88
89
90/* Kill a group chat
91 *
92 * Frees the memory and everything.
93 */
94void kill_groupchat(Group_Chat *chat);
95
96/*
97 * This is the main loop.
98 */
99void do_groupchat(Group_Chat *chat);
100
101/* if we receive a group chat packet we call this function so it can be handled.
102 return 0 if packet is handled correctly.
103 return 1 if it didn't handle the packet or if the packet was shit. */
104int handle_groupchatpacket(Group_Chat *chat, IP_Port source, uint8_t *packet, uint32_t length);
105
106
107void chat_bootstrap(Group_Chat *chat, IP_Port ip_port, uint8_t *client_id);
108
109#ifdef __cplusplus
110}
111#endif
112
113#endif
diff --git a/testing/experiment/group_chats_test.c b/testing/experiment/group_chats_test.c
index 3626c9eb..900da79c 100644
--- a/testing/experiment/group_chats_test.c
+++ b/testing/experiment/group_chats_test.c
@@ -1,4 +1,4 @@
1#include "group_chats.h" 1#include "../../toxcore/group_chats.h"
2#define NUM_CHATS 8 2#define NUM_CHATS 8
3 3
4#ifdef WIN32 4#ifdef WIN32
@@ -84,6 +84,7 @@ int main()
84 ip_port.port = htons(12745); 84 ip_port.port = htons(12745);
85 85
86 for (i = 0; i < NUM_CHATS; ++i) { 86 for (i = 0; i < NUM_CHATS; ++i) {
87 group_newpeer(chats[0], chats[i]->self_public_key);
87 chat_bootstrap(chats[i], ip_port, chats[0]->self_public_key); 88 chat_bootstrap(chats[i], ip_port, chats[0]->self_public_key);
88 printf("%u\n", i); 89 printf("%u\n", i);
89 } 90 }
diff --git a/testing/experiment/group_chats_test1.c b/testing/experiment/group_chats_test1.c
index f66c2d24..efd9ae84 100644
--- a/testing/experiment/group_chats_test1.c
+++ b/testing/experiment/group_chats_test1.c
@@ -1,4 +1,4 @@
1#include "group_chats.h" 1#include "../../toxcore/group_chats.h"
2#define NUM_CHATS 8 2#define NUM_CHATS 8
3 3
4#ifdef WIN32 4#ifdef WIN32