aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2014-10-01 18:48:42 +0200
committerHarald Welte <laforge@gnumonks.org>2014-10-01 18:48:42 +0200
commit6ca09c230d4b01ecf4cf7b54e6048191c2fb7d9a (patch)
tree332996648679535861a69fe479996d2fd84acddc
parent711dacdca574c0a4bea87a5ff04717e01aacb358 (diff)
Integrate asynchronous DNS resolver (c-ares) with libosmocore
As osmocom-style applications are centered around a single select loop, DNS queries need to be handled asynchronously to prevent blocking the entire program. The c-ares library is a popular option for async DNS resolving. However, it requires integration with the select loop of the application, which in our case lives inside libosmocore select.c. This patch adds the required integration. The backside is that it adds a mandatory dependency to c-ares (libcares), as well as 2-3 additional branches to every call to osmo_select_main().
-rw-r--r--configure.ac2
-rw-r--r--include/Makefile.am1
-rw-r--r--include/osmocom/core/ares.h10
-rw-r--r--libosmocore.pc.in2
-rw-r--r--src/Makefile.am6
-rw-r--r--src/select.c34
-rw-r--r--tests/Makefile.am7
-rw-r--r--tests/ares/ares_test.ok2
-rw-r--r--tests/testsuite.at6
9 files changed, 61 insertions, 9 deletions
diff --git a/configure.ac b/configure.ac
index deaa8bf7..046016eb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -17,6 +17,8 @@ LT_INIT([pic-only])
AC_CONFIG_MACRO_DIR([m4])
+PKG_CHECK_MODULES(LIBCARES, libcares)
+
dnl check os: some linker flags not available on osx
case $host in
*-darwin*)
diff --git a/include/Makefile.am b/include/Makefile.am
index 9f5c9662..7d054c94 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -1,6 +1,7 @@
nobase_include_HEADERS = \
osmocom/codec/codec.h \
osmocom/core/application.h \
+ osmocom/core/ares.h \
osmocom/core/backtrace.h \
osmocom/core/bit16gen.h \
osmocom/core/bit32gen.h \
diff --git a/include/osmocom/core/ares.h b/include/osmocom/core/ares.h
new file mode 100644
index 00000000..8abd3db1
--- /dev/null
+++ b/include/osmocom/core/ares.h
@@ -0,0 +1,10 @@
+#pragma once
+
+#include <ares.h>
+
+#include <osmocom/core/utils.h>
+
+extern struct value_string ares_status_strs[25];
+extern ares_channel osmo_ares_channel;
+
+int osmo_ares_init();
diff --git a/libosmocore.pc.in b/libosmocore.pc.in
index 7c298693..34cb294c 100644
--- a/libosmocore.pc.in
+++ b/libosmocore.pc.in
@@ -6,6 +6,6 @@ includedir=@includedir@
Name: Osmocom Core Library
Description: C Utility Library
Version: @VERSION@
-Libs: -L${libdir} -losmocore
+Libs: -L${libdir} -losmocore -lcares
Cflags: -I${includedir}/
diff --git a/src/Makefile.am b/src/Makefile.am
index f2b1b838..d36a36f5 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -2,11 +2,11 @@
# Please read Chapter 6 "Library interface versions" of the libtool documentation before making any modification
LIBVERSION=5:0:0
-AM_CFLAGS = -Wall $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)/include
+AM_CFLAGS = -Wall $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)/include -I$(LIBCARES_CFLAGS)
lib_LTLIBRARIES = libosmocore.la
-libosmocore_la_LIBADD = $(BACKTRACE_LIB)
+libosmocore_la_LIBADD = $(BACKTRACE_LIB) $(LIBCARES_LIBS)
libosmocore_la_SOURCES = timer.c select.c signal.c msgb.c bits.c \
bitvec.c statistics.c \
write_queue.c utils.c socket.c \
@@ -14,7 +14,7 @@ libosmocore_la_SOURCES = timer.c select.c signal.c msgb.c bits.c \
gsmtap_util.c crc16.c panic.c backtrace.c \
conv.c application.c rbtree.c strrb.c \
loggingrb.c crc8gen.c crc16gen.c crc32gen.c crc64gen.c \
- macaddr.c
+ macaddr.c ares.c
BUILT_SOURCES = crc8gen.c crc16gen.c crc32gen.c crc64gen.c
diff --git a/src/select.c b/src/select.c
index b29e5c5e..8a967223 100644
--- a/src/select.c
+++ b/src/select.c
@@ -22,9 +22,12 @@
#include <fcntl.h>
#include <stdio.h>
+#include <ares.h>
+
#include <osmocom/core/select.h>
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/timer.h>
+#include <osmocom/core/ares.h>
#include "../config.h"
@@ -103,7 +106,7 @@ int osmo_select_main(int polling)
struct osmo_fd *ufd, *tmp;
fd_set readset, writeset, exceptset;
int work = 0, rc;
- struct timeval no_time = {0, 0};
+ struct timeval *final_tv, no_time = {0, 0};
FD_ZERO(&readset);
FD_ZERO(&writeset);
@@ -121,14 +124,39 @@ int osmo_select_main(int polling)
FD_SET(ufd->fd, &exceptset);
}
+ if (osmo_ares_channel) {
+ /* patch in the socket file descripturs used by c-ares library */
+ rc = ares_fds(osmo_ares_channel, &readset, &writeset);
+ if (rc > maxfd)
+ maxfd = rc;
+ }
+
osmo_timers_check();
- if (!polling)
+ if (!polling) {
+ struct timeval *timer_tv;
+ struct timeval tv;
+
osmo_timers_prepare();
- rc = select(maxfd+1, &readset, &writeset, &exceptset, polling ? &no_time : osmo_timers_nearest());
+ /* obtain nearest timer timeout */
+ timer_tv = osmo_timers_nearest();
+ /* determine if ares has a nearer timeout */
+ if (osmo_ares_channel)
+ final_tv = ares_timeout(osmo_ares_channel, timer_tv, &tv);
+ else
+ final_tv = timer_tv;
+ } else
+ final_tv = &no_time;
+
+ rc = select(maxfd+1, &readset, &writeset, &exceptset, final_tv);
if (rc < 0)
return 0;
+ /* process any c-ares filedescriptors (if any) and take care of
+ * timeouts */
+ if (osmo_ares_channel)
+ ares_process(osmo_ares_channel, &readset, &writeset);
+
/* fire timers */
osmo_timers_update();
diff --git a/tests/Makefile.am b/tests/Makefile.am
index ea4bf9ca..40b6d0b1 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -7,7 +7,8 @@ check_PROGRAMS = timer/timer_test sms/sms_test ussd/ussd_test \
gb/bssgp_fc_test gb/gprs_ns_test kasumi/kasumi_test \
logging/logging_test fr/fr_test \
loggingrb/loggingrb_test strrb/strrb_test \
- vty/vty_test comp128/comp128_test utils/utils_test
+ vty/vty_test comp128/comp128_test utils/utils_test \
+ ares/ares_test
if ENABLE_MSGFILE
check_PROGRAMS += msgfile/msgfile_test
@@ -80,6 +81,8 @@ strrb_strrb_test_LDADD = $(top_builddir)/src/libosmocore.la
vty_vty_test_SOURCES = vty/vty_test.c
vty_vty_test_LDADD = $(top_builddir)/src/vty/libosmovty.la $(top_builddir)/src/libosmocore.la
+ares_ares_test_SOURCES = ares/ares_test.c
+ares_ares_test_LDADD = $(top_builddir)/src/libosmocore.la $(LIBCARES_LIBS)
# The `:;' works around a Bash 3.2 bug when the output is not writeable.
$(srcdir)/package.m4: $(top_srcdir)/configure.ac
@@ -112,7 +115,7 @@ EXTRA_DIST = testsuite.at $(srcdir)/package.m4 $(TESTSUITE) \
fr/fr_test.ok loggingrb/logging_test.ok \
loggingrb/logging_test.err strrb/strrb_test.ok \
vty/vty_test.ok comp128/comp128_test.ok \
- utils/utils_test.ok
+ utils/utils_test.ok ares/ares_test.ok
DISTCLEANFILES = atconfig
diff --git a/tests/ares/ares_test.ok b/tests/ares/ares_test.ok
new file mode 100644
index 00000000..507a6a51
--- /dev/null
+++ b/tests/ares/ares_test.ok
@@ -0,0 +1,2 @@
+Callback called: status=0, timeouts=0
+localhost.localdomain -> 127.0.0.1
diff --git a/tests/testsuite.at b/tests/testsuite.at
index 7ce2ee80..2886ae24 100644
--- a/tests/testsuite.at
+++ b/tests/testsuite.at
@@ -142,3 +142,9 @@ AT_KEYWORDS([timer])
cat $abs_srcdir/timer/timer_test.ok > expout
AT_CHECK([$abs_top_builddir/tests/timer/timer_test -s 5], [0], [expout], [ignore])
AT_CLEANUP
+
+AT_SETUP([ares])
+AT_KEYWORDS([ares])
+cat $abs_srcdir/ares/ares_test.ok > expout
+AT_CHECK([$abs_top_builddir/tests/ares/ares_test], [0], [expout], [ignore])
+AT_CLEANUP