Commit abb6f4fa authored by Ghislain MARY's avatar Ghislain MARY

Add mechanism to fallback to getaddrinfo() for DNS resolution when there is no...

Add mechanism to fallback to getaddrinfo() for DNS resolution when there is no way to get the DNS address from the system (eg. on Windows Phone).
parent 44447d13
...@@ -53,7 +53,7 @@ ...@@ -53,7 +53,7 @@
<ItemDefinitionGroup> <ItemDefinitionGroup>
<ClCompile> <ClCompile>
<WarningLevel>Level4</WarningLevel> <WarningLevel>Level4</WarningLevel>
<PreprocessorDefinitions>WIN32;_WINDOWS;_USRDLL;BELLESIP_EXPORTS;BELLESIP_INTERNAL_EXPORTS;HAVE_POLARSSL;HAVE_TUNNEL;HAVE_ANTLR_STRING_STREAM_NEW;HAVE_COMPILER_TLS;_CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;USE_FIXED_NAMESERVERS;ENABLE_SERVER_SOCKETS;HAVE_CONFIG_H;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_WINDOWS;_USRDLL;BELLESIP_EXPORTS;BELLESIP_INTERNAL_EXPORTS;HAVE_POLARSSL;HAVE_TUNNEL;HAVE_ANTLR_STRING_STREAM_NEW;HAVE_COMPILER_TLS;_CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;USE_FIXED_NAMESERVERS;USE_GETADDRINFO_FALLBACK;ENABLE_SERVER_SOCKETS;HAVE_CONFIG_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\include;$(ProjectDir)..\..\..\..\antlr3\runtime\C\include;$(ProjectDir)..\..\..\src;$(ProjectDir)..\..\..\..\polarssl\include;$(ProjectDir)..\..\..\..\tunnel\include;$(ProjectDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>$(ProjectDir)..\..\..\include;$(ProjectDir)..\..\..\..\antlr3\runtime\C\include;$(ProjectDir)..\..\..\src;$(ProjectDir)..\..\..\..\polarssl\include;$(ProjectDir)..\..\..\..\tunnel\include;$(ProjectDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<BasicRuntimeChecks>Default</BasicRuntimeChecks> <BasicRuntimeChecks>Default</BasicRuntimeChecks>
<PrecompiledHeader>NotUsing</PrecompiledHeader> <PrecompiledHeader>NotUsing</PrecompiledHeader>
......
...@@ -122,6 +122,12 @@ struct belle_sip_simple_resolver_context{ ...@@ -122,6 +122,12 @@ struct belle_sip_simple_resolver_context{
int family; int family;
int flags; int flags;
uint64_t start_time; uint64_t start_time;
#ifdef USE_GETADDRINFO_FALLBACK
belle_sip_thread_t getaddrinfo_thread;
belle_sip_mutex_t getaddrinfo_mutex;
unsigned char getaddrinfo_done;
unsigned char getaddrinfo_cancelled;
#endif
}; };
struct belle_sip_combined_resolver_context{ struct belle_sip_combined_resolver_context{
...@@ -396,7 +402,13 @@ static void append_dns_result(belle_sip_simple_resolver_context_t *ctx, struct s ...@@ -396,7 +402,13 @@ static void append_dns_result(belle_sip_simple_resolver_context_t *ctx, struct s
return; return;
} }
if (ctx->flags & AI_V4MAPPED) family=AF_INET6; if (ctx->flags & AI_V4MAPPED) family=AF_INET6;
#ifdef USE_GETADDRINFO_FALLBACK
belle_sip_mutex_lock(&ctx->getaddrinfo_mutex);
#endif
ctx->ai_list = ai_list_append(ctx->ai_list, belle_sip_ip_address_to_addrinfo(family, host, ctx->port)); ctx->ai_list = ai_list_append(ctx->ai_list, belle_sip_ip_address_to_addrinfo(family, host, ctx->port));
#ifdef USE_GETADDRINFO_FALLBACK
belle_sip_mutex_unlock(&ctx->getaddrinfo_mutex);
#endif
belle_sip_message("%s resolved to %s", ctx->name, host); belle_sip_message("%s resolved to %s", ctx->name, host);
} }
...@@ -464,22 +476,74 @@ static int resolver_process_data(belle_sip_simple_resolver_context_t *ctx, unsig ...@@ -464,22 +476,74 @@ static int resolver_process_data(belle_sip_simple_resolver_context_t *ctx, unsig
} }
free(ans); free(ans);
notify_results(ctx); notify_results(ctx);
#ifdef USE_GETADDRINFO_FALLBACK
ctx->getaddrinfo_cancelled = TRUE;
#endif
return BELLE_SIP_STOP; return BELLE_SIP_STOP;
} }
if (error != DNS_EAGAIN) { if (error != DNS_EAGAIN) {
belle_sip_error("%s dns_res_check() error: %s (%d)", __FUNCTION__, dns_strerror(error), error); belle_sip_error("%s dns_res_check() error: %s (%d)", __FUNCTION__, dns_strerror(error), error);
notify_results(ctx); #ifdef USE_GETADDRINFO_FALLBACK
return BELLE_SIP_STOP; if (ctx->getaddrinfo_done) {
}else{ notify_results(ctx);
belle_sip_message("%s dns_res_check() in progress",__FUNCTION__); return BELLE_SIP_STOP;
} else
// Wait for the getaddrinfo result
#endif
{
return BELLE_SIP_CONTINUE;
}
} else {
#ifdef USE_GETADDRINFO_FALLBACK
if (ctx->getaddrinfo_done) {
notify_results(ctx);
return BELLE_SIP_STOP;
} else
#endif
{
belle_sip_message("%s dns_res_check() in progress", __FUNCTION__);
}
} }
return BELLE_SIP_CONTINUE; return BELLE_SIP_CONTINUE;
} }
#ifdef USE_GETADDRINFO_FALLBACK
static void * _resolver_getaddrinfo_thread(void *ptr) {
belle_sip_simple_resolver_context_t *ctx = (belle_sip_simple_resolver_context_t *)ptr;
struct addrinfo *res = NULL;
struct addrinfo hints = { 0 };
char serv[10];
int err;
/* The thread owns a ref on the resolver context */
belle_sip_object_ref(ctx);
belle_sip_message("Resolver getaddrinfo thread started.");
snprintf(serv, sizeof(serv), "%i", ctx->port);
hints.ai_family = ctx->family;
hints.ai_flags = AI_NUMERICSERV;
err = getaddrinfo(ctx->name, serv, &hints, &res);
if (err != 0) {
belle_sip_error("getaddrinfo DNS resolution of %s failed: %s", ctx->name, gai_strerror(err));
} else if (!ctx->getaddrinfo_cancelled) {
append_dns_result(ctx, res->ai_addr, res->ai_addrlen);
}
ctx->getaddrinfo_done = TRUE;
// The results will be notified by the timeout in the resolver_process_data function
belle_sip_object_unref(ctx);
return NULL;
}
#endif
static int _resolver_send_query(belle_sip_simple_resolver_context_t *ctx) { static int _resolver_send_query(belle_sip_simple_resolver_context_t *ctx) {
int error; int error = 0;
if (!ctx->base.stack->resolver_send_error) { if (!ctx->base.stack->resolver_send_error) {
#ifdef USE_GETADDRINFO_FALLBACK
if (ctx->type == DNS_T_A) {
belle_sip_thread_create(&ctx->getaddrinfo_thread, NULL, _resolver_getaddrinfo_thread, ctx);
}
#endif
error = dns_res_submit(ctx->R, ctx->name, ctx->type, DNS_C_IN); error = dns_res_submit(ctx->R, ctx->name, ctx->type, DNS_C_IN);
if (error) if (error)
belle_sip_error("%s dns_res_submit error [%s]: %s", __FUNCTION__, ctx->name, dns_strerror(error)); belle_sip_error("%s dns_res_submit error [%s]: %s", __FUNCTION__, ctx->name, dns_strerror(error));
...@@ -511,10 +575,7 @@ static int resolver_process_data_delayed(belle_sip_simple_resolver_context_t *ct ...@@ -511,10 +575,7 @@ static int resolver_process_data_delayed(belle_sip_simple_resolver_context_t *ct
static int _resolver_start_query(belle_sip_simple_resolver_context_t *ctx) { static int _resolver_start_query(belle_sip_simple_resolver_context_t *ctx) {
struct dns_hints *(*hints)() = &dns_hints_local; struct dns_hints *(*hints)() = &dns_hints_local;
struct dns_options *opts; struct dns_options opts;
#ifndef HAVE_C99
struct dns_options opts_st;
#endif
int error; int error;
struct dns_resolv_conf *conf; struct dns_resolv_conf *conf;
...@@ -530,10 +591,9 @@ static int _resolver_start_query(belle_sip_simple_resolver_context_t *ctx) { ...@@ -530,10 +591,9 @@ static int _resolver_start_query(belle_sip_simple_resolver_context_t *ctx) {
if (!hosts(ctx)) if (!hosts(ctx))
return -1; return -1;
memset(&opts_st, 0, sizeof opts_st); memset(&opts, 0, sizeof opts);
opts = &opts_st;
if (!(ctx->R = dns_res_open(ctx->resconf, ctx->hosts, dns_hints_mortal(hints(ctx->resconf, &error)), cache(ctx), opts, &error))) { if (!(ctx->R = dns_res_open(ctx->resconf, ctx->hosts, dns_hints_mortal(hints(ctx->resconf, &error)), cache(ctx), &opts, &error))) {
belle_sip_error("%s dns_res_open error [%s]: %s", __FUNCTION__, ctx->name, dns_strerror(error)); belle_sip_error("%s dns_res_open error [%s]: %s", __FUNCTION__, ctx->name, dns_strerror(error));
return -1; return -1;
} }
...@@ -619,6 +679,14 @@ static void belle_sip_combined_resolver_context_destroy(belle_sip_combined_resol ...@@ -619,6 +679,14 @@ static void belle_sip_combined_resolver_context_destroy(belle_sip_combined_resol
static void belle_sip_simple_resolver_context_destroy(belle_sip_simple_resolver_context_t *ctx){ static void belle_sip_simple_resolver_context_destroy(belle_sip_simple_resolver_context_t *ctx){
/* Do not free elements of ctx->ai_list with belle_sip_freeaddrinfo(). Let the caller do it, otherwise /* Do not free elements of ctx->ai_list with belle_sip_freeaddrinfo(). Let the caller do it, otherwise
it will not be able to use them after the resolver has been destroyed. */ it will not be able to use them after the resolver has been destroyed. */
#ifdef USE_GETADDRINFO_FALLBACK
if (ctx->getaddrinfo_thread != 0) {
belle_sip_thread_join(ctx->getaddrinfo_thread, NULL);
}
if (ctx->getaddrinfo_mutex != 0) {
belle_sip_mutex_destroy(&ctx->getaddrinfo_mutex);
}
#endif
if (ctx->name != NULL) { if (ctx->name != NULL) {
belle_sip_free(ctx->name); belle_sip_free(ctx->name);
ctx->name = NULL; ctx->name = NULL;
...@@ -891,6 +959,9 @@ static belle_sip_resolver_context_t * belle_sip_stack_resolve_single(belle_sip_s ...@@ -891,6 +959,9 @@ static belle_sip_resolver_context_t * belle_sip_stack_resolve_single(belle_sip_s
if (family == 0) family = AF_UNSPEC; if (family == 0) family = AF_UNSPEC;
ctx->family = family; ctx->family = family;
ctx->type = (ctx->family == AF_INET6) ? DNS_T_AAAA : DNS_T_A; ctx->type = (ctx->family == AF_INET6) ? DNS_T_AAAA : DNS_T_A;
#ifdef USE_GETADDRINFO_FALLBACK
belle_sip_mutex_init(&ctx->getaddrinfo_mutex, NULL);
#endif
return (belle_sip_resolver_context_t*)resolver_start_query(ctx); return (belle_sip_resolver_context_t*)resolver_start_query(ctx);
} }
......
...@@ -47,7 +47,69 @@ void belle_sip_uninit_sockets(void){ ...@@ -47,7 +47,69 @@ void belle_sip_uninit_sockets(void){
if (sockets_initd==0) WSACleanup(); if (sockets_initd==0) WSACleanup();
} }
int belle_sip_socket_set_nonblocking (belle_sip_socket_t sock) typedef struct thread_param {
void * (*func)(void *);
void * arg;
} thread_param_t;
static unsigned WINAPI thread_starter(void *data) {
thread_param_t *params = (thread_param_t*)data;
void *ret = params->func(params->arg);
belle_sip_free(data);
return (DWORD)ret;
}
int belle_sip_thread_create(belle_sip_thread_t *thread, void *attr, void * (*func)(void *), void *data) {
thread_param_t *params = belle_sip_new(thread_param_t);
params->func = func;
params->arg = data;
*thread = (HANDLE)_beginthreadex(NULL, 0, thread_starter, params, 0, NULL);
return 0;
}
int belle_sip_thread_join(belle_sip_thread_t thread, void **unused) {
if (thread != NULL) {
WaitForSingleObject(thread, INFINITE);
CloseHandle(thread);
}
return 0;
}
int belle_sip_mutex_init(belle_sip_mutex_t *mutex, void *attr) {
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
*mutex = CreateMutex(NULL, FALSE, NULL);
#else
InitializeSRWLock(mutex);
#endif
return 0;
}
int belle_sip_mutex_lock(belle_sip_mutex_t * hMutex) {
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
WaitForSingleObject(*hMutex, INFINITE);
#else
AcquireSRWLockExclusive(hMutex);
#endif
return 0;
}
int belle_sip_mutex_unlock(belle_sip_mutex_t * hMutex) {
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
ReleaseMutex(*hMutex);
#else
ReleaseSRWLockExclusive(hMutex);
#endif
return 0;
}
int belle_sip_mutex_destroy(belle_sip_mutex_t * hMutex) {
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
CloseHandle(*hMutex);
#endif
return 0;
}
int belle_sip_socket_set_nonblocking(belle_sip_socket_t sock)
{ {
unsigned long nonBlock = 1; unsigned long nonBlock = 1;
return ioctlsocket(sock, FIONBIO , &nonBlock); return ioctlsocket(sock, FIONBIO , &nonBlock);
......
...@@ -116,6 +116,42 @@ static BELLESIP_INLINE int get_socket_error(void){ ...@@ -116,6 +116,42 @@ static BELLESIP_INLINE int get_socket_error(void){
const char *belle_sip_get_socket_error_string(); const char *belle_sip_get_socket_error_string();
const char *belle_sip_get_socket_error_string_from_code(int code); const char *belle_sip_get_socket_error_string_from_code(int code);
/*
* Thread abstraction layer
*/
#ifdef WIN32
typedef HANDLE belle_sip_thread_t;
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
typedef HANDLE belle_sip_mutex_t;
#else
typedef SRWLOCK belle_sip_mutex_t;
#endif
int belle_sip_thread_join(belle_sip_thread_t thread, void **retptr);
int belle_sip_thread_create(belle_sip_thread_t *thread, void *attr, void * (*routine)(void*), void *arg);
int belle_sip_mutex_init(belle_sip_mutex_t *m, void *attr_unused);
int belle_sip_mutex_lock(belle_sip_mutex_t *mutex);
int belle_sip_mutex_unlock(belle_sip_mutex_t *mutex);
int belle_sip_mutex_destroy(belle_sip_mutex_t *mutex);
#else
#include <pthread.h>
typedef pthread_t belle_sip_thread_t;
typedef pthread_mutex_t belle_sip_mutex_t;
#define belle_sip_thread_join(thread, retptr) pthread_join(thread, retptr)
#define belle_sip_thread_create(thread, attr, routine, arg) pthread_create(thread, attr, routine, arg)
#define belle_sip_mutex_init pthread_mutex_init
#define belle_sip_mutex_lock pthread_mutex_lock
#define belle_sip_mutex_unlock pthread_mutex_unlock
#define belle_sip_mutex_destroy pthread_mutex_destroy
#endif
#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
BELLESIP_INTERNAL_EXPORT void belle_sip_sleep(unsigned int ms); BELLESIP_INTERNAL_EXPORT void belle_sip_sleep(unsigned int ms);
#else #else
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment