summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml2
-rw-r--r--CMakeLists.txt20
-rw-r--r--auto_tests/Makefile.inc11
-rw-r--r--auto_tests/tox_loop_test.c61
-rw-r--r--circle.yml1
-rw-r--r--cmake/Dependencies.cmake32
-rw-r--r--cmake/ModulePackage.cmake27
-rw-r--r--configure.ac251
-rw-r--r--libtoxcore.pc.in2
-rw-r--r--toxcore/Makefile.inc6
-rw-r--r--toxcore/Messenger.c28
-rw-r--r--toxcore/Messenger.h20
-rw-r--r--toxcore/TCP_client.c11
-rw-r--r--toxcore/TCP_client.h16
-rw-r--r--toxcore/TCP_connection.c31
-rw-r--r--toxcore/TCP_connection.h4
-rw-r--r--toxcore/network.c10
-rw-r--r--toxcore/network.h13
-rw-r--r--toxcore/tox.api.h34
-rw-r--r--toxcore/tox.c338
-rw-r--r--toxcore/tox.h41
21 files changed, 852 insertions, 107 deletions
diff --git a/.travis.yml b/.travis.yml
index 2e636552..95924133 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -33,6 +33,8 @@ addons:
33 packages: 33 packages:
34 - check 34 - check
35 - libcv-dev # For av_test. 35 - libcv-dev # For av_test.
36 - libev-dev # For tox_loop.
37 - libevent-dev # For tox_loop.
36 - libhighgui-dev # For av_test. 38 - libhighgui-dev # For av_test.
37 - libopencv-contrib-dev # For av_test. 39 - libopencv-contrib-dev # For av_test.
38 - libsndfile1-dev # For av_test. 40 - libsndfile1-dev # For av_test.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e9743d49..5bcafaf3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -183,6 +183,12 @@ if (BUILD_TOXAV)
183 endif() 183 endif()
184endif() 184endif()
185 185
186if(LIBEV_FOUND)
187 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DHAVE_LIBEV")
188elseif(LIBEVENT_FOUND)
189 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DHAVE_LIBEVENT")
190endif()
191
186################################################################################ 192################################################################################
187# 193#
188# :: Tox Core Library 194# :: Tox Core Library
@@ -234,6 +240,18 @@ if(RT_LIBRARIES)
234 set(toxcore_PKGCONFIG_LIBS ${toxcore_PKGCONFIG_LIBS} "-lrt") 240 set(toxcore_PKGCONFIG_LIBS ${toxcore_PKGCONFIG_LIBS} "-lrt")
235endif() 241endif()
236 242
243if(LIBEV_FOUND)
244 target_link_modules(toxnetwork ${LIBEV_LIBRARIES})
245 set(toxcore_PKGCONFIG_LIBS ${toxcore_PKGCONFIG_LIBS} "-lev")
246elseif(LIBEVENT_FOUND)
247 target_link_modules(toxnetwork ${LIBEVENT_LIBRARIES})
248 if(NOT WIN32)
249 set(toxcore_PKGCONFIG_LIBS ${toxcore_PKGCONFIG_LIBS} "-levent -levent_pthreads")
250 else()
251 set(toxcore_PKGCONFIG_LIBS ${toxcore_PKGCONFIG_LIBS} "-levent")
252 endif()
253endif()
254
237if(WIN32) 255if(WIN32)
238 target_link_modules(toxnetwork ws2_32 iphlpapi) 256 target_link_modules(toxnetwork ws2_32 iphlpapi)
239 set(toxcore_PKGCONFIG_LIBS ${toxcore_PKGCONFIG_LIBS} "-lws2_32 -liphlpapi") 257 set(toxcore_PKGCONFIG_LIBS ${toxcore_PKGCONFIG_LIBS} "-lws2_32 -liphlpapi")
@@ -425,7 +443,7 @@ auto_test(resource_leak)
425auto_test(save_friend) 443auto_test(save_friend)
426auto_test(skeleton) 444auto_test(skeleton)
427auto_test(tox) 445auto_test(tox)
428auto_test(tox_loop_test) 446auto_test(tox_loop)
429auto_test(tox_many) 447auto_test(tox_many)
430auto_test(tox_many_tcp) 448auto_test(tox_many_tcp)
431auto_test(tox_one) 449auto_test(tox_one)
diff --git a/auto_tests/Makefile.inc b/auto_tests/Makefile.inc
index 698064c4..d8d8b1eb 100644
--- a/auto_tests/Makefile.inc
+++ b/auto_tests/Makefile.inc
@@ -1,7 +1,7 @@
1if BUILD_TESTS 1if BUILD_TESTS
2 2
3TESTS = encryptsave_test messenger_autotest crypto_test network_test onion_test TCP_test tox_test dht_autotest tox_strncasecmp_test 3TESTS = encryptsave_test messenger_autotest crypto_test network_test onion_test TCP_test tox_loop_test tox_test dht_autotest tox_strncasecmp_test
4check_PROGRAMS = encryptsave_test messenger_autotest crypto_test network_test onion_test TCP_test tox_test dht_autotest tox_strncasecmp_test 4check_PROGRAMS = encryptsave_test messenger_autotest crypto_test network_test onion_test TCP_test tox_loop_test tox_test dht_autotest tox_strncasecmp_test
5 5
6AUTOTEST_CFLAGS = \ 6AUTOTEST_CFLAGS = \
7 $(LIBSODIUM_CFLAGS) \ 7 $(LIBSODIUM_CFLAGS) \
@@ -61,6 +61,13 @@ TCP_test_CFLAGS = $(AUTOTEST_CFLAGS)
61TCP_test_LDADD = $(AUTOTEST_LDADD) 61TCP_test_LDADD = $(AUTOTEST_LDADD)
62 62
63 63
64tox_loop_test_SOURCES = ../auto_tests/tox_loop_test.c
65
66tox_loop_test_CFLAGS = $(AUTOTEST_CFLAGS)
67
68tox_loop_test_LDADD = $(AUTOTEST_LDADD)
69
70
64tox_test_SOURCES = ../auto_tests/tox_test.c 71tox_test_SOURCES = ../auto_tests/tox_test.c
65 72
66tox_test_CFLAGS = $(AUTOTEST_CFLAGS) 73tox_test_CFLAGS = $(AUTOTEST_CFLAGS)
diff --git a/auto_tests/tox_loop_test.c b/auto_tests/tox_loop_test.c
index 56e78bda..7589cc4b 100644
--- a/auto_tests/tox_loop_test.c
+++ b/auto_tests/tox_loop_test.c
@@ -1,15 +1,13 @@
1
2
3#include "helpers.h"
4
5#include "../toxcore/tox.h"
6
7#include <check.h> 1#include <check.h>
8#include <pthread.h> 2#include <pthread.h>
9#include <stdio.h>
10#include <stdlib.h> 3#include <stdlib.h>
4#include <time.h>
11#include <unistd.h> 5#include <unistd.h>
12 6
7#include "../toxcore/tox.h"
8
9#include "helpers.h"
10
13#define TCP_RELAY_PORT 33448 11#define TCP_RELAY_PORT 33448
14/* The Travis-CI container responds poorly to ::1 as a localhost address 12/* 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 */ 13 * You're encouraged to -D FORCE_TESTS_IPV6 on a local test */
@@ -19,38 +17,38 @@
19#define TOX_LOCALHOST "127.0.0.1" 17#define TOX_LOCALHOST "127.0.0.1"
20#endif 18#endif
21 19
22struct loop_test { 20typedef struct {
23 int start_count, stop_count; 21 int start_count, stop_count;
24 pthread_mutex_t mutex; 22 pthread_mutex_t mutex;
25 Tox *tox; 23 Tox *tox;
26}; 24} loop_test;
27 25
28void tox_loop_cb_start(Tox *tox, void *user_data) 26void tox_loop_cb_start(Tox *tox, void *user_data)
29{ 27{
30 struct loop_test *userdata = user_data; 28 loop_test *userdata = (loop_test *) user_data;
31 pthread_mutex_lock(&userdata->mutex); 29 pthread_mutex_lock(&userdata->mutex);
32 userdata->start_count++; 30 userdata->start_count++;
33} 31}
34 32
35void tox_loop_cb_stop(Tox *tox, void *user_data) 33void tox_loop_cb_stop(Tox *tox, void *user_data)
36{ 34{
37 struct loop_test *userdata = user_data; 35 loop_test *userdata = (loop_test *) user_data;
38 userdata->stop_count++; 36 userdata->stop_count++;
39 pthread_mutex_unlock(&userdata->mutex); 37 pthread_mutex_unlock(&userdata->mutex);
40} 38}
41 39
42void *tox_loop_worker(void *data) 40void *tox_loop_worker(void *data)
43{ 41{
44 struct loop_test *userdata = data; 42 loop_test *userdata = (loop_test *) data;
45 int retval = tox_loop(userdata->tox, data); 43 tox_loop(userdata->tox, data, NULL);
46 return (void *)retval; 44 return NULL;
47} 45}
48 46
49START_TEST(test_tox_loop) 47START_TEST(test_tox_loop)
50{ 48{
51 pthread_t worker1, worker2; 49 pthread_t worker, worker_tcp;
52 struct Tox_Options opts; 50 struct Tox_Options *opts = tox_options_new(NULL);
53 struct loop_test userdata; 51 loop_test userdata;
54 uint8_t dpk[TOX_PUBLIC_KEY_SIZE]; 52 uint8_t dpk[TOX_PUBLIC_KEY_SIZE];
55 int retval; 53 int retval;
56 54
@@ -58,43 +56,42 @@ START_TEST(test_tox_loop)
58 userdata.stop_count = 0; 56 userdata.stop_count = 0;
59 pthread_mutex_init(&userdata.mutex, NULL); 57 pthread_mutex_init(&userdata.mutex, NULL);
60 58
61 tox_options_default(&opts); 59 tox_options_set_tcp_port(opts, TCP_RELAY_PORT);
62 opts.tcp_port = TCP_RELAY_PORT; 60 userdata.tox = tox_new(opts, NULL);
63 userdata.tox = tox_new(&opts, 0);
64 tox_callback_loop_begin(userdata.tox, tox_loop_cb_start); 61 tox_callback_loop_begin(userdata.tox, tox_loop_cb_start);
65 tox_callback_loop_end(userdata.tox, tox_loop_cb_stop); 62 tox_callback_loop_end(userdata.tox, tox_loop_cb_stop);
66 pthread_create(&worker1, NULL, tox_loop_worker, &userdata); 63 pthread_create(&worker, NULL, tox_loop_worker, &userdata);
67 64
68 tox_self_get_dht_id(userdata.tox, dpk); 65 tox_self_get_dht_id(userdata.tox, dpk);
69 66
70 tox_options_default(&opts); 67 tox_options_default(opts);
71 struct loop_test userdata_tcp; 68 loop_test userdata_tcp;
72 userdata_tcp.start_count = 0; 69 userdata_tcp.start_count = 0;
73 userdata_tcp.stop_count = 0; 70 userdata_tcp.stop_count = 0;
74 pthread_mutex_init(&userdata_tcp.mutex, NULL); 71 pthread_mutex_init(&userdata_tcp.mutex, NULL);
75 userdata_tcp.tox = tox_new(&opts, 0); 72 userdata_tcp.tox = tox_new(opts, NULL);
76 tox_callback_loop_begin(userdata_tcp.tox, tox_loop_cb_start); 73 tox_callback_loop_begin(userdata_tcp.tox, tox_loop_cb_start);
77 tox_callback_loop_end(userdata_tcp.tox, tox_loop_cb_stop); 74 tox_callback_loop_end(userdata_tcp.tox, tox_loop_cb_stop);
78 pthread_create(&worker2, NULL, tox_loop_worker, &userdata_tcp); 75 pthread_create(&worker_tcp, NULL, tox_loop_worker, &userdata_tcp);
79 76
80 pthread_mutex_lock(&userdata_tcp.mutex); 77 pthread_mutex_lock(&userdata_tcp.mutex);
81 TOX_ERR_BOOTSTRAP error = 0; 78 TOX_ERR_BOOTSTRAP error;
82 ck_assert_msg(tox_add_tcp_relay(userdata_tcp.tox, TOX_LOCALHOST, TCP_RELAY_PORT, dpk, &error), "add relay error, %i", 79 ck_assert_msg(tox_add_tcp_relay(userdata_tcp.tox, TOX_LOCALHOST, TCP_RELAY_PORT, dpk, &error), "Add relay error, %i",
83 error); 80 error);
84 ck_assert_msg(tox_bootstrap(userdata_tcp.tox, TOX_LOCALHOST, 33445, dpk, 0), "Bootstrap error"); 81 ck_assert_msg(tox_bootstrap(userdata_tcp.tox, TOX_LOCALHOST, 33445, dpk, &error), "Bootstrap error, %i", error);
85 pthread_mutex_unlock(&userdata_tcp.mutex); 82 pthread_mutex_unlock(&userdata_tcp.mutex);
86 83
87 sleep(10); 84 sleep(10);
88 85
89 tox_loop_stop(userdata.tox); 86 tox_loop_stop(userdata.tox);
90 pthread_join(worker1, (void **)&retval); 87 pthread_join(worker, (void **)&retval);
91 ck_assert_msg(retval == 0, "tox_loop didn't return 0"); 88 ck_assert_msg(retval == 0, "tox_loop didn't return 0");
92 89
93 tox_kill(userdata.tox); 90 tox_kill(userdata.tox);
94 ck_assert_msg(userdata.start_count == userdata.stop_count, "start and stop must match"); 91 ck_assert_msg(userdata.start_count == userdata.stop_count, "start and stop must match");
95 92
96 tox_loop_stop(userdata_tcp.tox); 93 tox_loop_stop(userdata_tcp.tox);
97 pthread_join(worker2, (void **)&retval); 94 pthread_join(worker_tcp, (void **)&retval);
98 ck_assert_msg(retval == 0, "tox_loop didn't return 0"); 95 ck_assert_msg(retval == 0, "tox_loop didn't return 0");
99 96
100 tox_kill(userdata_tcp.tox); 97 tox_kill(userdata_tcp.tox);
@@ -103,9 +100,9 @@ START_TEST(test_tox_loop)
103END_TEST 100END_TEST
104 101
105#ifdef TRAVIS_ENV 102#ifdef TRAVIS_ENV
106uint8_t timeout_mux = 20; 103static uint8_t timeout_mux = 20;
107#else 104#else
108uint8_t timeout_mux = 10; 105static uint8_t timeout_mux = 10;
109#endif 106#endif
110 107
111static Suite *tox_suite(void) 108static Suite *tox_suite(void)
diff --git a/circle.yml b/circle.yml
index 6733024c..fe53b005 100644
--- a/circle.yml
+++ b/circle.yml
@@ -15,6 +15,7 @@ dependencies:
15 - sudo apt-get install clang 15 - sudo apt-get install clang
16 - sudo apt-get install build-essential libtool autotools-dev automake checkinstall check git yasm 16 - sudo apt-get install build-essential libtool autotools-dev automake checkinstall check git yasm
17 - sudo apt-get install libopus-dev libvpx-dev pkg-config 17 - sudo apt-get install libopus-dev libvpx-dev pkg-config
18 - sudo apt-get install libev-dev libevent-dev
18 19
19# ------------ network_test requires that "localhost" resolves to ::1 ------------ 20# ------------ network_test requires that "localhost" resolves to ::1 ------------
20 - sudo bash -c "echo '::1 localhost ipv6-localhost ipv6-loopback' >> /etc/hosts" # ipv6 localhost entry 21 - sudo bash -c "echo '::1 localhost ipv6-localhost ipv6-loopback' >> /etc/hosts" # ipv6 localhost entry
diff --git a/cmake/Dependencies.cmake b/cmake/Dependencies.cmake
index 5ad332bd..4cb96594 100644
--- a/cmake/Dependencies.cmake
+++ b/cmake/Dependencies.cmake
@@ -8,30 +8,38 @@ include(ModulePackage)
8 8
9find_package(Threads REQUIRED) 9find_package(Threads REQUIRED)
10 10
11find_library(NCURSES_LIBRARIES ncurses ) 11find_library(NCURSES_LIBRARIES ncurses )
12find_library(UTIL_LIBRARIES util ) 12find_library(UTIL_LIBRARIES util )
13find_library(RT_LIBRARIES rt ) 13find_library(RT_LIBRARIES rt )
14 14
15# For toxcore. 15# For toxcore.
16pkg_use_module(LIBSODIUM libsodium ) 16pkg_use_module(LIBSODIUM libsodium )
17pkg_use_module(LIBEV ev )
18if(NOT LIBEV_FOUND)
19 if(NOT WIN32)
20 pkg_use_module(LIBEVENT libevent_pthreads )
21 else()
22 pkg_use_module(LIBEVENT libevent )
23 endif()
24endif()
17 25
18# For toxav. 26# For toxav.
19pkg_use_module(OPUS opus ) 27pkg_use_module(OPUS opus )
20pkg_use_module(VPX vpx ) 28pkg_use_module(VPX vpx )
21 29
22# For tox-bootstrapd. 30# For tox-bootstrapd.
23pkg_use_module(LIBCONFIG libconfig ) 31pkg_use_module(LIBCONFIG libconfig )
24 32
25# For auto tests. 33# For auto tests.
26pkg_use_module(CHECK check ) 34pkg_use_module(CHECK check )
27 35
28# For tox-spectest. 36# For tox-spectest.
29pkg_use_module(MSGPACK msgpack ) 37pkg_use_module(MSGPACK msgpack )
30 38
31# For av_test. 39# For av_test.
32pkg_use_module(OPENCV opencv ) 40pkg_use_module(OPENCV opencv )
33pkg_use_module(PORTAUDIO portaudio-2.0) 41pkg_use_module(PORTAUDIO portaudio-2.0 )
34pkg_use_module(SNDFILE sndfile ) 42pkg_use_module(SNDFILE sndfile )
35 43
36############################################################################### 44###############################################################################
37# 45#
diff --git a/cmake/ModulePackage.cmake b/cmake/ModulePackage.cmake
index 3a4eb9b9..4d22ee41 100644
--- a/cmake/ModulePackage.cmake
+++ b/cmake/ModulePackage.cmake
@@ -2,6 +2,8 @@ option(ENABLE_SHARED "Build shared (dynamic) libraries for all modules" ON)
2option(ENABLE_STATIC "Build static libraries for all modules" ON) 2option(ENABLE_STATIC "Build static libraries for all modules" ON)
3option(COMPILE_AS_CXX "Compile all C code as C++ code" OFF) 3option(COMPILE_AS_CXX "Compile all C code as C++ code" OFF)
4 4
5include(FindPackageHandleStandardArgs)
6
5if(NOT ENABLE_SHARED AND NOT ENABLE_STATIC) 7if(NOT ENABLE_SHARED AND NOT ENABLE_STATIC)
6 message(WARNING 8 message(WARNING
7 "Both static and shared libraries are disabled; " 9 "Both static and shared libraries are disabled; "
@@ -48,6 +50,31 @@ function(pkg_use_module mod pkg)
48 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -isystem ${dir}" PARENT_SCOPE) 50 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -isystem ${dir}" PARENT_SCOPE)
49 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${dir}" PARENT_SCOPE) 51 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${dir}" PARENT_SCOPE)
50 endforeach() 52 endforeach()
53 else()
54 set(${mod}_DEFINITIONS ${${mod}_CFLAGS_OTHER})
55 find_path(${mod}_INCLUDE_DIR NAMES ${ARGV1}.h
56 HINTS ${${mod}_INCLUDEDIR} ${${mod}_INCLUDE_DIRS}
57 PATH_SUFFIXES ${ARGV1})
58 find_library(${mod}_LIBRARY NAMES ${ARGV1} lib${ARGV1}
59 HINTS ${${mod}_LIBDIR} ${${mod}_LIBRARY_DIRS})
60 find_package_handle_standard_args(${mod} DEFAULT_MSG
61 ${mod}_LIBRARY ${mod}_INCLUDE_DIR)
62
63 if(${mod}_FOUND)
64 mark_as_advanced(${mod}_INCLUDE_DIR ${mod}_LIBRARY)
65 set(${mod}_LIBRARIES ${${mod}_LIBRARY} PARENT_SCOPE)
66 set(${mod}_INCLUDE_DIRS ${${mod}_INCLUDE_DIR} PARENT_SCOPE)
67 set(${mod}_FOUND TRUE PARENT_SCOPE)
68 link_directories(${${mod}_LIBRARY_DIRS})
69 include_directories(${${mod}_INCLUDE_DIRS})
70 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${${mod}_CFLAGS_OTHER}" PARENT_SCOPE)
71 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${${mod}_CFLAGS_OTHER}" PARENT_SCOPE)
72
73 foreach(dir ${${mod}_INCLUDE_DIRS})
74 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -isystem ${dir}" PARENT_SCOPE)
75 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${dir}" PARENT_SCOPE)
76 endforeach()
77 endif()
51 endif() 78 endif()
52endfunction() 79endfunction()
53 80
diff --git a/configure.ac b/configure.ac
index 9eaa840f..18bc9234 100644
--- a/configure.ac
+++ b/configure.ac
@@ -31,6 +31,8 @@ LIBCHECK_FOUND="no"
31WANT_NACL="no" 31WANT_NACL="no"
32ADD_NACL_OBJECTS_TO_PKGCONFIG="yes" 32ADD_NACL_OBJECTS_TO_PKGCONFIG="yes"
33SET_SO_VERSION="yes" 33SET_SO_VERSION="yes"
34WANT_LIBEV="no"
35WANT_LIBEVENT="no"
34 36
35AC_ARG_ENABLE([soname-versions], 37AC_ARG_ENABLE([soname-versions],
36 [AC_HELP_STRING([--enable-soname-versions], [enable soname versions (must be disabled for android) (default: enabled)]) ], 38 [AC_HELP_STRING([--enable-soname-versions], [enable soname versions (must be disabled for android) (default: enabled)]) ],
@@ -55,6 +57,32 @@ AC_ARG_ENABLE([nacl],
55 ] 57 ]
56) 58)
57 59
60AC_ARG_ENABLE([libev],
61 [AC_HELP_STRING([--enable-libev], [use libev to watch for events (default: disabled)]) ],
62 [
63 if test "x$enableval" = "xyes"; then
64 WANT_LIBEV="yes"
65 elif test "x$enableval" = "xno"; then
66 WANT_LIBEV="no"
67 fi
68 ]
69)
70
71AC_ARG_ENABLE([libevent],
72 [AC_HELP_STRING([--enable-libevent], [use libevent to watch for events (default: disabled)]) ],
73 [
74 if test "x$enableval" = "xyes"; then
75 WANT_LIBEVENT="yes"
76 elif test "x$enableval" = "xno"; then
77 WANT_LIBEVENT="no"
78 fi
79 ]
80)
81
82if test "x$WANT_LIBEV" = "xyes" && test "x$WANT_LIBEVENT" = "xyes"; then
83 AC_MSG_ERROR([cannot enable both libev and libevent, please choose one])
84fi
85
58AC_ARG_ENABLE([randombytes-stir], 86AC_ARG_ENABLE([randombytes-stir],
59 [AC_HELP_STRING([--enable-randombytes-stir], [use randombytes_stir() instead of sodium_init() for faster startup on android (default: disabled)]) ], 87 [AC_HELP_STRING([--enable-randombytes-stir], [use randombytes_stir() instead of sodium_init() for faster startup on android (default: disabled)]) ],
60 [ 88 [
@@ -211,6 +239,10 @@ LIBSODIUM_SEARCH_HEADERS=
211LIBSODIUM_SEARCH_LIBS= 239LIBSODIUM_SEARCH_LIBS=
212NACL_SEARCH_HEADERS= 240NACL_SEARCH_HEADERS=
213NACL_SEARCH_LIBS= 241NACL_SEARCH_LIBS=
242LIBEV_SEARCH_HEADERS=
243LIBEV_SEARCH_LIBS=
244LIBEVENT_SEARCH_HEADERS=
245LIBEVENT_SEARCH_LIBS=
214 246
215AC_ARG_WITH(dependency-search, 247AC_ARG_WITH(dependency-search,
216 AC_HELP_STRING([--with-dependency-search=DIR], 248 AC_HELP_STRING([--with-dependency-search=DIR],
@@ -264,6 +296,42 @@ AC_ARG_WITH(libsodium-libs,
264 ] 296 ]
265) 297)
266 298
299AC_ARG_WITH(libev-headers,
300 AC_HELP_STRING([--with-libev-headers=DIR],
301 [search for libev header files in DIR]),
302 [
303 LIBEV_SEARCH_HEADERS="$withval"
304 AC_MSG_NOTICE([will search for libev header files in $withval])
305 ]
306)
307
308AC_ARG_WITH(libev-libs,
309 AC_HELP_STRING([--with-libev-libs=DIR],
310 [search for libev libraries in DIR]),
311 [
312 LIBEV_SEARCH_LIBS="$withval"
313 AC_MSG_NOTICE([will search for libev libraries in $withval])
314 ]
315)
316
317AC_ARG_WITH(libevent-headers,
318 AC_HELP_STRING([--with-libevent-headers=DIR],
319 [search for libevent header files in DIR]),
320 [
321 LIBEVENT_SEARCH_HEADERS="$withval"
322 AC_MSG_NOTICE([will search for libevent header files in $withval])
323 ]
324)
325
326AC_ARG_WITH(libevent-libs,
327 AC_HELP_STRING([--with-libevent-libs=DIR],
328 [search for libevent libraries in DIR]),
329 [
330 LIBEVENT_SEARCH_LIBS="$withval"
331 AC_MSG_NOTICE([will search for libevent libraries in $withval])
332 ]
333)
334
267if test "x$WANT_NACL" = "xyes"; then 335if test "x$WANT_NACL" = "xyes"; then
268 enable_shared=no 336 enable_shared=no
269 enable_static=yes 337 enable_static=yes
@@ -394,6 +462,123 @@ elif test "x$LIBSODIUM_FOUND" = "xno"; then
394 AC_SUBST(LIBSODIUM_LDFLAGS) 462 AC_SUBST(LIBSODIUM_LDFLAGS)
395fi 463fi
396 464
465if test "x$WANT_LIBEV" = "xyes"; then
466 if test -n "$PKG_CONFIG"; then
467 PKG_CHECK_MODULES([LIBEV], [libev],
468 [
469 LIBEV_PKG_CONFIG="yes"
470 ],
471 [
472 LIBEV_PKG_CONFIG="no"
473 ]
474 )
475 else
476 LIBEV_PKG_CONFIG="no"
477 fi
478
479 if test "x$LIBEV_PKG_CONFIG" = "xno"; then
480 LIBEV_LIBS=
481 LIBEV_LDFLAGS=
482 LDFLAGS_SAVE="$LDFLAGS"
483
484 if test -n "$LIBEV_SEARCH_LIBS"; then
485 LDFLAGS="-L$LIBEV_SEARCH_LIBS $LDFLAGS"
486 AC_CHECK_LIB(ev, ev_run,
487 [
488 LIBEV_LDFLAGS="-L$LIBEV_SEARCH_LIBS"
489 LIBEV_LIBS="-lev"
490 ],
491 [
492 AC_MSG_ERROR([required library libev was not found in requested location $LIBEV_SEARCH_LIBS])
493 ]
494 )
495 else
496 AC_CHECK_LIB(ev, ev_run,
497 [
498 LIBEV_LIBS="-lev"
499 ],
500 [
501 AC_MSG_ERROR([required library libev was not found in requested location $LIBEV_SEARCH_LIBS])
502 ]
503 )
504 fi
505
506 LDFLAGS="$LDFLAGS_SAVE"
507 fi
508
509 AC_SUBST(LIBEV_LIBS)
510 AC_SUBST(LIBEV_LDFLAGS)
511 AC_DEFINE([HAVE_LIBEV], [1], [Define to 1 if you have the 'libev' library (-lev).])
512fi
513
514if test "x$WANT_LIBEVENT" = "xyes"; then
515 if test -n "$PKG_CONFIG"; then
516 if test "x$WIN32" = "xno"; then
517 PKG_CHECK_MODULES([LIBEVENT], [libevent_pthreads],
518 [
519 LIBEVENT_PKG_CONFIG="yes"
520 ],
521 [
522 LIBEVENT_PKG_CONFIG="no"
523 ],
524 )
525 else
526 PKG_CHECK_MODULES([LIBEVENT], [libevent],
527 [
528 LIBEVENT_PKG_CONFIG="yes"
529 ],
530 [
531 LIBEVENT_PKG_CONFIG="no"
532 ],
533 )
534 fi
535 else
536 LIBEVENT_PKG_CONFIG="no"
537 fi
538
539 if test "x$LIBEVENT_PKG_CONFIG" = "xno"; then
540 LIBEVENT_LIBS=
541 LIBEVENT_LDFLAGS=
542 LDFLAGS_SAVE="$LDFLAGS"
543
544 if test -n "$LIBEVENT_SEARCH_LIBS"; then
545 LDFLAGS="-L$LIBEVENT_SEARCH_LIBS $LDFLAGS"
546 AC_CHECK_LIB(event, event_base_loop,
547 [
548 LIBEVENT_LDFLAGS="-L$LIBEVENT_SEARCH_LIBS"
549 if test "x$WIN32" = "xno"; then
550 LIBEVENT_LIBS="-levent -levent_pthreads"
551 else
552 LIBEVENT_LIBS="-levent"
553 fi
554 ],
555 [
556 AC_MSG_ERROR([required library libevent was not found in requested location $LIBEVENT_SEARCH_LIBS])
557 ]
558 )
559 else
560 AC_CHECK_LIB(event, event_base_loop,
561 [
562 if test "x$WIN32" = "xno"; then
563 LIBEVENT_LIBS="-levent -levent_pthreads"
564 else
565 LIBEVENT_LIBS="-levent"
566 fi
567 ],
568 [
569 AC_MSG_ERROR([required library libevent was not found in requested location $LIBEVENT_SEARCH_LIBS])
570 ]
571 )
572 fi
573
574 LDFLAGS="$LDFLAGS_SAVE"
575 fi
576
577 AC_SUBST(LIBEVENT_LIBS)
578 AC_SUBST(LIBEVENT_LDFLAGS)
579 AC_DEFINE([HAVE_LIBEVENT], [1], [Define to 1 if you have the 'libevent' library (-levent).])
580fi
581
397# Checks for header files. 582# Checks for header files.
398AC_CHECK_HEADERS([arpa/inet.h fcntl.h netdb.h netinet/in.h stdint.h stdlib.h string.h sys/socket.h sys/time.h unistd.h]) 583AC_CHECK_HEADERS([arpa/inet.h fcntl.h netdb.h netinet/in.h stdint.h stdlib.h string.h sys/socket.h sys/time.h unistd.h])
399 584
@@ -453,6 +638,72 @@ elif test "x$LIBSODIUM_FOUND" = "xno"; then
453 AC_SUBST(LIBSODIUM_CFLAGS) 638 AC_SUBST(LIBSODIUM_CFLAGS)
454fi 639fi
455 640
641if test "x$WANT_LIBEV" = "xyes"; then
642 if test "x$LIBEV_PKG_CONFIG" = "xno"; then
643 LIBEV_CFLAGS=
644 CFLAGS_SAVE="$CFLAGS"
645 CPPFLAGS_SAVE="$CPPFLAGS"
646
647 if test -n "$LIBEV_SEARCH_HEADERS"; then
648 CFLAGS="-I$LIBEV_SEARCH_HEADERS $CFLAGS"
649 CPPFLAGS="-I$LIBEV_SEARCH_HEADERS $CPPFLAGS"
650 AC_CHECK_HEADER(ev.h,
651 [
652 LIBEV_CFLAGS="-I$LIBEV_SEARCH_HEADERS"
653 ],
654 [
655 AC_MSG_ERROR([header files for required library libev were not found in requested location $LIBEV_SEARCH_HEADERS])
656 ]
657 )
658 else
659 AC_CHECK_HEADER(ev.h,
660 [],
661 [
662 AC_MSG_ERROR([header files for required library libev was not found on your system, please check http://libev.schmorp.de/])
663 ]
664 )
665 fi
666
667 CFLAGS="$CFLAGS_SAVE"
668 CPPFLAGS="$CPPFLAGS_SAVE"
669 fi
670
671 AC_SUBST(LIBEV_CFLAGS)
672fi
673
674if test "x$WANT_LIBEVENT" = "xyes"; then
675 if test "x$LIBEVENT_PKG_CONFIG" = "xno"; then
676 LIBEVENT_CFLAGS=
677 CFLAGS_SAVE="$CFLAGS"
678 CPPFLAGS_SAVE="$CPPFLAGS"
679
680 if test -n "$LIBEVENT_SEARCH_HEADERS"; then
681 CFLAGS="-I$LIBEVENT_SEARCH_HEADERS $CFLAGS"
682 CPPFLAGS="-I$LIBEVENT_SEARCH_HEADERS $CPPFLAGS"
683 AC_CHECK_HEADERS([event2/event.h event2/thread.h],
684 [
685 LIBEVENT_CFLAGS="-I$LIBEVENT_SEARCH_HEADERS"
686 ],
687 [
688 AC_MSG_ERROR([header files for required library libevent were not found in requested location $LIBEVENT_SEARCH_HEADERS])
689 ]
690 )
691 else
692 AC_CHECK_HEADERS([event2/event.h event2/thread.h],
693 [],
694 [
695 AC_MSG_ERROR([header files for required library libevent was not found on your system, please check http://libevent.org/])
696 ]
697 )
698 fi
699
700 CFLAGS="$CFLAGS_SAVE"
701 CPPFLAGS="$CPPFLAGS_SAVE"
702 fi
703
704 AC_SUBST(LIBEVENT_CFLAGS)
705fi
706
456# Checks for typedefs, structures, and compiler characteristics. 707# Checks for typedefs, structures, and compiler characteristics.
457AC_HEADER_STDBOOL 708AC_HEADER_STDBOOL
458AC_TYPE_INT16_T 709AC_TYPE_INT16_T
diff --git a/libtoxcore.pc.in b/libtoxcore.pc.in
index 90bb6c28..1ecb2272 100644
--- a/libtoxcore.pc.in
+++ b/libtoxcore.pc.in
@@ -7,5 +7,5 @@ Name: libtoxcore
7Description: Tox protocol library 7Description: Tox protocol library
8Requires: 8Requires:
9Version: @PACKAGE_VERSION@ 9Version: @PACKAGE_VERSION@
10Libs: @NACL_OBJECTS_PKGCONFIG@ -L${libdir} -ltoxcore @NACL_LDFLAGS@ -ltoxdns -ltoxencryptsave @NACL_LIBS@ @LIBS@ @MATH_LDFLAGS@ @PTHREAD_LDFLAGS@ 10Libs: @NACL_OBJECTS_PKGCONFIG@ -L${libdir} -ltoxcore @NACL_LDFLAGS@ -ltoxdns -ltoxencryptsave @NACL_LIBS@ @LIBEV_LIBS@ @LIBEVENT_LIBS@ @LIBS@ @MATH_LDFLAGS@ @PTHREAD_LDFLAGS@
11Cflags: -I${includedir} 11Cflags: -I${includedir}
diff --git a/toxcore/Makefile.inc b/toxcore/Makefile.inc
index 2ca25650..7501530c 100644
--- a/toxcore/Makefile.inc
+++ b/toxcore/Makefile.inc
@@ -55,12 +55,16 @@ libtoxcore_la_CFLAGS = -I$(top_srcdir) \
55 -I$(top_srcdir)/toxcore \ 55 -I$(top_srcdir)/toxcore \
56 $(LIBSODIUM_CFLAGS) \ 56 $(LIBSODIUM_CFLAGS) \
57 $(NACL_CFLAGS) \ 57 $(NACL_CFLAGS) \
58 $(LIBEV_CFLAGS) \
59 $(LIBEVENT_CFLAGS) \
58 $(PTHREAD_CFLAGS) 60 $(PTHREAD_CFLAGS)
59 61
60libtoxcore_la_LDFLAGS = $(LT_LDFLAGS) \ 62libtoxcore_la_LDFLAGS = $(LT_LDFLAGS) \
61 $(EXTRA_LT_LDFLAGS) \ 63 $(EXTRA_LT_LDFLAGS) \
62 $(LIBSODIUM_LDFLAGS) \ 64 $(LIBSODIUM_LDFLAGS) \
63 $(NACL_LDFLAGS) \ 65 $(NACL_LDFLAGS) \
66 $(LIBEV_LDFLAGS) \
67 $(LIBEVENT_LDFLAGS) \
64 $(MATH_LDFLAGS) \ 68 $(MATH_LDFLAGS) \
65 $(RT_LIBS) \ 69 $(RT_LIBS) \
66 $(WINSOCK2_LIBS) 70 $(WINSOCK2_LIBS)
@@ -68,6 +72,8 @@ libtoxcore_la_LDFLAGS = $(LT_LDFLAGS) \
68libtoxcore_la_LIBADD = $(LIBSODIUM_LIBS) \ 72libtoxcore_la_LIBADD = $(LIBSODIUM_LIBS) \
69 $(NACL_OBJECTS) \ 73 $(NACL_OBJECTS) \
70 $(NAC_LIBS) \ 74 $(NAC_LIBS) \
75 $(LIBEV_LIBS) \
76 $(LIBEVENT_LIBS) \
71 $(PTHREAD_LIBS) 77 $(PTHREAD_LIBS)
72 78
73if SET_SO_VERSION 79if SET_SO_VERSION
diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c
index 5dda5b30..24aa8a9b 100644
--- a/toxcore/Messenger.c
+++ b/toxcore/Messenger.c
@@ -1930,6 +1930,28 @@ Messenger *new_messenger(Messenger_Options *options, unsigned int *error)
1930 return NULL; 1930 return NULL;
1931 } 1931 }
1932 1932
1933#ifdef HAVE_LIBEV
1934 m->dispatcher = ev_loop_new(0);
1935#elif HAVE_LIBEVENT
1936#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
1937 evthread_use_windows_threads();
1938#else
1939 evthread_use_pthreads();
1940#endif /* WIN32 || _WIN32 || __WIN32__ */
1941 m->dispatcher = event_base_new();
1942#else
1943 m->loop_run = false;
1944#endif /* HAVE_LIBEV */
1945
1946#if defined(HAVE_LIBEV) || defined(HAVE_LIBEVENT)
1947
1948 if (!m->dispatcher) {
1949 free(m);
1950 return NULL;
1951 }
1952
1953#endif /* HAVE_LIBEV || HAVE_LIBEVENT */
1954
1933 Logger *log = NULL; 1955 Logger *log = NULL;
1934 1956
1935 if (options->log_callback) { 1957 if (options->log_callback) {
@@ -2057,6 +2079,12 @@ void kill_messenger(Messenger *m)
2057 clear_receipts(m, i); 2079 clear_receipts(m, i);
2058 } 2080 }
2059 2081
2082#ifdef HAVE_LIBEV
2083 ev_loop_destroy(m->dispatcher);
2084#elif HAVE_LIBEVENT
2085 event_base_free(m->dispatcher);
2086#endif
2087
2060 logger_kill(m->log); 2088 logger_kill(m->log);
2061 free(m->friendlist); 2089 free(m->friendlist);
2062 free(m); 2090 free(m);
diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h
index 7275ffbf..300e7f25 100644
--- a/toxcore/Messenger.h
+++ b/toxcore/Messenger.h
@@ -29,6 +29,13 @@
29#include "friend_requests.h" 29#include "friend_requests.h"
30#include "logger.h" 30#include "logger.h"
31 31
32#ifdef HAVE_LIBEV
33#include <ev.h>
34#elif HAVE_LIBEVENT
35#include <event2/event.h>
36#include <event2/thread.h>
37#endif
38
32#define MAX_NAME_LENGTH 128 39#define MAX_NAME_LENGTH 128
33/* TODO(irungentoo): this must depend on other variable. */ 40/* TODO(irungentoo): this must depend on other variable. */
34#define MAX_STATUSMESSAGE_LENGTH 1007 41#define MAX_STATUSMESSAGE_LENGTH 1007
@@ -273,9 +280,16 @@ struct Messenger {
273 void (*core_connection_change)(struct Messenger *m, unsigned int, void *); 280 void (*core_connection_change)(struct Messenger *m, unsigned int, void *);
274 unsigned int last_connection_status; 281 unsigned int last_connection_status;
275 282
276 uint8_t loop_run; 283#ifdef HAVE_LIBEV
277 void (*loop_begin_cb)(struct Messenger *tox, void *user_data); 284 struct ev_loop *dispatcher;
278 void (*loop_end_cb)(struct Messenger *tox, void *user_data); 285 ev_async stop_loop;
286#elif HAVE_LIBEVENT
287 struct event_base *dispatcher;
288#else
289 bool loop_run;
290#endif
291 void (*loop_begin_cb)(struct Messenger *m, void *user_data);
292 void (*loop_end_cb)(struct Messenger *m, void *user_data);
279 293
280 Messenger_Options options; 294 Messenger_Options options;
281}; 295};
diff --git a/toxcore/TCP_client.c b/toxcore/TCP_client.c
index 3e6de14a..8989f244 100644
--- a/toxcore/TCP_client.c
+++ b/toxcore/TCP_client.c
@@ -985,6 +985,17 @@ void kill_TCP_connection(TCP_Client_Connection *TCP_connection)
985 985
986 wipe_priority_list(TCP_connection); 986 wipe_priority_list(TCP_connection);
987 kill_sock(TCP_connection->sock); 987 kill_sock(TCP_connection->sock);
988
989#ifdef HAVE_LIBEV
990 ev_io_stop(TCP_connection->sock_listener.dispatcher, &TCP_connection->sock_listener.listener);
991#elif HAVE_LIBEVENT
992
993 if (TCP_connection->sock_listener) {
994 event_free(TCP_connection->sock_listener);
995 }
996
997#endif
998
988 crypto_memzero(TCP_connection, sizeof(TCP_Client_Connection)); 999 crypto_memzero(TCP_connection, sizeof(TCP_Client_Connection));
989 free(TCP_connection); 1000 free(TCP_connection);
990} 1001}
diff --git a/toxcore/TCP_client.h b/toxcore/TCP_client.h
index 21254314..8a698869 100644
--- a/toxcore/TCP_client.h
+++ b/toxcore/TCP_client.h
@@ -27,6 +27,12 @@
27#include "TCP_server.h" 27#include "TCP_server.h"
28#include "crypto_core.h" 28#include "crypto_core.h"
29 29
30#ifdef HAVE_LIBEV
31#include <ev.h>
32#elif HAVE_LIBEVENT
33#include <event2/event.h>
34#endif
35
30#define TCP_CONNECTION_TIMEOUT 10 36#define TCP_CONNECTION_TIMEOUT 10
31 37
32typedef enum { 38typedef enum {
@@ -52,7 +58,15 @@ enum {
52}; 58};
53typedef struct { 59typedef struct {
54 uint8_t status; 60 uint8_t status;
55 Socket sock; 61 Socket sock;
62#ifdef HAVE_LIBEV
63 struct {
64 ev_io listener;
65 struct ev_loop *dispatcher;
66 } sock_listener;
67#elif HAVE_LIBEVENT
68 struct event *sock_listener;
69#endif
56 uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE]; /* our public key */ 70 uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE]; /* our public key */
57 uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE]; /* public key of the server */ 71 uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE]; /* public key of the server */
58 IP_Port ip_port; /* The ip and port of the server */ 72 IP_Port ip_port; /* The ip and port of the server */
diff --git a/toxcore/TCP_connection.c b/toxcore/TCP_connection.c
index 18c1e76e..9b51443d 100644
--- a/toxcore/TCP_connection.c
+++ b/toxcore/TCP_connection.c
@@ -67,6 +67,37 @@ const uint8_t *tcp_connections_public_key(const TCP_Connections *tcp_c)
67} 67}
68 68
69 69
70/**
71 * Return number of elements of TCP connection array.
72 *
73 * @param tcp_c struct containing TCP_con array
74 *
75 * @return number of elements of TCP connection array
76 */
77uint32_t tcp_connections_length(const TCP_Connections *tcp_c)
78{
79 return tcp_c->tcp_connections_length;
80}
81
82
83/**
84 * Return TCP connection stored at "idx" position.
85 *
86 * @param tcp_c struct containing TCP_con array
87 * @param idx index of TCP connection to return (values from 0 to tcp_connections_length() - 1)
88 *
89 * @return TCP connection stored at "idx" position, or NULL if errors occurred
90 */
91const TCP_con *tcp_connections_connection_at(const TCP_Connections *tcp_c, uint32_t idx)
92{
93 if (idx >= tcp_c->tcp_connections_length) {
94 return NULL;
95 }
96
97 return &tcp_c->tcp_connections[idx];
98}
99
100
70/* Set the size of the array to num. 101/* Set the size of the array to num.
71 * 102 *
72 * return -1 if realloc fails. 103 * return -1 if realloc fails.
diff --git a/toxcore/TCP_connection.h b/toxcore/TCP_connection.h
index f023b1ab..276303e7 100644
--- a/toxcore/TCP_connection.h
+++ b/toxcore/TCP_connection.h
@@ -82,6 +82,10 @@ typedef struct TCP_Connections TCP_Connections;
82 82
83const uint8_t *tcp_connections_public_key(const TCP_Connections *tcp_c); 83const uint8_t *tcp_connections_public_key(const TCP_Connections *tcp_c);
84 84
85uint32_t tcp_connections_length(const TCP_Connections *tcp_c);
86
87const TCP_con *tcp_connections_connection_at(const TCP_Connections *tcp_c, uint32_t idx);
88
85/* Send a packet to the TCP connection. 89/* Send a packet to the TCP connection.
86 * 90 *
87 * return -1 on failure. 91 * return -1 on failure.
diff --git a/toxcore/network.c b/toxcore/network.c
index 215ab8e0..62b36ae6 100644
--- a/toxcore/network.c
+++ b/toxcore/network.c
@@ -797,6 +797,16 @@ void kill_networking(Networking_Core *net)
797 kill_sock(net->sock); 797 kill_sock(net->sock);
798 } 798 }
799 799
800#ifdef HAVE_LIBEV
801 ev_io_stop(net->sock_listener.dispatcher, &net->sock_listener.listener);
802#elif HAVE_LIBEVENT
803
804 if (net->sock_listener) {
805 event_free(net->sock_listener);
806 }
807
808#endif
809
800 free(net); 810 free(net);
801} 811}
802 812
diff --git a/toxcore/network.h b/toxcore/network.h
index 28795602..4f27a81d 100644
--- a/toxcore/network.h
+++ b/toxcore/network.h
@@ -33,6 +33,11 @@
33#include "ccompat.h" 33#include "ccompat.h"
34#include "logger.h" 34#include "logger.h"
35 35
36#ifdef HAVE_LIBEV
37#include <ev.h>
38#elif HAVE_LIBEVENT
39#include <event2/event.h>
40#endif
36#include <stdint.h> 41#include <stdint.h>
37#include <stdio.h> 42#include <stdio.h>
38#include <stdlib.h> 43#include <stdlib.h>
@@ -316,6 +321,14 @@ typedef struct {
316 uint16_t port; 321 uint16_t port;
317 /* Our UDP socket. */ 322 /* Our UDP socket. */
318 Socket sock; 323 Socket sock;
324#ifdef HAVE_LIBEV
325 struct {
326 ev_io listener;
327 struct ev_loop *dispatcher;
328 } sock_listener;
329#elif HAVE_LIBEVENT
330 struct event *sock_listener;
331#endif
319} Networking_Core; 332} Networking_Core;
320 333
321/* Run this before creating sockets. 334/* Run this before creating sockets.
diff --git a/toxcore/tox.api.h b/toxcore/tox.api.h
index 0bcf40e1..cacfa26c 100644
--- a/toxcore/tox.api.h
+++ b/toxcore/tox.api.h
@@ -838,19 +838,45 @@ const uint32_t iteration_interval();
838 */ 838 */
839void iterate(any user_data); 839void iterate(any user_data);
840 840
841
841/** 842/**
842 * Run $iterate() any time a packet arrives, only returns after ${loop.stop}(). 843 * Error codes for $loop().
843 */ 844 */
844uint32_t loop(any user_data); 845error for loop {
846 /**
847 * Invalid arguments passed.
848 */
849 NULL,
850 /**
851 * Failed running events dispatcher.
852 */
853 BREAK,
854 /**
855 * Failed running select().
856 */
857 SELECT,
858 /**
859 * Failed getting sockets file descriptors.
860 */
861 GET_FDS,
862}
863
864
865/**
866 * Run $iterate() any time a packet arrives, returns after ${loop.stop}() or ${kill}().
867 */
868bool loop(any user_data) with error for loop;
869
845 870
846namespace loop { 871namespace loop {
872
847 /** 873 /**
848 * Tell $loop() to return. 874 * Tell $loop() to return.
849 */ 875 */
850 void stop(); 876 void stop();
851 877
852 /** 878 /**
853 * Callback ran when $loop() calls into $iterate(), the client can lock a mutex here. 879 * This callback is invoked when $loop() calls into $iterate(), the client can lock a mutex here.
854 */ 880 */
855 event begin const { 881 event begin const {
856 /** 882 /**
@@ -860,7 +886,7 @@ namespace loop {
860 } 886 }
861 887
862 /** 888 /**
863 * Callback ran when $loop() is finished with $iterate(), the client can unlock the mutex here. 889 * This callback is invoked when $loop() is finished with $iterate(), the client can unlock the mutex here.
864 */ 890 */
865 event end const { 891 event end const {
866 /** 892 /**
diff --git a/toxcore/tox.c b/toxcore/tox.c
index 5e2f14d2..0234fbf3 100644
--- a/toxcore/tox.c
+++ b/toxcore/tox.c
@@ -34,9 +34,19 @@ typedef struct Messenger Tox;
34#include "Messenger.h" 34#include "Messenger.h"
35#include "group.h" 35#include "group.h"
36#include "logger.h" 36#include "logger.h"
37#include "net_crypto.h"
37 38
38#include "../toxencryptsave/defines.h" 39#include "../toxencryptsave/defines.h"
39 40
41#include <errno.h>
42#if !defined(HAVE_LIBEV) && !defined(HAVE_LIBEVENT)
43#if defined (WIN32) || defined(_WIN32) || defined(__WIN32__)
44#include <winsock2.h>
45#else
46#include <sys/select.h>
47#endif /* WIN32 || _WIN32 || __WIN32__ */
48#endif /* !HAVE_LIBEV && !HAVE_LIBEVENT */
49
40#define SET_ERROR_PARAMETER(param, x) {if(param) {*param = x;}} 50#define SET_ERROR_PARAMETER(param, x) {if(param) {*param = x;}}
41 51
42#if TOX_HASH_LENGTH != CRYPTO_SHA256_SIZE 52#if TOX_HASH_LENGTH != CRYPTO_SHA256_SIZE
@@ -71,6 +81,12 @@ typedef struct Messenger Tox;
71#error TOX_MAX_STATUS_MESSAGE_LENGTH is assumed to be equal to MAX_STATUSMESSAGE_LENGTH 81#error TOX_MAX_STATUS_MESSAGE_LENGTH is assumed to be equal to MAX_STATUSMESSAGE_LENGTH
72#endif 82#endif
73 83
84#if defined(HAVE_LIBEV) || defined(HAVE_LIBEVENT)
85typedef struct {
86 Tox *tox;
87 void *user_data;
88} Event_Arg;
89#endif
74 90
75bool tox_version_is_compatible(uint32_t major, uint32_t minor, uint32_t patch) 91bool tox_version_is_compatible(uint32_t major, uint32_t minor, uint32_t patch)
76{ 92{
@@ -203,6 +219,8 @@ void tox_kill(Tox *tox)
203 } 219 }
204 220
205 Messenger *m = tox; 221 Messenger *m = tox;
222
223 tox_loop_stop(tox);
206 kill_groupchats((Group_Chats *)m->conferences_object); 224 kill_groupchats((Group_Chats *)m->conferences_object);
207 kill_messenger(m); 225 kill_messenger(m);
208} 226}
@@ -342,68 +360,261 @@ void tox_iterate(Tox *tox, void *user_data)
342 do_groupchats((Group_Chats *)m->conferences_object, user_data); 360 do_groupchats((Group_Chats *)m->conferences_object, user_data);
343} 361}
344 362
345uint32_t tox_fd_count(Tox *tox) 363void tox_callback_loop_begin(Tox *tox, tox_loop_begin_cb *callback)
346{ 364{
365 if (tox == NULL) {
366 return;
367 }
368
347 Messenger *m = tox; 369 Messenger *m = tox;
348 return 1 + m->net_crypto->tcp_c->tcp_connections_length; 370 m->loop_begin_cb = callback;
349} 371}
350 372
351/** 373void tox_callback_loop_end(Tox *tox, tox_loop_end_cb *callback)
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{ 374{
375 if (tox == NULL) {
376 return;
377 }
378
357 Messenger *m = tox; 379 Messenger *m = tox;
358 int count = 0; 380 m->loop_end_cb = callback;
381}
359 382
360 if (max_sockets >= 1) { 383#ifdef HAVE_LIBEV
361 sockets[count] = m->net->sock; 384static void tox_stop_loop_cb(struct ev_loop *dispatcher, ev_async *listener, int events)
362 max_sockets--; 385{
363 count++; 386 if (dispatcher == NULL || listener == NULL) {
387 return;
364 } 388 }
365 389
366 TCP_Connections *conns = m->net_crypto->tcp_c; 390 Event_Arg *tmp = (Event_Arg *) listener->data;
367 int x; 391 Messenger *m = tmp->tox;
368 392
369 for (x = 0; x < conns->tcp_connections_length; x++) { 393 if (ev_is_active(&m->net->sock_listener.listener) || ev_is_pending(&m->net->sock_listener.listener)) {
370 if (max_sockets == 0) { 394 ev_io_stop(dispatcher, &m->net->sock_listener.listener);
371 break; 395 }
372 }
373 396
374 TCP_con *conn = &conns->tcp_connections[x]; 397 uint32_t len = tcp_connections_length(m->net_crypto->tcp_c);
375 sockets[count] = conn->connection->sock; 398
376 count++; 399 for (uint32_t i = 0; i < len; i++) {
377 max_sockets--; 400 const TCP_con *conn = tcp_connections_connection_at(m->net_crypto->tcp_c, i);
401
402 if (ev_is_active(&conn->connection->sock_listener.listener)
403 || ev_is_pending(&conn->connection->sock_listener.listener)) {
404 ev_io_stop(dispatcher, &conn->connection->sock_listener.listener);
405 }
378 } 406 }
379 407
380 return count; 408 ev_async_stop(dispatcher, listener);
409
410 ev_break(dispatcher, EVBREAK_ALL);
381} 411}
382 412
383void tox_callback_loop_begin(Tox *tox, tox_loop_begin_cb *callback) 413static void tox_do_iterate(struct ev_loop *dispatcher, ev_io *sock_listener, int events)
384{ 414{
385 Messenger *m = tox; 415 if (dispatcher == NULL || sock_listener == NULL) {
386 m->loop_begin_cb = callback; 416 return;
417 }
418
419 Event_Arg *tmp = (Event_Arg *) sock_listener->data;
420 Messenger *m = tmp->tox;
421
422 if (m->loop_begin_cb) {
423 m->loop_begin_cb(m, tmp->user_data);
424 }
425
426 tox_iterate(tmp->tox, tmp->user_data);
427
428 if (!ev_is_active(&m->net->sock_listener.listener) && !ev_is_pending(&m->net->sock_listener.listener)) {
429 m->net->sock_listener.dispatcher = dispatcher;
430 ev_io_init(&m->net->sock_listener.listener, tox_do_iterate, m->net->sock, EV_READ);
431 m->net->sock_listener.listener.data = sock_listener->data;
432 ev_io_start(dispatcher, &m->net->sock_listener.listener);
433 }
434
435 uint32_t len = tcp_connections_length(m->net_crypto->tcp_c);
436
437 for (uint32_t i = 0; i < len; i++) {
438 const TCP_con *conn = tcp_connections_connection_at(m->net_crypto->tcp_c, i);
439
440 if (!ev_is_active(&conn->connection->sock_listener.listener)
441 && !ev_is_pending(&conn->connection->sock_listener.listener)) {
442 conn->connection->sock_listener.dispatcher = dispatcher;
443 ev_io_init(&conn->connection->sock_listener.listener, tox_do_iterate, conn->connection->sock, EV_READ);
444 conn->connection->sock_listener.listener.data = sock_listener->data;
445 ev_io_start(m->dispatcher, &conn->connection->sock_listener.listener);
446 }
447 }
448
449 if (m->loop_end_cb) {
450 m->loop_end_cb(m, tmp->user_data);
451 }
387} 452}
453#elif HAVE_LIBEVENT
454static void tox_do_iterate(evutil_socket_t fd, short events, void *arg)
455{
456 if (arg == NULL) {
457 return;
458 }
388 459
389void tox_callback_loop_end(Tox *tox, tox_loop_end_cb *callback) 460 Event_Arg *tmp = (Event_Arg *) arg;
461 Messenger *m = tmp->tox;
462 struct timeval timeout;
463
464 if (m->loop_begin_cb) {
465 m->loop_begin_cb(m, tmp->user_data);
466 }
467
468 tox_iterate(tmp->tox, tmp->user_data);
469
470 timeout.tv_sec = 0;
471
472 // TODO(cleverca22): use a longer timeout.
473 timeout.tv_usec = tox_iteration_interval(tmp->tox) * 1000 * 2;
474
475 if (!m->net->sock_listener) {
476 m->net->sock_listener = event_new(m->dispatcher, m->net->sock, EV_READ | EV_PERSIST, tox_do_iterate, arg);
477 }
478
479 event_add(m->net->sock_listener, &timeout);
480
481 uint32_t len = tcp_connections_length(m->net_crypto->tcp_c);
482
483 for (uint32_t i = 0; i < len; i++) {
484 const TCP_con *conn = tcp_connections_connection_at(m->net_crypto->tcp_c, i);
485
486 if (!conn->connection->sock_listener) {
487 conn->connection->sock_listener = event_new(m->dispatcher, conn->connection->sock, EV_READ | EV_PERSIST, tox_do_iterate,
488 arg);
489 }
490
491 event_add(conn->connection->sock_listener, NULL);
492 }
493
494 if (m->loop_end_cb) {
495 m->loop_end_cb(m, tmp->user_data);
496 }
497}
498#else
499/**
500 * Gathers a list of every network file descriptor,
501 * where an activity is expected on.
502 *
503 * @param sockets a pointer to an array (the pointed array can be NULL).
504 * @param sockets_num the number of current known sockets (will be updated by the funciton).
505 *
506 * @return false if errors occurred, true otherwise.
507 */
508static bool tox_fds(Messenger *m, Socket **sockets, uint32_t *sockets_num)
390{ 509{
391 Messenger *m = tox; 510 if (m == NULL || sockets == NULL || sockets_num == NULL) {
392 m->loop_end_cb = callback; 511 return false;
512 }
513
514 uint32_t len = tcp_connections_length(m->net_crypto->tcp_c);
515 uint32_t fdcount = 1 + len;
516
517 if (fdcount != *sockets_num || *sockets == NULL) {
518 Socket *tmp_sockets = (Socket *) realloc(*sockets, fdcount * sizeof(Socket));
519
520 if (tmp_sockets == NULL) {
521 return false;
522 }
523
524 *sockets = tmp_sockets;
525 *sockets_num = fdcount;
526 }
527
528 (*sockets)[0] = m->net->sock;
529
530 uint32_t i = 0;
531
532 while (i < fdcount - 1 && i < len) {
533 const TCP_con *conn = tcp_connections_connection_at(m->net_crypto->tcp_c, i);
534 i++;
535
536 if (conn != NULL) {
537 (*sockets)[i] = conn->connection->sock;
538 } else {
539 (*sockets)[i] = 0;
540 }
541 }
542
543 return true;
393} 544}
545#endif
394 546
395uint32_t tox_loop(Tox *tox, void *user_data) 547bool tox_loop(Tox *tox, void *user_data, TOX_ERR_LOOP *error)
396{ 548{
397 struct timeval timeout; 549 if (tox == NULL) {
398 int maxfd; 550 SET_ERROR_PARAMETER(error, TOX_ERR_LOOP_NULL);
399 uint32_t i, list_size = 0; 551
400 uint32_t *fdlist = NULL; 552 return false;
553 }
554
401 Messenger *m = tox; 555 Messenger *m = tox;
402 m->loop_run = true;
403 fd_set readable;
404 556
557#ifdef HAVE_LIBEV
558 bool ret = true;
559 Event_Arg *tmp = (Event_Arg *) calloc(1, sizeof(Event_Arg));
560
561 tmp->tox = tox;
562 tmp->user_data = user_data;
563
564 ev_async_init(&m->stop_loop, tox_stop_loop_cb);
565 m->stop_loop.data = tmp;
566 ev_async_start(m->dispatcher, &m->stop_loop);
567
568 ev_io stub_listener;
569 ev_init(&stub_listener, tox_do_iterate);
570 stub_listener.data = tmp;
571 tox_do_iterate(m->dispatcher, &stub_listener, 0);
572
573 // TODO(Ansa89): travis states that "ev_run" returns "void",
574 // but "man 3 ev" states it returns "bool"
575#if 0
576 ret = !ev_run(m->dispatcher, 0);
577
578 if (ret) {
579 SET_ERROR_PARAMETER(error, TOX_ERR_LOOP_OK);
580 } else {
581 SET_ERROR_PARAMETER(error, TOX_ERR_LOOP_BREAK);
582 }
583
584#endif
585
586 ev_run(m->dispatcher, 0);
587
588 SET_ERROR_PARAMETER(error, TOX_ERR_LOOP_OK);
589
590 free(tmp);
591#elif HAVE_LIBEVENT
592 Event_Arg *tmp = (Event_Arg *) calloc(1, sizeof(Event_Arg));
593
594 tmp->tox = tox;
595 tmp->user_data = user_data;
596
597 tox_do_iterate(0, 0, tmp);
598 bool ret = event_base_dispatch(m->dispatcher) < 0 ? false : true;
599
600 if (ret) {
601 SET_ERROR_PARAMETER(error, TOX_ERR_LOOP_OK);
602 } else {
603 SET_ERROR_PARAMETER(error, TOX_ERR_LOOP_BREAK);
604 }
605
606 free(tmp);
607#else
608 bool ret = true;
609 uint32_t fdcount = 0;
610 Socket *fdlist = NULL;
611
612 m->loop_run = true;
405 613
406 while (m->loop_run) { 614 while (m->loop_run) {
615 Socket maxfd;
616 fd_set readable;
617
407 if (m->loop_begin_cb) { 618 if (m->loop_begin_cb) {
408 m->loop_begin_cb(tox, user_data); 619 m->loop_begin_cb(tox, user_data);
409 } 620 }
@@ -413,16 +624,27 @@ uint32_t tox_loop(Tox *tox, void *user_data)
413 maxfd = 0; 624 maxfd = 0;
414 FD_ZERO(&readable); 625 FD_ZERO(&readable);
415 626
416 uint32_t fdcount = tox_fd_count(tox); 627 // TODO(cleverca22): is it a good idea to reuse previous fdlist when
628 // fdcount!=0 && tox_fds()==false?
629 if (fdcount == 0 && !tox_fds(m, &fdlist, &fdcount)) {
630 // We must stop because maxfd won't be set.
631 // TODO(cleverca22): should we call loop_end_cb() on error?
632 if (m->loop_end_cb) {
633 m->loop_end_cb(tox, user_data);
634 }
635
636 SET_ERROR_PARAMETER(error, TOX_ERR_LOOP_GET_FDS);
637
638 free(fdlist);
417 639
418 if (fdcount > list_size) { 640 return false;
419 fdlist = realloc(fdlist, fdcount * sizeof(uint32_t));
420 list_size = fdcount;
421 } 641 }
422 642
423 fdcount = tox_fds(tox, fdlist, list_size); 643 for (uint32_t i = 0; i < fdcount; i++) {
644 if (fdlist[i] == 0) {
645 continue;
646 }
424 647
425 for (i = 0; i < fdcount; i++) {
426 FD_SET(fdlist[i], &readable); 648 FD_SET(fdlist[i], &readable);
427 649
428 if (fdlist[i] > maxfd) { 650 if (fdlist[i] > maxfd) {
@@ -430,27 +652,49 @@ uint32_t tox_loop(Tox *tox, void *user_data)
430 } 652 }
431 } 653 }
432 654
655 struct timeval timeout;
656
433 timeout.tv_sec = 0; 657 timeout.tv_sec = 0;
434 timeout.tv_usec = tox_iteration_interval(tox) * 1000 * 2; // TODO, use a longer timeout (cleverca22) 658
659 // TODO(cleverca22): use a longer timeout.
660 timeout.tv_usec = tox_iteration_interval(tox) * 1000 * 2;
435 661
436 if (m->loop_end_cb) { 662 if (m->loop_end_cb) {
437 m->loop_end_cb(tox, user_data); 663 m->loop_end_cb(tox, user_data);
438 } 664 }
439 665
440 int ret = select(maxfd, &readable, NULL, NULL, &timeout); 666 if (select(maxfd, &readable, NULL, NULL, &timeout) < 0 && errno != EBADF) {
667 SET_ERROR_PARAMETER(error, TOX_ERR_LOOP_SELECT);
668
669 free(fdlist);
441 670
442 if (ret < 0) { 671 return false;
443 return ret;
444 } 672 }
445 } 673 }
446 674
447 return 0; 675 SET_ERROR_PARAMETER(error, TOX_ERR_LOOP_OK);
676
677 free(fdlist);
678#endif
679
680 return ret;
448} 681}
449 682
450void tox_loop_stop(Tox *tox) 683void tox_loop_stop(Tox *tox)
451{ 684{
685 if (tox == NULL) {
686 return;
687 }
688
452 Messenger *m = tox; 689 Messenger *m = tox;
690
691#ifdef HAVE_LIBEV
692 ev_async_send(m->dispatcher, &m->stop_loop);
693#elif HAVE_LIBEVENT
694 event_base_loopbreak(m->dispatcher);
695#else
453 m->loop_run = false; 696 m->loop_run = false;
697#endif
454} 698}
455 699
456void tox_self_get_address(const Tox *tox, uint8_t *address) 700void tox_self_get_address(const Tox *tox, uint8_t *address)
diff --git a/toxcore/tox.h b/toxcore/tox.h
index 0be019cd..ab4ae7b1 100644
--- a/toxcore/tox.h
+++ b/toxcore/tox.h
@@ -991,9 +991,42 @@ uint32_t tox_iteration_interval(const Tox *tox);
991void tox_iterate(Tox *tox, void *user_data); 991void tox_iterate(Tox *tox, void *user_data);
992 992
993/** 993/**
994 * Run tox_iterate() any time a packet arrives, only returns after tox_loop_stop(). 994 * Error codes for tox_loop().
995 */ 995 */
996uint32_t tox_loop(Tox *tox, void *user_data); 996typedef enum TOX_ERR_LOOP {
997
998 /**
999 * The function returned successfully.
1000 */
1001 TOX_ERR_LOOP_OK,
1002
1003 /**
1004 * Invalid arguments passed.
1005 */
1006 TOX_ERR_LOOP_NULL,
1007
1008 /**
1009 * Failed running events dispatcher.
1010 */
1011 TOX_ERR_LOOP_BREAK,
1012
1013 /**
1014 * Failed running select().
1015 */
1016 TOX_ERR_LOOP_SELECT,
1017
1018 /**
1019 * Failed getting sockets file descriptors.
1020 */
1021 TOX_ERR_LOOP_GET_FDS,
1022
1023} TOX_ERR_LOOP;
1024
1025
1026/**
1027 * Run tox_iterate() any time a packet arrives, returns after tox_loop_stop() or tox_kill().
1028 */
1029bool tox_loop(Tox *tox, void *user_data, TOX_ERR_LOOP *error);
997 1030
998/** 1031/**
999 * Tell tox_loop() to return. 1032 * Tell tox_loop() to return.
@@ -1009,7 +1042,7 @@ typedef void tox_loop_begin_cb(Tox *tox, void *user_data);
1009/** 1042/**
1010 * Set the callback for the `loop_begin` event. Pass NULL to unset. 1043 * Set the callback for the `loop_begin` event. Pass NULL to unset.
1011 * 1044 *
1012 * Callback ran when tox_loop() calls into tox_iterate(), the client can lock a mutex here. 1045 * This callback is invoked when tox_loop() calls into tox_iterate(), the client can lock a mutex here.
1013 */ 1046 */
1014void tox_callback_loop_begin(Tox *tox, tox_loop_begin_cb *callback); 1047void tox_callback_loop_begin(Tox *tox, tox_loop_begin_cb *callback);
1015 1048
@@ -1022,7 +1055,7 @@ typedef void tox_loop_end_cb(Tox *tox, void *user_data);
1022/** 1055/**
1023 * Set the callback for the `loop_end` event. Pass NULL to unset. 1056 * Set the callback for the `loop_end` event. Pass NULL to unset.
1024 * 1057 *
1025 * Callback ran when tox_loop() is finished with tox_iterate(), the client can unlock the mutex here. 1058 * This callback is invoked when tox_loop() is finished with tox_iterate(), the client can unlock the mutex here.
1026 */ 1059 */
1027void tox_callback_loop_end(Tox *tox, tox_loop_end_cb *callback); 1060void tox_callback_loop_end(Tox *tox, tox_loop_end_cb *callback);
1028 1061