diff options
author | michael bishop <cleverca22@gmail.com> | 2016-09-12 11:36:49 -0300 |
---|---|---|
committer | Ansa89 <ansalonistefano@gmail.com> | 2017-04-01 17:47:34 +0200 |
commit | 200ee1cace2f17537e6982ac447ea65d7c7a00b3 (patch) | |
tree | 5c3cdfd8be52b9b621d859eed877c38d88314f08 | |
parent | 124d9e0446856002d9d19abddae12107345d67bc (diff) |
initial version of tox_loop
-rw-r--r-- | CMakeLists.txt | 1 | ||||
-rw-r--r-- | auto_tests/tox_loop_test.c | 135 | ||||
-rw-r--r-- | toxcore/Messenger.h | 4 | ||||
-rw-r--r-- | toxcore/tox.api.h | 32 | ||||
-rw-r--r-- | toxcore/tox.c | 111 | ||||
-rw-r--r-- | toxcore/tox.h | 36 |
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) | |||
425 | auto_test(save_friend) | 425 | auto_test(save_friend) |
426 | auto_test(skeleton) | 426 | auto_test(skeleton) |
427 | auto_test(tox) | 427 | auto_test(tox) |
428 | auto_test(tox_loop_test) | ||
428 | auto_test(tox_many) | 429 | auto_test(tox_many) |
429 | auto_test(tox_many_tcp) | 430 | auto_test(tox_many_tcp) |
430 | auto_test(tox_one) | 431 | auto_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 | |||
22 | struct loop_test { | ||
23 | int start_count, stop_count; | ||
24 | pthread_mutex_t mutex; | ||
25 | Tox *tox; | ||
26 | }; | ||
27 | |||
28 | void 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 | |||
35 | void 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 | |||
42 | void *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 | |||
49 | START_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 | } | ||
103 | END_TEST | ||
104 | |||
105 | #ifdef TRAVIS_ENV | ||
106 | uint8_t timeout_mux = 20; | ||
107 | #else | ||
108 | uint8_t timeout_mux = 10; | ||
109 | #endif | ||
110 | |||
111 | static 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 | |||
121 | int 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 | */ |
839 | void iterate(any user_data); | 839 | void iterate(any user_data); |
840 | 840 | ||
841 | /** | ||
842 | * Run $iterate() any time a packet arrives, only returns after ${loop.stop}(). | ||
843 | */ | ||
844 | uint32_t loop(any user_data); | ||
845 | |||
846 | namespace 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 | ||
345 | uint32_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 | */ | ||
355 | uint32_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 | |||
383 | void tox_callback_loop_begin(Tox *tox, tox_loop_begin_cb *callback) | ||
384 | { | ||
385 | Messenger *m = tox; | ||
386 | m->loop_begin_cb = callback; | ||
387 | } | ||
388 | |||
389 | void tox_callback_loop_end(Tox *tox, tox_loop_end_cb *callback) | ||
390 | { | ||
391 | Messenger *m = tox; | ||
392 | m->loop_end_cb = callback; | ||
393 | } | ||
394 | |||
395 | uint32_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 | |||
450 | void tox_loop_stop(Tox *tox) | ||
451 | { | ||
452 | Messenger *m = tox; | ||
453 | m->loop_run = false; | ||
454 | } | ||
455 | |||
345 | void tox_self_get_address(const Tox *tox, uint8_t *address) | 456 | void 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 | */ |
991 | void tox_iterate(Tox *tox, void *user_data); | 991 | void 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 | */ | ||
996 | uint32_t tox_loop(Tox *tox, void *user_data); | ||
997 | |||
998 | /** | ||
999 | * Tell tox_loop() to return. | ||
1000 | */ | ||
1001 | void tox_loop_stop(Tox *tox); | ||
1002 | |||
1003 | /** | ||
1004 | * No extra parameters. | ||
1005 | */ | ||
1006 | typedef 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 | */ | ||
1014 | void tox_callback_loop_begin(Tox *tox, tox_loop_begin_cb *callback); | ||
1015 | |||
1016 | /** | ||
1017 | * No extra parameters. | ||
1018 | */ | ||
1019 | typedef 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 | */ | ||
1027 | void tox_callback_loop_end(Tox *tox, tox_loop_end_cb *callback); | ||
1028 | |||
993 | 1029 | ||
994 | /******************************************************************************* | 1030 | /******************************************************************************* |
995 | * | 1031 | * |