mirror of https://github.com/getdnsapi/getdns.git
Replace mini_event extension by default_eventloop
* default_eventloop was prototyped in getdns_query and is still in there as my_eventloop * It interfaces directly with the scheduling primitives of getdns. * It can operate entirely from stack and does not have to do any memory allocations or deallocations. * Adapted configure.ac to allow libunbound to be linked with Windows (with the removal of winsock_event.c we have no symbol clashed anymore) * Added STUB_TCP_WOULDBLOCK return code in stub_resolving helper functions, to anticipate dealing with edge triggered event loops (versus level triggered). (i.e. Windows)
This commit is contained in:
parent
39f7e87f1a
commit
4fd8d3dddd
70
configure.ac
70
configure.ac
|
@ -453,45 +453,39 @@ if test "$USE_WINSOCK" = 1; then
|
||||||
AC_DEFINE_UNQUOTED([GETDNS_ON_WINDOWS], [1], [Define this to enable Windows build.])
|
AC_DEFINE_UNQUOTED([GETDNS_ON_WINDOWS], [1], [Define this to enable Windows build.])
|
||||||
AC_DEFINE_UNQUOTED([STUB_NATIVE_DNSSEC], [1])
|
AC_DEFINE_UNQUOTED([STUB_NATIVE_DNSSEC], [1])
|
||||||
LIBS="$LIBS -lgdi32 -liphlpapi"
|
LIBS="$LIBS -lgdi32 -liphlpapi"
|
||||||
my_with_libunbound=0
|
|
||||||
my_with_libidn=0
|
|
||||||
else
|
|
||||||
my_with_libidn=1
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
if test $my_with_libidn = 1
|
my_with_libidn=1
|
||||||
then
|
AC_ARG_WITH(libidn, AS_HELP_STRING([--with-libidn=pathname],
|
||||||
AC_ARG_WITH(libidn, AS_HELP_STRING([--with-libidn=pathname],
|
[path to libidn (default: search /usr/local ..)]),
|
||||||
[path to libidn (default: search /usr/local ..)]),
|
[], [withval="yes"])
|
||||||
[], [withval="yes"])
|
if test x_$withval = x_yes; then
|
||||||
if test x_$withval = x_yes; then
|
for dir in /usr/local /opt/local /usr/pkg /usr/sfw; do
|
||||||
for dir in /usr/local /opt/local /usr/pkg /usr/sfw; do
|
if test -f "$dir/include/idna.h"; then
|
||||||
if test -f "$dir/include/idna.h"; then
|
CFLAGS="$CFLAGS -I$dir/include"
|
||||||
CFLAGS="$CFLAGS -I$dir/include"
|
LDFLAGS="$LDFLAGS -L$dir/lib"
|
||||||
LDFLAGS="$LDFLAGS -L$dir/lib"
|
AC_MSG_NOTICE([Found libidn in $dir])
|
||||||
AC_MSG_NOTICE([Found libidn in $dir])
|
break
|
||||||
break
|
|
||||||
fi
|
|
||||||
if test -f "$dir/include/idn/idna.h"; then
|
|
||||||
CFLAGS="$CFLAGS -I$dir/include/idn"
|
|
||||||
LDFLAGS="$LDFLAGS -L$dir/lib"
|
|
||||||
AC_MSG_NOTICE([Found libidn in $dir])
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
if test -f "/usr/include/idn/idna.h"; then
|
|
||||||
CFLAGS="$CFLAGS -I/usr/include/idn"
|
|
||||||
#LDFLAGS="$LDFLAGS -L/usr/lib"
|
|
||||||
AC_MSG_NOTICE([Found libidn in /usr])
|
|
||||||
fi
|
fi
|
||||||
|
if test -f "$dir/include/idn/idna.h"; then
|
||||||
|
CFLAGS="$CFLAGS -I$dir/include/idn"
|
||||||
|
LDFLAGS="$LDFLAGS -L$dir/lib"
|
||||||
|
AC_MSG_NOTICE([Found libidn in $dir])
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if test -f "/usr/include/idn/idna.h"; then
|
||||||
|
CFLAGS="$CFLAGS -I/usr/include/idn"
|
||||||
|
#LDFLAGS="$LDFLAGS -L/usr/lib"
|
||||||
|
AC_MSG_NOTICE([Found libidn in /usr])
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if test x_$withval != x_no; then
|
||||||
|
CFLAGS="$CFLAGS -I$withval/include"
|
||||||
|
LDFLAGS="$LDFLAGS -L$withval/lib"
|
||||||
else
|
else
|
||||||
if test x_$withval != x_no; then
|
my_with_libidn=0
|
||||||
CFLAGS="$CFLAGS -I$withval/include"
|
|
||||||
LDFLAGS="$LDFLAGS -L$withval/lib"
|
|
||||||
else
|
|
||||||
my_with_libidn=0
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -1161,6 +1155,14 @@ const char *inet_ntop(int af, const void *src, char *dst, size_t size);
|
||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_INTTYPES_H
|
||||||
|
#include <inttypes.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PRIu64
|
||||||
|
#define PRIu64 "llu"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_ATTR_FORMAT
|
#ifdef HAVE_ATTR_FORMAT
|
||||||
# define ATTR_FORMAT(archetype, string_index, first_to_check) \
|
# define ATTR_FORMAT(archetype, string_index, first_to_check) \
|
||||||
__attribute__ ((format (archetype, string_index, first_to_check)))
|
__attribute__ ((format (archetype, string_index, first_to_check)))
|
||||||
|
|
|
@ -149,16 +149,24 @@ depend:
|
||||||
|
|
||||||
# Dependencies for the examples
|
# Dependencies for the examples
|
||||||
example-all-functions.lo example-all-functions.o: $(srcdir)/example-all-functions.c $(srcdir)/getdns_libevent.h \
|
example-all-functions.lo example-all-functions.o: $(srcdir)/example-all-functions.c $(srcdir)/getdns_libevent.h \
|
||||||
../../src/config.h ../../src/getdns/getdns.h \
|
../../src/config.h \
|
||||||
$(srcdir)/../../src/getdns/getdns_ext_libevent.h ../../src/getdns/getdns_extra.h
|
../../src/getdns/getdns.h \
|
||||||
example-reverse.lo example-reverse.o: $(srcdir)/example-reverse.c $(srcdir)/getdns_libevent.h ../../src/config.h \
|
$(srcdir)/../../src/getdns/getdns_ext_libevent.h \
|
||||||
../../src/getdns/getdns.h $(srcdir)/../../src/getdns/getdns_ext_libevent.h \
|
../../src/getdns/getdns_extra.h
|
||||||
|
example-reverse.lo example-reverse.o: $(srcdir)/example-reverse.c $(srcdir)/getdns_libevent.h \
|
||||||
|
../../src/config.h \
|
||||||
|
../../src/getdns/getdns.h \
|
||||||
|
$(srcdir)/../../src/getdns/getdns_ext_libevent.h \
|
||||||
../../src/getdns/getdns_extra.h
|
../../src/getdns/getdns_extra.h
|
||||||
example-simple-answers.lo example-simple-answers.o: $(srcdir)/example-simple-answers.c $(srcdir)/getdns_libevent.h \
|
example-simple-answers.lo example-simple-answers.o: $(srcdir)/example-simple-answers.c $(srcdir)/getdns_libevent.h \
|
||||||
../../src/config.h ../../src/getdns/getdns.h \
|
../../src/config.h \
|
||||||
$(srcdir)/../../src/getdns/getdns_ext_libevent.h ../../src/getdns/getdns_extra.h
|
../../src/getdns/getdns.h \
|
||||||
|
$(srcdir)/../../src/getdns/getdns_ext_libevent.h \
|
||||||
|
../../src/getdns/getdns_extra.h
|
||||||
example-synchronous.lo example-synchronous.o: $(srcdir)/example-synchronous.c $(srcdir)/getdns_core_only.h \
|
example-synchronous.lo example-synchronous.o: $(srcdir)/example-synchronous.c $(srcdir)/getdns_core_only.h \
|
||||||
../../src/getdns/getdns.h
|
../../src/getdns/getdns.h
|
||||||
example-tree.lo example-tree.o: $(srcdir)/example-tree.c $(srcdir)/getdns_libevent.h ../../src/config.h \
|
example-tree.lo example-tree.o: $(srcdir)/example-tree.c $(srcdir)/getdns_libevent.h \
|
||||||
../../src/getdns/getdns.h $(srcdir)/../../src/getdns/getdns_ext_libevent.h \
|
../../src/config.h \
|
||||||
|
../../src/getdns/getdns.h \
|
||||||
|
$(srcdir)/../../src/getdns/getdns_ext_libevent.h \
|
||||||
../../src/getdns/getdns_extra.h
|
../../src/getdns/getdns_extra.h
|
||||||
|
|
236
src/Makefile.in
236
src/Makefile.in
|
@ -74,9 +74,9 @@ LIBOBJDIR=
|
||||||
LIBOBJS=@LIBOBJS@
|
LIBOBJS=@LIBOBJS@
|
||||||
COMPAT_OBJ=$(LIBOBJS:.o=.lo)
|
COMPAT_OBJ=$(LIBOBJS:.o=.lo)
|
||||||
|
|
||||||
UTIL_OBJ=mini_event.lo winsock_event.lo rbtree.lo val_secalgo.lo
|
UTIL_OBJ=rbtree.lo val_secalgo.lo
|
||||||
|
|
||||||
EXTENSION_OBJ=libmini_event.lo libevent.lo libev.lo
|
EXTENSION_OBJ=default_eventloop.lo libevent.lo libev.lo
|
||||||
|
|
||||||
NON_C99_OBJS=context.lo libuv.lo
|
NON_C99_OBJS=context.lo libuv.lo
|
||||||
|
|
||||||
|
@ -144,8 +144,8 @@ libgetdns_ext_ev.la: libgetdns.la libev.lo
|
||||||
$(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) -o $@ libev.lo libgetdns.la $(LDFLAGS) $(EXTENSION_LIBEV_LDFLAGS) $(EXTENSION_LIBEV_EXT_LIBS) -rpath $(libdir) -version-info $(libversion) -no-undefined -export-symbols $(srcdir)/extension/libev.symbols
|
$(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) -o $@ libev.lo libgetdns.la $(LDFLAGS) $(EXTENSION_LIBEV_LDFLAGS) $(EXTENSION_LIBEV_EXT_LIBS) -rpath $(libdir) -version-info $(libversion) -no-undefined -export-symbols $(srcdir)/extension/libev.symbols
|
||||||
|
|
||||||
|
|
||||||
libgetdns.la: $(GETDNS_OBJ) version.lo context.lo libmini_event.lo $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ)
|
libgetdns.la: $(GETDNS_OBJ) version.lo context.lo default_eventloop.lo $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ)
|
||||||
$(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) -o $@ $(GETDNS_OBJ) version.lo context.lo libmini_event.lo $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(LDFLAGS) -rpath $(libdir) -version-info $(libversion) -no-undefined -export-symbols $(srcdir)/libgetdns.symbols
|
$(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) -o $@ $(GETDNS_OBJ) version.lo context.lo default_eventloop.lo $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(LDFLAGS) -rpath $(libdir) -version-info $(libversion) -no-undefined -export-symbols $(srcdir)/libgetdns.symbols
|
||||||
|
|
||||||
|
|
||||||
test: all
|
test: all
|
||||||
|
@ -225,114 +225,136 @@ depend:
|
||||||
FORCE:
|
FORCE:
|
||||||
|
|
||||||
# Dependencies for gldns, utils, the extensions and compat functions
|
# Dependencies for gldns, utils, the extensions and compat functions
|
||||||
const-info.lo const-info.o: $(srcdir)/const-info.c getdns/getdns.h getdns/getdns_extra.h \
|
const-info.lo const-info.o: $(srcdir)/const-info.c getdns/getdns.h \
|
||||||
getdns/getdns.h $(srcdir)/const-info.h
|
getdns/getdns_extra.h $(srcdir)/const-info.h
|
||||||
context.lo context.o: $(srcdir)/context.c config.h $(srcdir)/debug.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \
|
context.lo context.o: $(srcdir)/context.c config.h $(srcdir)/debug.h \
|
||||||
$(srcdir)/gldns/wire2str.h $(srcdir)/context.h getdns/getdns.h getdns/getdns_extra.h \
|
$(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/context.h \
|
||||||
getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/libmini_event.h \
|
getdns/getdns.h \
|
||||||
config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h $(srcdir)/types-internal.h \
|
getdns/getdns_extra.h $(srcdir)/types-internal.h \
|
||||||
$(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \
|
$(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h \
|
||||||
$(srcdir)/dnssec.h $(srcdir)/stub.h $(srcdir)/list.h $(srcdir)/dict.h $(srcdir)/pubkey-pinning.h
|
$(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/stub.h $(srcdir)/list.h $(srcdir)/dict.h \
|
||||||
convert.lo convert.o: $(srcdir)/convert.c config.h getdns/getdns.h getdns/getdns_extra.h \
|
$(srcdir)/pubkey-pinning.h
|
||||||
getdns/getdns.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \
|
convert.lo convert.o: $(srcdir)/convert.c config.h \
|
||||||
$(srcdir)/extension/libmini_event.h config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \
|
getdns/getdns.h \
|
||||||
$(srcdir)/types-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \
|
getdns/getdns_extra.h $(srcdir)/util-internal.h \
|
||||||
$(srcdir)/gldns/wire2str.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/convert.h
|
$(srcdir)/context.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h \
|
||||||
dict.lo dict.o: $(srcdir)/dict.c config.h $(srcdir)/types-internal.h getdns/getdns.h \
|
$(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/wire2str.h \
|
||||||
getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h \
|
$(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/convert.h
|
||||||
$(srcdir)/context.h $(srcdir)/extension/libmini_event.h config.h $(srcdir)/util/mini_event.h \
|
dict.lo dict.o: $(srcdir)/dict.c config.h $(srcdir)/types-internal.h \
|
||||||
$(srcdir)/util/rbtree.h $(srcdir)/types-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
|
getdns/getdns.h \
|
||||||
$(srcdir)/gldns/pkthdr.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/const-info.h $(srcdir)/gldns/wire2str.h
|
getdns/getdns_extra.h $(srcdir)/util/rbtree.h \
|
||||||
dnssec.lo dnssec.o: $(srcdir)/dnssec.c config.h $(srcdir)/debug.h getdns/getdns.h $(srcdir)/context.h \
|
$(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h $(srcdir)/rr-iter.h \
|
||||||
getdns/getdns_extra.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \
|
$(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/const-info.h \
|
||||||
$(srcdir)/extension/libmini_event.h config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \
|
$(srcdir)/gldns/wire2str.h
|
||||||
$(srcdir)/types-internal.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
|
dnssec.lo dnssec.o: $(srcdir)/dnssec.c config.h $(srcdir)/debug.h \
|
||||||
$(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h \
|
getdns/getdns.h $(srcdir)/context.h \
|
||||||
$(srcdir)/gldns/keyraw.h $(srcdir)/gldns/parseutil.h $(srcdir)/general.h $(srcdir)/dict.h $(srcdir)/list.h \
|
getdns/getdns_extra.h $(srcdir)/types-internal.h \
|
||||||
$(srcdir)/util/val_secalgo.h
|
$(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h \
|
||||||
general.lo general.o: $(srcdir)/general.c config.h $(srcdir)/gldns/wire2str.h $(srcdir)/context.h getdns/getdns.h \
|
$(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/str2wire.h \
|
||||||
getdns/getdns_extra.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \
|
$(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/parseutil.h \
|
||||||
$(srcdir)/extension/libmini_event.h config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \
|
$(srcdir)/general.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/util/val_secalgo.h
|
||||||
$(srcdir)/types-internal.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
|
general.lo general.o: $(srcdir)/general.c config.h $(srcdir)/general.h \
|
||||||
$(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/stub.h $(srcdir)/general.h
|
getdns/getdns.h $(srcdir)/types-internal.h \
|
||||||
list.lo list.o: $(srcdir)/list.c $(srcdir)/types-internal.h getdns/getdns.h getdns/getdns_extra.h \
|
getdns/getdns_extra.h $(srcdir)/util/rbtree.h \
|
||||||
getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h config.h $(srcdir)/context.h \
|
$(srcdir)/gldns/wire2str.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h $(srcdir)/util-internal.h \
|
||||||
$(srcdir)/extension/libmini_event.h config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \
|
$(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/stub.h \
|
||||||
$(srcdir)/types-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \
|
$(srcdir)/dict.h
|
||||||
$(srcdir)/list.h $(srcdir)/dict.h
|
list.lo list.o: $(srcdir)/list.c $(srcdir)/types-internal.h \
|
||||||
pubkey-pinning.lo pubkey-pinning.o: $(srcdir)/pubkey-pinning.c config.h $(srcdir)/debug.h getdns/getdns.h \
|
getdns/getdns.h \
|
||||||
$(srcdir)/context.h getdns/getdns.h getdns/getdns_extra.h $(srcdir)/types-internal.h \
|
getdns/getdns_extra.h $(srcdir)/util/rbtree.h \
|
||||||
$(srcdir)/util/rbtree.h $(srcdir)/extension/libmini_event.h config.h $(srcdir)/util/mini_event.h \
|
$(srcdir)/util-internal.h config.h $(srcdir)/context.h \
|
||||||
$(srcdir)/util/rbtree.h $(srcdir)/types-internal.h
|
$(srcdir)/extension/default_eventloop.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
|
||||||
request-internal.lo request-internal.o: $(srcdir)/request-internal.c config.h $(srcdir)/types-internal.h \
|
$(srcdir)/gldns/pkthdr.h $(srcdir)/list.h $(srcdir)/dict.h
|
||||||
getdns/getdns.h getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \
|
pubkey-pinning.lo pubkey-pinning.o: $(srcdir)/pubkey-pinning.c config.h \
|
||||||
$(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/libmini_event.h config.h \
|
$(srcdir)/debug.h getdns/getdns.h $(srcdir)/context.h \
|
||||||
$(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h $(srcdir)/types-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \
|
getdns/getdns_extra.h $(srcdir)/types-internal.h \
|
||||||
$(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h \
|
$(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h
|
||||||
|
request-internal.lo request-internal.o: $(srcdir)/request-internal.c \
|
||||||
|
config.h $(srcdir)/types-internal.h \
|
||||||
|
getdns/getdns.h \
|
||||||
|
getdns/getdns_extra.h $(srcdir)/util/rbtree.h \
|
||||||
|
$(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h $(srcdir)/rr-iter.h \
|
||||||
|
$(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h \
|
||||||
$(srcdir)/gldns/rrdef.h $(srcdir)/dict.h $(srcdir)/debug.h
|
$(srcdir)/gldns/rrdef.h $(srcdir)/dict.h $(srcdir)/debug.h
|
||||||
rr-dict.lo rr-dict.o: $(srcdir)/rr-dict.c $(srcdir)/rr-dict.h config.h getdns/getdns.h $(srcdir)/gldns/gbuffer.h \
|
rr-dict.lo rr-dict.o: $(srcdir)/rr-dict.c $(srcdir)/rr-dict.h config.h \
|
||||||
$(srcdir)/util-internal.h $(srcdir)/context.h getdns/getdns_extra.h getdns/getdns.h \
|
getdns/getdns.h $(srcdir)/gldns/gbuffer.h \
|
||||||
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/libmini_event.h config.h \
|
$(srcdir)/util-internal.h $(srcdir)/context.h \
|
||||||
$(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h $(srcdir)/types-internal.h $(srcdir)/rr-iter.h \
|
getdns/getdns_extra.h $(srcdir)/types-internal.h \
|
||||||
$(srcdir)/gldns/pkthdr.h $(srcdir)/dict.h
|
$(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h $(srcdir)/rr-iter.h $(srcdir)/gldns/pkthdr.h \
|
||||||
rr-iter.lo rr-iter.o: $(srcdir)/rr-iter.c $(srcdir)/rr-iter.h getdns/getdns.h $(srcdir)/rr-dict.h config.h \
|
$(srcdir)/dict.h
|
||||||
$(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h
|
rr-iter.lo rr-iter.o: $(srcdir)/rr-iter.c $(srcdir)/rr-iter.h \
|
||||||
stub.lo stub.o: $(srcdir)/stub.c config.h $(srcdir)/debug.h $(srcdir)/stub.h getdns/getdns.h $(srcdir)/types-internal.h \
|
getdns/getdns.h $(srcdir)/rr-dict.h \
|
||||||
getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/gldns/gbuffer.h \
|
config.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \
|
||||||
$(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \
|
$(srcdir)/gldns/rrdef.h
|
||||||
$(srcdir)/gldns/wire2str.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/context.h $(srcdir)/extension/libmini_event.h \
|
stub.lo stub.o: $(srcdir)/stub.c config.h $(srcdir)/debug.h $(srcdir)/stub.h \
|
||||||
config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h $(srcdir)/types-internal.h \
|
getdns/getdns.h $(srcdir)/types-internal.h \
|
||||||
$(srcdir)/util-internal.h $(srcdir)/general.h $(srcdir)/pubkey-pinning.h
|
getdns/getdns_extra.h $(srcdir)/util/rbtree.h \
|
||||||
sync.lo sync.o: $(srcdir)/sync.c getdns/getdns.h config.h $(srcdir)/context.h getdns/getdns_extra.h \
|
$(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h \
|
||||||
getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/libmini_event.h \
|
$(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/context.h \
|
||||||
config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h $(srcdir)/types-internal.h $(srcdir)/general.h \
|
$(srcdir)/extension/default_eventloop.h $(srcdir)/util-internal.h $(srcdir)/general.h $(srcdir)/pubkey-pinning.h
|
||||||
$(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \
|
sync.lo sync.o: $(srcdir)/sync.c getdns/getdns.h \
|
||||||
$(srcdir)/dnssec.h $(srcdir)/stub.h $(srcdir)/gldns/wire2str.h
|
config.h $(srcdir)/context.h \
|
||||||
util-internal.lo util-internal.o: $(srcdir)/util-internal.c config.h getdns/getdns.h $(srcdir)/dict.h \
|
getdns/getdns_extra.h $(srcdir)/types-internal.h \
|
||||||
$(srcdir)/util/rbtree.h $(srcdir)/types-internal.h getdns/getdns_extra.h getdns/getdns.h \
|
$(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h $(srcdir)/general.h $(srcdir)/util-internal.h \
|
||||||
$(srcdir)/list.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/libmini_event.h config.h \
|
$(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/stub.h \
|
||||||
$(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h $(srcdir)/types-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \
|
$(srcdir)/gldns/wire2str.h
|
||||||
$(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h
|
util-internal.lo util-internal.o: $(srcdir)/util-internal.c config.h \
|
||||||
version.lo version.o: version.c
|
getdns/getdns.h $(srcdir)/dict.h $(srcdir)/util/rbtree.h \
|
||||||
gbuffer.lo gbuffer.o: $(srcdir)/gldns/gbuffer.c config.h $(srcdir)/gldns/gbuffer.h
|
$(srcdir)/types-internal.h getdns/getdns_extra.h \
|
||||||
keyraw.lo keyraw.o: $(srcdir)/gldns/keyraw.c config.h $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/rrdef.h
|
$(srcdir)/list.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h $(srcdir)/rr-iter.h \
|
||||||
parse.lo parse.o: $(srcdir)/gldns/parse.c config.h $(srcdir)/gldns/parse.h $(srcdir)/gldns/parseutil.h \
|
$(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h
|
||||||
|
gbuffer.lo gbuffer.o: $(srcdir)/gldns/gbuffer.c config.h \
|
||||||
$(srcdir)/gldns/gbuffer.h
|
$(srcdir)/gldns/gbuffer.h
|
||||||
parseutil.lo parseutil.o: $(srcdir)/gldns/parseutil.c config.h $(srcdir)/gldns/parseutil.h
|
keyraw.lo keyraw.o: $(srcdir)/gldns/keyraw.c config.h \
|
||||||
rrdef.lo rrdef.o: $(srcdir)/gldns/rrdef.c config.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/parseutil.h
|
$(srcdir)/gldns/keyraw.h $(srcdir)/gldns/rrdef.h
|
||||||
str2wire.lo str2wire.o: $(srcdir)/gldns/str2wire.c config.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \
|
parse.lo parse.o: $(srcdir)/gldns/parse.c config.h \
|
||||||
$(srcdir)/gldns/wire2str.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/parse.h $(srcdir)/gldns/parseutil.h
|
$(srcdir)/gldns/parse.h $(srcdir)/gldns/parseutil.h $(srcdir)/gldns/gbuffer.h
|
||||||
wire2str.lo wire2str.o: $(srcdir)/gldns/wire2str.c config.h $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/str2wire.h \
|
parseutil.lo parseutil.o: $(srcdir)/gldns/parseutil.c config.h \
|
||||||
$(srcdir)/gldns/rrdef.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/parseutil.h $(srcdir)/gldns/gbuffer.h \
|
$(srcdir)/gldns/parseutil.h
|
||||||
$(srcdir)/gldns/keyraw.h
|
rrdef.lo rrdef.o: $(srcdir)/gldns/rrdef.c config.h \
|
||||||
|
$(srcdir)/gldns/rrdef.h $(srcdir)/gldns/parseutil.h
|
||||||
|
str2wire.lo str2wire.o: $(srcdir)/gldns/str2wire.c config.h \
|
||||||
|
$(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/gbuffer.h \
|
||||||
|
$(srcdir)/gldns/parse.h $(srcdir)/gldns/parseutil.h
|
||||||
|
wire2str.lo wire2str.o: $(srcdir)/gldns/wire2str.c config.h \
|
||||||
|
$(srcdir)/gldns/wire2str.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/pkthdr.h \
|
||||||
|
$(srcdir)/gldns/parseutil.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/keyraw.h
|
||||||
arc4_lock.lo arc4_lock.o: $(srcdir)/compat/arc4_lock.c config.h
|
arc4_lock.lo arc4_lock.o: $(srcdir)/compat/arc4_lock.c config.h
|
||||||
arc4random.lo arc4random.o: $(srcdir)/compat/arc4random.c config.h $(srcdir)/compat/chacha_private.h
|
arc4random.lo arc4random.o: $(srcdir)/compat/arc4random.c config.h \
|
||||||
arc4random_uniform.lo arc4random_uniform.o: $(srcdir)/compat/arc4random_uniform.c config.h
|
$(srcdir)/compat/chacha_private.h
|
||||||
explicit_bzero.lo explicit_bzero.o: $(srcdir)/compat/explicit_bzero.c config.h
|
arc4random_uniform.lo arc4random_uniform.o: $(srcdir)/compat/arc4random_uniform.c \
|
||||||
getentropy_linux.lo getentropy_linux.o: $(srcdir)/compat/getentropy_linux.c config.h
|
config.h
|
||||||
getentropy_osx.lo getentropy_osx.o: $(srcdir)/compat/getentropy_osx.c config.h
|
explicit_bzero.lo explicit_bzero.o: $(srcdir)/compat/explicit_bzero.c \
|
||||||
getentropy_solaris.lo getentropy_solaris.o: $(srcdir)/compat/getentropy_solaris.c config.h
|
config.h
|
||||||
|
getentropy_linux.lo getentropy_linux.o: $(srcdir)/compat/getentropy_linux.c \
|
||||||
|
config.h
|
||||||
|
getentropy_osx.lo getentropy_osx.o: $(srcdir)/compat/getentropy_osx.c \
|
||||||
|
config.h
|
||||||
|
getentropy_solaris.lo getentropy_solaris.o: $(srcdir)/compat/getentropy_solaris.c \
|
||||||
|
config.h
|
||||||
getentropy_win.lo getentropy_win.o: $(srcdir)/compat/getentropy_win.c
|
getentropy_win.lo getentropy_win.o: $(srcdir)/compat/getentropy_win.c
|
||||||
inet_ntop.lo inet_ntop.o: $(srcdir)/compat/inet_ntop.c config.h
|
inet_ntop.lo inet_ntop.o: $(srcdir)/compat/inet_ntop.c config.h
|
||||||
inet_pton.lo inet_pton.o: $(srcdir)/compat/inet_pton.c config.h
|
inet_pton.lo inet_pton.o: $(srcdir)/compat/inet_pton.c config.h
|
||||||
sha512.lo sha512.o: $(srcdir)/compat/sha512.c config.h
|
sha512.lo sha512.o: $(srcdir)/compat/sha512.c config.h
|
||||||
strlcpy.lo strlcpy.o: $(srcdir)/compat/strlcpy.c config.h
|
strlcpy.lo strlcpy.o: $(srcdir)/compat/strlcpy.c config.h
|
||||||
mini_event.lo mini_event.o: $(srcdir)/util/mini_event.c config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \
|
rbtree.lo rbtree.o: $(srcdir)/util/rbtree.c config.h $(srcdir)/util/log.h \
|
||||||
$(srcdir)/util/fptr_wlist.h
|
$(srcdir)/debug.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/rbtree.h
|
||||||
rbtree.lo rbtree.o: $(srcdir)/util/rbtree.c config.h $(srcdir)/util/log.h $(srcdir)/debug.h config.h \
|
val_secalgo.lo val_secalgo.o: $(srcdir)/util/val_secalgo.c config.h \
|
||||||
$(srcdir)/util/fptr_wlist.h $(srcdir)/util/rbtree.h
|
$(srcdir)/util/val_secalgo.h $(srcdir)/util/log.h $(srcdir)/debug.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/keyraw.h \
|
||||||
val_secalgo.lo val_secalgo.o: $(srcdir)/util/val_secalgo.c config.h $(srcdir)/util/val_secalgo.h $(srcdir)/util/log.h \
|
$(srcdir)/gldns/gbuffer.h
|
||||||
$(srcdir)/debug.h config.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/gbuffer.h
|
default_eventloop.lo default_eventloop.o: $(srcdir)/extension/default_eventloop.c \
|
||||||
winsock_event.lo winsock_event.o: $(srcdir)/util/winsock_event.c config.h
|
$(srcdir)/extension/default_eventloop.h config.h \
|
||||||
libev.lo libev.o: $(srcdir)/extension/libev.c config.h $(srcdir)/types-internal.h getdns/getdns.h \
|
getdns/getdns.h \
|
||||||
getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \
|
getdns/getdns_extra.h $(srcdir)/debug.h
|
||||||
$(srcdir)/getdns/getdns_ext_libev.h getdns/getdns_extra.h
|
libev.lo libev.o: $(srcdir)/extension/libev.c config.h \
|
||||||
libevent.lo libevent.o: $(srcdir)/extension/libevent.c config.h $(srcdir)/types-internal.h \
|
$(srcdir)/types-internal.h getdns/getdns.h \
|
||||||
getdns/getdns.h getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \
|
getdns/getdns_extra.h $(srcdir)/util/rbtree.h \
|
||||||
$(srcdir)/getdns/getdns_ext_libevent.h getdns/getdns_extra.h
|
$(srcdir)/getdns/getdns_ext_libev.h
|
||||||
libmini_event.lo libmini_event.o: $(srcdir)/extension/libmini_event.c config.h $(srcdir)/debug.h config.h \
|
libevent.lo libevent.o: $(srcdir)/extension/libevent.c config.h \
|
||||||
$(srcdir)/types-internal.h getdns/getdns.h getdns/getdns_extra.h getdns/getdns.h \
|
$(srcdir)/types-internal.h getdns/getdns.h \
|
||||||
$(srcdir)/util/rbtree.h $(srcdir)/extension/libmini_event.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h
|
getdns/getdns_extra.h $(srcdir)/util/rbtree.h \
|
||||||
libuv.lo libuv.o: $(srcdir)/extension/libuv.c config.h $(srcdir)/debug.h config.h $(srcdir)/types-internal.h \
|
$(srcdir)/getdns/getdns_ext_libevent.h
|
||||||
getdns/getdns.h getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \
|
libuv.lo libuv.o: $(srcdir)/extension/libuv.c config.h $(srcdir)/debug.h \
|
||||||
$(srcdir)/getdns/getdns_ext_libuv.h getdns/getdns_extra.h
|
$(srcdir)/types-internal.h getdns/getdns.h \
|
||||||
|
getdns/getdns_extra.h $(srcdir)/util/rbtree.h \
|
||||||
|
$(srcdir)/getdns/getdns_ext_libuv.h
|
||||||
|
|
|
@ -966,6 +966,9 @@ getdns_context_create_with_extended_memory_functions(
|
||||||
struct getdns_context *result = NULL;
|
struct getdns_context *result = NULL;
|
||||||
mf_union mf;
|
mf_union mf;
|
||||||
gldns_buffer gbuf;
|
gldns_buffer gbuf;
|
||||||
|
#ifdef USE_WINSOCK
|
||||||
|
WORD wVersionRequested;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!context || !malloc || !realloc || !free)
|
if (!context || !malloc || !realloc || !free)
|
||||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||||
|
@ -979,6 +982,14 @@ getdns_context_create_with_extended_memory_functions(
|
||||||
if (!result)
|
if (!result)
|
||||||
return GETDNS_RETURN_MEMORY_ERROR;
|
return GETDNS_RETURN_MEMORY_ERROR;
|
||||||
|
|
||||||
|
#ifdef USE_WINSOCK
|
||||||
|
/* We need to run WSAStartup() to be able to use getaddrinfo() */
|
||||||
|
wVersionRequested = MAKEWORD(2, 2);
|
||||||
|
if (WSAStartup(wVersionRequested, &result->wsaData)) {
|
||||||
|
r = GETDNS_RETURN_GENERIC_ERROR;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
result->processing = 0;
|
result->processing = 0;
|
||||||
result->destroying = 0;
|
result->destroying = 0;
|
||||||
result->my_mf.mf_arg = userarg;
|
result->my_mf.mf_arg = userarg;
|
||||||
|
@ -1050,9 +1061,8 @@ getdns_context_create_with_extended_memory_functions(
|
||||||
result->tls_query_padding_blocksize = 1; /* default is to not try to pad */
|
result->tls_query_padding_blocksize = 1; /* default is to not try to pad */
|
||||||
result-> tls_ctx = NULL;
|
result-> tls_ctx = NULL;
|
||||||
|
|
||||||
result->extension = &result->mini_event.loop;
|
result->extension = &result->default_eventloop.loop;
|
||||||
if ((r = _getdns_mini_event_init(result, &result->mini_event)))
|
_getdns_default_eventloop_init(&result->default_eventloop);
|
||||||
goto error;
|
|
||||||
|
|
||||||
result->fchg_resolvconf = NULL;
|
result->fchg_resolvconf = NULL;
|
||||||
result->fchg_hosts = NULL;
|
result->fchg_hosts = NULL;
|
||||||
|
@ -1198,6 +1208,9 @@ getdns_context_destroy(struct getdns_context *context)
|
||||||
_getdns_traverse_postorder(&context->local_hosts,
|
_getdns_traverse_postorder(&context->local_hosts,
|
||||||
destroy_local_host, context);
|
destroy_local_host, context);
|
||||||
|
|
||||||
|
#ifdef USE_WINSOCK
|
||||||
|
WSACleanup();
|
||||||
|
#endif
|
||||||
GETDNS_FREE(context->my_mf, context);
|
GETDNS_FREE(context->my_mf, context);
|
||||||
} /* getdns_context_destroy */
|
} /* getdns_context_destroy */
|
||||||
|
|
||||||
|
@ -2798,55 +2811,36 @@ _getdns_bindata_destroy(struct mem_funcs *mfs,
|
||||||
|
|
||||||
/* TODO: Remove next_timeout argument from getdns_context_get_num_pending_requests
|
/* TODO: Remove next_timeout argument from getdns_context_get_num_pending_requests
|
||||||
*/
|
*/
|
||||||
void _getdns_handle_timeouts(struct _getdns_event_base* base, struct timeval* now,
|
|
||||||
struct timeval* wait);
|
|
||||||
uint32_t
|
uint32_t
|
||||||
getdns_context_get_num_pending_requests(struct getdns_context* context,
|
getdns_context_get_num_pending_requests(getdns_context* context,
|
||||||
struct timeval* next_timeout)
|
struct timeval* next_timeout)
|
||||||
{
|
{
|
||||||
struct timeval dispose;
|
(void)next_timeout;
|
||||||
|
|
||||||
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
|
if (!context)
|
||||||
|
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||||
|
|
||||||
if (context->outbound_requests.count)
|
if (context->outbound_requests.count)
|
||||||
context->extension->vmt->run_once(context->extension, 0);
|
context->extension->vmt->run_once(context->extension, 0);
|
||||||
|
|
||||||
/* TODO: Remove this when next_timeout is gone */
|
|
||||||
if (context->extension == &context->mini_event.loop)
|
|
||||||
_getdns_handle_timeouts(context->mini_event.base,
|
|
||||||
&context->mini_event.time_tv,
|
|
||||||
next_timeout ? next_timeout : &dispose);
|
|
||||||
|
|
||||||
return context->outbound_requests.count;
|
return context->outbound_requests.count;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* process async reqs */
|
/* process async reqs */
|
||||||
getdns_return_t
|
getdns_return_t
|
||||||
getdns_context_process_async(struct getdns_context* context)
|
getdns_context_process_async(getdns_context *context)
|
||||||
{
|
{
|
||||||
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
|
if (!context)
|
||||||
|
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||||
|
|
||||||
#ifdef HAVE_LIBUNBOUND
|
|
||||||
if (ub_poll(context->unbound_ctx) && ub_process(context->unbound_ctx)){
|
|
||||||
/* need an async return code? */
|
|
||||||
return GETDNS_RETURN_GENERIC_ERROR;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
context->extension->vmt->run_once(context->extension, 0);
|
context->extension->vmt->run_once(context->extension, 0);
|
||||||
|
|
||||||
return GETDNS_RETURN_GOOD;
|
return GETDNS_RETURN_GOOD;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
getdns_context_run(getdns_context *context)
|
getdns_context_run(getdns_context *context)
|
||||||
{
|
{
|
||||||
if (context->extension == &context->mini_event.loop) {
|
context->extension->vmt->run(context->extension);
|
||||||
if (getdns_context_get_num_pending_requests(context, NULL) > 0 &&
|
|
||||||
!getdns_context_process_async(context))
|
|
||||||
context->extension->vmt->run(context->extension);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
context->extension->vmt->run(context->extension);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct timeout_accumulator {
|
typedef struct timeout_accumulator {
|
||||||
|
@ -2891,8 +2885,9 @@ getdns_context_detach_eventloop(struct getdns_context* context)
|
||||||
/* cancel all outstanding requests */
|
/* cancel all outstanding requests */
|
||||||
cancel_outstanding_requests(context, 1);
|
cancel_outstanding_requests(context, 1);
|
||||||
context->extension->vmt->cleanup(context->extension);
|
context->extension->vmt->cleanup(context->extension);
|
||||||
context->extension = &context->mini_event.loop;
|
context->extension = &context->default_eventloop.loop;
|
||||||
return _getdns_mini_event_init(context, &context->mini_event);
|
_getdns_default_eventloop_init(&context->default_eventloop);
|
||||||
|
return GETDNS_RETURN_GOOD;
|
||||||
}
|
}
|
||||||
|
|
||||||
getdns_return_t
|
getdns_return_t
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
#include "getdns/getdns_extra.h"
|
#include "getdns/getdns_extra.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "types-internal.h"
|
#include "types-internal.h"
|
||||||
#include "extension/libmini_event.h"
|
#include "extension/default_eventloop.h"
|
||||||
#include "util/rbtree.h"
|
#include "util/rbtree.h"
|
||||||
|
|
||||||
struct getdns_dns_req;
|
struct getdns_dns_req;
|
||||||
|
@ -245,7 +245,7 @@ struct getdns_context {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* The default extension */
|
/* The default extension */
|
||||||
_getdns_mini_event mini_event;
|
_getdns_default_eventloop default_eventloop;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* state data used to detect changes to the system config files
|
* state data used to detect changes to the system config files
|
||||||
|
@ -255,6 +255,10 @@ struct getdns_context {
|
||||||
|
|
||||||
uint8_t trust_anchors_spc[1024];
|
uint8_t trust_anchors_spc[1024];
|
||||||
|
|
||||||
|
#ifdef USE_WINSOCK
|
||||||
|
/* We need to run WSAStartup() to be able to use getaddrinfo() */
|
||||||
|
WSADATA wsaData;
|
||||||
|
#endif
|
||||||
}; /* getdns_context */
|
}; /* getdns_context */
|
||||||
|
|
||||||
/** internal functions **/
|
/** internal functions **/
|
||||||
|
|
|
@ -0,0 +1,281 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2013, NLNet Labs, Verisign, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the names of the copyright holders nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "extension/default_eventloop.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
static uint64_t get_now_plus(uint64_t amount)
|
||||||
|
{
|
||||||
|
struct timeval tv;
|
||||||
|
uint64_t now;
|
||||||
|
|
||||||
|
if (gettimeofday(&tv, NULL)) {
|
||||||
|
perror("gettimeofday() failed");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
now = tv.tv_sec * 1000000 + tv.tv_usec;
|
||||||
|
|
||||||
|
return (now + amount * 1000) >= now ? now + amount * 1000 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static getdns_return_t
|
||||||
|
default_eventloop_schedule(getdns_eventloop *loop,
|
||||||
|
int fd, uint64_t timeout, getdns_eventloop_event *event)
|
||||||
|
{
|
||||||
|
_getdns_default_eventloop *default_loop = (_getdns_default_eventloop *)loop;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
DEBUG_SCHED( "%s(loop: %p, fd: %d, timeout: %"PRIu64", event: %p, FD_SETSIZE: %d)\n"
|
||||||
|
, __FUNCTION__, loop, fd, timeout, event, FD_SETSIZE);
|
||||||
|
|
||||||
|
if (!loop || !event)
|
||||||
|
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
if (fd >= FD_SETSIZE) {
|
||||||
|
DEBUG_SCHED( "ERROR: fd %d >= FD_SETSIZE: %d!\n"
|
||||||
|
, fd, FD_SETSIZE);
|
||||||
|
return GETDNS_RETURN_GENERIC_ERROR;
|
||||||
|
}
|
||||||
|
if (fd >= 0) {
|
||||||
|
if (!(event->read_cb || event->write_cb)) {
|
||||||
|
DEBUG_SCHED("ERROR: fd event without "
|
||||||
|
"read or write cb!\n");
|
||||||
|
return GETDNS_RETURN_GENERIC_ERROR;
|
||||||
|
}
|
||||||
|
#if defined(SCHED_DEBUG) && SCHED_DEBUG
|
||||||
|
if (default_loop->fd_events[fd]) {
|
||||||
|
DEBUG_SCHED( "ERROR: Event present at fd slot: %p!\n"
|
||||||
|
, default_loop->fd_events[fd]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
default_loop->fd_events[fd] = event;
|
||||||
|
default_loop->fd_timeout_times[fd] = get_now_plus(timeout);
|
||||||
|
event->ev = (void *) (intptr_t) fd + 1;
|
||||||
|
|
||||||
|
DEBUG_SCHED( "scheduled read/write at %d\n", fd);
|
||||||
|
return GETDNS_RETURN_GOOD;
|
||||||
|
}
|
||||||
|
if (!event->timeout_cb) {
|
||||||
|
DEBUG_SCHED("ERROR: fd < 0 without timeout_cb!\n");
|
||||||
|
return GETDNS_RETURN_GENERIC_ERROR;
|
||||||
|
}
|
||||||
|
if (event->read_cb) {
|
||||||
|
DEBUG_SCHED("ERROR: timeout event with read_cb! Clearing.\n");
|
||||||
|
event->read_cb = NULL;
|
||||||
|
}
|
||||||
|
if (event->write_cb) {
|
||||||
|
DEBUG_SCHED("ERROR: timeout event with write_cb! Clearing.\n");
|
||||||
|
event->write_cb = NULL;
|
||||||
|
}
|
||||||
|
for (i = 0; i < MAX_TIMEOUTS; i++) {
|
||||||
|
if (default_loop->timeout_events[i] == NULL) {
|
||||||
|
default_loop->timeout_events[i] = event;
|
||||||
|
default_loop->timeout_times[i] = get_now_plus(timeout);
|
||||||
|
event->ev = (void *) (intptr_t) i + 1;
|
||||||
|
|
||||||
|
DEBUG_SCHED( "scheduled timeout at %d\n", (int)i);
|
||||||
|
return GETDNS_RETURN_GOOD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DEBUG_SCHED("ERROR: Out of timeout slots!\n");
|
||||||
|
return GETDNS_RETURN_GENERIC_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static getdns_return_t
|
||||||
|
default_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event)
|
||||||
|
{
|
||||||
|
_getdns_default_eventloop *default_loop = (_getdns_default_eventloop *)loop;
|
||||||
|
ssize_t i;
|
||||||
|
|
||||||
|
if (!loop || !event)
|
||||||
|
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
DEBUG_SCHED( "%s(loop: %p, event: %p)\n", __FUNCTION__, loop, event);
|
||||||
|
|
||||||
|
i = (intptr_t)event->ev - 1;
|
||||||
|
if (i < 0 || i > FD_SETSIZE) {
|
||||||
|
return GETDNS_RETURN_GENERIC_ERROR;
|
||||||
|
}
|
||||||
|
if (event->timeout_cb && !event->read_cb && !event->write_cb) {
|
||||||
|
#if defined(SCHED_DEBUG) && SCHED_DEBUG
|
||||||
|
if (default_loop->timeout_events[i] != event)
|
||||||
|
DEBUG_SCHED( "ERROR: Different/wrong event present at "
|
||||||
|
"timeout slot: %p!\n"
|
||||||
|
, default_loop->timeout_events[i]);
|
||||||
|
#endif
|
||||||
|
default_loop->timeout_events[i] = NULL;
|
||||||
|
} else {
|
||||||
|
#if defined(SCHED_DEBUG) && SCHED_DEBUG
|
||||||
|
if (default_loop->fd_events[i] != event)
|
||||||
|
DEBUG_SCHED( "ERROR: Different/wrong event present at "
|
||||||
|
"fd slot: %p!\n"
|
||||||
|
, default_loop->fd_events[i]);
|
||||||
|
#endif
|
||||||
|
default_loop->fd_events[i] = NULL;
|
||||||
|
}
|
||||||
|
event->ev = NULL;
|
||||||
|
return GETDNS_RETURN_GOOD;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
default_eventloop_cleanup(getdns_eventloop *loop)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
default_read_cb(int fd, getdns_eventloop_event *event)
|
||||||
|
{
|
||||||
|
DEBUG_SCHED( "%s(fd: %d, event: %p)\n", __FUNCTION__, fd, event);
|
||||||
|
event->read_cb(event->userarg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
default_write_cb(int fd, getdns_eventloop_event *event)
|
||||||
|
{
|
||||||
|
DEBUG_SCHED( "%s(fd: %d, event: %p)\n", __FUNCTION__, fd, event);
|
||||||
|
event->write_cb(event->userarg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
default_timeout_cb(int fd, getdns_eventloop_event *event)
|
||||||
|
{
|
||||||
|
DEBUG_SCHED( "%s(fd: %d, event: %p)\n", __FUNCTION__, fd, event);
|
||||||
|
event->timeout_cb(event->userarg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
default_eventloop_run_once(getdns_eventloop *loop, int blocking)
|
||||||
|
{
|
||||||
|
_getdns_default_eventloop *default_loop = (_getdns_default_eventloop *)loop;
|
||||||
|
|
||||||
|
fd_set readfds, writefds;
|
||||||
|
int fd, max_fd = -1;
|
||||||
|
uint64_t now, timeout = (uint64_t)-1;
|
||||||
|
size_t i;
|
||||||
|
struct timeval tv;
|
||||||
|
|
||||||
|
if (!loop)
|
||||||
|
return;
|
||||||
|
|
||||||
|
FD_ZERO(&readfds);
|
||||||
|
FD_ZERO(&writefds);
|
||||||
|
now = get_now_plus(0);
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_TIMEOUTS; i++) {
|
||||||
|
if (!default_loop->timeout_events[i])
|
||||||
|
continue;
|
||||||
|
if (now > default_loop->timeout_times[i])
|
||||||
|
default_timeout_cb(-1, default_loop->timeout_events[i]);
|
||||||
|
else if (default_loop->timeout_times[i] < timeout)
|
||||||
|
timeout = default_loop->timeout_times[i];
|
||||||
|
}
|
||||||
|
for (fd = 0; fd < FD_SETSIZE; fd++) {
|
||||||
|
if (!default_loop->fd_events[fd])
|
||||||
|
continue;
|
||||||
|
if (default_loop->fd_events[fd]->read_cb)
|
||||||
|
FD_SET(fd, &readfds);
|
||||||
|
if (default_loop->fd_events[fd]->write_cb)
|
||||||
|
FD_SET(fd, &writefds);
|
||||||
|
if (fd > max_fd)
|
||||||
|
max_fd = fd;
|
||||||
|
if (default_loop->fd_timeout_times[fd] < timeout)
|
||||||
|
timeout = default_loop->fd_timeout_times[fd];
|
||||||
|
}
|
||||||
|
if (max_fd == -1 && timeout == (uint64_t)-1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (! blocking || now > timeout) {
|
||||||
|
tv.tv_sec = 0;
|
||||||
|
tv.tv_usec = 0;
|
||||||
|
} else {
|
||||||
|
tv.tv_sec = (timeout - now) / 1000000;
|
||||||
|
tv.tv_usec = (timeout - now) % 1000000;
|
||||||
|
}
|
||||||
|
if (select(max_fd + 1, &readfds, &writefds, NULL,
|
||||||
|
(timeout == ((uint64_t)-1) ? NULL : &tv)) < 0) {
|
||||||
|
perror("select() failed");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
now = get_now_plus(0);
|
||||||
|
for (fd = 0; fd < FD_SETSIZE; fd++) {
|
||||||
|
if (default_loop->fd_events[fd] &&
|
||||||
|
default_loop->fd_events[fd]->read_cb &&
|
||||||
|
FD_ISSET(fd, &readfds))
|
||||||
|
default_read_cb(fd, default_loop->fd_events[fd]);
|
||||||
|
|
||||||
|
if (default_loop->fd_events[fd] &&
|
||||||
|
default_loop->fd_events[fd]->write_cb &&
|
||||||
|
FD_ISSET(fd, &writefds))
|
||||||
|
default_write_cb(fd, default_loop->fd_events[fd]);
|
||||||
|
|
||||||
|
if (default_loop->fd_events[fd] &&
|
||||||
|
default_loop->fd_events[fd]->timeout_cb &&
|
||||||
|
now > default_loop->fd_timeout_times[fd])
|
||||||
|
default_timeout_cb(fd, default_loop->fd_events[fd]);
|
||||||
|
|
||||||
|
i = fd;
|
||||||
|
if (default_loop->timeout_events[i] &&
|
||||||
|
default_loop->timeout_events[i]->timeout_cb &&
|
||||||
|
now > default_loop->timeout_times[i])
|
||||||
|
default_timeout_cb(-1, default_loop->timeout_events[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
default_eventloop_run(getdns_eventloop *loop)
|
||||||
|
{
|
||||||
|
_getdns_default_eventloop *default_loop = (_getdns_default_eventloop *)loop;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (!loop)
|
||||||
|
return;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
while (i < MAX_TIMEOUTS) {
|
||||||
|
if (default_loop->fd_events[i] || default_loop->timeout_events[i]) {
|
||||||
|
default_eventloop_run_once(loop, 1);
|
||||||
|
i = 0;
|
||||||
|
} else {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_getdns_default_eventloop_init(_getdns_default_eventloop *loop)
|
||||||
|
{
|
||||||
|
static getdns_eventloop_vmt default_eventloop_vmt = {
|
||||||
|
default_eventloop_cleanup,
|
||||||
|
default_eventloop_schedule,
|
||||||
|
default_eventloop_clear,
|
||||||
|
default_eventloop_run,
|
||||||
|
default_eventloop_run_once
|
||||||
|
};
|
||||||
|
|
||||||
|
(void) memset(loop, 0, sizeof(_getdns_default_eventloop));
|
||||||
|
loop->loop.vmt = &default_eventloop_vmt;
|
||||||
|
}
|
|
@ -1,11 +1,10 @@
|
||||||
/**
|
/*
|
||||||
*
|
* \file default_eventloop.h
|
||||||
* \file libmini_event.h
|
|
||||||
* @brief Build in default eventloop extension that uses select.
|
* @brief Build in default eventloop extension that uses select.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013, NLnet Labs, Verisign, Inc.
|
* Copyright (c) 2013, NLNet Labs, Verisign, Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -30,34 +29,31 @@
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
#ifndef DEFAULT_EVENTLOOP_H_
|
||||||
#ifndef _GETDNS_LIBMINI_EVENT_H_
|
#define DEFAULT_EVENTLOOP_H_
|
||||||
#define _GETDNS_LIBMINI_EVENT_H_
|
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#ifndef USE_WINSOCK
|
#include "getdns/getdns.h"
|
||||||
#include "util/mini_event.h"
|
#include "getdns/getdns_extra.h"
|
||||||
#else
|
|
||||||
#include "util/winsock_event.h"
|
|
||||||
#endif
|
|
||||||
#include "types-internal.h"
|
|
||||||
|
|
||||||
typedef struct _getdns_mini_event {
|
/* No more than select's capability queries can be outstanding,
|
||||||
getdns_eventloop loop;
|
* The number of outstanding timeouts should be less or equal then
|
||||||
time_t time_secs;
|
* the number of outstanding queries, so MAX_TIMEOUTS equal to
|
||||||
struct timeval time_tv;
|
* FD_SETSIZE should be safe.
|
||||||
struct _getdns_event_base *base;
|
*/
|
||||||
size_t n_events;
|
#define MAX_TIMEOUTS FD_SETSIZE
|
||||||
struct mem_funcs mf;
|
|
||||||
} _getdns_mini_event;
|
|
||||||
|
|
||||||
getdns_return_t
|
/* Eventloop based on select */
|
||||||
_getdns_mini_event_init(getdns_context *context, _getdns_mini_event *mini_event);
|
typedef struct _getdns_default_eventloop {
|
||||||
|
getdns_eventloop loop;
|
||||||
|
getdns_eventloop_event *fd_events[FD_SETSIZE];
|
||||||
|
uint64_t fd_timeout_times[FD_SETSIZE];
|
||||||
|
getdns_eventloop_event *timeout_events[MAX_TIMEOUTS];
|
||||||
|
uint64_t timeout_times[MAX_TIMEOUTS];
|
||||||
|
} _getdns_default_eventloop;
|
||||||
|
|
||||||
getdns_return_t
|
|
||||||
_getdns_mini_event_create(getdns_context *ctxt, _getdns_mini_event **mini_event);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
_getdns_mini_event_destroy(_getdns_mini_event *mini_event);
|
_getdns_default_eventloop_init(_getdns_default_eventloop *loop);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* _GETDNS_LIBMINI_EVENT_H_ */
|
|
|
@ -1,238 +0,0 @@
|
||||||
/**
|
|
||||||
*
|
|
||||||
* \file libmini_event.c
|
|
||||||
* @brief Build in default eventloop extension that uses select.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2013, NLnet Labs, Verisign, Inc.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
* * Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* * Neither the names of the copyright holders nor the
|
|
||||||
* names of its contributors may be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
|
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include "debug.h"
|
|
||||||
#include "types-internal.h"
|
|
||||||
#include "extension/libmini_event.h"
|
|
||||||
#if defined(SCHED_DEBUG) && SCHED_DEBUG
|
|
||||||
#include <inttypes.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void
|
|
||||||
_getdns_mini_event_cleanup(getdns_eventloop *loop)
|
|
||||||
{
|
|
||||||
_getdns_mini_event *ext = (_getdns_mini_event *)loop;
|
|
||||||
_getdns_event_base_free(ext->base);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
_getdns_mini_event_destroy(_getdns_mini_event *ext)
|
|
||||||
{
|
|
||||||
assert(ext);
|
|
||||||
ext->loop.vmt->cleanup(&ext->loop);
|
|
||||||
GETDNS_FREE(ext->mf, ext);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _getdns_handle_timeouts(struct _getdns_event_base* base,
|
|
||||||
struct timeval* now, struct timeval* wait);
|
|
||||||
int _getdns_handle_select(struct _getdns_event_base* base, struct timeval* wait);
|
|
||||||
|
|
||||||
static int
|
|
||||||
_getdns_mini_event_settime(_getdns_mini_event *ext)
|
|
||||||
{
|
|
||||||
if (gettimeofday(&ext->time_tv, NULL) < 0)
|
|
||||||
return -1;
|
|
||||||
ext->time_secs = (time_t)ext->time_tv.tv_sec;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
_getdns_mini_event_run(getdns_eventloop *loop)
|
|
||||||
{
|
|
||||||
_getdns_mini_event *ext = (_getdns_mini_event *)loop;
|
|
||||||
struct timeval wait;
|
|
||||||
|
|
||||||
if (ext->n_events == 0 || _getdns_mini_event_settime(ext) < 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
do {
|
|
||||||
(void) _getdns_handle_timeouts(ext->base, &ext->time_tv, &wait);
|
|
||||||
|
|
||||||
if (!ext->n_events)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (_getdns_handle_select(ext->base, &wait))
|
|
||||||
break;
|
|
||||||
|
|
||||||
} while (ext->n_events);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
_getdns_mini_event_run_once(getdns_eventloop *loop, int blocking)
|
|
||||||
{
|
|
||||||
static struct timeval immediately = { 0, 0 };
|
|
||||||
_getdns_mini_event *ext = (_getdns_mini_event *)loop;
|
|
||||||
struct timeval wait;
|
|
||||||
|
|
||||||
if (blocking) {
|
|
||||||
if (_getdns_mini_event_settime(ext) < 0)
|
|
||||||
return;
|
|
||||||
_getdns_handle_timeouts(ext->base, &ext->time_tv, &wait);
|
|
||||||
if (_getdns_handle_select(ext->base, &wait) < 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
} else if (_getdns_handle_select(ext->base, &immediately) < 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_getdns_handle_timeouts(ext->base, &ext->time_tv, &wait);
|
|
||||||
}
|
|
||||||
|
|
||||||
static getdns_return_t
|
|
||||||
_getdns_mini_event_clear(getdns_eventloop *loop, getdns_eventloop_event *el_ev)
|
|
||||||
{
|
|
||||||
getdns_return_t r = GETDNS_RETURN_GOOD;
|
|
||||||
_getdns_mini_event *ext = (_getdns_mini_event *)loop;
|
|
||||||
|
|
||||||
assert(el_ev->ev);
|
|
||||||
DEBUG_SCHED("1. _getdns_mini_event_clear(loop: %p, el_ev: %p[userarg: %p, r: %p, w: %p, t: %p, ev: %p]); n_events: %d, times: %d\n", loop, el_ev, el_ev->userarg, el_ev->read_cb, el_ev->write_cb, el_ev->timeout_cb, el_ev->ev, (int)ext->n_events, (int)ext->base->times->count);
|
|
||||||
|
|
||||||
if (_getdns_event_del(el_ev->ev) != 0)
|
|
||||||
r = GETDNS_RETURN_GENERIC_ERROR;
|
|
||||||
|
|
||||||
GETDNS_FREE(ext->mf, el_ev->ev);
|
|
||||||
el_ev->ev = NULL;
|
|
||||||
|
|
||||||
ext->n_events--;
|
|
||||||
DEBUG_SCHED("2. %d <- _getdns_mini_event_clear(loop: %p, el_ev: %p[userarg: %p, r: %p, w: %p, t: %p, ev: %p]); n_events: %d, times: %d\n", r, loop, el_ev, el_ev->userarg, el_ev->read_cb, el_ev->write_cb, el_ev->timeout_cb, el_ev->ev, (int)ext->n_events, (int)ext->base->times->count);
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
_getdns_mini_event_callback(int fd, short bits, void *arg)
|
|
||||||
{
|
|
||||||
getdns_eventloop_event *el_ev = (getdns_eventloop_event *)arg;
|
|
||||||
DEBUG_SCHED("1. _getdns_mini_event_callback(fd: %d, bits: %d, el_ev: %p[userarg: %p, r: %p, w: %p, t: %p, ev: %p])\n", fd, (int)bits, el_ev, el_ev->userarg, el_ev->read_cb, el_ev->write_cb, el_ev->timeout_cb, el_ev->ev);
|
|
||||||
if (bits & EV_READ) {
|
|
||||||
assert(el_ev->read_cb);
|
|
||||||
el_ev->read_cb(el_ev->userarg);
|
|
||||||
} else if (bits & EV_WRITE) {
|
|
||||||
assert(el_ev->write_cb);
|
|
||||||
el_ev->write_cb(el_ev->userarg);
|
|
||||||
} else if (bits & EV_TIMEOUT) {
|
|
||||||
assert(el_ev->timeout_cb);
|
|
||||||
el_ev->timeout_cb(el_ev->userarg);
|
|
||||||
} else
|
|
||||||
assert(ASSERT_UNREACHABLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static getdns_return_t
|
|
||||||
_getdns_mini_event_schedule(getdns_eventloop *loop,
|
|
||||||
int fd, uint64_t timeout, getdns_eventloop_event *el_ev)
|
|
||||||
{
|
|
||||||
_getdns_mini_event *ext = (_getdns_mini_event *)loop;
|
|
||||||
struct _getdns_event *my_ev;
|
|
||||||
struct timeval tv = { timeout / 1000, (timeout % 1000) * 1000 };
|
|
||||||
|
|
||||||
assert(el_ev);
|
|
||||||
assert(!(el_ev->read_cb || el_ev->write_cb) || fd >= 0);
|
|
||||||
assert( el_ev->read_cb || el_ev->write_cb || el_ev->timeout_cb);
|
|
||||||
|
|
||||||
if (!(my_ev = GETDNS_MALLOC(ext->mf, struct _getdns_event)))
|
|
||||||
return GETDNS_RETURN_MEMORY_ERROR;
|
|
||||||
|
|
||||||
el_ev->ev = my_ev;
|
|
||||||
DEBUG_SCHED("1. _getdns_mini_event_schedule(loop: %p, fd: %d, timeout: %"PRId64", el_ev: %p[userarg: %p, r: %p, w: %p, t: %p, ev: %p]); n_events: %d\n", loop, fd, timeout, el_ev, el_ev->userarg, el_ev->read_cb, el_ev->write_cb, el_ev->timeout_cb, el_ev->ev, (int)ext->n_events);
|
|
||||||
_getdns_event_set(my_ev, fd, (
|
|
||||||
(el_ev->read_cb ? EV_READ|EV_PERSIST : 0) |
|
|
||||||
(el_ev->write_cb ? EV_WRITE|EV_PERSIST : 0) |
|
|
||||||
(el_ev->timeout_cb ? EV_TIMEOUT : 0)),
|
|
||||||
_getdns_mini_event_callback, el_ev);
|
|
||||||
|
|
||||||
if (_getdns_mini_event_settime(ext))
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
(void) _getdns_event_base_set(ext->base, my_ev);
|
|
||||||
if (_getdns_event_add(my_ev, el_ev->timeout_cb ? &tv : NULL))
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
ext->n_events++;
|
|
||||||
DEBUG_SCHED("2. _getdns_mini_event_schedule(loop: %p, fd: %d, timeout: %"PRId64", el_ev: %p[userarg: %p, r: %p, w: %p, t: %p, ev: %p]); n_events: %d\n", loop, fd, timeout, el_ev, el_ev->userarg, el_ev->read_cb, el_ev->write_cb, el_ev->timeout_cb, el_ev->ev, (int)ext->n_events);
|
|
||||||
|
|
||||||
return GETDNS_RETURN_GOOD;
|
|
||||||
error:
|
|
||||||
GETDNS_FREE(ext->mf, my_ev);
|
|
||||||
el_ev->ev = NULL;
|
|
||||||
|
|
||||||
DEBUG_SCHED("3. _getdns_mini_event_schedule(loop: %p, fd: %d, timeout: %"PRId64", el_ev: %p[userarg: %p, r: %p, w: %p, t: %p, ev: %p]); n_events: %d\n", loop, fd, timeout, el_ev, el_ev->userarg, el_ev->read_cb, el_ev->write_cb, el_ev->timeout_cb, el_ev->ev, (int)ext->n_events);
|
|
||||||
return GETDNS_RETURN_GENERIC_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
getdns_return_t
|
|
||||||
_getdns_mini_event_init(getdns_context *context, _getdns_mini_event *ext)
|
|
||||||
{
|
|
||||||
static getdns_eventloop_vmt _getdns_mini_event_vmt = {
|
|
||||||
_getdns_mini_event_cleanup,
|
|
||||||
_getdns_mini_event_schedule,
|
|
||||||
_getdns_mini_event_clear,
|
|
||||||
_getdns_mini_event_run,
|
|
||||||
_getdns_mini_event_run_once
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!context)
|
|
||||||
return GETDNS_RETURN_BAD_CONTEXT;
|
|
||||||
if (!ext)
|
|
||||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
|
||||||
|
|
||||||
#ifdef USE_WINSOCK
|
|
||||||
int r;
|
|
||||||
WSADATA wsa_data;
|
|
||||||
|
|
||||||
if ((r = WSAStartup(MAKEWORD(2, 2), &wsa_data)) != 0) {
|
|
||||||
printf("could not init winsock. WSAStartup: %s",
|
|
||||||
wsa_strerror(r));
|
|
||||||
return GETDNS_RETURN_GENERIC_ERROR;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ext->n_events = 0;
|
|
||||||
ext->loop.vmt = &_getdns_mini_event_vmt;
|
|
||||||
ext->base = _getdns_event_init(&ext->time_secs, &ext->time_tv);
|
|
||||||
if (!ext->base)
|
|
||||||
return GETDNS_RETURN_MEMORY_ERROR;
|
|
||||||
|
|
||||||
ext->mf = *priv_getdns_context_mf(context);
|
|
||||||
return GETDNS_RETURN_GOOD;
|
|
||||||
}
|
|
||||||
|
|
||||||
getdns_return_t
|
|
||||||
_getdns_mini_event_create(getdns_context *context, _getdns_mini_event **ext)
|
|
||||||
{
|
|
||||||
if (!context) return GETDNS_RETURN_BAD_CONTEXT;
|
|
||||||
if (!ext) return GETDNS_RETURN_INVALID_PARAMETER;
|
|
||||||
|
|
||||||
*ext = GETDNS_MALLOC(*priv_getdns_context_mf(context), _getdns_mini_event);
|
|
||||||
return _getdns_mini_event_init(context, *ext);
|
|
||||||
}
|
|
104
src/stub.c
104
src/stub.c
|
@ -50,12 +50,20 @@
|
||||||
#include "pubkey-pinning.h"
|
#include "pubkey-pinning.h"
|
||||||
|
|
||||||
#ifdef USE_WINSOCK
|
#ifdef USE_WINSOCK
|
||||||
#define EINPROGRESS 112
|
|
||||||
#define EWOULDBLOCK 140
|
|
||||||
typedef u_short sa_family_t;
|
typedef u_short sa_family_t;
|
||||||
#include "util/winsock_event.h"
|
#define _getdns_EWOULDBLOCK (WSAGetLastError() == WSATRY_AGAIN ||\
|
||||||
|
WSAGetLastError() == WSAEWOULDBLOCK)
|
||||||
|
#define _getdns_EINPROGRESS (WSAGetLastError() == WSAEINPROGRESS)
|
||||||
|
#else
|
||||||
|
#define _getdns_EWOULDBLOCK (errno == EAGAIN || errno == EWOULDBLOCK)
|
||||||
|
#define _getdns_EINPROGRESS (errno == EINPROGRESS)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* WSA TODO:
|
||||||
|
* STUB_TCP_WOULDBLOCK added to deal with edge triggered event loops (versus
|
||||||
|
* level triggered). See also lines containing WSA TODO below...
|
||||||
|
*/
|
||||||
|
#define STUB_TCP_WOULDBLOCK -6
|
||||||
#define STUB_OUT_OF_OPTIONS -5 /* upstream options exceeded MAXIMUM_UPSTREAM_OPTION_SPACE */
|
#define STUB_OUT_OF_OPTIONS -5 /* upstream options exceeded MAXIMUM_UPSTREAM_OPTION_SPACE */
|
||||||
#define STUB_TLS_SETUP_ERROR -4
|
#define STUB_TLS_SETUP_ERROR -4
|
||||||
#define STUB_TCP_AGAIN -3
|
#define STUB_TCP_AGAIN -3
|
||||||
|
@ -402,10 +410,21 @@ tcp_connected(getdns_upstream *upstream) {
|
||||||
int error = 0;
|
int error = 0;
|
||||||
socklen_t len = (socklen_t)sizeof(error);
|
socklen_t len = (socklen_t)sizeof(error);
|
||||||
getsockopt(upstream->fd, SOL_SOCKET, SO_ERROR, (void*)&error, &len);
|
getsockopt(upstream->fd, SOL_SOCKET, SO_ERROR, (void*)&error, &len);
|
||||||
if (error == EINPROGRESS || error == EWOULDBLOCK)
|
#ifdef USE_WINSOCK
|
||||||
return STUB_TCP_AGAIN; /* try again */
|
if (error == WSAEINPROGRESS)
|
||||||
|
return STUB_TCP_WOULDBLOCK;
|
||||||
|
else if (error == WSAEWOULDBLOCK)
|
||||||
|
return STUB_TCP_WOULDBLOCK;
|
||||||
else if (error != 0)
|
else if (error != 0)
|
||||||
return STUB_TCP_ERROR;
|
return STUB_TCP_ERROR;
|
||||||
|
#else
|
||||||
|
if (error == EINPROGRESS)
|
||||||
|
return STUB_TCP_WOULDBLOCK;
|
||||||
|
else if (error == EWOULDBLOCK || error == EAGAIN)
|
||||||
|
return STUB_TCP_WOULDBLOCK;
|
||||||
|
else if (error != 0)
|
||||||
|
return STUB_TCP_ERROR;
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -625,7 +644,7 @@ stub_tls_timeout_cb(void *userarg)
|
||||||
/****************************/
|
/****************************/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
stub_tcp_read(int fd, getdns_tcp_state *tcp, struct mem_funcs *mf, getdns_eventloop_event* event)
|
stub_tcp_read(int fd, getdns_tcp_state *tcp, struct mem_funcs *mf)
|
||||||
{
|
{
|
||||||
ssize_t read;
|
ssize_t read;
|
||||||
uint8_t *buf;
|
uint8_t *buf;
|
||||||
|
@ -642,33 +661,21 @@ stub_tcp_read(int fd, getdns_tcp_state *tcp, struct mem_funcs *mf, getdns_eventl
|
||||||
}
|
}
|
||||||
read = recv(fd, (void *)tcp->read_pos, tcp->to_read, 0);
|
read = recv(fd, (void *)tcp->read_pos, tcp->to_read, 0);
|
||||||
if (read == -1) {
|
if (read == -1) {
|
||||||
#ifdef USE_WINSOCK
|
if (_getdns_EWOULDBLOCK)
|
||||||
printf("read (in tcp ) %s\n",
|
return STUB_TCP_WOULDBLOCK;
|
||||||
wsa_strerror(WSAGetLastError()));
|
|
||||||
if (WSAGetLastError() == WSAECONNRESET)
|
|
||||||
return STUB_TCP_AGAIN;
|
|
||||||
if (WSAGetLastError() == WSAEINPROGRESS)
|
|
||||||
return STUB_TCP_AGAIN;
|
|
||||||
if (WSAGetLastError() == WSAEWOULDBLOCK) {
|
|
||||||
winsock_tcp_wouldblock(event->ev, EV_READ);
|
|
||||||
return STUB_TCP_AGAIN;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
if (errno == EAGAIN || errno == EWOULDBLOCK)
|
|
||||||
return STUB_TCP_AGAIN;
|
|
||||||
else
|
else
|
||||||
return STUB_TCP_ERROR;
|
return STUB_TCP_ERROR;
|
||||||
#endif
|
|
||||||
} else if (read == 0) {
|
} else if (read == 0) {
|
||||||
/* Remote end closed the socket */
|
/* Remote end closed the socket */
|
||||||
/* TODO: Try to reconnect */
|
/* TODO: Try to reconnect */
|
||||||
return STUB_TCP_ERROR;
|
return STUB_TCP_ERROR;
|
||||||
|
} else if (read> tcp->to_read) {
|
||||||
|
return STUB_TCP_ERROR;
|
||||||
}
|
}
|
||||||
tcp->to_read -= read;
|
tcp->to_read -= read;
|
||||||
tcp->read_pos += read;
|
tcp->read_pos += read;
|
||||||
|
|
||||||
if ((int)tcp->to_read > 0)
|
if (tcp->to_read > 0)
|
||||||
return STUB_TCP_AGAIN;
|
return STUB_TCP_AGAIN;
|
||||||
|
|
||||||
read = tcp->read_pos - tcp->read_buf;
|
read = tcp->read_pos - tcp->read_buf;
|
||||||
|
@ -721,7 +728,7 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
|
||||||
if (! tcp->write_buf) {
|
if (! tcp->write_buf) {
|
||||||
/* No, this is an initial write. Try to send
|
/* No, this is an initial write. Try to send
|
||||||
*/
|
*/
|
||||||
do {
|
do {
|
||||||
query_id = arc4random();
|
query_id = arc4random();
|
||||||
query_id_intptr = (intptr_t)query_id;
|
query_id_intptr = (intptr_t)query_id;
|
||||||
netreq->node.key = (void *)query_id_intptr;
|
netreq->node.key = (void *)query_id_intptr;
|
||||||
|
@ -754,8 +761,8 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
|
||||||
/* We have an initialized packet buffer.
|
/* We have an initialized packet buffer.
|
||||||
* Lets see how much of it we can write
|
* Lets see how much of it we can write
|
||||||
*/
|
*/
|
||||||
#ifdef USE_TCP_FASTOPEN
|
|
||||||
/* We use sendto() here which will do both a connect and send */
|
/* We use sendto() here which will do both a connect and send */
|
||||||
|
#ifdef USE_TCP_FASTOPEN
|
||||||
written = sendto(fd, netreq->query - 2, pkt_len + 2,
|
written = sendto(fd, netreq->query - 2, pkt_len + 2,
|
||||||
MSG_FASTOPEN, (struct sockaddr *)&(netreq->upstream->addr),
|
MSG_FASTOPEN, (struct sockaddr *)&(netreq->upstream->addr),
|
||||||
netreq->upstream->addr_len);
|
netreq->upstream->addr_len);
|
||||||
|
@ -763,29 +770,19 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
|
||||||
just fall back to a 'normal' write. */
|
just fall back to a 'normal' write. */
|
||||||
if (written == -1 && errno == EISCONN)
|
if (written == -1 && errno == EISCONN)
|
||||||
written = write(fd, netreq->query - 2, pkt_len + 2);
|
written = write(fd, netreq->query - 2, pkt_len + 2);
|
||||||
|
|
||||||
if ((written == -1 && (errno == EAGAIN ||
|
|
||||||
errno == EWOULDBLOCK ||
|
|
||||||
/* Add the error case where the connection is in progress which is when
|
|
||||||
a cookie is not available (e.g. when doing the first request to an
|
|
||||||
upstream). We must let the handshake complete since non-blocking. */
|
|
||||||
errno == EINPROGRESS)) ||
|
|
||||||
written < pkt_len + 2) {
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#ifdef USE_WINSOCK
|
|
||||||
written = sendto(fd, (const char *)(netreq->query - 2),
|
written = sendto(fd, (const char *)(netreq->query - 2),
|
||||||
pkt_len + 2, 0,
|
pkt_len + 2, 0,
|
||||||
(struct sockaddr *)&(netreq->upstream->addr),
|
(struct sockaddr *)&(netreq->upstream->addr),
|
||||||
netreq->upstream->addr_len);
|
netreq->upstream->addr_len);
|
||||||
|
|
||||||
#else
|
|
||||||
written = write(fd, netreq->query - 2, pkt_len + 2);
|
|
||||||
#endif
|
#endif
|
||||||
if ((written == -1 && (errno == EAGAIN ||
|
if ((written == -1 && (_getdns_EWOULDBLOCK ||
|
||||||
errno == EWOULDBLOCK)) ||
|
/* Add the error case where the connection is in progress which is when
|
||||||
|
a cookie is not available (e.g. when doing the first request to an
|
||||||
|
upstream). We must let the handshake complete since non-blocking. */
|
||||||
|
_getdns_EINPROGRESS)) ||
|
||||||
written < pkt_len + 2) {
|
written < pkt_len + 2) {
|
||||||
#endif
|
|
||||||
/* We couldn't write the whole packet.
|
/* We couldn't write the whole packet.
|
||||||
* We have to return with STUB_TCP_AGAIN.
|
* We have to return with STUB_TCP_AGAIN.
|
||||||
* Setup tcp to track the state.
|
* Setup tcp to track the state.
|
||||||
|
@ -794,7 +791,7 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
|
||||||
tcp->write_buf_len = pkt_len + 2;
|
tcp->write_buf_len = pkt_len + 2;
|
||||||
tcp->written = written >= 0 ? written : 0;
|
tcp->written = written >= 0 ? written : 0;
|
||||||
|
|
||||||
return STUB_TCP_AGAIN;
|
return STUB_TCP_WOULDBLOCK;
|
||||||
|
|
||||||
} else if (written == -1)
|
} else if (written == -1)
|
||||||
return STUB_TCP_ERROR;
|
return STUB_TCP_ERROR;
|
||||||
|
@ -809,8 +806,8 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
|
||||||
written = write(fd, tcp->write_buf + tcp->written,
|
written = write(fd, tcp->write_buf + tcp->written,
|
||||||
tcp->write_buf_len - tcp->written);
|
tcp->write_buf_len - tcp->written);
|
||||||
if (written == -1) {
|
if (written == -1) {
|
||||||
if (errno == EAGAIN || errno == EWOULDBLOCK)
|
if (_getdns_EWOULDBLOCK)
|
||||||
return STUB_TCP_AGAIN;
|
return STUB_TCP_WOULDBLOCK;
|
||||||
else
|
else
|
||||||
return STUB_TCP_ERROR;
|
return STUB_TCP_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -1304,7 +1301,7 @@ stub_udp_read_cb(void *userarg)
|
||||||
* i.e. overflow
|
* i.e. overflow
|
||||||
*/
|
*/
|
||||||
0, NULL, NULL);
|
0, NULL, NULL);
|
||||||
if (read == -1 && (errno = EAGAIN || errno == EWOULDBLOCK))
|
if (read == -1 && _getdns_EWOULDBLOCK)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (read < GLDNS_HEADER_SIZE)
|
if (read < GLDNS_HEADER_SIZE)
|
||||||
|
@ -1405,13 +1402,16 @@ upstream_read_cb(void *userarg)
|
||||||
|
|
||||||
if (tls_should_read(upstream))
|
if (tls_should_read(upstream))
|
||||||
q = stub_tls_read(upstream, &upstream->tcp,
|
q = stub_tls_read(upstream, &upstream->tcp,
|
||||||
&upstream->upstreams->mf);
|
&upstream->upstreams->mf);
|
||||||
else
|
else
|
||||||
q = stub_tcp_read(upstream->fd, &upstream->tcp,
|
q = stub_tcp_read(upstream->fd, &upstream->tcp,
|
||||||
&upstream->upstreams->mf, &upstream->event);
|
&upstream->upstreams->mf);
|
||||||
|
|
||||||
switch (q) {
|
switch (q) {
|
||||||
case STUB_TCP_AGAIN:
|
case STUB_TCP_AGAIN:
|
||||||
|
/* WSA TODO: if callback is still upstream_read_cb, do it again
|
||||||
|
*/
|
||||||
|
case STUB_TCP_WOULDBLOCK:
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case STUB_TCP_ERROR:
|
case STUB_TCP_ERROR:
|
||||||
|
@ -1463,6 +1463,10 @@ upstream_read_cb(void *userarg)
|
||||||
upstream_reschedule_netreq_events(upstream, netreq);
|
upstream_reschedule_netreq_events(upstream, netreq);
|
||||||
|
|
||||||
_getdns_check_dns_req_complete(netreq->owner);
|
_getdns_check_dns_req_complete(netreq->owner);
|
||||||
|
|
||||||
|
/* WSA TODO: if callback is still upstream_read_cb, do it again
|
||||||
|
*/
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1499,6 +1503,10 @@ upstream_write_cb(void *userarg)
|
||||||
|
|
||||||
switch (q) {
|
switch (q) {
|
||||||
case STUB_TCP_AGAIN:
|
case STUB_TCP_AGAIN:
|
||||||
|
/* WSA TODO: if callback is still upstream_write_cb, do it again
|
||||||
|
*/
|
||||||
|
|
||||||
|
case STUB_TCP_WOULDBLOCK:
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case STUB_TCP_ERROR:
|
case STUB_TCP_ERROR:
|
||||||
|
@ -1553,6 +1561,8 @@ upstream_write_cb(void *userarg)
|
||||||
netreq_upstream_write_cb : NULL),
|
netreq_upstream_write_cb : NULL),
|
||||||
stub_timeout_cb));
|
stub_timeout_cb));
|
||||||
}
|
}
|
||||||
|
/* WSA TODO: if callback is still upstream_write_cb, do it again
|
||||||
|
*/
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@
|
||||||
#include "gldns/wire2str.h"
|
#include "gldns/wire2str.h"
|
||||||
|
|
||||||
typedef struct getdns_sync_loop {
|
typedef struct getdns_sync_loop {
|
||||||
_getdns_mini_event loop;
|
_getdns_default_eventloop loop;
|
||||||
#ifdef HAVE_LIBUNBOUND
|
#ifdef HAVE_LIBUNBOUND
|
||||||
getdns_eventloop_event ub_event;
|
getdns_eventloop_event ub_event;
|
||||||
#endif
|
#endif
|
||||||
|
@ -61,14 +61,12 @@ getdns_sync_loop_init(getdns_context *context, getdns_sync_loop *loop)
|
||||||
#ifdef HAVE_LIBUNBOUND
|
#ifdef HAVE_LIBUNBOUND
|
||||||
getdns_eventloop *ext = &loop->loop.loop;
|
getdns_eventloop *ext = &loop->loop.loop;
|
||||||
#endif
|
#endif
|
||||||
getdns_return_t r;
|
|
||||||
|
|
||||||
loop->response = NULL;
|
loop->response = NULL;
|
||||||
loop->to_run = 1;
|
loop->to_run = 1;
|
||||||
loop->context = context;
|
loop->context = context;
|
||||||
|
|
||||||
if ((r = _getdns_mini_event_init(context, &loop->loop)))
|
_getdns_default_eventloop_init(&loop->loop);
|
||||||
return r;
|
|
||||||
|
|
||||||
#ifdef HAVE_LIBUNBOUND
|
#ifdef HAVE_LIBUNBOUND
|
||||||
loop->ub_event.userarg = loop->context;
|
loop->ub_event.userarg = loop->context;
|
||||||
|
|
|
@ -232,21 +232,24 @@ depend:
|
||||||
.PHONY: clean test
|
.PHONY: clean test
|
||||||
|
|
||||||
# Dependencies for the unit tests
|
# Dependencies for the unit tests
|
||||||
check_getdns.lo check_getdns.o: $(srcdir)/check_getdns.c ../getdns/getdns.h $(srcdir)/check_getdns_common.h \
|
check_getdns.lo check_getdns.o: $(srcdir)/check_getdns.c \
|
||||||
../getdns/getdns_extra.h $(srcdir)/check_getdns_general.h \
|
../getdns/getdns.h \
|
||||||
$(srcdir)/check_getdns_general_sync.h $(srcdir)/check_getdns_address.h \
|
$(srcdir)/check_getdns_common.h \
|
||||||
$(srcdir)/check_getdns_address_sync.h $(srcdir)/check_getdns_hostname.h \
|
../getdns/getdns_extra.h \
|
||||||
$(srcdir)/check_getdns_hostname_sync.h $(srcdir)/check_getdns_context_create.h \
|
$(srcdir)/check_getdns_general.h $(srcdir)/check_getdns_general_sync.h \
|
||||||
$(srcdir)/check_getdns_context_destroy.h $(srcdir)/check_getdns_cancel_callback.h \
|
$(srcdir)/check_getdns_address.h $(srcdir)/check_getdns_address_sync.h \
|
||||||
$(srcdir)/check_getdns_list_get_length.h $(srcdir)/check_getdns_list_get_data_type.h \
|
$(srcdir)/check_getdns_hostname.h $(srcdir)/check_getdns_hostname_sync.h \
|
||||||
$(srcdir)/check_getdns_list_get_dict.h $(srcdir)/check_getdns_list_get_list.h \
|
$(srcdir)/check_getdns_context_create.h $(srcdir)/check_getdns_context_destroy.h \
|
||||||
$(srcdir)/check_getdns_list_get_int.h $(srcdir)/check_getdns_list_get_bindata.h \
|
$(srcdir)/check_getdns_cancel_callback.h $(srcdir)/check_getdns_list_get_length.h \
|
||||||
$(srcdir)/check_getdns_dict_get_names.h $(srcdir)/check_getdns_dict_get_data_type.h \
|
$(srcdir)/check_getdns_list_get_data_type.h $(srcdir)/check_getdns_list_get_dict.h \
|
||||||
$(srcdir)/check_getdns_dict_get_dict.h $(srcdir)/check_getdns_dict_get_list.h \
|
$(srcdir)/check_getdns_list_get_list.h $(srcdir)/check_getdns_list_get_int.h \
|
||||||
$(srcdir)/check_getdns_dict_get_bindata.h $(srcdir)/check_getdns_dict_get_int.h \
|
$(srcdir)/check_getdns_list_get_bindata.h $(srcdir)/check_getdns_dict_get_names.h \
|
||||||
$(srcdir)/check_getdns_dict_destroy.h $(srcdir)/check_getdns_dict_set_dict.h \
|
$(srcdir)/check_getdns_dict_get_data_type.h $(srcdir)/check_getdns_dict_get_dict.h \
|
||||||
$(srcdir)/check_getdns_dict_set_list.h $(srcdir)/check_getdns_dict_set_bindata.h \
|
$(srcdir)/check_getdns_dict_get_list.h $(srcdir)/check_getdns_dict_get_bindata.h \
|
||||||
$(srcdir)/check_getdns_dict_set_int.h $(srcdir)/check_getdns_convert_ulabel_to_alabel.h \
|
$(srcdir)/check_getdns_dict_get_int.h $(srcdir)/check_getdns_dict_destroy.h \
|
||||||
|
$(srcdir)/check_getdns_dict_set_dict.h $(srcdir)/check_getdns_dict_set_list.h \
|
||||||
|
$(srcdir)/check_getdns_dict_set_bindata.h $(srcdir)/check_getdns_dict_set_int.h \
|
||||||
|
$(srcdir)/check_getdns_convert_ulabel_to_alabel.h \
|
||||||
$(srcdir)/check_getdns_convert_alabel_to_ulabel.h $(srcdir)/check_getdns_pretty_print_dict.h \
|
$(srcdir)/check_getdns_convert_alabel_to_ulabel.h $(srcdir)/check_getdns_pretty_print_dict.h \
|
||||||
$(srcdir)/check_getdns_display_ip_address.h \
|
$(srcdir)/check_getdns_display_ip_address.h \
|
||||||
$(srcdir)/check_getdns_context_set_context_update_callback.h \
|
$(srcdir)/check_getdns_context_set_context_update_callback.h \
|
||||||
|
@ -254,36 +257,59 @@ check_getdns.lo check_getdns.o: $(srcdir)/check_getdns.c ../getdns/getdns.h $(sr
|
||||||
$(srcdir)/check_getdns_context_set_upstream_recursive_servers.h \
|
$(srcdir)/check_getdns_context_set_upstream_recursive_servers.h \
|
||||||
$(srcdir)/check_getdns_service.h $(srcdir)/check_getdns_service_sync.h \
|
$(srcdir)/check_getdns_service.h $(srcdir)/check_getdns_service_sync.h \
|
||||||
$(srcdir)/check_getdns_transport.h
|
$(srcdir)/check_getdns_transport.h
|
||||||
check_getdns_common.lo check_getdns_common.o: $(srcdir)/check_getdns_common.c ../getdns/getdns.h \
|
check_getdns_common.lo check_getdns_common.o: $(srcdir)/check_getdns_common.c \
|
||||||
../config.h $(srcdir)/check_getdns_common.h ../getdns/getdns_extra.h \
|
../getdns/getdns.h \
|
||||||
|
../config.h $(srcdir)/check_getdns_common.h \
|
||||||
|
../getdns/getdns_extra.h \
|
||||||
$(srcdir)/check_getdns_eventloop.h
|
$(srcdir)/check_getdns_eventloop.h
|
||||||
check_getdns_context_set_timeout.lo check_getdns_context_set_timeout.o: $(srcdir)/check_getdns_context_set_timeout.c \
|
check_getdns_context_set_timeout.lo check_getdns_context_set_timeout.o: $(srcdir)/check_getdns_context_set_timeout.c \
|
||||||
$(srcdir)/check_getdns_context_set_timeout.h $(srcdir)/check_getdns_common.h \
|
$(srcdir)/check_getdns_context_set_timeout.h $(srcdir)/check_getdns_common.h \
|
||||||
../getdns/getdns.h ../getdns/getdns_extra.h
|
../getdns/getdns.h \
|
||||||
|
../getdns/getdns_extra.h
|
||||||
check_getdns_libev.lo check_getdns_libev.o: $(srcdir)/check_getdns_libev.c $(srcdir)/check_getdns_eventloop.h \
|
check_getdns_libev.lo check_getdns_libev.o: $(srcdir)/check_getdns_libev.c $(srcdir)/check_getdns_eventloop.h \
|
||||||
../config.h ../getdns/getdns.h $(srcdir)/../getdns/getdns_ext_libev.h \
|
../config.h \
|
||||||
../getdns/getdns_extra.h $(srcdir)/check_getdns_common.h
|
../getdns/getdns.h \
|
||||||
|
$(srcdir)/../getdns/getdns_ext_libev.h \
|
||||||
|
../getdns/getdns_extra.h \
|
||||||
|
$(srcdir)/check_getdns_common.h
|
||||||
check_getdns_libevent.lo check_getdns_libevent.o: $(srcdir)/check_getdns_libevent.c $(srcdir)/check_getdns_eventloop.h \
|
check_getdns_libevent.lo check_getdns_libevent.o: $(srcdir)/check_getdns_libevent.c $(srcdir)/check_getdns_eventloop.h \
|
||||||
../config.h ../getdns/getdns.h $(srcdir)/../getdns/getdns_ext_libevent.h \
|
../config.h \
|
||||||
../getdns/getdns_extra.h $(srcdir)/check_getdns_libevent.h $(srcdir)/check_getdns_common.h
|
../getdns/getdns.h \
|
||||||
|
$(srcdir)/../getdns/getdns_ext_libevent.h \
|
||||||
|
../getdns/getdns_extra.h \
|
||||||
|
$(srcdir)/check_getdns_libevent.h $(srcdir)/check_getdns_common.h
|
||||||
check_getdns_libuv.lo check_getdns_libuv.o: $(srcdir)/check_getdns_libuv.c $(srcdir)/check_getdns_eventloop.h \
|
check_getdns_libuv.lo check_getdns_libuv.o: $(srcdir)/check_getdns_libuv.c $(srcdir)/check_getdns_eventloop.h \
|
||||||
../config.h ../getdns/getdns.h $(srcdir)/../getdns/getdns_ext_libuv.h \
|
../config.h \
|
||||||
../getdns/getdns_extra.h $(srcdir)/check_getdns_common.h
|
../getdns/getdns.h \
|
||||||
|
$(srcdir)/../getdns/getdns_ext_libuv.h \
|
||||||
|
../getdns/getdns_extra.h \
|
||||||
|
$(srcdir)/check_getdns_common.h
|
||||||
check_getdns_selectloop.lo check_getdns_selectloop.o: $(srcdir)/check_getdns_selectloop.c \
|
check_getdns_selectloop.lo check_getdns_selectloop.o: $(srcdir)/check_getdns_selectloop.c \
|
||||||
$(srcdir)/check_getdns_eventloop.h ../config.h ../getdns/getdns.h \
|
$(srcdir)/check_getdns_eventloop.h ../config.h \
|
||||||
|
../getdns/getdns.h \
|
||||||
../getdns/getdns_extra.h
|
../getdns/getdns_extra.h
|
||||||
check_getdns_transport.lo check_getdns_transport.o: $(srcdir)/check_getdns_transport.c \
|
check_getdns_transport.lo check_getdns_transport.o: $(srcdir)/check_getdns_transport.c \
|
||||||
$(srcdir)/check_getdns_transport.h $(srcdir)/check_getdns_common.h ../getdns/getdns.h \
|
$(srcdir)/check_getdns_transport.h $(srcdir)/check_getdns_common.h \
|
||||||
|
../getdns/getdns.h \
|
||||||
../getdns/getdns_extra.h
|
../getdns/getdns_extra.h
|
||||||
getdns_query.lo getdns_query.o: $(srcdir)/getdns_query.c ../config.h $(srcdir)/../debug.h ../config.h \
|
getdns_query.lo getdns_query.o: $(srcdir)/getdns_query.c \
|
||||||
../getdns/getdns.h ../getdns/getdns_extra.h
|
../config.h $(srcdir)/../debug.h \
|
||||||
scratchpad.template.lo scratchpad.template.o: scratchpad.template.c ../getdns/getdns.h \
|
../getdns/getdns.h \
|
||||||
|
../getdns/getdns_extra.h
|
||||||
|
scratchpad.template.lo scratchpad.template.o: scratchpad.template.c \
|
||||||
|
../getdns/getdns.h \
|
||||||
../getdns/getdns_extra.h
|
../getdns/getdns_extra.h
|
||||||
testmessages.lo testmessages.o: $(srcdir)/testmessages.c $(srcdir)/testmessages.h
|
testmessages.lo testmessages.o: $(srcdir)/testmessages.c $(srcdir)/testmessages.h
|
||||||
tests_dict.lo tests_dict.o: $(srcdir)/tests_dict.c $(srcdir)/testmessages.h ../getdns/getdns.h
|
tests_dict.lo tests_dict.o: $(srcdir)/tests_dict.c $(srcdir)/testmessages.h \
|
||||||
tests_list.lo tests_list.o: $(srcdir)/tests_list.c $(srcdir)/testmessages.h ../getdns/getdns.h
|
../getdns/getdns.h
|
||||||
tests_namespaces.lo tests_namespaces.o: $(srcdir)/tests_namespaces.c $(srcdir)/testmessages.h ../getdns/getdns.h
|
tests_list.lo tests_list.o: $(srcdir)/tests_list.c $(srcdir)/testmessages.h \
|
||||||
tests_stub_async.lo tests_stub_async.o: $(srcdir)/tests_stub_async.c ../config.h $(srcdir)/testmessages.h \
|
../getdns/getdns.h
|
||||||
../getdns/getdns.h ../getdns/getdns_extra.h
|
tests_namespaces.lo tests_namespaces.o: $(srcdir)/tests_namespaces.c $(srcdir)/testmessages.h \
|
||||||
tests_stub_sync.lo tests_stub_sync.o: $(srcdir)/tests_stub_sync.c $(srcdir)/testmessages.h ../getdns/getdns.h \
|
../getdns/getdns.h
|
||||||
|
tests_stub_async.lo tests_stub_async.o: $(srcdir)/tests_stub_async.c \
|
||||||
|
../config.h $(srcdir)/testmessages.h \
|
||||||
|
../getdns/getdns.h \
|
||||||
|
../getdns/getdns_extra.h
|
||||||
|
tests_stub_sync.lo tests_stub_sync.o: $(srcdir)/tests_stub_sync.c $(srcdir)/testmessages.h \
|
||||||
|
../getdns/getdns.h \
|
||||||
../getdns/getdns_extra.h
|
../getdns/getdns_extra.h
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
mkdir ub || true
|
mkdir ub || true
|
||||||
cd ub
|
cd ub
|
||||||
for f in mini_event.c mini_event.h rbtree.c rbtree.h
|
for f in rbtree.c rbtree.h
|
||||||
do
|
do
|
||||||
wget http://unbound.net/svn/trunk/util/$f || \
|
wget http://unbound.net/svn/trunk/util/$f || \
|
||||||
ftp http://unbound.net/svn/trunk/util/$f || continue
|
ftp http://unbound.net/svn/trunk/util/$f || continue
|
||||||
|
|
|
@ -1,394 +0,0 @@
|
||||||
/*
|
|
||||||
* mini_event.c - implementation of part of libevent api, portably.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2007, NLnet Labs. All rights reserved.
|
|
||||||
*
|
|
||||||
* This software is open source.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
*
|
|
||||||
* Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* Neither the name of the NLNET LABS nor the names of its contributors may
|
|
||||||
* be used to endorse or promote products derived from this software without
|
|
||||||
* specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
|
||||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
||||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
||||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \file
|
|
||||||
* fake libevent implementation. Less broad in functionality, and only
|
|
||||||
* supports select(2).
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#ifdef HAVE_TIME_H
|
|
||||||
#include <time.h>
|
|
||||||
#endif
|
|
||||||
#include <sys/time.h>
|
|
||||||
|
|
||||||
#if defined(USE_MINI_EVENT) && !defined(USE_WINSOCK)
|
|
||||||
#include <signal.h>
|
|
||||||
#include "util/mini_event.h"
|
|
||||||
#include "util/fptr_wlist.h"
|
|
||||||
|
|
||||||
/** compare events in tree, based on timevalue, ptr for uniqueness */
|
|
||||||
int _getdns_mini_ev_cmp(const void* a, const void* b)
|
|
||||||
{
|
|
||||||
const struct _getdns_event *e = (const struct _getdns_event*)a;
|
|
||||||
const struct _getdns_event *f = (const struct _getdns_event*)b;
|
|
||||||
if(e->ev_timeout.tv_sec < f->ev_timeout.tv_sec)
|
|
||||||
return -1;
|
|
||||||
if(e->ev_timeout.tv_sec > f->ev_timeout.tv_sec)
|
|
||||||
return 1;
|
|
||||||
if(e->ev_timeout.tv_usec < f->ev_timeout.tv_usec)
|
|
||||||
return -1;
|
|
||||||
if(e->ev_timeout.tv_usec > f->ev_timeout.tv_usec)
|
|
||||||
return 1;
|
|
||||||
if(e < f)
|
|
||||||
return -1;
|
|
||||||
if(e > f)
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** set time */
|
|
||||||
static int
|
|
||||||
settime(struct _getdns_event_base* base)
|
|
||||||
{
|
|
||||||
if(gettimeofday(base->time_tv, NULL) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
#ifndef S_SPLINT_S
|
|
||||||
*base->time_secs = (time_t)base->time_tv->tv_sec;
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** create event base */
|
|
||||||
void *_getdns_event_init(time_t* time_secs, struct timeval* time_tv)
|
|
||||||
{
|
|
||||||
struct _getdns_event_base* base = (struct _getdns_event_base*)malloc(
|
|
||||||
sizeof(struct _getdns_event_base));
|
|
||||||
if(!base)
|
|
||||||
return NULL;
|
|
||||||
memset(base, 0, sizeof(*base));
|
|
||||||
base->time_secs = time_secs;
|
|
||||||
base->time_tv = time_tv;
|
|
||||||
if(settime(base) < 0) {
|
|
||||||
_getdns_event_base_free(base);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
base->times = _getdns_rbtree_create(_getdns_mini_ev_cmp);
|
|
||||||
if(!base->times) {
|
|
||||||
_getdns_event_base_free(base);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
base->capfd = MAX_FDS;
|
|
||||||
#ifdef FD_SETSIZE
|
|
||||||
if((int)FD_SETSIZE < base->capfd)
|
|
||||||
base->capfd = (int)FD_SETSIZE;
|
|
||||||
#endif
|
|
||||||
base->fds = (struct _getdns_event**)calloc((size_t)base->capfd,
|
|
||||||
sizeof(struct _getdns_event*));
|
|
||||||
if(!base->fds) {
|
|
||||||
_getdns_event_base_free(base);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
base->signals = (struct _getdns_event**)calloc(MAX_SIG, sizeof(struct _getdns_event*));
|
|
||||||
if(!base->signals) {
|
|
||||||
_getdns_event_base_free(base);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
#ifndef S_SPLINT_S
|
|
||||||
FD_ZERO(&base->reads);
|
|
||||||
FD_ZERO(&base->writes);
|
|
||||||
#endif
|
|
||||||
return base;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** get version */
|
|
||||||
const char *_getdns_event_get_version(void)
|
|
||||||
{
|
|
||||||
return "mini-event-"PACKAGE_VERSION;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** get polling method, select */
|
|
||||||
const char *_getdns_event_get_method(void)
|
|
||||||
{
|
|
||||||
return "select";
|
|
||||||
}
|
|
||||||
|
|
||||||
/** call timeouts handlers, and return how long to wait for next one or -1 */
|
|
||||||
void _getdns_handle_timeouts(struct _getdns_event_base* base, struct timeval* now,
|
|
||||||
struct timeval* wait)
|
|
||||||
{
|
|
||||||
struct _getdns_event* p;
|
|
||||||
#ifndef S_SPLINT_S
|
|
||||||
wait->tv_sec = (time_t)-1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
while((_getdns_rbnode_t*)(p = (struct _getdns_event*)_getdns_rbtree_first(base->times))
|
|
||||||
!=RBTREE_NULL) {
|
|
||||||
#ifndef S_SPLINT_S
|
|
||||||
if(p->ev_timeout.tv_sec > now->tv_sec ||
|
|
||||||
(p->ev_timeout.tv_sec==now->tv_sec &&
|
|
||||||
p->ev_timeout.tv_usec > now->tv_usec)) {
|
|
||||||
/* there is a next larger timeout. wait for it */
|
|
||||||
wait->tv_sec = p->ev_timeout.tv_sec - now->tv_sec;
|
|
||||||
if(now->tv_usec > p->ev_timeout.tv_usec) {
|
|
||||||
wait->tv_sec--;
|
|
||||||
wait->tv_usec = 1000000 - (now->tv_usec -
|
|
||||||
p->ev_timeout.tv_usec);
|
|
||||||
} else {
|
|
||||||
wait->tv_usec = p->ev_timeout.tv_usec
|
|
||||||
- now->tv_usec;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
/* event times out, remove it */
|
|
||||||
(void)_getdns_rbtree_delete(base->times, p);
|
|
||||||
p->ev_events &= ~EV_TIMEOUT;
|
|
||||||
fptr_ok(fptr_whitelist_event(p->ev_callback));
|
|
||||||
(*p->ev_callback)(p->ev_fd, EV_TIMEOUT, p->ev_arg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** call select and callbacks for that */
|
|
||||||
int _getdns_handle_select(struct _getdns_event_base* base, struct timeval* wait)
|
|
||||||
{
|
|
||||||
fd_set r, w;
|
|
||||||
int ret, i;
|
|
||||||
|
|
||||||
#ifndef S_SPLINT_S
|
|
||||||
if(wait->tv_sec==(time_t)-1)
|
|
||||||
wait = NULL;
|
|
||||||
#endif
|
|
||||||
memmove(&r, &base->reads, sizeof(fd_set));
|
|
||||||
memmove(&w, &base->writes, sizeof(fd_set));
|
|
||||||
memmove(&base->ready, &base->content, sizeof(fd_set));
|
|
||||||
|
|
||||||
if((ret = select(base->maxfd+1, &r, &w, NULL, wait)) == -1) {
|
|
||||||
ret = errno;
|
|
||||||
if(settime(base) < 0)
|
|
||||||
return -1;
|
|
||||||
errno = ret;
|
|
||||||
if(ret == EAGAIN || ret == EINTR)
|
|
||||||
return 0;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if(settime(base) < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
for(i=0; i<base->maxfd+1; i++) {
|
|
||||||
short bits = 0;
|
|
||||||
if(!base->fds[i] || !(FD_ISSET(i, &base->ready))) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if(FD_ISSET(i, &r)) {
|
|
||||||
bits |= EV_READ;
|
|
||||||
ret--;
|
|
||||||
}
|
|
||||||
if(FD_ISSET(i, &w)) {
|
|
||||||
bits |= EV_WRITE;
|
|
||||||
ret--;
|
|
||||||
}
|
|
||||||
bits &= base->fds[i]->ev_events;
|
|
||||||
if(bits) {
|
|
||||||
fptr_ok(fptr_whitelist_event(
|
|
||||||
base->fds[i]->ev_callback));
|
|
||||||
(*base->fds[i]->ev_callback)(base->fds[i]->ev_fd,
|
|
||||||
bits, base->fds[i]->ev_arg);
|
|
||||||
if(ret==0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** run select in a loop */
|
|
||||||
int _getdns_event_base_dispatch(struct _getdns_event_base* base)
|
|
||||||
{
|
|
||||||
struct timeval wait;
|
|
||||||
if(settime(base) < 0)
|
|
||||||
return -1;
|
|
||||||
while(!base->need_to_exit)
|
|
||||||
{
|
|
||||||
/* see if timeouts need handling */
|
|
||||||
_getdns_handle_timeouts(base, base->time_tv, &wait);
|
|
||||||
if(base->need_to_exit)
|
|
||||||
return 0;
|
|
||||||
/* do select */
|
|
||||||
if(_getdns_handle_select(base, &wait) < 0) {
|
|
||||||
if(base->need_to_exit)
|
|
||||||
return 0;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** exit that loop */
|
|
||||||
int _getdns_event_base_loopexit(struct _getdns_event_base* base,
|
|
||||||
struct timeval* ATTR_UNUSED(tv))
|
|
||||||
{
|
|
||||||
base->need_to_exit = 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* free event base, free events yourself */
|
|
||||||
void _getdns_event_base_free(struct _getdns_event_base* base)
|
|
||||||
{
|
|
||||||
if(!base)
|
|
||||||
return;
|
|
||||||
if(base->times)
|
|
||||||
free(base->times);
|
|
||||||
if(base->fds)
|
|
||||||
free(base->fds);
|
|
||||||
if(base->signals)
|
|
||||||
free(base->signals);
|
|
||||||
free(base);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** set content of event */
|
|
||||||
void _getdns_event_set(struct _getdns_event* ev, int fd, short bits,
|
|
||||||
void (*cb)(int, short, void *), void* arg)
|
|
||||||
{
|
|
||||||
ev->node.key = ev;
|
|
||||||
ev->ev_fd = fd;
|
|
||||||
ev->ev_events = bits;
|
|
||||||
ev->ev_callback = cb;
|
|
||||||
fptr_ok(fptr_whitelist_event(ev->ev_callback));
|
|
||||||
ev->ev_arg = arg;
|
|
||||||
ev->added = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* add event to a base */
|
|
||||||
int _getdns_event_base_set(struct _getdns_event_base* base, struct _getdns_event* ev)
|
|
||||||
{
|
|
||||||
ev->ev_base = base;
|
|
||||||
ev->added = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* add event to make it active, you may not change it with _getdns_event_set anymore */
|
|
||||||
int _getdns_event_add(struct _getdns_event* ev, struct timeval* tv)
|
|
||||||
{
|
|
||||||
if(ev->added)
|
|
||||||
_getdns_event_del(ev);
|
|
||||||
if(ev->ev_fd != -1 && ev->ev_fd >= ev->ev_base->capfd)
|
|
||||||
return -1;
|
|
||||||
if( (ev->ev_events&(EV_READ|EV_WRITE)) && ev->ev_fd != -1) {
|
|
||||||
ev->ev_base->fds[ev->ev_fd] = ev;
|
|
||||||
if(ev->ev_events&EV_READ) {
|
|
||||||
FD_SET(FD_SET_T ev->ev_fd, &ev->ev_base->reads);
|
|
||||||
}
|
|
||||||
if(ev->ev_events&EV_WRITE) {
|
|
||||||
FD_SET(FD_SET_T ev->ev_fd, &ev->ev_base->writes);
|
|
||||||
}
|
|
||||||
FD_SET(FD_SET_T ev->ev_fd, &ev->ev_base->content);
|
|
||||||
FD_CLR(FD_SET_T ev->ev_fd, &ev->ev_base->ready);
|
|
||||||
if(ev->ev_fd > ev->ev_base->maxfd)
|
|
||||||
ev->ev_base->maxfd = ev->ev_fd;
|
|
||||||
}
|
|
||||||
if(tv && (ev->ev_events&EV_TIMEOUT)) {
|
|
||||||
#ifndef S_SPLINT_S
|
|
||||||
struct timeval *now = ev->ev_base->time_tv;
|
|
||||||
ev->ev_timeout.tv_sec = tv->tv_sec + now->tv_sec;
|
|
||||||
ev->ev_timeout.tv_usec = tv->tv_usec + now->tv_usec;
|
|
||||||
while(ev->ev_timeout.tv_usec > 1000000) {
|
|
||||||
ev->ev_timeout.tv_usec -= 1000000;
|
|
||||||
ev->ev_timeout.tv_sec++;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
(void)_getdns_rbtree_insert(ev->ev_base->times, &ev->node);
|
|
||||||
}
|
|
||||||
ev->added = 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* remove event, you may change it again */
|
|
||||||
int _getdns_event_del(struct _getdns_event* ev)
|
|
||||||
{
|
|
||||||
if(ev->ev_fd != -1 && ev->ev_fd >= ev->ev_base->capfd)
|
|
||||||
return -1;
|
|
||||||
if((ev->ev_events&EV_TIMEOUT))
|
|
||||||
(void)_getdns_rbtree_delete(ev->ev_base->times, &ev->node);
|
|
||||||
if((ev->ev_events&(EV_READ|EV_WRITE)) && ev->ev_fd != -1) {
|
|
||||||
ev->ev_base->fds[ev->ev_fd] = NULL;
|
|
||||||
FD_CLR(FD_SET_T ev->ev_fd, &ev->ev_base->reads);
|
|
||||||
FD_CLR(FD_SET_T ev->ev_fd, &ev->ev_base->writes);
|
|
||||||
FD_CLR(FD_SET_T ev->ev_fd, &ev->ev_base->ready);
|
|
||||||
FD_CLR(FD_SET_T ev->ev_fd, &ev->ev_base->content);
|
|
||||||
}
|
|
||||||
ev->added = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** which base gets to handle signals */
|
|
||||||
static struct _getdns_event_base* signal_base = NULL;
|
|
||||||
/** signal handler */
|
|
||||||
static RETSIGTYPE sigh(int sig)
|
|
||||||
{
|
|
||||||
struct _getdns_event* ev;
|
|
||||||
if(!signal_base || sig < 0 || sig >= MAX_SIG)
|
|
||||||
return;
|
|
||||||
ev = signal_base->signals[sig];
|
|
||||||
if(!ev)
|
|
||||||
return;
|
|
||||||
fptr_ok(fptr_whitelist_event(ev->ev_callback));
|
|
||||||
(*ev->ev_callback)(sig, EV_SIGNAL, ev->ev_arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** install signal handler */
|
|
||||||
int _getdns_signal_add(struct _getdns_event* ev, struct timeval* ATTR_UNUSED(tv))
|
|
||||||
{
|
|
||||||
if(ev->ev_fd == -1 || ev->ev_fd >= MAX_SIG)
|
|
||||||
return -1;
|
|
||||||
signal_base = ev->ev_base;
|
|
||||||
ev->ev_base->signals[ev->ev_fd] = ev;
|
|
||||||
ev->added = 1;
|
|
||||||
if(signal(ev->ev_fd, sigh) == SIG_ERR) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** remove signal handler */
|
|
||||||
int _getdns_signal_del(struct _getdns_event* ev)
|
|
||||||
{
|
|
||||||
if(ev->ev_fd == -1 || ev->ev_fd >= MAX_SIG)
|
|
||||||
return -1;
|
|
||||||
ev->ev_base->signals[ev->ev_fd] = NULL;
|
|
||||||
ev->added = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else /* USE_MINI_EVENT */
|
|
||||||
#ifndef USE_WINSOCK
|
|
||||||
int _getdns_mini_ev_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif /* not USE_WINSOCK */
|
|
||||||
#endif /* USE_MINI_EVENT */
|
|
|
@ -1,178 +0,0 @@
|
||||||
/*
|
|
||||||
* mini-event.h - micro implementation of libevent api, using select() only.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2007, NLnet Labs. All rights reserved.
|
|
||||||
*
|
|
||||||
* This software is open source.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
*
|
|
||||||
* Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* Neither the name of the NLNET LABS nor the names of its contributors may
|
|
||||||
* be used to endorse or promote products derived from this software without
|
|
||||||
* specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
|
||||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
||||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
||||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \file
|
|
||||||
* This file implements part of the event(3) libevent api.
|
|
||||||
* The back end is only select. Max number of fds is limited.
|
|
||||||
* Max number of signals is limited, one handler per signal only.
|
|
||||||
* And one handler per fd.
|
|
||||||
*
|
|
||||||
* Although limited to select() and a max (1024) open fds, it
|
|
||||||
* is efficient:
|
|
||||||
* o dispatch call caches fd_sets to use.
|
|
||||||
* o handler calling takes time ~ to the number of fds.
|
|
||||||
* o timeouts are stored in a redblack tree, sorted, so take log(n).
|
|
||||||
* Timeouts are only accurate to the second (no subsecond accuracy).
|
|
||||||
* To avoid cpu hogging, fractional timeouts are rounded up to a whole second.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef MINI_EVENT_H
|
|
||||||
#define MINI_EVENT_H
|
|
||||||
|
|
||||||
#if defined(USE_MINI_EVENT) && !defined(USE_WINSOCK)
|
|
||||||
|
|
||||||
#ifndef HAVE_EVENT_BASE_FREE
|
|
||||||
#define HAVE_EVENT_BASE_FREE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/** event timeout */
|
|
||||||
#define EV_TIMEOUT 0x01
|
|
||||||
/** event fd readable */
|
|
||||||
#define EV_READ 0x02
|
|
||||||
/** event fd writable */
|
|
||||||
#define EV_WRITE 0x04
|
|
||||||
/** event signal */
|
|
||||||
#define EV_SIGNAL 0x08
|
|
||||||
/** event must persist */
|
|
||||||
#define EV_PERSIST 0x10
|
|
||||||
|
|
||||||
/* needs our redblack tree */
|
|
||||||
#include "util/rbtree.h"
|
|
||||||
|
|
||||||
/** max number of file descriptors to support */
|
|
||||||
#define MAX_FDS 1024
|
|
||||||
/** max number of signals to support */
|
|
||||||
#define MAX_SIG 32
|
|
||||||
|
|
||||||
/** event base */
|
|
||||||
struct _getdns_event_base
|
|
||||||
{
|
|
||||||
/** sorted by timeout (absolute), ptr */
|
|
||||||
_getdns_rbtree_t* times;
|
|
||||||
/** array of 0 - maxfd of ptr to event for it */
|
|
||||||
struct _getdns_event** fds;
|
|
||||||
/** max fd in use */
|
|
||||||
int maxfd;
|
|
||||||
/** capacity - size of the fds array */
|
|
||||||
int capfd;
|
|
||||||
/* fdset for read write, for fds ready, and added */
|
|
||||||
fd_set
|
|
||||||
/** fds for reading */
|
|
||||||
reads,
|
|
||||||
/** fds for writing */
|
|
||||||
writes,
|
|
||||||
/** fds determined ready for use */
|
|
||||||
ready,
|
|
||||||
/** ready plus newly added events. */
|
|
||||||
content;
|
|
||||||
/** array of 0 - maxsig of ptr to event for it */
|
|
||||||
struct _getdns_event** signals;
|
|
||||||
/** if we need to exit */
|
|
||||||
int need_to_exit;
|
|
||||||
/** where to store time in seconds */
|
|
||||||
time_t* time_secs;
|
|
||||||
/** where to store time in microseconds */
|
|
||||||
struct timeval* time_tv;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Event structure. Has some of the event elements.
|
|
||||||
*/
|
|
||||||
struct _getdns_event {
|
|
||||||
/** node in timeout rbtree */
|
|
||||||
_getdns_rbnode_t node;
|
|
||||||
/** is event already added */
|
|
||||||
int added;
|
|
||||||
|
|
||||||
/** event base it belongs to */
|
|
||||||
struct _getdns_event_base *ev_base;
|
|
||||||
/** fd to poll or -1 for timeouts. signal number for sigs. */
|
|
||||||
int ev_fd;
|
|
||||||
/** what events this event is interested in, see EV_.. above. */
|
|
||||||
short ev_events;
|
|
||||||
/** timeout value */
|
|
||||||
struct timeval ev_timeout;
|
|
||||||
|
|
||||||
/** callback to call: fd, eventbits, userarg */
|
|
||||||
void (*ev_callback)(int, short, void *arg);
|
|
||||||
/** callback user arg */
|
|
||||||
void *ev_arg;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* function prototypes (some are as they appear in event.h) */
|
|
||||||
/** create event base */
|
|
||||||
void *_getdns_event_init(time_t* time_secs, struct timeval* time_tv);
|
|
||||||
/** get version */
|
|
||||||
const char *_getdns_event_get_version(void);
|
|
||||||
/** get polling method, select */
|
|
||||||
const char *_getdns_event_get_method(void);
|
|
||||||
/** run select in a loop */
|
|
||||||
int _getdns_event_base_dispatch(struct _getdns_event_base *);
|
|
||||||
/** exit that loop */
|
|
||||||
int _getdns_event_base_loopexit(struct _getdns_event_base *, struct timeval *);
|
|
||||||
/** free event base. Free events yourself */
|
|
||||||
void _getdns_event_base_free(struct _getdns_event_base *);
|
|
||||||
/** set content of event */
|
|
||||||
void _getdns_event_set(struct _getdns_event *, int, short, void (*)(int, short, void *), void *);
|
|
||||||
/** add event to a base. You *must* call this for every event. */
|
|
||||||
int _getdns_event_base_set(struct _getdns_event_base *, struct _getdns_event *);
|
|
||||||
/** add event to make it active. You may not change it with _getdns_event_set anymore */
|
|
||||||
int _getdns_event_add(struct _getdns_event *, struct timeval *);
|
|
||||||
/** remove event. You may change it again */
|
|
||||||
int _getdns_event_del(struct _getdns_event *);
|
|
||||||
|
|
||||||
/** add a timer */
|
|
||||||
#define _getdns_evtimer_add(ev, tv) _getdns_event_add(ev, tv)
|
|
||||||
/** remove a timer */
|
|
||||||
#define _getdns_evtimer_del(ev) _getdns_event_del(ev)
|
|
||||||
|
|
||||||
/* uses different implementation. Cannot mix fd/timeouts and signals inside
|
|
||||||
* the same struct _getdns_event. create several event structs for that. */
|
|
||||||
/** install signal handler */
|
|
||||||
int _getdns_signal_add(struct _getdns_event *, struct timeval *);
|
|
||||||
/** set signal event contents */
|
|
||||||
#define _getdns_signal_set(ev, x, cb, arg) \
|
|
||||||
_getdns_event_set(ev, x, EV_SIGNAL|EV_PERSIST, cb, arg)
|
|
||||||
/** remove signal handler */
|
|
||||||
int _getdns_signal_del(struct _getdns_event *);
|
|
||||||
|
|
||||||
#endif /* USE_MINI_EVENT and not USE_WINSOCK */
|
|
||||||
|
|
||||||
/** compare events in tree, based on timevalue, ptr for uniqueness */
|
|
||||||
int _getdns_mini_ev_cmp(const void* a, const void* b);
|
|
||||||
|
|
||||||
#endif /* MINI_EVENT_H */
|
|
|
@ -1,844 +0,0 @@
|
||||||
/*
|
|
||||||
* util/winsock_event.c - implementation of the getdns winsock event handler.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2015, Verisign/NLnet Labs. All rights reserved.
|
|
||||||
*
|
|
||||||
* This software is open source.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
*
|
|
||||||
* Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* Neither the name of the NLNET LABS/Verisign nor the names of its contributors may
|
|
||||||
* be used to endorse or promote products derived from this software without
|
|
||||||
* specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
|
||||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
||||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
||||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* \file
|
|
||||||
* Implementation of the getdns WinSock2 API event notification handler
|
|
||||||
* for the getdns Windows port.
|
|
||||||
* Code is originally from the Unbound source for Windows.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#ifdef USE_WINSOCK // only included for Windows builds
|
|
||||||
#include <signal.h>
|
|
||||||
#ifdef HAVE_TIME_H
|
|
||||||
#include <time.h>
|
|
||||||
#endif
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include "util/winsock_event.h"
|
|
||||||
#include "util/fptr_wlist.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* implementation of log_err
|
|
||||||
* @param format: format string printf-style.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
log_err(const char *format, ...)
|
|
||||||
{
|
|
||||||
va_list args;
|
|
||||||
va_start(args, format);
|
|
||||||
fprintf(stderr, "error ");
|
|
||||||
fprintf(stderr, format, args);
|
|
||||||
va_end(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
char* wsa_strerror(DWORD err)
|
|
||||||
{
|
|
||||||
static char unknown[32];
|
|
||||||
|
|
||||||
switch (err) {
|
|
||||||
case WSA_INVALID_HANDLE: return "Specified event object handle is invalid.";
|
|
||||||
case WSA_NOT_ENOUGH_MEMORY: return "Insufficient memory available.";
|
|
||||||
case WSA_INVALID_PARAMETER: return "One or more parameters are invalid.";
|
|
||||||
case WSA_OPERATION_ABORTED: return "Overlapped operation aborted.";
|
|
||||||
case WSA_IO_INCOMPLETE: return "Overlapped I/O event object not in signaled state.";
|
|
||||||
case WSA_IO_PENDING: return "Overlapped operations will complete later.";
|
|
||||||
case WSAEINTR: return "Interrupted function call.";
|
|
||||||
case WSAEBADF: return "File handle is not valid.";
|
|
||||||
case WSAEACCES: return "Permission denied.";
|
|
||||||
case WSAEFAULT: return "Bad address.";
|
|
||||||
case WSAEINVAL: return "Invalid argument.";
|
|
||||||
case WSAEMFILE: return "Too many open files.";
|
|
||||||
case WSAEWOULDBLOCK: return "Resource temporarily unavailable.";
|
|
||||||
case WSAEINPROGRESS: return "Operation now in progress.";
|
|
||||||
case WSAEALREADY: return "Operation already in progress.";
|
|
||||||
case WSAENOTSOCK: return "Socket operation on nonsocket.";
|
|
||||||
case WSAEDESTADDRREQ: return "Destination address required.";
|
|
||||||
case WSAEMSGSIZE: return "Message too long.";
|
|
||||||
case WSAEPROTOTYPE: return "Protocol wrong type for socket.";
|
|
||||||
case WSAENOPROTOOPT: return "Bad protocol option.";
|
|
||||||
case WSAEPROTONOSUPPORT: return "Protocol not supported.";
|
|
||||||
case WSAESOCKTNOSUPPORT: return "Socket type not supported.";
|
|
||||||
case WSAEOPNOTSUPP: return "Operation not supported.";
|
|
||||||
case WSAEPFNOSUPPORT: return "Protocol family not supported.";
|
|
||||||
case WSAEAFNOSUPPORT: return "Address family not supported by protocol family.";
|
|
||||||
case WSAEADDRINUSE: return "Address already in use.";
|
|
||||||
case WSAEADDRNOTAVAIL: return "Cannot assign requested address.";
|
|
||||||
case WSAENETDOWN: return "Network is down.";
|
|
||||||
case WSAENETUNREACH: return "Network is unreachable.";
|
|
||||||
case WSAENETRESET: return "Network dropped connection on reset.";
|
|
||||||
case WSAECONNABORTED: return "Software caused connection abort.";
|
|
||||||
case WSAECONNRESET: return "Connection reset by peer.";
|
|
||||||
case WSAENOBUFS: return "No buffer space available.";
|
|
||||||
case WSAEISCONN: return "Socket is already connected.";
|
|
||||||
case WSAENOTCONN: return "Socket is not connected.";
|
|
||||||
case WSAESHUTDOWN: return "Cannot send after socket shutdown.";
|
|
||||||
case WSAETOOMANYREFS: return "Too many references.";
|
|
||||||
case WSAETIMEDOUT: return "Connection timed out.";
|
|
||||||
case WSAECONNREFUSED: return "Connection refused.";
|
|
||||||
case WSAELOOP: return "Cannot translate name.";
|
|
||||||
case WSAENAMETOOLONG: return "Name too long.";
|
|
||||||
case WSAEHOSTDOWN: return "Host is down.";
|
|
||||||
case WSAEHOSTUNREACH: return "No route to host.";
|
|
||||||
case WSAENOTEMPTY: return "Directory not empty.";
|
|
||||||
case WSAEPROCLIM: return "Too many processes.";
|
|
||||||
case WSAEUSERS: return "User quota exceeded.";
|
|
||||||
case WSAEDQUOT: return "Disk quota exceeded.";
|
|
||||||
case WSAESTALE: return "Stale file handle reference.";
|
|
||||||
case WSAEREMOTE: return "Item is remote.";
|
|
||||||
case WSASYSNOTREADY: return "Network subsystem is unavailable.";
|
|
||||||
case WSAVERNOTSUPPORTED: return "Winsock.dll version out of range.";
|
|
||||||
case WSANOTINITIALISED: return "Successful WSAStartup not yet performed.";
|
|
||||||
case WSAEDISCON: return "Graceful shutdown in progress.";
|
|
||||||
case WSAENOMORE: return "No more results.";
|
|
||||||
case WSAECANCELLED: return "Call has been canceled.";
|
|
||||||
case WSAEINVALIDPROCTABLE: return "Procedure call table is invalid.";
|
|
||||||
case WSAEINVALIDPROVIDER: return "Service provider is invalid.";
|
|
||||||
case WSAEPROVIDERFAILEDINIT: return "Service provider failed to initialize.";
|
|
||||||
case WSASYSCALLFAILURE: return "System call failure.";
|
|
||||||
case WSASERVICE_NOT_FOUND: return "Service not found.";
|
|
||||||
case WSATYPE_NOT_FOUND: return "Class type not found.";
|
|
||||||
case WSA_E_NO_MORE: return "No more results.";
|
|
||||||
case WSA_E_CANCELLED: return "Call was canceled.";
|
|
||||||
case WSAEREFUSED: return "Database query was refused.";
|
|
||||||
case WSAHOST_NOT_FOUND: return "Host not found.";
|
|
||||||
case WSATRY_AGAIN: return "Nonauthoritative host not found.";
|
|
||||||
case WSANO_RECOVERY: return "This is a nonrecoverable error.";
|
|
||||||
case WSANO_DATA: return "Valid name, no data record of requested type.";
|
|
||||||
case WSA_QOS_RECEIVERS: return "QOS receivers.";
|
|
||||||
case WSA_QOS_SENDERS: return "QOS senders.";
|
|
||||||
case WSA_QOS_NO_SENDERS: return "No QOS senders.";
|
|
||||||
case WSA_QOS_NO_RECEIVERS: return "QOS no receivers.";
|
|
||||||
case WSA_QOS_REQUEST_CONFIRMED: return "QOS request confirmed.";
|
|
||||||
case WSA_QOS_ADMISSION_FAILURE: return "QOS admission error.";
|
|
||||||
case WSA_QOS_POLICY_FAILURE: return "QOS policy failure.";
|
|
||||||
case WSA_QOS_BAD_STYLE: return "QOS bad style.";
|
|
||||||
case WSA_QOS_BAD_OBJECT: return "QOS bad object.";
|
|
||||||
case WSA_QOS_TRAFFIC_CTRL_ERROR: return "QOS traffic control error.";
|
|
||||||
case WSA_QOS_GENERIC_ERROR: return "QOS generic error.";
|
|
||||||
case WSA_QOS_ESERVICETYPE: return "QOS service type error.";
|
|
||||||
case WSA_QOS_EFLOWSPEC: return "QOS flowspec error.";
|
|
||||||
case WSA_QOS_EPROVSPECBUF: return "Invalid QOS provider buffer.";
|
|
||||||
case WSA_QOS_EFILTERSTYLE: return "Invalid QOS filter style.";
|
|
||||||
case WSA_QOS_EFILTERTYPE: return "Invalid QOS filter type.";
|
|
||||||
case WSA_QOS_EFILTERCOUNT: return "Incorrect QOS filter count.";
|
|
||||||
case WSA_QOS_EOBJLENGTH: return "Invalid QOS object length.";
|
|
||||||
case WSA_QOS_EFLOWCOUNT: return "Incorrect QOS flow count.";
|
|
||||||
/*case WSA_QOS_EUNKOWNPSOBJ: return "Unrecognized QOS object.";*/
|
|
||||||
case WSA_QOS_EPOLICYOBJ: return "Invalid QOS policy object.";
|
|
||||||
case WSA_QOS_EFLOWDESC: return "Invalid QOS flow descriptor.";
|
|
||||||
case WSA_QOS_EPSFLOWSPEC: return "Invalid QOS provider-specific flowspec.";
|
|
||||||
case WSA_QOS_EPSFILTERSPEC: return "Invalid QOS provider-specific filterspec.";
|
|
||||||
case WSA_QOS_ESDMODEOBJ: return "Invalid QOS shape discard mode object.";
|
|
||||||
case WSA_QOS_ESHAPERATEOBJ: return "Invalid QOS shaping rate object.";
|
|
||||||
case WSA_QOS_RESERVED_PETYPE: return "Reserved policy QOS element type.";
|
|
||||||
default:
|
|
||||||
snprintf(unknown, sizeof(unknown),
|
|
||||||
"unknown WSA error code %d", (int)err);
|
|
||||||
return unknown;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int _getdns_mini_ev_cmp(const void* a, const void* b)
|
|
||||||
{
|
|
||||||
const struct _getdns_event *e = (const struct _getdns_event*)a;
|
|
||||||
const struct _getdns_event *f = (const struct _getdns_event*)b;
|
|
||||||
if(e->ev_timeout.tv_sec < f->ev_timeout.tv_sec)
|
|
||||||
return -1;
|
|
||||||
if(e->ev_timeout.tv_sec > f->ev_timeout.tv_sec)
|
|
||||||
return 1;
|
|
||||||
if(e->ev_timeout.tv_usec < f->ev_timeout.tv_usec)
|
|
||||||
return -1;
|
|
||||||
if(e->ev_timeout.tv_usec > f->ev_timeout.tv_usec)
|
|
||||||
return 1;
|
|
||||||
if(e < f)
|
|
||||||
return -1;
|
|
||||||
if(e > f)
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** set time */
|
|
||||||
static int
|
|
||||||
settime(struct _getdns_event_base* base)
|
|
||||||
{
|
|
||||||
if(gettimeofday(base->time_tv, NULL) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
#ifndef S_SPLINT_S
|
|
||||||
*base->time_secs = (time_t)base->time_tv->tv_sec;
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef WINSOCK_DEBUG
|
|
||||||
/**
|
|
||||||
* Find a fd in the list of items.
|
|
||||||
* Note that not all items have a fd associated (those are -1).
|
|
||||||
* Signals are stored separately, and not searched.
|
|
||||||
* @param base: event base to look in.
|
|
||||||
* @param fd: what socket to look for.
|
|
||||||
* @return the index in the array, or -1 on failure.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
find_fd(struct _getdns_event_base* base, int fd)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for(i=0; i<base->max; i++) {
|
|
||||||
if(base->items[i]->ev_fd == fd)
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** Find ptr in base array */
|
|
||||||
static void
|
|
||||||
zero_waitfor(WSAEVENT waitfor[], WSAEVENT x)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for(i=0; i<WSK_MAX_ITEMS; i++) {
|
|
||||||
if(waitfor[i] == x)
|
|
||||||
waitfor[i] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void *_getdns_event_init(time_t* time_secs, struct timeval* time_tv)
|
|
||||||
{
|
|
||||||
struct _getdns_event_base* base = (struct _getdns_event_base*)malloc(
|
|
||||||
sizeof(struct _getdns_event_base));
|
|
||||||
if(!base)
|
|
||||||
return NULL;
|
|
||||||
memset(base, 0, sizeof(*base));
|
|
||||||
base->time_secs = time_secs;
|
|
||||||
base->time_tv = time_tv;
|
|
||||||
if(settime(base) < 0) {
|
|
||||||
_getdns_event_base_free(base);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
base->items = (struct _getdns_event**)calloc(WSK_MAX_ITEMS,
|
|
||||||
sizeof(struct _getdns_event*));
|
|
||||||
if(!base->items) {
|
|
||||||
_getdns_event_base_free(base);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
base->cap = WSK_MAX_ITEMS;
|
|
||||||
base->max = 0;
|
|
||||||
base->times = _getdns_rbtree_create(_getdns_mini_ev_cmp);
|
|
||||||
if(!base->times) {
|
|
||||||
_getdns_event_base_free(base);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
base->signals = (struct _getdns_event**)calloc(MAX_SIG,
|
|
||||||
sizeof(struct _getdns_event*));
|
|
||||||
if(!base->signals) {
|
|
||||||
_getdns_event_base_free(base);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
base->tcp_stickies = 0;
|
|
||||||
base->tcp_reinvigorated = 0;
|
|
||||||
|
|
||||||
return base;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *_getdns_event_get_version(void)
|
|
||||||
{
|
|
||||||
return "winsock-event-"PACKAGE_VERSION;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *_getdns_event_get_method(void)
|
|
||||||
{
|
|
||||||
return "WSAWaitForMultipleEvents";
|
|
||||||
}
|
|
||||||
|
|
||||||
/** call timeouts handlers, and return how long to wait for next one or -1 */
|
|
||||||
void _getdns_handle_timeouts(struct _getdns_event_base* base, struct timeval* now,
|
|
||||||
struct timeval* wait)
|
|
||||||
{
|
|
||||||
struct _getdns_event* p;
|
|
||||||
#ifndef S_SPLINT_S
|
|
||||||
wait->tv_sec = (time_t)-1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
while((_getdns_rbnode_t*)(p = (struct _getdns_event*)_getdns_rbtree_first(base->times))
|
|
||||||
!=RBTREE_NULL) {
|
|
||||||
#ifndef S_SPLINT_S
|
|
||||||
if(p->ev_timeout.tv_sec > now->tv_sec ||
|
|
||||||
(p->ev_timeout.tv_sec==now->tv_sec &&
|
|
||||||
p->ev_timeout.tv_usec > now->tv_usec)) {
|
|
||||||
/* there is a next larger timeout. wait for it */
|
|
||||||
wait->tv_sec = p->ev_timeout.tv_sec - now->tv_sec;
|
|
||||||
if(now->tv_usec > p->ev_timeout.tv_usec) {
|
|
||||||
wait->tv_sec--;
|
|
||||||
wait->tv_usec = 1000000 - (now->tv_usec -
|
|
||||||
p->ev_timeout.tv_usec);
|
|
||||||
} else {
|
|
||||||
wait->tv_usec = p->ev_timeout.tv_usec
|
|
||||||
- now->tv_usec;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
/* event times out, remove it */
|
|
||||||
(void)_getdns_rbtree_delete(base->times, p);
|
|
||||||
p->ev_events &= ~EV_TIMEOUT;
|
|
||||||
fptr_ok(fptr_whitelist_event(p->ev_callback));
|
|
||||||
(*p->ev_callback)(p->ev_fd, EV_TIMEOUT, p->ev_arg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** handle is_signal events and see if signalled */
|
|
||||||
static void _getdns_handle_signal(struct _getdns_event* ev)
|
|
||||||
{
|
|
||||||
printf("In _getdns_handle_signal\n");
|
|
||||||
DWORD ret;
|
|
||||||
//log_assert(ev->is_signal && ev->hEvent);
|
|
||||||
/* see if the event is signalled */
|
|
||||||
ret = WSAWaitForMultipleEvents(1, &ev->hEvent, 0 /* any object */,
|
|
||||||
0 /* return immediately */, 0 /* not alertable for IOcomple*/);
|
|
||||||
if(ret == WSA_WAIT_IO_COMPLETION || ret == WSA_WAIT_FAILED) {
|
|
||||||
log_err("getdns: WSAWaitForMultipleEvents(signal) failed: %s",
|
|
||||||
wsa_strerror(WSAGetLastError()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(ret == WSA_WAIT_TIMEOUT) {
|
|
||||||
/* not signalled */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* reset the signal */
|
|
||||||
if(!WSAResetEvent(ev->hEvent))
|
|
||||||
log_err("getdns: WSAResetEvent failed: %s",
|
|
||||||
wsa_strerror(WSAGetLastError()));
|
|
||||||
/* do the callback (which may set the signal again) */
|
|
||||||
fptr_ok(fptr_whitelist_event(ev->ev_callback));
|
|
||||||
(*ev->ev_callback)(ev->ev_fd, ev->ev_events, ev->ev_arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** call select and callbacks for that */
|
|
||||||
int _getdns_handle_select(struct _getdns_event_base* base, struct timeval* wait)
|
|
||||||
{
|
|
||||||
DWORD timeout = 0; /* in milliseconds */
|
|
||||||
DWORD ret;
|
|
||||||
WSANETWORKEVENTS netev;
|
|
||||||
struct _getdns_event* eventlist[WSK_MAX_ITEMS];
|
|
||||||
int i, numwait = 0, startidx = 0;
|
|
||||||
int newstickies = 0;
|
|
||||||
struct timeval nultm;
|
|
||||||
|
|
||||||
#ifndef S_SPLINT_S
|
|
||||||
if(wait->tv_sec==(time_t)-1)
|
|
||||||
wait = NULL;
|
|
||||||
if (wait)
|
|
||||||
// timeout = 10 + wait->tv_usec / 1000;
|
|
||||||
timeout = wait->tv_sec * 1000 + wait->tv_usec / 1000;
|
|
||||||
if(base->tcp_stickies) {
|
|
||||||
wait = &nultm;
|
|
||||||
nultm.tv_sec = 0;
|
|
||||||
nultm.tv_usec = 0;
|
|
||||||
timeout = 0; /* no waiting, we have sticky events */
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* prepare event array */
|
|
||||||
for(i=0; i<base->max; i++) {
|
|
||||||
if(base->items[i]->ev_fd == -1 && !base->items[i]->is_signal)
|
|
||||||
continue; /* skip timer only events */
|
|
||||||
eventlist[numwait] = base->items[i];
|
|
||||||
base->waitfor[numwait++] = base->items[i]->hEvent;
|
|
||||||
printf("winsock_event bmax=%d numwait=%d wait=%x "
|
|
||||||
"timeout=%d hEvent %d\n", base->max, numwait, (int)wait,
|
|
||||||
(int)timeout, (int)base->items[i]->hEvent);
|
|
||||||
if (numwait == WSK_MAX_ITEMS)
|
|
||||||
break; /* sanity check */
|
|
||||||
}
|
|
||||||
//log_assert(numwait <= WSA_MAXIMUM_WAIT_EVENTS);
|
|
||||||
|
|
||||||
/* do the wait */
|
|
||||||
if(numwait == 0) {
|
|
||||||
/* WSAWaitFor.. doesn't like 0 event objects */
|
|
||||||
if(wait) {
|
|
||||||
Sleep(timeout);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
//gv: do not schedule udp write
|
|
||||||
for (i = 0; i<base->max; i++) {
|
|
||||||
if (!base->items[i]->is_tcp && base->items[i]->ev_events&EV_WRITE) {
|
|
||||||
printf("skip UDP sched\n");
|
|
||||||
(*eventlist[i]->ev_callback)(eventlist[i]->ev_fd,
|
|
||||||
EV_WRITE & eventlist[i]->ev_events,
|
|
||||||
eventlist[i]->ev_arg);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf("before wait %d\n", base->items[0]->ev_events);
|
|
||||||
ret = WSAWaitForMultipleEvents(numwait, base->waitfor,
|
|
||||||
0 /* do not wait for all, just one will do */,
|
|
||||||
wait?timeout:WSA_INFINITE,
|
|
||||||
0); /* we are not alertable (IO completion events) */
|
|
||||||
printf("after wait %d %d\n", (int)ret, numwait);
|
|
||||||
if(ret == WSA_WAIT_IO_COMPLETION) {
|
|
||||||
//printf("getdns: WSAWaitForMultipleEvents failed: WSA_WAIT_IO_COMPLETION");
|
|
||||||
return -1;
|
|
||||||
} else if(ret == WSA_WAIT_FAILED) {
|
|
||||||
//printf("getdns: WSAWaitForMultipleEvents failed: %s",
|
|
||||||
// wsa_strerror(WSAGetLastError()));
|
|
||||||
return -1;
|
|
||||||
} else if(ret == WSA_WAIT_TIMEOUT) {
|
|
||||||
printf("timeout\n");
|
|
||||||
} else
|
|
||||||
startidx = ret - WSA_WAIT_EVENT_0;
|
|
||||||
}
|
|
||||||
////verbose(VERB_CLIENT, "winsock_event wake was_timeout=%d startidx=%d",
|
|
||||||
// was_timeout, startidx);
|
|
||||||
|
|
||||||
/* get new time after wait */
|
|
||||||
if(settime(base) < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* callbacks */
|
|
||||||
if(base->tcp_stickies)
|
|
||||||
startidx = 0; /* process all events, some are sticky */
|
|
||||||
for(i=startidx; i<numwait; i++)
|
|
||||||
eventlist[i]->just_checked = 1;
|
|
||||||
|
|
||||||
//verbose(VERB_CLIENT, "winsock_event signals");
|
|
||||||
for(i=startidx; i<numwait; i++) {
|
|
||||||
if(!base->waitfor[i])
|
|
||||||
continue; /* was deleted */
|
|
||||||
if(eventlist[i]->is_signal) {
|
|
||||||
eventlist[i]->just_checked = 0;
|
|
||||||
_getdns_handle_signal(eventlist[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* early exit - do not process network, exit quickly */
|
|
||||||
if(base->need_to_exit)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
//verbose(VERB_CLIENT, "winsock_event net");
|
|
||||||
for(i=startidx; i<numwait; i++) {
|
|
||||||
short bits = 0;
|
|
||||||
/* eventlist[i] fired */
|
|
||||||
/* see if eventlist[i] is still valid and just checked from
|
|
||||||
* WSAWaitForEvents */
|
|
||||||
if(!base->waitfor[i])
|
|
||||||
continue; /* was deleted */
|
|
||||||
if(!eventlist[i]->just_checked)
|
|
||||||
continue; /* added by other callback */
|
|
||||||
if(eventlist[i]->is_signal)
|
|
||||||
continue; /* not a network event at all */
|
|
||||||
eventlist[i]->just_checked = 0;
|
|
||||||
|
|
||||||
if(WSAEnumNetworkEvents(eventlist[i]->ev_fd,
|
|
||||||
base->waitfor[i], /* reset the event handle */
|
|
||||||
/*NULL,*/ /* do not reset the event handle */
|
|
||||||
&netev) != 0) {
|
|
||||||
log_err("getdns: WSAEnumNetworkEvents failed: %s",
|
|
||||||
wsa_strerror(WSAGetLastError()));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if((netev.lNetworkEvents & FD_READ)) {
|
|
||||||
if(netev.iErrorCode[FD_READ_BIT] != 0)
|
|
||||||
printf("FD_READ_BIT error: %s\n",
|
|
||||||
wsa_strerror(netev.iErrorCode[FD_READ_BIT]));
|
|
||||||
bits |= EV_READ;
|
|
||||||
printf("FD_READ_BIT\n");
|
|
||||||
}
|
|
||||||
if((netev.lNetworkEvents & FD_WRITE)) {
|
|
||||||
if(netev.iErrorCode[FD_WRITE_BIT] != 0)
|
|
||||||
printf("FD_WRITE_BIT error: %s\n",
|
|
||||||
wsa_strerror(netev.iErrorCode[FD_WRITE_BIT]));
|
|
||||||
bits |= EV_WRITE;
|
|
||||||
printf("FD_WRITE_BIT\n");
|
|
||||||
}
|
|
||||||
if((netev.lNetworkEvents & FD_CONNECT)) {
|
|
||||||
if(netev.iErrorCode[FD_CONNECT_BIT] != 0)
|
|
||||||
printf("FD_CONNECT_BIT error: %s\n",
|
|
||||||
wsa_strerror(netev.iErrorCode[FD_CONNECT_BIT]));
|
|
||||||
bits |= EV_READ;
|
|
||||||
bits |= EV_WRITE;
|
|
||||||
printf("FD_CONNECT_BIT\n");
|
|
||||||
}
|
|
||||||
if((netev.lNetworkEvents & FD_ACCEPT)) {
|
|
||||||
if(netev.iErrorCode[FD_ACCEPT_BIT] != 0)
|
|
||||||
printf("FD_ACCEPT_BIT error: %s\n",
|
|
||||||
wsa_strerror(netev.iErrorCode[FD_ACCEPT_BIT]));
|
|
||||||
bits |= EV_READ;
|
|
||||||
printf("FD_ACCEPT_BIT\n");
|
|
||||||
}
|
|
||||||
if((netev.lNetworkEvents & FD_CLOSE)) {
|
|
||||||
if(netev.iErrorCode[FD_CLOSE_BIT] != 0)
|
|
||||||
printf("FD_CLOSE_BIT error: %s\n",
|
|
||||||
wsa_strerror(netev.iErrorCode[FD_CLOSE_BIT]));
|
|
||||||
//g bits |= EV_READ;
|
|
||||||
//g bits |= EV_WRITE;
|
|
||||||
printf("FD_CLOSE_BIT\n");
|
|
||||||
}
|
|
||||||
if(eventlist[i]->is_tcp && eventlist[i]->stick_events) {
|
|
||||||
|
|
||||||
printf("winsock %d pass sticky %s%s\n",
|
|
||||||
eventlist[i]->ev_fd,
|
|
||||||
(eventlist[i]->old_events&EV_READ)?"EV_READ":"",
|
|
||||||
(eventlist[i]->old_events&EV_WRITE)?"EV_WRITE":"");
|
|
||||||
|
|
||||||
bits |= eventlist[i]->old_events;
|
|
||||||
}
|
|
||||||
if(eventlist[i]->is_tcp && bits) {
|
|
||||||
eventlist[i]->old_events = bits;
|
|
||||||
eventlist[i]->stick_events = 1;
|
|
||||||
if((eventlist[i]->ev_events & bits)) {
|
|
||||||
newstickies = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("winsock %d store sticky %s%s",
|
|
||||||
eventlist[i]->ev_fd,
|
|
||||||
(eventlist[i]->old_events&EV_READ)?"EV_READ":"",
|
|
||||||
(eventlist[i]->old_events&EV_WRITE) ? "EV_WRITE" : "");
|
|
||||||
|
|
||||||
}
|
|
||||||
if((bits & eventlist[i]->ev_events)) {
|
|
||||||
printf( "winsock event callback %p fd=%d "
|
|
||||||
"%s%s%s%s%s ; %s%s%s\n",
|
|
||||||
eventlist[i], eventlist[i]->ev_fd,
|
|
||||||
(netev.lNetworkEvents&FD_READ)?" FD_READ":"",
|
|
||||||
(netev.lNetworkEvents&FD_WRITE)?" FD_WRITE":"",
|
|
||||||
(netev.lNetworkEvents&FD_CONNECT)?
|
|
||||||
" FD_CONNECT":"",
|
|
||||||
(netev.lNetworkEvents&FD_ACCEPT)?
|
|
||||||
" FD_ACCEPT":"",
|
|
||||||
(netev.lNetworkEvents&FD_CLOSE)?" FD_CLOSE":"",
|
|
||||||
(bits&EV_READ)?" EV_READ":"",
|
|
||||||
(bits&EV_WRITE)?" EV_WRITE":"",
|
|
||||||
(bits&EV_TIMEOUT)?" EV_TIMEOUT":"");
|
|
||||||
|
|
||||||
fptr_ok(fptr_whitelist_event(
|
|
||||||
eventlist[i]->ev_callback));
|
|
||||||
(*eventlist[i]->ev_callback)(eventlist[i]->ev_fd,
|
|
||||||
bits & eventlist[i]->ev_events,
|
|
||||||
eventlist[i]->ev_arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(eventlist[i]->is_tcp && bits)
|
|
||||||
printf( "winsock %d got sticky %s%s\n",
|
|
||||||
eventlist[i]->ev_fd,
|
|
||||||
(eventlist[i]->old_events&EV_READ)?"EV_READ":"",
|
|
||||||
(eventlist[i]->old_events&EV_WRITE)?"EV_WRITE":"");
|
|
||||||
|
|
||||||
}
|
|
||||||
//verbose(VERB_CLIENT, "winsock_event net");
|
|
||||||
if(base->tcp_reinvigorated) {
|
|
||||||
printf("winsock_event reinvigorated\n");
|
|
||||||
base->tcp_reinvigorated = 0;
|
|
||||||
newstickies = 1;
|
|
||||||
}
|
|
||||||
base->tcp_stickies = newstickies;
|
|
||||||
//gprintf("winsock_event handle_select end\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int _getdns_event_base_dispatch(struct _getdns_event_base *base)
|
|
||||||
{
|
|
||||||
struct timeval wait;
|
|
||||||
if(settime(base) < 0)
|
|
||||||
return -1;
|
|
||||||
while(!base->need_to_exit)
|
|
||||||
{
|
|
||||||
/* see if timeouts need handling */
|
|
||||||
_getdns_handle_timeouts(base, base->time_tv, &wait);
|
|
||||||
if(base->need_to_exit)
|
|
||||||
return 0;
|
|
||||||
/* do select */
|
|
||||||
if(_getdns_handle_select(base, &wait) < 0) {
|
|
||||||
if(base->need_to_exit)
|
|
||||||
return 0;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int _getdns_event_base_loopexit(struct _getdns_event_base *base,
|
|
||||||
struct timeval * ATTR_UNUSED(tv))
|
|
||||||
{
|
|
||||||
base->need_to_exit = 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _getdns_event_base_free(struct _getdns_event_base *base)
|
|
||||||
{
|
|
||||||
if(!base)
|
|
||||||
return;
|
|
||||||
if(base->items)
|
|
||||||
free(base->items);
|
|
||||||
if(base->times)
|
|
||||||
free(base->times);
|
|
||||||
if(base->signals)
|
|
||||||
free(base->signals);
|
|
||||||
free(base);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _getdns_event_set(struct _getdns_event *ev, int fd, short bits,
|
|
||||||
void (*cb)(int, short, void *), void *arg)
|
|
||||||
{
|
|
||||||
ev->node.key = ev;
|
|
||||||
ev->ev_fd = fd;
|
|
||||||
ev->ev_events = bits;
|
|
||||||
ev->ev_callback = cb;
|
|
||||||
fptr_ok(fptr_whitelist_event(ev->ev_callback));
|
|
||||||
ev->ev_arg = arg;
|
|
||||||
ev->just_checked = 0;
|
|
||||||
ev->added = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int _getdns_event_base_set(struct _getdns_event_base *base, struct _getdns_event *ev)
|
|
||||||
{
|
|
||||||
ev->ev_base = base;
|
|
||||||
ev->old_events = 0;
|
|
||||||
ev->stick_events = 0;
|
|
||||||
ev->added = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int _getdns_event_add(struct _getdns_event *ev, struct timeval *tv)
|
|
||||||
{
|
|
||||||
printf( "event_add %p added=%d fd=%d tv=" ARG_LL "d %s%s%s\n",
|
|
||||||
ev, ev->added, ev->ev_fd,
|
|
||||||
(tv?(long long)tv->tv_sec*1000+(long long)tv->tv_usec/1000:-1),
|
|
||||||
(ev->ev_events&EV_READ)?" EV_READ":"",
|
|
||||||
(ev->ev_events&EV_WRITE)?" EV_WRITE":"",
|
|
||||||
(ev->ev_events&EV_TIMEOUT)?" EV_TIMEOUT":"");
|
|
||||||
|
|
||||||
if(ev->added)
|
|
||||||
_getdns_event_del(ev);
|
|
||||||
|
|
||||||
ev->is_tcp = 0;
|
|
||||||
ev->is_signal = 0;
|
|
||||||
ev->just_checked = 0;
|
|
||||||
|
|
||||||
if ((ev->ev_events&(EV_READ | EV_WRITE)) && ev->ev_fd != -1) {
|
|
||||||
BOOL b = 0;
|
|
||||||
int t, l;
|
|
||||||
long events = 0;
|
|
||||||
//gprintf("\getdns_event_add %d %d\n", ev->ev_fd, events);
|
|
||||||
|
|
||||||
if (ev->ev_base->max == ev->ev_base->cap)
|
|
||||||
return -1;
|
|
||||||
ev->idx = ev->ev_base->max++;
|
|
||||||
ev->ev_base->items[ev->idx] = ev;
|
|
||||||
|
|
||||||
if ((ev->ev_events&EV_READ))
|
|
||||||
events |= FD_READ;
|
|
||||||
if ((ev->ev_events&EV_WRITE))
|
|
||||||
{
|
|
||||||
events |= FD_CONNECT;
|
|
||||||
events |= FD_WRITE;
|
|
||||||
}
|
|
||||||
|
|
||||||
//printf("\getdns_event_add %d read = %d write = %d %d\n", ev->ev_fd, ev->ev_events&EV_READ, ev->ev_events&EV_WRITE, events);
|
|
||||||
|
|
||||||
l = sizeof(t);
|
|
||||||
if(getsockopt(ev->ev_fd, SOL_SOCKET, SO_TYPE,
|
|
||||||
(void*)&t, &l) != 0)
|
|
||||||
log_err("getdns: getsockopt(SO_TYPE) failed: %s",
|
|
||||||
wsa_strerror(WSAGetLastError()));
|
|
||||||
if(t == SOCK_STREAM) {
|
|
||||||
/* TCP socket */
|
|
||||||
ev->is_tcp = 1;
|
|
||||||
events |= FD_CLOSE;
|
|
||||||
if( (ev->ev_events&EV_WRITE) )
|
|
||||||
events |= FD_CONNECT;
|
|
||||||
l = sizeof(b);
|
|
||||||
if(getsockopt(ev->ev_fd, SOL_SOCKET, SO_ACCEPTCONN,
|
|
||||||
(void*)&b, &l) != 0)
|
|
||||||
log_err("getdns: getsockopt(SO_ACCEPTCONN) failed: %s",
|
|
||||||
wsa_strerror(WSAGetLastError()));
|
|
||||||
if(b) /* TCP accept socket */
|
|
||||||
events |= FD_ACCEPT;
|
|
||||||
}
|
|
||||||
ev->hEvent = WSACreateEvent();
|
|
||||||
if(ev->hEvent == WSA_INVALID_EVENT)
|
|
||||||
log_err("getdns: WSACreateEvent failed: %s",
|
|
||||||
wsa_strerror(WSAGetLastError()));
|
|
||||||
/* automatically sets fd to nonblocking mode.
|
|
||||||
* nonblocking cannot be disabled, until wsaES(fd, NULL, 0) */
|
|
||||||
printf("\nWSAEventSelect %d events %d hEvent %d\n", ev->ev_fd, (int)events, (int)ev->hEvent);
|
|
||||||
if (WSAEventSelect(ev->ev_fd, ev->hEvent, events) != 0) {
|
|
||||||
log_err("getdns: WSAEventSelect in getdns failed: %s",
|
|
||||||
wsa_strerror(WSAGetLastError()));
|
|
||||||
}
|
|
||||||
if(ev->is_tcp && ev->stick_events &&
|
|
||||||
(ev->ev_events & ev->old_events)) {
|
|
||||||
/* go to processing the sticky event right away */
|
|
||||||
printf("\nWSAEventSelect sticky %d events %d hEvent %d\n", ev->ev_fd, (int)events, (int)ev->hEvent);
|
|
||||||
ev->ev_base->tcp_reinvigorated = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(tv && (ev->ev_events&EV_TIMEOUT)) {
|
|
||||||
printf("\nWSAEventSelect timeout %d hEvent %d\n", ev->ev_fd, (int)ev->hEvent);
|
|
||||||
|
|
||||||
#ifndef S_SPLINT_S
|
|
||||||
struct timeval *now = ev->ev_base->time_tv;
|
|
||||||
ev->ev_timeout.tv_sec = tv->tv_sec + now->tv_sec;
|
|
||||||
ev->ev_timeout.tv_usec = tv->tv_usec + now->tv_usec;
|
|
||||||
while(ev->ev_timeout.tv_usec > 1000000) {
|
|
||||||
ev->ev_timeout.tv_usec -= 1000000;
|
|
||||||
ev->ev_timeout.tv_sec++;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
(void)_getdns_rbtree_insert(ev->ev_base->times, &ev->node);
|
|
||||||
}
|
|
||||||
ev->added = 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int _getdns_event_del(struct _getdns_event *ev)
|
|
||||||
{
|
|
||||||
//verbose(VERB_ALGO, "event_del %p added=%d fd=%d tv=" ARG_LL "d %s%s%s",
|
|
||||||
// ev, ev->added, ev->ev_fd,
|
|
||||||
// (ev->ev_events&EV_TIMEOUT)?(long long)ev->ev_timeout.tv_sec*1000+
|
|
||||||
// (long long)ev->ev_timeout.tv_usec/1000:-1,
|
|
||||||
// (ev->ev_events&EV_READ)?" EV_READ":"",
|
|
||||||
// (ev->ev_events&EV_WRITE)?" EV_WRITE":"",
|
|
||||||
// (ev->ev_events&EV_TIMEOUT)?" EV_TIMEOUT":"");
|
|
||||||
if(!ev->added)
|
|
||||||
return 0;
|
|
||||||
//log_assert(ev->added);
|
|
||||||
if((ev->ev_events&EV_TIMEOUT))
|
|
||||||
(void)_getdns_rbtree_delete(ev->ev_base->times, &ev->node);
|
|
||||||
if((ev->ev_events&(EV_READ|EV_WRITE)) && ev->ev_fd != -1) {
|
|
||||||
//log_assert(ev->ev_base->max > 0);
|
|
||||||
/* remove item and compact the list */
|
|
||||||
ev->ev_base->items[ev->idx] =
|
|
||||||
ev->ev_base->items[ev->ev_base->max-1];
|
|
||||||
ev->ev_base->items[ev->ev_base->max-1] = NULL;
|
|
||||||
ev->ev_base->max--;
|
|
||||||
if(ev->idx < ev->ev_base->max)
|
|
||||||
ev->ev_base->items[ev->idx]->idx = ev->idx;
|
|
||||||
zero_waitfor(ev->ev_base->waitfor, ev->hEvent);
|
|
||||||
|
|
||||||
if(WSAEventSelect(ev->ev_fd, ev->hEvent, 0) != 0)
|
|
||||||
log_err("getdns: WSAEventSelect(disable) failed: %s",
|
|
||||||
wsa_strerror(WSAGetLastError()));
|
|
||||||
if(!WSACloseEvent(ev->hEvent))
|
|
||||||
log_err("getdns: WSACloseEvent failed: %s",
|
|
||||||
wsa_strerror(WSAGetLastError()));
|
|
||||||
}
|
|
||||||
ev->just_checked = 0;
|
|
||||||
ev->added = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** which base gets to handle signals */
|
|
||||||
static struct _getdns_event_base* signal_base = NULL;
|
|
||||||
/** signal handler */
|
|
||||||
static RETSIGTYPE sigh(int sig)
|
|
||||||
{
|
|
||||||
if(!signal_base || sig < 0 || sig >= MAX_SIG)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int _getdns_signal_add(struct _getdns_event *ev, struct timeval * ATTR_UNUSED(tv))
|
|
||||||
{
|
|
||||||
if(ev->ev_fd == -1 || ev->ev_fd >= MAX_SIG)
|
|
||||||
return -1;
|
|
||||||
signal_base = ev->ev_base;
|
|
||||||
ev->ev_base->signals[ev->ev_fd] = ev;
|
|
||||||
ev->added = 1;
|
|
||||||
if(signal(ev->ev_fd, sigh) == SIG_ERR) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int _getdns_signal_del(struct _getdns_event *ev)
|
|
||||||
{
|
|
||||||
if(ev->ev_fd == -1 || ev->ev_fd >= MAX_SIG)
|
|
||||||
return -1;
|
|
||||||
ev->ev_base->signals[ev->ev_fd] = NULL;
|
|
||||||
ev->added = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void winsock_tcp_wouldblock(struct _getdns_event* ev, int eventbits)
|
|
||||||
{
|
|
||||||
printf("winsock: tcp wouldblock %s\n",
|
|
||||||
eventbits==EV_READ?"EV_READ":"EV_WRITE");
|
|
||||||
ev->old_events &= (~eventbits);
|
|
||||||
if(ev->old_events == 0)
|
|
||||||
ev->stick_events = 0;
|
|
||||||
/* in case this is the last sticky event, we could
|
|
||||||
* possibly run an empty handler loop to reset the base
|
|
||||||
* tcp_stickies variable
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
int winsock_register_wsaevent(struct _getdns_event_base* base, struct _getdns_event* ev,
|
|
||||||
WSAEVENT wsaevent, void (*cb)(int, short, void*), void* arg)
|
|
||||||
{
|
|
||||||
if(base->max == base->cap)
|
|
||||||
return 0;
|
|
||||||
memset(ev, 0, sizeof(*ev));
|
|
||||||
ev->ev_fd = -1;
|
|
||||||
ev->ev_events = EV_READ;
|
|
||||||
ev->ev_callback = cb;
|
|
||||||
ev->ev_arg = arg;
|
|
||||||
ev->is_signal = 1;
|
|
||||||
ev->hEvent = wsaevent;
|
|
||||||
ev->added = 1;
|
|
||||||
ev->ev_base = base;
|
|
||||||
ev->idx = ev->ev_base->max++;
|
|
||||||
ev->ev_base->items[ev->idx] = ev;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void winsock_unregister_wsaevent(struct _getdns_event* ev)
|
|
||||||
{
|
|
||||||
if(!ev || !ev->added) return;
|
|
||||||
//log_assert(ev->added && ev->ev_base->max > 0)
|
|
||||||
/* remove item and compact the list */
|
|
||||||
ev->ev_base->items[ev->idx] = ev->ev_base->items[ev->ev_base->max-1];
|
|
||||||
ev->ev_base->items[ev->ev_base->max-1] = NULL;
|
|
||||||
ev->ev_base->max--;
|
|
||||||
if(ev->idx < ev->ev_base->max)
|
|
||||||
ev->ev_base->items[ev->idx]->idx = ev->idx;
|
|
||||||
ev->added = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else /* USE_WINSOCK */
|
|
||||||
/** symbol so this codefile defines symbols. pleasing ranlib on OSX 10.5 */
|
|
||||||
int winsock_unused_symbol = 1;
|
|
||||||
#endif /* USE_WINSOCK */
|
|
|
@ -1,295 +0,0 @@
|
||||||
/*
|
|
||||||
* util/winsock_event.h - getdns event handling for winsock on windows
|
|
||||||
* extracted from Unbound source code and modified for getdns
|
|
||||||
*
|
|
||||||
* Copyright (c) 2015, NLnet Labs/Verisign. All rights reserved.
|
|
||||||
*
|
|
||||||
* This software is open source.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
*
|
|
||||||
* Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* Neither the name of the NLNET LABS or Verisign nor the names of its contributors may
|
|
||||||
* be used to endorse or promote products derived from this software without
|
|
||||||
* specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
|
||||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
||||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
||||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \file
|
|
||||||
*
|
|
||||||
* This file contains interface functions with the WinSock2 API on Windows.
|
|
||||||
* It uses the winsock WSAWaitForMultipleEvents interface on a number of
|
|
||||||
* sockets.
|
|
||||||
* Code is originally from the Unbound source for Windows.
|
|
||||||
*
|
|
||||||
* Note that windows can only wait for max 64 events at one time.
|
|
||||||
*
|
|
||||||
* Also, file descriptors cannot be waited for.
|
|
||||||
*
|
|
||||||
* Named pipes are not easily available (and are not usable in select() ).
|
|
||||||
* For interprocess communication, it is possible to wait for a hEvent to
|
|
||||||
* be signaled by another thread.
|
|
||||||
*
|
|
||||||
* When a socket becomes readable, then it will not be flagged as
|
|
||||||
* readable again until you have gotten WOULDBLOCK from a recv routine.
|
|
||||||
* That means the event handler must store the readability (edge notify)
|
|
||||||
* and process the incoming data until it blocks.
|
|
||||||
* The function performing recv then has to inform the event handler that
|
|
||||||
* the socket has blocked, and the event handler can mark it as such.
|
|
||||||
* Thus, this file transforms the edge notify from windows to a level notify
|
|
||||||
* that is compatible with UNIX.
|
|
||||||
* The WSAEventSelect page says that it does do level notify, as long
|
|
||||||
* as you call a recv/write/accept at least once when it is signalled.
|
|
||||||
* This last bit is not true, even though documented in server2008 api docs
|
|
||||||
* from microsoft, it does not happen at all. Instead you have to test for
|
|
||||||
* WSAEWOULDBLOCK on a tcp stream, and only then retest the socket.
|
|
||||||
* And before that remember the previous result as still valid.
|
|
||||||
*
|
|
||||||
* To stay 'fair', instead of emptying a socket completely, the event handler
|
|
||||||
* can test the other (marked as blocking) sockets for new events.
|
|
||||||
*
|
|
||||||
* Additionally, TCP accept sockets get special event support.
|
|
||||||
*
|
|
||||||
* Socket numbers are not starting small, they can be any number (say 33060).
|
|
||||||
* Therefore, bitmaps are not used, but arrays.
|
|
||||||
*
|
|
||||||
* on winsock, you must use recv() and send() for TCP reads and writes,
|
|
||||||
* not read() and write(), those work only on files.
|
|
||||||
*
|
|
||||||
* Also fseek and fseeko do not work if a FILE is not fopen-ed in binary mode.
|
|
||||||
*
|
|
||||||
* When under a high load windows gives out lots of errors, from recvfrom
|
|
||||||
* on udp sockets for example (WSAECONNRESET). Even though the udp socket
|
|
||||||
* has no connection per se.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef UTIL_WINSOCK_EVENT_H
|
|
||||||
#define UTIL_WINSOCK_EVENT_H
|
|
||||||
|
|
||||||
// Only enabled for Windows
|
|
||||||
#ifdef USE_WINSOCK
|
|
||||||
|
|
||||||
#ifndef HAVE_EVENT_BASE_FREE
|
|
||||||
#define HAVE_EVENT_BASE_FREE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* redefine the calls to different names so that there is no name
|
|
||||||
* collision with other code that uses libevent names. (that uses libunbound)*/
|
|
||||||
#define _getdns_event_init winsockevent_init
|
|
||||||
#define event_get_version winsockevent_get_version
|
|
||||||
#define event_get_method winsockevent_get_method
|
|
||||||
#define _getdns_event_base_dispatch winsockevent_base_dispatch
|
|
||||||
#define event_base_loopexit winsockevent_base_loopexit
|
|
||||||
#define _getdns_event_base_free winsockevent_base_free
|
|
||||||
#define _getdns_event_set winsockevent_set
|
|
||||||
#define _getdns_event_base_set winsockevent_base_set
|
|
||||||
#define _getdns_event_add winsockevent_add
|
|
||||||
#define _getdns_event_del winsockevent_del
|
|
||||||
#define signal_add winsocksignal_add
|
|
||||||
#define signal_del winsocksignal_del
|
|
||||||
|
|
||||||
/** event timeout */
|
|
||||||
#define EV_TIMEOUT 0x01
|
|
||||||
/** event fd readable */
|
|
||||||
#define EV_READ 0x02
|
|
||||||
/** event fd writable */
|
|
||||||
#define EV_WRITE 0x04
|
|
||||||
/** event signal */
|
|
||||||
#define EV_SIGNAL 0x08
|
|
||||||
/** event must persist */
|
|
||||||
#define EV_PERSIST 0x10
|
|
||||||
|
|
||||||
/* needs our redblack tree */
|
|
||||||
#include "util/rbtree.h"
|
|
||||||
|
|
||||||
/** max number of signals to support */
|
|
||||||
#define MAX_SIG 32
|
|
||||||
|
|
||||||
/** The number of items that the winsock event handler can service.
|
|
||||||
* Windows cannot handle more anyway */
|
|
||||||
#define WSK_MAX_ITEMS 64
|
|
||||||
|
|
||||||
/**
|
|
||||||
* event base for winsock event handler
|
|
||||||
*/
|
|
||||||
struct _getdns_event_base
|
|
||||||
{
|
|
||||||
/** sorted by timeout (absolute), ptr */
|
|
||||||
_getdns_rbtree_t* times;
|
|
||||||
/** array (first part in use) of handles to work on */
|
|
||||||
struct _getdns_event** items;
|
|
||||||
/** number of items in use in array */
|
|
||||||
int max;
|
|
||||||
/** capacity of array, size of array in items */
|
|
||||||
int cap;
|
|
||||||
/** array of 0 - maxsig of ptr to event for it */
|
|
||||||
struct _getdns_event** signals;
|
|
||||||
/** if we need to exit */
|
|
||||||
int need_to_exit;
|
|
||||||
/** where to store time in seconds */
|
|
||||||
time_t* time_secs;
|
|
||||||
/** where to store time in microseconds */
|
|
||||||
struct timeval* time_tv;
|
|
||||||
/**
|
|
||||||
* TCP streams have sticky events to them, these are not
|
|
||||||
* reported by the windows event system anymore, we have to
|
|
||||||
* keep reporting those events as present until wouldblock() is
|
|
||||||
* signalled by the handler back to use.
|
|
||||||
*/
|
|
||||||
int tcp_stickies;
|
|
||||||
/**
|
|
||||||
* should next cycle process reinvigorated stickies,
|
|
||||||
* these are stickies that have been stored, but due to a new
|
|
||||||
* event_add a sudden interest in the event has incepted.
|
|
||||||
*/
|
|
||||||
int tcp_reinvigorated;
|
|
||||||
/** The list of events that is currently being processed. */
|
|
||||||
WSAEVENT waitfor[WSK_MAX_ITEMS];
|
|
||||||
|
|
||||||
/* fdset for read write, for fds ready, and added */
|
|
||||||
fd_set
|
|
||||||
/** fds for reading */
|
|
||||||
reads,
|
|
||||||
/** fds for writing */
|
|
||||||
writes,
|
|
||||||
/** fds determined ready for use */
|
|
||||||
ready,
|
|
||||||
/** ready plus newly added events. */
|
|
||||||
content;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Event structure. Has some of the event elements.
|
|
||||||
*/
|
|
||||||
struct _getdns_event {
|
|
||||||
/** node in timeout rbtree */
|
|
||||||
_getdns_rbnode_t node;
|
|
||||||
/** is event already added */
|
|
||||||
int added;
|
|
||||||
|
|
||||||
/** event base it belongs to */
|
|
||||||
struct _getdns_event_base *ev_base;
|
|
||||||
/** fd to poll or -1 for timeouts. signal number for sigs. */
|
|
||||||
int ev_fd;
|
|
||||||
/** what events this event is interested in, see EV_.. above. */
|
|
||||||
short ev_events;
|
|
||||||
/** timeout value */
|
|
||||||
struct timeval ev_timeout;
|
|
||||||
|
|
||||||
/** callback to call: fd, eventbits, userarg */
|
|
||||||
void (*ev_callback)(int, short, void *);
|
|
||||||
/** callback user arg */
|
|
||||||
void *ev_arg;
|
|
||||||
|
|
||||||
/* ----- nonpublic part, for winsock_event only ----- */
|
|
||||||
/** index of this event in the items array (if added) */
|
|
||||||
int idx;
|
|
||||||
/** the event handle to wait for new events to become ready */
|
|
||||||
WSAEVENT hEvent;
|
|
||||||
/** true if this filedes is a TCP socket and needs special attention */
|
|
||||||
int is_tcp;
|
|
||||||
/** remembered EV_ values */
|
|
||||||
short old_events;
|
|
||||||
/** should remembered EV_ values be used for TCP streams.
|
|
||||||
* Reset after WOULDBLOCK is signaled using the function. */
|
|
||||||
int stick_events;
|
|
||||||
|
|
||||||
/** true if this event is a signaling WSAEvent by the user.
|
|
||||||
* User created and user closed WSAEvent. Only signaled/unsigneled,
|
|
||||||
* no read/write/distinctions needed. */
|
|
||||||
int is_signal;
|
|
||||||
/** used during callbacks to see which events were just checked */
|
|
||||||
int just_checked;
|
|
||||||
};
|
|
||||||
|
|
||||||
char* wsa_strerror(DWORD err);
|
|
||||||
void log_err(const char *format, ...);
|
|
||||||
/** create event base */
|
|
||||||
void *_getdns_event_init(time_t* time_secs, struct timeval* time_tv);
|
|
||||||
/** get version */
|
|
||||||
const char *event_get_version(void);
|
|
||||||
/** get polling method (select,epoll) */
|
|
||||||
const char *event_get_method(void);
|
|
||||||
/** run select in a loop */
|
|
||||||
int _getdns_event_base_dispatch(struct _getdns_event_base *);
|
|
||||||
/** exit that loop */
|
|
||||||
int event_base_loopexit(struct _getdns_event_base *, struct timeval *);
|
|
||||||
/** free event base. Free events yourself */
|
|
||||||
void _getdns_event_base_free(struct _getdns_event_base *);
|
|
||||||
/** set content of event */
|
|
||||||
void _getdns_event_set(struct _getdns_event *, int, short, void (*)(int, short, void *), void *);
|
|
||||||
|
|
||||||
/** add event to a base. You *must* call this for every event. */
|
|
||||||
int _getdns_event_base_set(struct _getdns_event_base *, struct _getdns_event *);
|
|
||||||
/** add event to make it active. You may not change it with event_set anymore */
|
|
||||||
int _getdns_event_add(struct _getdns_event *, struct timeval *);
|
|
||||||
/** remove event. You may change it again */
|
|
||||||
int _getdns_event_del(struct _getdns_event *);
|
|
||||||
|
|
||||||
#define evtimer_add(ev, tv) event_add(ev, tv)
|
|
||||||
#define evtimer_del(ev) event_del(ev)
|
|
||||||
|
|
||||||
/* uses different implementation. Cannot mix fd/timeouts and signals inside
|
|
||||||
* the same struct event. create several event structs for that. */
|
|
||||||
/** install signal handler */
|
|
||||||
int signal_add(struct _getdns_event *, struct timeval *);
|
|
||||||
/** set signal event contents */
|
|
||||||
#define signal_set(ev, x, cb, arg) \
|
|
||||||
event_set(ev, x, EV_SIGNAL|EV_PERSIST, cb, arg)
|
|
||||||
/** remove signal handler */
|
|
||||||
int signal_del(struct _getdns_event *);
|
|
||||||
|
|
||||||
/** compare events in tree, based on timevalue, ptr for uniqueness */
|
|
||||||
int getdns_mini_ev_cmp(const void* a, const void* b);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Routine for windows only, where the handling layer can signal that
|
|
||||||
* a TCP stream encountered WSAEWOULDBLOCK for a stream and thus needs
|
|
||||||
* retesting the event.
|
|
||||||
* Pass if EV_READ or EV_WRITE gave wouldblock.
|
|
||||||
*/
|
|
||||||
void winsock_tcp_wouldblock(struct _getdns_event* ev, int eventbit);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Routine for windows only. where you pass a signal WSAEvent that
|
|
||||||
* you wait for. When the event is signaled, the callback gets called.
|
|
||||||
* The callback has to WSAResetEvent to disable the signal.
|
|
||||||
* @param base: the event base.
|
|
||||||
* @param ev: the event structure for data storage
|
|
||||||
* can be passed uninitialised.
|
|
||||||
* @param wsaevent: the WSAEvent that gets signaled.
|
|
||||||
* @param cb: callback routine.
|
|
||||||
* @param arg: user argument to callback routine.
|
|
||||||
* @return false on error.
|
|
||||||
*/
|
|
||||||
int winsock_register_wsaevent(struct _getdns_event_base* base, struct _getdns_event* ev,
|
|
||||||
WSAEVENT wsaevent, void (*cb)(int, short, void*), void* arg);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unregister a wsaevent. User has to close the WSAEVENT itself.
|
|
||||||
* @param ev: event data storage.
|
|
||||||
*/
|
|
||||||
void winsock_unregister_wsaevent(struct _getdns_event* ev);
|
|
||||||
|
|
||||||
#endif /* USE_WINSOCK */
|
|
||||||
#endif /* UTIL_WINSOCK_EVENT_H */
|
|
Loading…
Reference in New Issue