resolver: add c-ares support
This patch based on the patch from @gbour (see #7). With --enable-cares old implementation will be replaced with c-ares API.
This commit is contained in:
@@ -8,6 +8,7 @@ PARSER_LIBS=@PARSER_LIBS@
|
|||||||
SSL_CFLAGS = @openssl_CFLAGS@
|
SSL_CFLAGS = @openssl_CFLAGS@
|
||||||
SSL_LIBS = @openssl_LIBS@
|
SSL_LIBS = @openssl_LIBS@
|
||||||
|
|
||||||
|
RESOLV_CFLAGS = @RESOLV_CFLAGS@
|
||||||
RESOLV_LIBS = @RESOLV_LIBS@
|
RESOLV_LIBS = @RESOLV_LIBS@
|
||||||
|
|
||||||
STROPHE_FLAGS = -I$(top_srcdir) -Wall -Wextra -Wno-unused-parameter
|
STROPHE_FLAGS = -I$(top_srcdir) -Wall -Wextra -Wno-unused-parameter
|
||||||
@@ -16,7 +17,7 @@ STROPHE_LIBS = libstrophe.la
|
|||||||
## Main build targets
|
## Main build targets
|
||||||
lib_LTLIBRARIES = libstrophe.la
|
lib_LTLIBRARIES = libstrophe.la
|
||||||
|
|
||||||
libstrophe_la_CFLAGS = $(SSL_CFLAGS) $(STROPHE_FLAGS) $(PARSER_CFLAGS)
|
libstrophe_la_CFLAGS = $(SSL_CFLAGS) $(STROPHE_FLAGS) $(PARSER_CFLAGS) $(RESOLV_CFLAGS)
|
||||||
libstrophe_la_LDFLAGS = $(SSL_LIBS) $(PARSER_LIBS) $(RESOLV_LIBS) -no-undefined
|
libstrophe_la_LDFLAGS = $(SSL_LIBS) $(PARSER_LIBS) $(RESOLV_LIBS) -no-undefined
|
||||||
# Export only public API
|
# Export only public API
|
||||||
libstrophe_la_LDFLAGS += -export-symbols-regex '^xmpp_'
|
libstrophe_la_LDFLAGS += -export-symbols-regex '^xmpp_'
|
||||||
|
|||||||
17
configure.ac
17
configure.ac
@@ -21,6 +21,8 @@ AC_ARG_WITH([libxml2],
|
|||||||
[AS_HELP_STRING([--with-libxml2], [use libxml2 for XML parsing, expat is the default])])
|
[AS_HELP_STRING([--with-libxml2], [use libxml2 for XML parsing, expat is the default])])
|
||||||
AC_ARG_ENABLE([tls],
|
AC_ARG_ENABLE([tls],
|
||||||
[AS_HELP_STRING([--disable-tls], [disable TLS support])])
|
[AS_HELP_STRING([--disable-tls], [disable TLS support])])
|
||||||
|
AC_ARG_ENABLE([cares],
|
||||||
|
[AS_HELP_STRING([--enable-cares], [use c-ares for DNS resolution])])
|
||||||
|
|
||||||
if test "x$enable_tls" != xno; then
|
if test "x$enable_tls" != xno; then
|
||||||
PKG_CHECK_MODULES([openssl], [openssl],
|
PKG_CHECK_MODULES([openssl], [openssl],
|
||||||
@@ -84,6 +86,18 @@ AC_MSG_NOTICE([libstrophe will use the $with_parser XML parser])
|
|||||||
|
|
||||||
AC_SEARCH_LIBS([socket], [socket])
|
AC_SEARCH_LIBS([socket], [socket])
|
||||||
|
|
||||||
|
if test "x$enable_cares" = xyes; then
|
||||||
|
PKG_CHECK_MODULES([libcares], [libcares >= 1.7.0],
|
||||||
|
[
|
||||||
|
PC_REQUIRES="libcares ${PC_REQUIRES}"
|
||||||
|
RESOLV_CFLAGS=$libcares_CFLAGS
|
||||||
|
RESOLV_LIBS=$libcares_LIBS
|
||||||
|
AC_DEFINE([HAVE_CARES])
|
||||||
|
],
|
||||||
|
[AC_MSG_ERROR([libcares not found])])
|
||||||
|
# TODO: if pkg-config doesn't find, check the library manually
|
||||||
|
else
|
||||||
|
|
||||||
AS_CASE([$PLATFORM],
|
AS_CASE([$PLATFORM],
|
||||||
[bsd], [RESOLV_LIBS=""],
|
[bsd], [RESOLV_LIBS=""],
|
||||||
[qnx], [RESOLV_LIBS="-lsocket"],
|
[qnx], [RESOLV_LIBS="-lsocket"],
|
||||||
@@ -110,6 +124,8 @@ AC_LINK_IFELSE([AC_LANG_SOURCE([
|
|||||||
LIBS="${LIBS_TMP}"
|
LIBS="${LIBS_TMP}"
|
||||||
PC_LIBS="${RESOLV_LIBS} ${PC_LIBS}"
|
PC_LIBS="${RESOLV_LIBS} ${PC_LIBS}"
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
m4_ifdef([PKG_INSTALLDIR], [PKG_INSTALLDIR],
|
m4_ifdef([PKG_INSTALLDIR], [PKG_INSTALLDIR],
|
||||||
[AC_ARG_WITH([pkgconfigdir],
|
[AC_ARG_WITH([pkgconfigdir],
|
||||||
[AS_HELP_STRING([--with-pkgconfigdir],
|
[AS_HELP_STRING([--with-pkgconfigdir],
|
||||||
@@ -126,6 +142,7 @@ AC_SUBST([PC_LIBS], [${PC_LIBS}])
|
|||||||
|
|
||||||
AC_SUBST(PARSER_CFLAGS)
|
AC_SUBST(PARSER_CFLAGS)
|
||||||
AC_SUBST(PARSER_LIBS)
|
AC_SUBST(PARSER_LIBS)
|
||||||
|
AC_SUBST(RESOLV_CFLAGS)
|
||||||
AC_SUBST(RESOLV_LIBS)
|
AC_SUBST(RESOLV_LIBS)
|
||||||
AC_CONFIG_FILES([Makefile libstrophe.pc])
|
AC_CONFIG_FILES([Makefile libstrophe.pc])
|
||||||
AC_OUTPUT
|
AC_OUTPUT
|
||||||
|
|||||||
@@ -47,6 +47,7 @@
|
|||||||
|
|
||||||
#include "strophe.h"
|
#include "strophe.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "resolver.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
/* Workaround for visual studio without va_copy support. */
|
/* Workaround for visual studio without va_copy support. */
|
||||||
@@ -63,6 +64,7 @@
|
|||||||
void xmpp_initialize(void)
|
void xmpp_initialize(void)
|
||||||
{
|
{
|
||||||
sock_initialize();
|
sock_initialize();
|
||||||
|
resolver_initialize();
|
||||||
tls_initialize();
|
tls_initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,6 +75,7 @@
|
|||||||
void xmpp_shutdown(void)
|
void xmpp_shutdown(void)
|
||||||
{
|
{
|
||||||
tls_shutdown();
|
tls_shutdown();
|
||||||
|
resolver_shutdown();
|
||||||
sock_shutdown();
|
sock_shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
387
src/resolver.c
387
src/resolver.c
@@ -1,4 +1,4 @@
|
|||||||
/* resolver.h
|
/* resolver.c
|
||||||
* strophe XMPP client library -- DNS resolver
|
* strophe XMPP client library -- DNS resolver
|
||||||
*
|
*
|
||||||
* Copyright (C) 2015 Dmitry Podgorny <pasis.ua@gmail.com>
|
* Copyright (C) 2015 Dmitry Podgorny <pasis.ua@gmail.com>
|
||||||
@@ -13,11 +13,15 @@
|
|||||||
* DNS resolver.
|
* DNS resolver.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _WIN32
|
#if !defined(_WIN32) && !defined(HAVE_CARES)
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <arpa/nameser.h>
|
#include <arpa/nameser.h>
|
||||||
#include <resolv.h> /* res_query */
|
#include <resolv.h> /* res_query */
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 && HAVE_CARES */
|
||||||
|
|
||||||
|
#ifdef HAVE_CARES
|
||||||
|
#include <ares.h>
|
||||||
|
#endif /* HAVE_CARES */
|
||||||
|
|
||||||
#include <string.h> /* strncpy */
|
#include <string.h> /* strncpy */
|
||||||
|
|
||||||
@@ -31,6 +35,189 @@
|
|||||||
#define MESSAGE_T_SRV 33
|
#define MESSAGE_T_SRV 33
|
||||||
#define MESSAGE_C_IN 1
|
#define MESSAGE_C_IN 1
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Forward declarations.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#ifdef HAVE_CARES
|
||||||
|
static int resolver_ares_srv_lookup_buf(xmpp_ctx_t *ctx,
|
||||||
|
const unsigned char *buf,
|
||||||
|
size_t len,
|
||||||
|
resolver_srv_rr_t **srv_rr_list);
|
||||||
|
static int resolver_ares_srv_lookup(xmpp_ctx_t *ctx, const char *fulldomain,
|
||||||
|
resolver_srv_rr_t **srv_rr_list);
|
||||||
|
#endif /* HAVE_CARES */
|
||||||
|
|
||||||
|
#ifndef HAVE_CARES
|
||||||
|
static int resolver_raw_srv_lookup_buf(xmpp_ctx_t *ctx,
|
||||||
|
const unsigned char *buf,
|
||||||
|
size_t len,
|
||||||
|
resolver_srv_rr_t **srv_rr_list);
|
||||||
|
#endif /* !HAVE_CARES */
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
static int resolver_win32_srv_lookup(xmpp_ctx_t *ctx, const char *fulldomain,
|
||||||
|
resolver_srv_rr_t **srv_rr_list);
|
||||||
|
static int resolver_win32_srv_query(const char *fulldomain,
|
||||||
|
unsigned char *buf, size_t len);
|
||||||
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Implementation.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
void resolver_initialize(void)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_CARES
|
||||||
|
ares_library_init(ARES_LIB_INIT_ALL);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void resolver_shutdown(void)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_CARES
|
||||||
|
ares_library_cleanup();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void resolver_srv_list_sort(resolver_srv_rr_t **srv_rr_list)
|
||||||
|
{
|
||||||
|
resolver_srv_rr_t *rr_head;
|
||||||
|
resolver_srv_rr_t *rr_current;
|
||||||
|
resolver_srv_rr_t *rr_next;
|
||||||
|
resolver_srv_rr_t *rr_prev;
|
||||||
|
int swap;
|
||||||
|
|
||||||
|
rr_head = *srv_rr_list;
|
||||||
|
|
||||||
|
if ((rr_head == NULL) || (rr_head->next == NULL)) {
|
||||||
|
/* Empty or single record list */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
rr_prev = NULL;
|
||||||
|
rr_current = rr_head;
|
||||||
|
rr_next = rr_head->next;
|
||||||
|
swap = 0;
|
||||||
|
while (rr_next != NULL) {
|
||||||
|
/*
|
||||||
|
* RFC2052: A client MUST attempt to contact the target host
|
||||||
|
* with the lowest-numbered priority it can reach.
|
||||||
|
* RFC2052: When selecting a target host among the
|
||||||
|
* those that have the same priority, the chance of trying
|
||||||
|
* this one first SHOULD be proportional to its weight.
|
||||||
|
*/
|
||||||
|
if ((rr_current->priority > rr_next->priority) ||
|
||||||
|
(rr_current->priority == rr_next->priority &&
|
||||||
|
rr_current->weight < rr_next->weight))
|
||||||
|
{
|
||||||
|
/* Swap node */
|
||||||
|
swap = 1;
|
||||||
|
if (rr_prev != NULL) {
|
||||||
|
rr_prev->next = rr_next;
|
||||||
|
} else {
|
||||||
|
/* Swap head node */
|
||||||
|
rr_head = rr_next;
|
||||||
|
}
|
||||||
|
rr_current->next = rr_next->next;
|
||||||
|
rr_next->next = rr_current;
|
||||||
|
|
||||||
|
rr_prev = rr_next;
|
||||||
|
rr_next = rr_current->next;
|
||||||
|
} else {
|
||||||
|
/* Next node */
|
||||||
|
rr_prev = rr_current;
|
||||||
|
rr_current = rr_next;
|
||||||
|
rr_next = rr_next->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (swap != 0);
|
||||||
|
|
||||||
|
*srv_rr_list = rr_head;
|
||||||
|
}
|
||||||
|
|
||||||
|
int resolver_srv_lookup_buf(xmpp_ctx_t *ctx, const unsigned char *buf,
|
||||||
|
size_t len, resolver_srv_rr_t **srv_rr_list)
|
||||||
|
{
|
||||||
|
int set;
|
||||||
|
|
||||||
|
#ifdef HAVE_CARES
|
||||||
|
set = resolver_ares_srv_lookup_buf(ctx, buf, len, srv_rr_list);
|
||||||
|
#else
|
||||||
|
set = resolver_raw_srv_lookup_buf(ctx, buf, len, srv_rr_list);
|
||||||
|
#endif
|
||||||
|
resolver_srv_list_sort(srv_rr_list);
|
||||||
|
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
|
||||||
|
int resolver_srv_lookup(xmpp_ctx_t *ctx, const char *service, const char *proto,
|
||||||
|
const char *domain, resolver_srv_rr_t **srv_rr_list)
|
||||||
|
{
|
||||||
|
#define RESOLVER_BUF_MAX 65536
|
||||||
|
unsigned char *buf;
|
||||||
|
char fulldomain[2048];
|
||||||
|
int len;
|
||||||
|
int set = XMPP_DOMAIN_NOT_FOUND;
|
||||||
|
|
||||||
|
(void)buf;
|
||||||
|
(void)len;
|
||||||
|
|
||||||
|
xmpp_snprintf(fulldomain, sizeof(fulldomain),
|
||||||
|
"_%s._%s.%s", service, proto, domain);
|
||||||
|
|
||||||
|
*srv_rr_list = NULL;
|
||||||
|
|
||||||
|
#ifdef HAVE_CARES
|
||||||
|
set = resolver_ares_srv_lookup(ctx, fulldomain, srv_rr_list);
|
||||||
|
#else /* HAVE_CARES */
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
set = resolver_win32_srv_lookup(ctx, fulldomain, srv_rr_list);
|
||||||
|
if (set == XMPP_DOMAIN_FOUND)
|
||||||
|
return set;
|
||||||
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
|
buf = xmpp_alloc(ctx, RESOLVER_BUF_MAX);
|
||||||
|
if (buf == NULL)
|
||||||
|
return XMPP_DOMAIN_NOT_FOUND;
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
len = resolver_win32_srv_query(fulldomain, buf, RESOLVER_BUF_MAX);
|
||||||
|
#else /* _WIN32 */
|
||||||
|
len = res_query(fulldomain, MESSAGE_C_IN, MESSAGE_T_SRV, buf,
|
||||||
|
RESOLVER_BUF_MAX);
|
||||||
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
|
if (len > 0)
|
||||||
|
set = resolver_srv_lookup_buf(ctx, buf, (size_t)len, srv_rr_list);
|
||||||
|
|
||||||
|
xmpp_free(ctx, buf);
|
||||||
|
|
||||||
|
#endif /* HAVE_CARES */
|
||||||
|
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
|
||||||
|
void resolver_srv_free(xmpp_ctx_t *ctx, resolver_srv_rr_t *srv_rr_list)
|
||||||
|
{
|
||||||
|
resolver_srv_rr_t *rr;
|
||||||
|
|
||||||
|
while (srv_rr_list != NULL) {
|
||||||
|
rr = srv_rr_list->next;
|
||||||
|
xmpp_free(ctx, srv_rr_list);
|
||||||
|
srv_rr_list = rr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef HAVE_CARES
|
||||||
|
/*******************************************************************************
|
||||||
|
* Resolver raw implementation.
|
||||||
|
*
|
||||||
|
* This code is common for both unix and win32.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
struct message_header {
|
struct message_header {
|
||||||
uint16_t id;
|
uint16_t id;
|
||||||
uint8_t octet2;
|
uint8_t octet2;
|
||||||
@@ -41,13 +228,6 @@ struct message_header {
|
|||||||
uint16_t arcount;
|
uint16_t arcount;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
static int resolver_win32_srv_lookup(xmpp_ctx_t *ctx, const char *fulldomain,
|
|
||||||
resolver_srv_rr_t **srv_rr_list);
|
|
||||||
static int resolver_win32_srv_query(const char *fulldomain,
|
|
||||||
unsigned char *buf, size_t len);
|
|
||||||
#endif /* _WIN32 */
|
|
||||||
|
|
||||||
/* the same as ntohs(), but receives pointer to the value */
|
/* the same as ntohs(), but receives pointer to the value */
|
||||||
static uint16_t xmpp_ntohs_ptr(const void *ptr)
|
static uint16_t xmpp_ntohs_ptr(const void *ptr)
|
||||||
{
|
{
|
||||||
@@ -160,63 +340,6 @@ static unsigned message_name_len(const unsigned char *buf, size_t buf_len,
|
|||||||
return message_name_get(buf, buf_len, buf_offset, NULL, SIZE_MAX);
|
return message_name_get(buf, buf_len, buf_offset, NULL, SIZE_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void resolver_srv_list_sort(resolver_srv_rr_t **srv_rr_list)
|
|
||||||
{
|
|
||||||
resolver_srv_rr_t * rr_head;
|
|
||||||
resolver_srv_rr_t * rr_current;
|
|
||||||
resolver_srv_rr_t * rr_next;
|
|
||||||
resolver_srv_rr_t * rr_prev;
|
|
||||||
int swap;
|
|
||||||
|
|
||||||
rr_head = *srv_rr_list;
|
|
||||||
|
|
||||||
if ((rr_head == NULL) || (rr_head->next == NULL)) {
|
|
||||||
/* Empty or single record list */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
do {
|
|
||||||
rr_prev = NULL;
|
|
||||||
rr_current = rr_head;
|
|
||||||
rr_next = rr_head->next;
|
|
||||||
swap = 0;
|
|
||||||
while (rr_next != NULL) {
|
|
||||||
/*
|
|
||||||
* RFC2052: A client MUST attempt to contact the target host
|
|
||||||
* with the lowest-numbered priority it can reach.
|
|
||||||
* RFC2052: When selecting a target host among the
|
|
||||||
* those that have the same priority, the chance of trying
|
|
||||||
* this one first SHOULD be proportional to its weight.
|
|
||||||
*/
|
|
||||||
if ((rr_current->priority > rr_next->priority) ||
|
|
||||||
(rr_current->priority == rr_next->priority &&
|
|
||||||
rr_current->weight < rr_next->weight))
|
|
||||||
{
|
|
||||||
/* Swap node */
|
|
||||||
swap = 1;
|
|
||||||
if (rr_prev != NULL) {
|
|
||||||
rr_prev->next = rr_next;
|
|
||||||
} else {
|
|
||||||
/* Swap head node */
|
|
||||||
rr_head = rr_next;
|
|
||||||
}
|
|
||||||
rr_current->next = rr_next->next;
|
|
||||||
rr_next->next = rr_current;
|
|
||||||
|
|
||||||
rr_prev = rr_next;
|
|
||||||
rr_next = rr_current->next;
|
|
||||||
} else {
|
|
||||||
/* Next node */
|
|
||||||
rr_prev = rr_current;
|
|
||||||
rr_current = rr_next;
|
|
||||||
rr_next = rr_next->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (swap != 0);
|
|
||||||
|
|
||||||
*srv_rr_list = rr_head;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define BUF_OVERFLOW_CHECK(ptr, len) do { \
|
#define BUF_OVERFLOW_CHECK(ptr, len) do { \
|
||||||
if ((ptr) >= (len)) { \
|
if ((ptr) >= (len)) { \
|
||||||
if (*srv_rr_list != NULL) \
|
if (*srv_rr_list != NULL) \
|
||||||
@@ -226,8 +349,10 @@ static void resolver_srv_list_sort(resolver_srv_rr_t **srv_rr_list)
|
|||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
int resolver_srv_lookup_buf(xmpp_ctx_t *ctx, const unsigned char *buf,
|
static int resolver_raw_srv_lookup_buf(xmpp_ctx_t *ctx,
|
||||||
size_t len, resolver_srv_rr_t **srv_rr_list)
|
const unsigned char *buf,
|
||||||
|
size_t len,
|
||||||
|
resolver_srv_rr_t **srv_rr_list)
|
||||||
{
|
{
|
||||||
unsigned i;
|
unsigned i;
|
||||||
unsigned j;
|
unsigned j;
|
||||||
@@ -292,52 +417,110 @@ int resolver_srv_lookup_buf(xmpp_ctx_t *ctx, const unsigned char *buf,
|
|||||||
}
|
}
|
||||||
j += rdlength;
|
j += rdlength;
|
||||||
}
|
}
|
||||||
resolver_srv_list_sort(srv_rr_list);
|
|
||||||
|
|
||||||
return *srv_rr_list != NULL ? XMPP_DOMAIN_FOUND : XMPP_DOMAIN_NOT_FOUND;
|
return *srv_rr_list != NULL ? XMPP_DOMAIN_FOUND : XMPP_DOMAIN_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
int resolver_srv_lookup(xmpp_ctx_t *ctx, const char *service, const char *proto,
|
#endif /* !HAVE_CARES */
|
||||||
const char *domain, resolver_srv_rr_t **srv_rr_list)
|
|
||||||
{
|
|
||||||
char fulldomain[2048];
|
|
||||||
unsigned char buf[65535];
|
|
||||||
int len;
|
|
||||||
int set = XMPP_DOMAIN_NOT_FOUND;
|
|
||||||
|
|
||||||
xmpp_snprintf(fulldomain, sizeof(fulldomain),
|
#ifdef HAVE_CARES
|
||||||
"_%s._%s.%s", service, proto, domain);
|
/*******************************************************************************
|
||||||
|
* Resolver implementation using c-ares library.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
struct resolver_ares_ctx {
|
||||||
|
xmpp_ctx_t *ctx;
|
||||||
|
int result;
|
||||||
|
resolver_srv_rr_t *srv_rr_list;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int resolver_ares_srv_lookup_buf(xmpp_ctx_t *ctx,
|
||||||
|
const unsigned char *buf,
|
||||||
|
size_t len,
|
||||||
|
resolver_srv_rr_t **srv_rr_list)
|
||||||
|
{
|
||||||
|
struct ares_srv_reply *srv;
|
||||||
|
struct ares_srv_reply *item;
|
||||||
|
resolver_srv_rr_t *rr;
|
||||||
|
int rc;
|
||||||
|
|
||||||
*srv_rr_list = NULL;
|
*srv_rr_list = NULL;
|
||||||
|
|
||||||
#ifdef _WIN32
|
rc = ares_parse_srv_reply(buf, len, &srv);
|
||||||
set = resolver_win32_srv_lookup(ctx, fulldomain, srv_rr_list);
|
if (rc != ARES_SUCCESS)
|
||||||
if (set == XMPP_DOMAIN_FOUND)
|
return XMPP_DOMAIN_NOT_FOUND;
|
||||||
return set;
|
|
||||||
len = resolver_win32_srv_query(fulldomain, buf, sizeof(buf));
|
|
||||||
#else /* _WIN32 */
|
|
||||||
len = res_query(fulldomain, MESSAGE_C_IN, MESSAGE_T_SRV, buf, sizeof(buf));
|
|
||||||
#endif /* _WIN32 */
|
|
||||||
|
|
||||||
if (len > 0)
|
item = srv;
|
||||||
set = resolver_srv_lookup_buf(ctx, buf, (size_t)len, srv_rr_list);
|
while (item != NULL) {
|
||||||
|
rr = xmpp_alloc(ctx, sizeof(*rr));
|
||||||
return set;
|
if (rr == NULL)
|
||||||
}
|
break;
|
||||||
|
rr->next = *srv_rr_list;
|
||||||
void resolver_srv_free(xmpp_ctx_t *ctx, resolver_srv_rr_t *srv_rr_list)
|
rr->priority = item->priority;
|
||||||
{
|
rr->weight = item->weight;
|
||||||
resolver_srv_rr_t *rr;
|
rr->port = item->port;
|
||||||
|
strncpy(rr->target, item->host, sizeof(rr->target) - 1);
|
||||||
while (srv_rr_list != NULL) {
|
rr->target[sizeof(rr->target) - 1] = '\0';
|
||||||
rr = srv_rr_list->next;
|
*srv_rr_list = rr;
|
||||||
xmpp_free(ctx, srv_rr_list);
|
item = item->next;
|
||||||
srv_rr_list = rr;
|
|
||||||
}
|
}
|
||||||
|
ares_free_data(srv);
|
||||||
|
|
||||||
|
return *srv_rr_list == NULL ? XMPP_DOMAIN_NOT_FOUND : XMPP_DOMAIN_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
static void ares_srv_lookup_callback(void *arg, int status, int timeouts,
|
||||||
|
unsigned char *buf, int len)
|
||||||
|
{
|
||||||
|
struct resolver_ares_ctx *actx = arg;
|
||||||
|
|
||||||
|
if (status != ARES_SUCCESS)
|
||||||
|
actx->result = XMPP_DOMAIN_NOT_FOUND;
|
||||||
|
else
|
||||||
|
actx->result = resolver_ares_srv_lookup_buf(actx->ctx, buf, len,
|
||||||
|
&actx->srv_rr_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int resolver_ares_srv_lookup(xmpp_ctx_t *ctx, const char *fulldomain,
|
||||||
|
resolver_srv_rr_t **srv_rr_list)
|
||||||
|
{
|
||||||
|
struct resolver_ares_ctx actx;
|
||||||
|
ares_channel chan;
|
||||||
|
struct timeval tv;
|
||||||
|
struct timeval *tvp;
|
||||||
|
fd_set rfds;
|
||||||
|
fd_set wfds;
|
||||||
|
int nfds;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
actx.ctx = ctx;
|
||||||
|
actx.result = XMPP_DOMAIN_NOT_FOUND;
|
||||||
|
actx.srv_rr_list = NULL;
|
||||||
|
|
||||||
|
rc = ares_init(&chan);
|
||||||
|
if (rc == ARES_SUCCESS) {
|
||||||
|
ares_query(chan, fulldomain, MESSAGE_C_IN, MESSAGE_T_SRV,
|
||||||
|
ares_srv_lookup_callback, &actx);
|
||||||
|
while (1) {
|
||||||
|
FD_ZERO(&rfds);
|
||||||
|
FD_ZERO(&wfds);
|
||||||
|
nfds = ares_fds(chan, &rfds, &wfds);
|
||||||
|
if (nfds == 0)
|
||||||
|
break;
|
||||||
|
tvp = ares_timeout(chan, NULL, &tv);
|
||||||
|
select(nfds, &rfds, &wfds, NULL, tvp);
|
||||||
|
ares_process(chan, &rfds, &wfds);
|
||||||
|
}
|
||||||
|
ares_destroy(chan);
|
||||||
|
}
|
||||||
|
|
||||||
|
*srv_rr_list = actx.srv_rr_list;
|
||||||
|
return actx.result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* HAVE_CARES */
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Next part was copied from sock.c and contains old win32 code.
|
* Next part was copied from sock.c and contains old win32 code.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -33,6 +33,9 @@ typedef struct resolver_srv_rr_struc {
|
|||||||
struct resolver_srv_rr_struc *next;
|
struct resolver_srv_rr_struc *next;
|
||||||
} resolver_srv_rr_t;
|
} resolver_srv_rr_t;
|
||||||
|
|
||||||
|
void resolver_initialize(void);
|
||||||
|
void resolver_shutdown(void);
|
||||||
|
|
||||||
/** Perform lookup for RFC1035 message format.
|
/** Perform lookup for RFC1035 message format.
|
||||||
* This function allocates all elements.
|
* This function allocates all elements.
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user