forked from enlightenment/efl
as I promised long, long ago, ecore now has its own asynchronous dns resolver! everyone cheer for not needing c-ares any longer!
dns.c is the work of William Ahern (http://25thandclement.com/~william/projects/dns.c.html) and has been in development for ~4 years. it has zero documentation, no examples, and no comments: I'm pretty sure he's an EFL developer in disguise. this new resolver is roughly 10-12% faster than c-ares, will never randomly break, requires no external libraries, and is much simpler on the efl side. by default, dns.c resolution is enabled any time ipv6 support is detected and c-ares support is not requested; it should work on all platforms (wink wink vtorri), but it has no way of disabling ipv6 (someone can go through dns.c/h and do that if they feel so inclined) SVN revision: 71690
This commit is contained in:
parent
dec06820ec
commit
161ac501e5
|
@ -706,3 +706,5 @@
|
||||||
2012-06-04 Mike Blumenkrantz
|
2012-06-04 Mike Blumenkrantz
|
||||||
|
|
||||||
* ECORE_{CON,IPC}_NO_PROXY now available for disabling proxying on certain connections
|
* ECORE_{CON,IPC}_NO_PROXY now available for disabling proxying on certain connections
|
||||||
|
* Added new resolver method: dns.c -- This is used by default now when ipv6 is enabled
|
||||||
|
and c-ares support is disabled.
|
||||||
|
|
|
@ -12,6 +12,7 @@ Additions:
|
||||||
- ECORE_X_RANDR_OUTPUT_POLICY_ASK
|
- ECORE_X_RANDR_OUTPUT_POLICY_ASK
|
||||||
* ecore_con:
|
* ecore_con:
|
||||||
- ECORE_{CON,IPC}_NO_PROXY now available for disabling proxying on certain connections
|
- ECORE_{CON,IPC}_NO_PROXY now available for disabling proxying on certain connections
|
||||||
|
- New dns.c resolver backend for faster dns lookups
|
||||||
|
|
||||||
Fixes:
|
Fixes:
|
||||||
* ecore
|
* ecore
|
||||||
|
|
|
@ -1488,6 +1488,7 @@ if test "x${have_ecore_con}" = "xyes" ; then
|
||||||
if test "x${have_ipv6}" = "xyes" ; then
|
if test "x${have_ipv6}" = "xyes" ; then
|
||||||
AC_DEFINE(HAVE_IPV6, 1, [Define if IPV6 is supported])
|
AC_DEFINE(HAVE_IPV6, 1, [Define if IPV6 is supported])
|
||||||
fi
|
fi
|
||||||
|
AM_CONDITIONAL([HAVE_IPV6], [test "x${have_ipv6}" = "xyes"])
|
||||||
|
|
||||||
ECORE_CHECK_CURL([${want_curl}],
|
ECORE_CHECK_CURL([${want_curl}],
|
||||||
[
|
[
|
||||||
|
@ -2067,7 +2068,13 @@ fi
|
||||||
if test "x$want_ecore_con_local_sockets" = "xyes" ; then
|
if test "x$want_ecore_con_local_sockets" = "xyes" ; then
|
||||||
echo " Abstract Sockets.........: $want_ecore_con_abstract_sockets"
|
echo " Abstract Sockets.........: $want_ecore_con_abstract_sockets"
|
||||||
fi
|
fi
|
||||||
echo " c-ares.....................: $have_cares"
|
if test "x$have_cares" = "xyes" ; then
|
||||||
|
echo " Resolver...................: c-ares"
|
||||||
|
elif test "x$have_ipv6" = "xyes" ; then
|
||||||
|
echo " Resolver...................: dns.c"
|
||||||
|
else
|
||||||
|
echo " Resolver...................: fork"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
echo " Ecore_Ipc....................: $have_ecore_ipc"
|
echo " Ecore_Ipc....................: $have_ecore_ipc"
|
||||||
if test "x$have_ecore_ipc" = "xyes" ; then
|
if test "x$have_ecore_ipc" = "xyes" ; then
|
||||||
|
|
|
@ -34,8 +34,13 @@ endif
|
||||||
if HAVE_CARES
|
if HAVE_CARES
|
||||||
libecore_con_la_SOURCES += ecore_con_ares.c
|
libecore_con_la_SOURCES += ecore_con_ares.c
|
||||||
else
|
else
|
||||||
|
if HAVE_IPV6
|
||||||
|
AM_CPPFLAGS += -Wno-override-init
|
||||||
|
libecore_con_la_SOURCES += ecore_con_dns.c dns.c dns.h
|
||||||
|
else
|
||||||
libecore_con_la_SOURCES += ecore_con_info.c
|
libecore_con_la_SOURCES += ecore_con_info.c
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
libecore_con_la_CFLAGS = @WIN32_CFLAGS@
|
libecore_con_la_CFLAGS = @WIN32_CFLAGS@
|
||||||
libecore_con_la_LIBADD = \
|
libecore_con_la_LIBADD = \
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,334 @@
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This version of ecore_con_info uses dns.c to provide asynchronous dns lookup.
|
||||||
|
*
|
||||||
|
* dns.c is written by William Ahern:
|
||||||
|
* http://25thandclement.com/~william/projects/dns.c.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_NETINET_IN_H
|
||||||
|
# include <netinet/in.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_ARPA_INET_H
|
||||||
|
# include <arpa/inet.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "dns.h"
|
||||||
|
|
||||||
|
#include "Ecore.h"
|
||||||
|
#include "Ecore_Con.h"
|
||||||
|
#include "ecore_con_private.h"
|
||||||
|
|
||||||
|
typedef struct dns_addrinfo dns_addrinfo;
|
||||||
|
typedef struct dns_resolv_conf dns_resolv_conf;
|
||||||
|
typedef struct dns_resolver dns_resolver;
|
||||||
|
typedef struct dns_hosts dns_hosts;
|
||||||
|
|
||||||
|
typedef struct _Ecore_Con_DNS Ecore_Con_DNS;
|
||||||
|
|
||||||
|
struct _Ecore_Con_DNS
|
||||||
|
{
|
||||||
|
Ecore_Con_Server *svr;
|
||||||
|
Ecore_Con_Info_Cb done_cb;
|
||||||
|
void *data;
|
||||||
|
dns_addrinfo *ai;
|
||||||
|
dns_resolver *resolv;
|
||||||
|
struct addrinfo hints;
|
||||||
|
Ecore_Fd_Handler *fdh;
|
||||||
|
Ecore_Timer *timer;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int _ecore_con_dns_init = 0;
|
||||||
|
static dns_resolv_conf *resconf = NULL;
|
||||||
|
static dns_hosts *hosts = NULL;
|
||||||
|
|
||||||
|
static void
|
||||||
|
_ecore_con_dns_free(Ecore_Con_DNS *dns)
|
||||||
|
{
|
||||||
|
if (dns->svr->infos) dns->svr->infos = eina_list_remove(dns->svr->infos, dns);
|
||||||
|
if (dns->timer) ecore_timer_del(dns->timer);
|
||||||
|
if (dns->fdh) ecore_main_fd_handler_del(dns->fdh);
|
||||||
|
dns_res_close(dns->resolv);
|
||||||
|
free(dns);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_dns_addrinfo_get(Ecore_Con_DNS *dns, const char *addr, int port)
|
||||||
|
{
|
||||||
|
int error = 0;
|
||||||
|
char service[NI_MAXSERV];
|
||||||
|
|
||||||
|
snprintf(service, sizeof(service), "%d", port);
|
||||||
|
dns->ai = dns_ai_open(addr, service, DNS_T_A, (const struct addrinfo *)&dns->hints, dns->resolv, &error);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_ecore_con_dns_check(Ecore_Con_DNS *dns)
|
||||||
|
{
|
||||||
|
struct addrinfo *ent = NULL;
|
||||||
|
int error = 0;
|
||||||
|
char addr[NI_MAXHOST + 1];
|
||||||
|
|
||||||
|
error = dns_ai_nextent(&ent, dns->ai);
|
||||||
|
|
||||||
|
switch (error)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case EAGAIN:
|
||||||
|
return 1;
|
||||||
|
default:
|
||||||
|
ERR("resolve failed: %s", dns_strerror(error));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
Ecore_Con_Info result;
|
||||||
|
#if 0
|
||||||
|
char pretty[512];
|
||||||
|
dns_ai_print(pretty, sizeof(pretty), ent, dns->ai);
|
||||||
|
printf("%s\n", pretty);
|
||||||
|
#endif
|
||||||
|
dns_inet_ntop(dns_sa_family(ent->ai_addr), dns_sa_addr(dns_sa_family(ent->ai_addr), ent->ai_addr), addr, sizeof(addr));
|
||||||
|
result.size = 0;
|
||||||
|
strncpy(result.ip, addr, sizeof(result.ip));
|
||||||
|
snprintf(result.service, sizeof(result.service), "%u", ntohs(*dns_sa_port(dns_sa_family(ent->ai_addr), ent->ai_addr)));
|
||||||
|
memcpy(&result.info, ent, sizeof(result.info));
|
||||||
|
if (dns->fdh) ecore_main_fd_handler_del(dns->fdh);
|
||||||
|
dns->fdh = NULL;
|
||||||
|
dns->done_cb(dns->data, &result);
|
||||||
|
free(ent);
|
||||||
|
_ecore_con_dns_free(dns);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
error:
|
||||||
|
dns->done_cb(dns->data, NULL);
|
||||||
|
_ecore_con_dns_free(dns);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_dns_fd_cb(Ecore_Con_DNS *dns, Ecore_Fd_Handler *fdh)
|
||||||
|
{
|
||||||
|
if (_ecore_con_dns_check(dns) == 1)
|
||||||
|
ecore_main_fd_handler_active_set(fdh, dns_ai_events(dns->ai));
|
||||||
|
return ECORE_CALLBACK_RENEW;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_dns_timer_cb(Ecore_Con_DNS *dns)
|
||||||
|
{
|
||||||
|
dns->done_cb(dns->data, NULL);
|
||||||
|
_ecore_con_dns_free(dns);
|
||||||
|
dns->timer = NULL;
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ecore_con_info_init(void)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
if (_ecore_con_dns_init) return ++_ecore_con_dns_init;
|
||||||
|
|
||||||
|
resconf = dns_resconf_local(&err);
|
||||||
|
if (!resconf)
|
||||||
|
{
|
||||||
|
ERR("resconf_open: %s", dns_strerror(err));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
hosts = dns_hosts_local(&err);
|
||||||
|
if (!hosts)
|
||||||
|
{
|
||||||
|
ERR("hosts_open: %s", dns_strerror(err));
|
||||||
|
dns_resconf_close(resconf);
|
||||||
|
resconf = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
dns_hosts_acquire(hosts);
|
||||||
|
dns_resconf_acquire(resconf);
|
||||||
|
/* this is super slow don't do it */
|
||||||
|
//resconf->options.recurse = 1;
|
||||||
|
return ++_ecore_con_dns_init;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ecore_con_info_shutdown(void)
|
||||||
|
{
|
||||||
|
if (!_ecore_con_dns_init) return 0;
|
||||||
|
if (--_ecore_con_dns_init) return _ecore_con_dns_init;
|
||||||
|
dns_resconf_close(dns_resconf_mortal(resconf));
|
||||||
|
resconf = NULL;
|
||||||
|
dns_hosts_close(dns_hosts_mortal(hosts));
|
||||||
|
hosts = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ecore_con_info_data_clear(void *info)
|
||||||
|
{
|
||||||
|
Ecore_Con_DNS *dns = info;
|
||||||
|
if (dns) dns->data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ecore_con_info_tcp_connect(Ecore_Con_Server *svr,
|
||||||
|
Ecore_Con_Info_Cb done_cb,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
struct addrinfo hints;
|
||||||
|
|
||||||
|
memset(&hints, 0, sizeof(struct addrinfo));
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
hints.ai_family = AF_INET6;
|
||||||
|
#else
|
||||||
|
hints.ai_family = AF_INET;
|
||||||
|
#endif
|
||||||
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
hints.ai_flags = AI_CANONNAME;
|
||||||
|
hints.ai_protocol = IPPROTO_TCP;
|
||||||
|
|
||||||
|
return ecore_con_info_get(svr, done_cb, data, &hints);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ecore_con_info_tcp_listen(Ecore_Con_Server *svr,
|
||||||
|
Ecore_Con_Info_Cb done_cb,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
struct addrinfo hints;
|
||||||
|
|
||||||
|
memset(&hints, 0, sizeof(struct addrinfo));
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
hints.ai_family = AF_INET6;
|
||||||
|
#else
|
||||||
|
hints.ai_family = AF_INET;
|
||||||
|
#endif
|
||||||
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
hints.ai_flags = AI_PASSIVE;
|
||||||
|
hints.ai_protocol = IPPROTO_TCP;
|
||||||
|
|
||||||
|
return ecore_con_info_get(svr, done_cb, data, &hints);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ecore_con_info_udp_connect(Ecore_Con_Server *svr,
|
||||||
|
Ecore_Con_Info_Cb done_cb,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
struct addrinfo hints;
|
||||||
|
|
||||||
|
memset(&hints, 0, sizeof(struct addrinfo));
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
hints.ai_family = AF_INET6;
|
||||||
|
#else
|
||||||
|
hints.ai_family = AF_INET;
|
||||||
|
#endif
|
||||||
|
hints.ai_socktype = SOCK_DGRAM;
|
||||||
|
hints.ai_flags = AI_CANONNAME;
|
||||||
|
hints.ai_protocol = IPPROTO_UDP;
|
||||||
|
|
||||||
|
return ecore_con_info_get(svr, done_cb, data, &hints);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ecore_con_info_udp_listen(Ecore_Con_Server *svr,
|
||||||
|
Ecore_Con_Info_Cb done_cb,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
struct addrinfo hints;
|
||||||
|
|
||||||
|
memset(&hints, 0, sizeof(struct addrinfo));
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
hints.ai_family = AF_INET6;
|
||||||
|
#else
|
||||||
|
hints.ai_family = AF_INET;
|
||||||
|
#endif
|
||||||
|
hints.ai_socktype = SOCK_DGRAM;
|
||||||
|
hints.ai_flags = AI_PASSIVE;
|
||||||
|
hints.ai_protocol = IPPROTO_UDP;
|
||||||
|
|
||||||
|
return ecore_con_info_get(svr, done_cb, data, &hints);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ecore_con_info_mcast_listen(Ecore_Con_Server *svr,
|
||||||
|
Ecore_Con_Info_Cb done_cb,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
struct addrinfo hints;
|
||||||
|
|
||||||
|
memset(&hints, 0, sizeof(struct addrinfo));
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
hints.ai_family = AF_INET6;
|
||||||
|
#else
|
||||||
|
hints.ai_family = AF_INET;
|
||||||
|
#endif
|
||||||
|
hints.ai_socktype = SOCK_DGRAM;
|
||||||
|
hints.ai_protocol = IPPROTO_UDP;
|
||||||
|
|
||||||
|
return ecore_con_info_get(svr, done_cb, data, &hints);
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI int
|
||||||
|
ecore_con_info_get(Ecore_Con_Server *svr,
|
||||||
|
Ecore_Con_Info_Cb done_cb,
|
||||||
|
void *data,
|
||||||
|
struct addrinfo *hints)
|
||||||
|
{
|
||||||
|
Ecore_Con_DNS *dns;
|
||||||
|
int error = 0;
|
||||||
|
|
||||||
|
dns = calloc(1, sizeof(Ecore_Con_DNS));
|
||||||
|
if (!dns) return 0;
|
||||||
|
|
||||||
|
dns->svr = svr;
|
||||||
|
dns->done_cb = done_cb;
|
||||||
|
dns->data = data;
|
||||||
|
|
||||||
|
if (hints)
|
||||||
|
memcpy(&dns->hints, hints, sizeof(struct addrinfo));
|
||||||
|
|
||||||
|
if (!(dns->resolv = dns_res_open(resconf, hosts, dns_hints_mortal(dns_hints_local(resconf, &error)), NULL, dns_opts(), &error)))
|
||||||
|
{
|
||||||
|
ERR("res_open: %s", dns_strerror(error));
|
||||||
|
goto reserr;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
error = _dns_addrinfo_get(dns, svr->ecs ? svr->ecs->ip : svr->name, dns->svr->ecs ? dns->svr->ecs->port : dns->svr->port);
|
||||||
|
if (error && (error != EAGAIN))
|
||||||
|
{
|
||||||
|
ERR("resolver: %s", dns_strerror(error));
|
||||||
|
goto seterr;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (_ecore_con_dns_check(dns))
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
dns->fdh = ecore_main_fd_handler_add(dns_ai_pollfd(dns->ai), dns_ai_events(dns->ai), (Ecore_Fd_Cb)_dns_fd_cb, dns, NULL, NULL);
|
||||||
|
svr->infos = eina_list_append(svr->infos, dns);
|
||||||
|
dns->timer = ecore_timer_add(5.0, (Ecore_Task_Cb)_dns_timer_cb, dns);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
seterr:
|
||||||
|
if (dns->resolv) dns_res_close(dns->resolv);
|
||||||
|
reserr:
|
||||||
|
free(dns);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue