summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormichael bishop <cleverca22@gmail.com>2016-09-12 11:36:49 -0300
committerAnsa89 <ansalonistefano@gmail.com>2017-04-01 17:47:34 +0200
commit200ee1cace2f17537e6982ac447ea65d7c7a00b3 (patch)
tree5c3cdfd8be52b9b621d859eed877c38d88314f08
parent124d9e0446856002d9d19abddae12107345d67bc (diff)
initial version of tox_loop
-rw-r--r--CMakeLists.txt1
-rw-r--r--auto_tests/tox_loop_test.c135
-rw-r--r--toxcore/Messenger.h4
-rw-r--r--toxcore/tox.api.h32
-rw-r--r--toxcore/tox.c111
-rw-r--r--toxcore/tox.h36
6 files changed, 319 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a3b12cef..e9743d49 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -425,6 +425,7 @@ auto_test(resource_leak)
425auto_test(save_friend) 425auto_test(save_friend)
426auto_test(skeleton) 426auto_test(skeleton)
427auto_test(tox) 427auto_test(tox)
428auto_test(tox_loop_test)
428auto_test(tox_many) 429auto_test(tox_many)
429auto_test(tox_many_tcp) 430auto_test(tox_many_tcp)
430auto_test(tox_one) 431auto_test(tox_one)
diff --git a/auto_tests/tox_loop_test.c b/auto_tests/tox_loop_test.c
new file mode 100644
index 00000000..56e78bda
--- /dev/null
+++ b/auto_tests/tox_loop_test.c
@@ -0,0 +1,135 @@
1
2
3#include "helpers.h"
4
5#include "../toxcore/tox.h"
6
7#include <check.h>
8#include <pthread.h>
9#include <stdio.h>
10#include <stdlib.h>
11#include <unistd.h>
12
13#define TCP_RELAY_PORT 33448
14/* The Travis-CI container responds poorly to ::1 as a localhost address
15 * You're encouraged to -D FORCE_TESTS_IPV6 on a local test */
16#ifdef FORCE_TESTS_IPV6
17#define TOX_LOCALHOST "::1"
18#else
19#define TOX_LOCALHOST "127.0.0.1"
20#endif
21
22struct loop_test {
23 int start_count, stop_count;
24 pthread_mutex_t mutex;
25 Tox *tox;
26};
27
28void tox_loop_cb_start(Tox *tox, void *user_data)
29{
30 struct loop_test *userdata = user_data;
31 pthread_mutex_lock(&userdata->mutex);
32 userdata->start_count++;
33}
34
35void tox_loop_cb_stop(Tox *tox, void *user_data)
36{
37 struct loop_test *userdata = user_data;
38 userdata->stop_count++;
39 pthread_mutex_unlock(&userdata->mutex);
40}
41
42void *tox_loop_worker(void *data)
43{
44 struct loop_test *userdata = data;
45 int retval = tox_loop(userdata->tox, data);
46 return (void *)retval;
47}
48
49START_TEST(test_tox_loop)
50{
51 pthread_t worker1, worker2;
52 struct Tox_Options opts;
53 struct loop_test userdata;
54 uint8_t dpk[TOX_PUBLIC_KEY_SIZE];
55 int retval;
56
57 userdata.start_count = 0;
58 userdata.stop_count = 0;
59 pthread_mutex_init(&userdata.mutex, NULL);
60
61 tox_options_default(&opts);
62 opts.tcp_port = TCP_RELAY_PORT;
63 userdata.tox = tox_new(&opts, 0);
64 tox_callback_loop_begin(userdata.tox, tox_loop_cb_start);
65 tox_callback_loop_end(userdata.tox, tox_loop_cb_stop);
66 pthread_create(&worker1, NULL, tox_loop_worker, &userdata);
67
68 tox_self_get_dht_id(userdata.tox, dpk);
69
70 tox_options_default(&opts);
71 struct loop_test userdata_tcp;
72 userdata_tcp.start_count = 0;
73 userdata_tcp.stop_count = 0;
74 pthread_mutex_init(&userdata_tcp.mutex, NULL);
75 userdata_tcp.tox = tox_new(&opts, 0);
76 tox_callback_loop_begin(userdata_tcp.tox, tox_loop_cb_start);
77 tox_callback_loop_end(userdata_tcp.tox, tox_loop_cb_stop);
78 pthread_create(&worker2, NULL, tox_loop_worker, &userdata_tcp);
79
80 pthread_mutex_lock(&userdata_tcp.mutex);
81 TOX_ERR_BOOTSTRAP error = 0;
82 ck_assert_msg(tox_add_tcp_relay(userdata_tcp.tox, TOX_LOCALHOST, TCP_RELAY_PORT, dpk, &error), "add relay error, %i",
83 error);
84 ck_assert_msg(tox_bootstrap(userdata_tcp.tox, TOX_LOCALHOST, 33445, dpk, 0), "Bootstrap error");
85 pthread_mutex_unlock(&userdata_tcp.mutex);
86
87 sleep(10);
88
89 tox_loop_stop(userdata.tox);
90 pthread_join(worker1, (void **)&retval);
91 ck_assert_msg(retval == 0, "tox_loop didn't return 0");
92
93 tox_kill(userdata.tox);
94 ck_assert_msg(userdata.start_count == userdata.stop_count, "start and stop must match");
95
96 tox_loop_stop(userdata_tcp.tox);
97 pthread_join(worker2, (void **)&retval);
98 ck_assert_msg(retval == 0, "tox_loop didn't return 0");
99
100 tox_kill(userdata_tcp.tox);
101 ck_assert_msg(userdata_tcp.start_count == userdata_tcp.stop_count, "start and stop must match");
102}
103END_TEST
104
105#ifdef TRAVIS_ENV
106uint8_t timeout_mux = 20;
107#else
108uint8_t timeout_mux = 10;
109#endif
110
111static Suite *tox_suite(void)
112{
113 Suite *s = suite_create("Tox loop");
114
115 /* test the new tox_loop function */
116 DEFTESTCASE_SLOW(tox_loop, 4 * timeout_mux);
117
118 return s;
119}
120
121int main(int argc, char *argv[])
122{
123 srand((unsigned int) time(NULL));
124
125 Suite *tox = tox_suite();
126 SRunner *test_runner = srunner_create(tox);
127
128 int number_failed = 0;
129 srunner_run_all(test_runner, CK_NORMAL);
130 number_failed = srunner_ntests_failed(test_runner);
131
132 srunner_free(test_runner);
133
134 return number_failed;
135}
diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h
index e1dba698..7275ffbf 100644
--- a/toxcore/Messenger.h
+++ b/toxcore/Messenger.h
@@ -273,6 +273,10 @@ struct Messenger {
273 void (*core_connection_change)(struct Messenger *m, unsigned int, void *); 273 void (*core_connection_change)(struct Messenger *m, unsigned int, void *);
274 unsigned int last_connection_status; 274 unsigned int last_connection_status;
275 275
276 uint8_t loop_run;
277 void (*loop_begin_cb)(struct Messenger *tox, void *user_data);
278 void (*loop_end_cb)(struct Messenger *tox, void *user_data);
279
276 Messenger_Options options; 280 Messenger_Options options;
277}; 281};
278 282
diff --git a/toxcore/tox.api.h b/toxcore/tox.api.h
index 281cb998..0bcf40e1 100644
--- a/toxcore/tox.api.h
+++ b/toxcore/tox.api.h
@@ -838,6 +838,38 @@ const uint32_t iteration_interval();
838 */ 838 */
839void iterate(any user_data); 839void iterate(any user_data);
840 840
841/**
842 * Run $iterate() any time a packet arrives, only returns after ${loop.stop}().
843 */
844uint32_t loop(any user_data);
845
846namespace loop {
847 /**
848 * Tell $loop() to return.
849 */
850 void stop();
851
852 /**
853 * Callback ran when $loop() calls into $iterate(), the client can lock a mutex here.
854 */
855 event begin const {
856 /**
857 * No extra parameters.
858 */
859 typedef void();
860 }
861
862 /**
863 * Callback ran when $loop() is finished with $iterate(), the client can unlock the mutex here.
864 */
865 event end const {
866 /**
867 * No extra parameters.
868 */
869 typedef void();
870 }
871}
872
841 873
842/******************************************************************************* 874/*******************************************************************************
843 * 875 *
diff --git a/toxcore/tox.c b/toxcore/tox.c
index fe34c284..5e2f14d2 100644
--- a/toxcore/tox.c
+++ b/toxcore/tox.c
@@ -342,6 +342,117 @@ void tox_iterate(Tox *tox, void *user_data)
342 do_groupchats((Group_Chats *)m->conferences_object, user_data); 342 do_groupchats((Group_Chats *)m->conferences_object, user_data);
343} 343}
344 344
345uint32_t tox_fd_count(Tox *tox)
346{
347 Messenger *m = tox;
348 return 1 + m->net_crypto->tcp_c->tcp_connections_length;
349}
350
351/**
352 * Gathers a list of every network FD activity is expected on
353 * @param sockets an array of size tox_fd_count()
354 */
355uint32_t tox_fds(Tox *tox, uint32_t *sockets, uint32_t max_sockets)
356{
357 Messenger *m = tox;
358 int count = 0;
359
360 if (max_sockets >= 1) {
361 sockets[count] = m->net->sock;
362 max_sockets--;
363 count++;
364 }
365
366 TCP_Connections *conns = m->net_crypto->tcp_c;
367 int x;
368
369 for (x = 0; x < conns->tcp_connections_length; x++) {
370 if (max_sockets == 0) {
371 break;
372 }
373
374 TCP_con *conn = &conns->tcp_connections[x];
375 sockets[count] = conn->connection->sock;
376 count++;
377 max_sockets--;
378 }
379
380 return count;
381}
382
383void tox_callback_loop_begin(Tox *tox, tox_loop_begin_cb *callback)
384{
385 Messenger *m = tox;
386 m->loop_begin_cb = callback;
387}
388
389void tox_callback_loop_end(Tox *tox, tox_loop_end_cb *callback)
390{
391 Messenger *m = tox;
392 m->loop_end_cb = callback;
393}
394
395uint32_t tox_loop(Tox *tox, void *user_data)
396{
397 struct timeval timeout;
398 int maxfd;
399 uint32_t i, list_size = 0;
400 uint32_t *fdlist = NULL;
401 Messenger *m = tox;
402 m->loop_run = true;
403 fd_set readable;
404
405
406 while (m->loop_run) {
407 if (m->loop_begin_cb) {
408 m->loop_begin_cb(tox, user_data);
409 }
410
411 tox_iterate(tox, user_data);
412
413 maxfd = 0;
414 FD_ZERO(&readable);
415
416 uint32_t fdcount = tox_fd_count(tox);
417
418 if (fdcount > list_size) {
419 fdlist = realloc(fdlist, fdcount * sizeof(uint32_t));
420 list_size = fdcount;
421 }
422
423 fdcount = tox_fds(tox, fdlist, list_size);
424
425 for (i = 0; i < fdcount; i++) {
426 FD_SET(fdlist[i], &readable);
427
428 if (fdlist[i] > maxfd) {
429 maxfd = fdlist[i];
430 }
431 }
432
433 timeout.tv_sec = 0;
434 timeout.tv_usec = tox_iteration_interval(tox) * 1000 * 2; // TODO, use a longer timeout (cleverca22)
435
436 if (m->loop_end_cb) {
437 m->loop_end_cb(tox, user_data);
438 }
439
440 int ret = select(maxfd, &readable, NULL, NULL, &timeout);
441
442 if (ret < 0) {
443 return ret;
444 }
445 }
446
447 return 0;
448}
449
450void tox_loop_stop(Tox *tox)
451{
452 Messenger *m = tox;
453 m->loop_run = false;
454}
455
345void tox_self_get_address(const Tox *tox, uint8_t *address) 456void tox_self_get_address(const Tox *tox, uint8_t *address)
346{ 457{
347 if (address) { 458 if (address) {
diff --git a/toxcore/tox.h b/toxcore/tox.h
index 75757b6f..0be019cd 100644
--- a/toxcore/tox.h
+++ b/toxcore/tox.h
@@ -990,6 +990,42 @@ uint32_t tox_iteration_interval(const Tox *tox);
990 */ 990 */
991void tox_iterate(Tox *tox, void *user_data); 991void tox_iterate(Tox *tox, void *user_data);
992 992
993/**
994 * Run tox_iterate() any time a packet arrives, only returns after tox_loop_stop().
995 */
996uint32_t tox_loop(Tox *tox, void *user_data);
997
998/**
999 * Tell tox_loop() to return.
1000 */
1001void tox_loop_stop(Tox *tox);
1002
1003/**
1004 * No extra parameters.
1005 */
1006typedef void tox_loop_begin_cb(Tox *tox, void *user_data);
1007
1008
1009/**
1010 * Set the callback for the `loop_begin` event. Pass NULL to unset.
1011 *
1012 * Callback ran when tox_loop() calls into tox_iterate(), the client can lock a mutex here.
1013 */
1014void tox_callback_loop_begin(Tox *tox, tox_loop_begin_cb *callback);
1015
1016/**
1017 * No extra parameters.
1018 */
1019typedef void tox_loop_end_cb(Tox *tox, void *user_data);
1020
1021
1022/**
1023 * Set the callback for the `loop_end` event. Pass NULL to unset.
1024 *
1025 * Callback ran when tox_loop() is finished with tox_iterate(), the client can unlock the mutex here.
1026 */
1027void tox_callback_loop_end(Tox *tox, tox_loop_end_cb *callback);
1028
993 1029
994/******************************************************************************* 1030/*******************************************************************************
995 * 1031 *