Commit 41666379 authored by Simon Morlat's avatar Simon Morlat
Browse files

Merge branch 'feature/resolver-improvements'

parents 0b57292c dbc0781b
Pipeline #274 failed with stage
in 0 seconds
......@@ -25,6 +25,9 @@ typedef struct belle_sip_dns_srv belle_sip_dns_srv_t;
typedef struct belle_sip_resolver_context belle_sip_resolver_context_t;
#define BELLE_SIP_RESOLVER_CONTEXT(obj) BELLE_SIP_CAST(obj,belle_sip_resolver_context_t)
typedef struct belle_sip_resolver_results belle_sip_resolver_results_t;
#define BELLE_SIP_RESOLVER_RESULTS(obj) BELLE_SIP_CAST(obj,belle_sip_resolver_results_t)
/**
* Callback prototype for asynchronous DNS SRV resolution.
* The srv_list contains struct dns_srv elements that must be taken and (possibly later) freed by the callee, using belle_sip_free().
......@@ -33,10 +36,10 @@ typedef void (*belle_sip_resolver_srv_callback_t)(void *data, const char *name,
/**
* Callback prototype for asynchronous DNS A and AAAA resolution.
* The ai_list contains addrinfo elements that must be taken and (possibly later) freed by the callee, using freeaddrinfo().
* These elements are linked by their ai_next field.
* The 'results' object must be acquired (ref'd) in order for being accessed outside of the callback.
* The results object provides SRV records list and addrinfo list.
**/
typedef void (*belle_sip_resolver_callback_t)(void *data, const char *name, struct addrinfo *ai_list, uint32_t ttl);
typedef void (*belle_sip_resolver_callback_t)(void *data, belle_sip_resolver_results_t *results);
BELLE_SIP_BEGIN_DECLS
......@@ -49,6 +52,20 @@ BELLESIP_EXPORT unsigned short belle_sip_dns_srv_get_weight(const belle_sip_dns_
BELLESIP_EXPORT unsigned short belle_sip_dns_srv_get_port(const belle_sip_dns_srv_t *obj);
/**
* Find the belle_sip_dns_srv_t object associated with a particular addrinfo.
* The srv_list and the addrinfo must be the ones given by the belle_sip_resolver_callback_t callback invoked consecutively to a call
* to belle_sip_stack_resolve().
**/
BELLESIP_EXPORT const belle_sip_dns_srv_t * belle_sip_resolver_results_get_srv_from_addrinfo(const belle_sip_resolver_results_t *obj, const struct addrinfo *ai);
BELLESIP_EXPORT const bctbx_list_t *belle_sip_resolver_results_get_srv_records(const belle_sip_resolver_results_t *obj);
BELLESIP_EXPORT const struct addrinfo *belle_sip_resolver_results_get_addrinfos(const belle_sip_resolver_results_t *obj);
BELLESIP_EXPORT int belle_sip_resolver_results_get_ttl(const belle_sip_resolver_results_t *obj);
BELLESIP_EXPORT const char * belle_sip_resolver_results_get_name(const belle_sip_resolver_results_t *obj);
/**
* Asynchronously performs DNS SRV followed A/AAAA query. Automatically fallbacks to A/AAAA if SRV isn't found.
......
......@@ -149,7 +149,8 @@ BELLE_SIP_DECLARE_TYPES_BEGIN(belle_sip,1)
BELLE_SIP_TYPE_ID(belle_sip_header_accept_t),
BELLE_SIP_TYPE_ID(belle_sip_header_reason_t),
BELLE_SIP_TYPE_ID(belle_sip_header_authentication_info_t),
BELLE_SIP_TYPE_ID(belle_sip_mdns_register_t)
BELLE_SIP_TYPE_ID(belle_sip_mdns_register_t),
BELLE_SIP_TYPE_ID(belle_sip_resolver_results_t)
BELLE_SIP_DECLARE_TYPES_END
......
......@@ -234,6 +234,7 @@ BELLE_SIP_DECLARE_VPTR(belle_sip_header_authentication_info_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_mdns_source_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_mdns_register_t);
#endif
BELLE_SIP_DECLARE_VPTR(belle_sip_resolver_results_t);
BELLE_SIP_DECLARE_CUSTOM_VPTR_BEGIN(belle_sip_resolver_context_t,belle_sip_source_t)
......
......@@ -50,7 +50,7 @@ struct belle_sip_dns_srv{
unsigned short weight;
unsigned short port;
unsigned char a_done;
unsigned char pad;
unsigned char dont_free_a_results;
int cumulative_weight; /*used only temporarily*/
char *target;
belle_sip_combined_resolver_context_t *root_resolver;/* used internally to combine SRV and A queries*/
......@@ -71,7 +71,7 @@ static void belle_sip_dns_srv_destroy(belle_sip_dns_srv_t *obj){
belle_sip_object_unref(obj->a_resolver);
obj->a_resolver=NULL;
}
if (obj->a_results){
if (obj->a_results && !obj->dont_free_a_results){
bctbx_freeaddrinfo(obj->a_results);
obj->a_results=NULL;
}
......@@ -97,10 +97,17 @@ belle_sip_dns_srv_t *belle_sip_mdns_srv_create(short unsigned int priority, shor
belle_sip_dns_srv_t *belle_sip_dns_srv_create(struct dns_srv *srv){
belle_sip_dns_srv_t *obj=belle_sip_object_new(belle_sip_dns_srv_t);
size_t end_pos;
obj->priority=srv->priority;
obj->weight=srv->weight;
obj->port=srv->port;
obj->target=belle_sip_strdup(srv->target);
/*remove trailing '.' at the end*/
end_pos = strlen(obj->target);
if (end_pos > 0){
end_pos--;
if (obj->target[end_pos] == '.') obj->target[end_pos] = '\0';
}
return obj;
}
......@@ -124,6 +131,87 @@ BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_dns_srv_t);
BELLE_SIP_INSTANCIATE_VPTR(belle_sip_dns_srv_t, belle_sip_object_t,belle_sip_dns_srv_destroy, NULL, NULL,TRUE);
struct belle_sip_resolver_results{
belle_sip_object_t base;
struct addrinfo *ai_list;
bctbx_list_t *srv_list;
char *name;
uint32_t ttl;
};
static void belle_sip_resolver_results_destroy(belle_sip_resolver_results_t *obj){
if (obj->ai_list) bctbx_freeaddrinfo(obj->ai_list);
bctbx_list_free_with_data(obj->srv_list, belle_sip_object_unref);
if (obj->name) bctbx_free(obj->name);
}
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_resolver_results_t);
BELLE_SIP_INSTANCIATE_VPTR(belle_sip_resolver_results_t, belle_sip_object_t,belle_sip_resolver_results_destroy, NULL, NULL,FALSE);
static int addrinfo_in_range(const struct addrinfo *ai, const struct addrinfo *begin, const struct addrinfo *end){
const struct addrinfo *it;
for (it = begin ; it != end; it = it->ai_next){
if (it == NULL){
belle_sip_error("addrinfo_in_range(): it == NULL, this should not happen, this is a bug !");
break;
}
if (it == ai){
return 1;
}
}
return 0;
}
static const belle_sip_dns_srv_t * _belle_sip_dns_srv_get_from_addrinfo(const belle_sip_list_t *srv_list, const struct addrinfo *ai){
/* We simply iterate on the addrinfo pointed by the srv objects in the srv list until we find "ai".
* This is not very efficient but there is not that much alternatives:
* - there is no user pointer in struct addrinfo
* - there might not be srv record for a domain, in which case the srv_list is empty...
*/
const bctbx_list_t *elem;
for (elem = srv_list; elem != NULL; elem = elem->next){
const belle_sip_dns_srv_t *srv = (const belle_sip_dns_srv_t *) elem->data;
const belle_sip_dns_srv_t *next_srv = elem->next ? (const belle_sip_dns_srv_t *) elem->next->data : NULL;
if (addrinfo_in_range(ai, srv->a_results, next_srv ? next_srv->a_results : NULL)){
return srv;
}
}
return NULL;
}
const belle_sip_dns_srv_t * belle_sip_resolver_results_get_srv_from_addrinfo(const belle_sip_resolver_results_t *obj, const struct addrinfo *ai){
return _belle_sip_dns_srv_get_from_addrinfo(obj->srv_list, ai);
}
const bctbx_list_t *belle_sip_resolver_results_get_srv_records(const belle_sip_resolver_results_t *obj){
return obj->srv_list;
}
const struct addrinfo *belle_sip_resolver_results_get_addrinfos(const belle_sip_resolver_results_t *obj){
return obj->ai_list;
}
int belle_sip_resolver_results_get_ttl(const belle_sip_resolver_results_t *obj){
return obj->ttl;
}
const char *belle_sip_resolver_results_get_name(const belle_sip_resolver_results_t *obj){
return obj->name;
}
belle_sip_resolver_results_t *belle_sip_resolver_results_create(const char *name, struct addrinfo *ai_list, belle_sip_list_t *srv_list, int ttl){
belle_sip_resolver_results_t *obj = belle_sip_object_new(belle_sip_resolver_results_t);
obj->ai_list = ai_list;
obj->srv_list = srv_list;
obj->ttl = ttl;
obj->name = bctbx_strdup(name);
return obj;
}
struct belle_sip_resolver_context{
belle_sip_source_t source;
belle_sip_stack_t *stack;
......@@ -466,11 +554,14 @@ static void simple_resolver_context_notify(belle_sip_resolver_context_t *obj) {
belle_sip_simple_resolver_context_t *ctx = BELLE_SIP_SIMPLE_RESOLVER_CONTEXT(obj);
if ((ctx->type == DNS_T_A) || (ctx->type == DNS_T_AAAA)) {
struct addrinfo **ai_list = &ctx->ai_list;
belle_sip_resolver_results_t *results;
#if defined(USE_GETADDRINFO_FALLBACK) || defined(HAVE_MDNS)
if (ctx->getaddrinfo_ai_list != NULL) ai_list = &ctx->getaddrinfo_ai_list;
#endif
ctx->cb(ctx->cb_data, ctx->name, *ai_list, BELLE_SIP_RESOLVER_CONTEXT(obj)->min_ttl);
results = belle_sip_resolver_results_create(ctx->name, *ai_list, NULL, BELLE_SIP_RESOLVER_CONTEXT(obj)->min_ttl);
ctx->cb(ctx->cb_data, results);
*ai_list = NULL;
belle_sip_object_unref(results);
} else if (ctx->type == DNS_T_SRV) {
ctx->srv_list = srv_select_by_weight(ctx->srv_list);
ctx->srv_cb(ctx->srv_cb_data, ctx->name, ctx->srv_list, BELLE_SIP_RESOLVER_CONTEXT(obj)->min_ttl);
......@@ -480,10 +571,13 @@ static void simple_resolver_context_notify(belle_sip_resolver_context_t *obj) {
static void dual_resolver_context_notify(belle_sip_resolver_context_t *obj) {
belle_sip_dual_resolver_context_t *ctx = BELLE_SIP_DUAL_RESOLVER_CONTEXT(obj);
struct addrinfo *results = ctx->aaaa_results;
belle_sip_resolver_results_t *result_obj;
results = ai_list_append(results, ctx->a_results);
ctx->a_results = NULL;
ctx->aaaa_results = NULL;
ctx->cb(ctx->cb_data, ctx->name, results, BELLE_SIP_RESOLVER_CONTEXT(obj)->min_ttl);
result_obj = belle_sip_resolver_results_create(ctx->name, results, NULL, BELLE_SIP_RESOLVER_CONTEXT(obj)->min_ttl);
ctx->cb(ctx->cb_data, result_obj);
belle_sip_object_unref(result_obj);
}
static void combined_resolver_context_cleanup(belle_sip_combined_resolver_context_t *ctx) {
......@@ -501,8 +595,11 @@ static void combined_resolver_context_cleanup(belle_sip_combined_resolver_contex
static void combined_resolver_context_notify(belle_sip_resolver_context_t *obj) {
belle_sip_combined_resolver_context_t *ctx = BELLE_SIP_COMBINED_RESOLVER_CONTEXT(obj);
ctx->cb(ctx->cb_data, ctx->name, ctx->final_results, BELLE_SIP_RESOLVER_CONTEXT(obj)->min_ttl);
belle_sip_resolver_results_t *results = belle_sip_resolver_results_create(ctx->name, ctx->final_results, ctx->srv_results, BELLE_SIP_RESOLVER_CONTEXT(obj)->min_ttl);
ctx->cb(ctx->cb_data, results);
belle_sip_object_unref(results);
ctx->final_results = NULL;
ctx->srv_results = NULL;
combined_resolver_context_cleanup(ctx);
}
......@@ -1217,9 +1314,10 @@ static char * srv_prefix_from_service_and_transport(const char *service, const c
return belle_sip_strdup_printf("_%s._udp.", service);
}
static void process_a_fallback_result(void *data, const char *name, struct addrinfo *ai_list, uint32_t ttl){
static void process_a_fallback_result(void *data, belle_sip_resolver_results_t *results){
belle_sip_combined_resolver_context_t *ctx=(belle_sip_combined_resolver_context_t *)data;
ctx->final_results=ai_list;
ctx->final_results = results->ai_list;
results->ai_list = NULL;
belle_sip_resolver_context_notify(BELLE_SIP_RESOLVER_CONTEXT(ctx));
}
......@@ -1241,22 +1339,21 @@ static void combined_resolver_context_check_finished(belle_sip_combined_resolver
for(elem=obj->srv_results;elem!=NULL;elem=elem->next){
belle_sip_dns_srv_t *srv=(belle_sip_dns_srv_t*)elem->data;
final=ai_list_append(final,srv->a_results);
srv->a_results=NULL;
srv->dont_free_a_results = TRUE;
}
belle_sip_list_free_with_data(obj->srv_results,belle_sip_object_unref);
obj->srv_results=NULL;
obj->final_results=final;
belle_sip_resolver_context_notify(BELLE_SIP_RESOLVER_CONTEXT(obj));
}
}
static void process_a_from_srv(void *data, const char *name, struct addrinfo *ai_list, uint32_t ttl){
static void process_a_from_srv(void *data, belle_sip_resolver_results_t *results){
belle_sip_dns_srv_t *srv=(belle_sip_dns_srv_t*)data;
srv->a_results=ai_list;
srv->a_results = results->ai_list;
results->ai_list = NULL;
srv->a_done=TRUE;
belle_sip_message("A query finished for srv result [%s]",srv->target);
if (ttl < BELLE_SIP_RESOLVER_CONTEXT(srv->root_resolver)->min_ttl) BELLE_SIP_RESOLVER_CONTEXT(srv->root_resolver)->min_ttl = ttl;
combined_resolver_context_check_finished(srv->root_resolver, ttl);
if (results->ttl < BELLE_SIP_RESOLVER_CONTEXT(srv->root_resolver)->min_ttl) BELLE_SIP_RESOLVER_CONTEXT(srv->root_resolver)->min_ttl = results->ttl;
combined_resolver_context_check_finished(srv->root_resolver, results->ttl);
}
static void srv_resolve_a(belle_sip_combined_resolver_context_t *obj, belle_sip_dns_srv_t *srv){
......@@ -1337,8 +1434,10 @@ belle_sip_resolver_context_t * belle_sip_stack_resolve(belle_sip_stack_t *stack,
belle_sip_object_unref(ctx);
return BELLE_SIP_RESOLVER_CONTEXT(ctx);
} else {
/* There is no resolve to be done */
cb(data, name, res, UINT32_MAX);
/* There is no resolution to be done */
belle_sip_resolver_results_t *results = belle_sip_resolver_results_create(name, res, NULL, UINT32_MAX);
cb(data, results);
belle_sip_object_unref(results);
return NULL;
}
}
......@@ -1376,16 +1475,18 @@ static void dual_resolver_context_check_finished(belle_sip_dual_resolver_context
}
}
static void on_ipv4_results(void *data, const char *name, struct addrinfo *ai_list, uint32_t ttl) {
static void on_ipv4_results(void *data, belle_sip_resolver_results_t *results) {
belle_sip_dual_resolver_context_t *ctx = BELLE_SIP_DUAL_RESOLVER_CONTEXT(data);
ctx->a_results = ai_list;
ctx->a_results = results->ai_list;
results->ai_list = NULL;
ctx->a_notified = TRUE;
dual_resolver_context_check_finished(ctx);
}
static void on_ipv6_results(void *data, const char *name, struct addrinfo *ai_list, uint32_t ttl) {
static void on_ipv6_results(void *data, belle_sip_resolver_results_t *results) {
belle_sip_dual_resolver_context_t *ctx = BELLE_SIP_DUAL_RESOLVER_CONTEXT(data);
ctx->aaaa_results = ai_list;
ctx->aaaa_results = results->ai_list;
results->ai_list = NULL;
ctx->aaaa_notified = TRUE;
dual_resolver_context_check_finished(ctx);
}
......@@ -1430,8 +1531,10 @@ belle_sip_resolver_context_t * belle_sip_stack_resolve_a(belle_sip_stack_t *stac
belle_sip_error("belle_sip_stack_resolve_a(): unsupported address family [%i]",family);
}
} else {
/* There is no resolve to be done */
cb(data, name, res, UINT32_MAX);
/* There is no resolution to be done */
belle_sip_resolver_results_t *results = belle_sip_resolver_results_create(name, res, NULL, UINT32_MAX);
cb(data, results);
belle_sip_object_unref(results);
}
return NULL;
}
......
......@@ -109,7 +109,6 @@ static size_t belle_sip_channel_input_stream_get_buff_length(belle_sip_channel_i
static void belle_sip_channel_destroy(belle_sip_channel_t *obj){
belle_sip_channel_input_stream_reset(&obj->input_stream);
if (obj->peer_list) bctbx_freeaddrinfo(obj->peer_list);
if (obj->peer_cname) belle_sip_free(obj->peer_cname);
belle_sip_free(obj->peer_name);
if (obj->local_ip) belle_sip_free(obj->local_ip);
......@@ -120,6 +119,8 @@ static void belle_sip_channel_destroy(belle_sip_channel_t *obj){
belle_sip_resolver_context_cancel(obj->resolver_ctx);
belle_sip_object_unref(obj->resolver_ctx);
}
SET_OBJECT_PROPERTY(obj, resolver_results, NULL);
if (obj->static_peer_list) bctbx_freeaddrinfo(obj->static_peer_list);
if (obj->inactivity_timer){
belle_sip_main_loop_remove_source(obj->stack->ml,obj->inactivity_timer);
belle_sip_object_unref(obj->inactivity_timer);
......@@ -745,7 +746,7 @@ static void update_inactivity_timer(belle_sip_channel_t *obj, int from_recv){
* locaport locaport to use for binding, can be set to 0 if port doesn't matter
* peer_cname canonical name of remote host, used for TLS verification
* peername peer's hostname, either ip address or DNS name
* pee_port peer's port to connect to.
* peer_port peer's port to connect to.
*/
void belle_sip_channel_init(belle_sip_channel_t *obj, belle_sip_stack_t *stack,const char *bindip,int localport,const char *peer_cname, const char *peername, int peer_port){
/*to initialize our base class:*/
......@@ -787,7 +788,7 @@ void belle_sip_channel_init_with_addr(belle_sip_channel_t *obj, belle_sip_stack_
ai.ai_addrlen=addrlen;
bctbx_addrinfo_to_ip_address(&ai,remoteip,sizeof(remoteip),&peer_port);
belle_sip_channel_init(obj,stack,bindip,localport,NULL,remoteip,peer_port);
obj->peer_list=obj->current_peer=bctbx_ip_address_to_addrinfo(ai.ai_family, ai.ai_socktype, obj->peer_name,obj->peer_port);
obj->peer_list = obj->current_peer = obj->static_peer_list = bctbx_ip_address_to_addrinfo(ai.ai_family, ai.ai_socktype, obj->peer_name,obj->peer_port);
obj->ai_family=ai.ai_family;
}
......@@ -835,7 +836,8 @@ void belle_sip_channel_remove_listener(belle_sip_channel_t *obj, belle_sip_chann
}
int belle_sip_channel_matches(const belle_sip_channel_t *obj, const belle_sip_hop_t *hop, const struct addrinfo *addr){
if (hop && strcmp(hop->host,obj->peer_name)==0 && (hop->port==obj->peer_port || obj->srv_overrides_port)){
if (hop && (strcmp(hop->host,obj->peer_name)==0 || (obj->current_peer_cname && strcmp(hop->host,obj->current_peer_cname)==0))
&& (hop->port==obj->peer_port || obj->srv_overrides_port)){
if (hop->cname && obj->peer_cname && strcmp(hop->cname,obj->peer_cname)!=0)
return 0; /*cname mismatch*/
return 1;
......@@ -1000,13 +1002,26 @@ static void channel_connect_next(belle_sip_channel_t *obj){
belle_sip_object_unref(obj);
}
static void channel_set_current_peer(belle_sip_channel_t *obj, const struct addrinfo *ai){
if (obj->resolver_results){
const belle_sip_dns_srv_t *srv = belle_sip_resolver_results_get_srv_from_addrinfo(obj->resolver_results, ai);
obj->current_peer_cname = srv ? belle_sip_dns_srv_get_target(srv) : NULL;
if (obj->current_peer_cname){
belle_sip_message("channel[%p]: current peer hostname is [%s].", obj, obj->current_peer_cname);
}
}else{
obj->current_peer_cname = NULL;
}
obj->current_peer = ai;
}
static void belle_sip_channel_handle_error(belle_sip_channel_t *obj){
if (obj->state!=BELLE_SIP_CHANNEL_READY || obj->soft_error){
/* Previous connection attempts were failed (channel could not get ready) OR soft error reported*/
obj->soft_error = FALSE;
/* See if you can retry on an alternate ip address.*/
if (obj->current_peer && obj->current_peer->ai_next){ /*obj->current_peer may be null in case of dns error*/
obj->current_peer=obj->current_peer->ai_next;
channel_set_current_peer(obj, obj->current_peer->ai_next);
channel_set_state(obj,BELLE_SIP_CHANNEL_RETRY);
belle_sip_channel_close(obj);
belle_sip_main_loop_do_later(obj->stack->ml,(belle_sip_callback_t)channel_connect_next,belle_sip_object_ref(obj));
......@@ -1440,50 +1455,63 @@ static int channel_dns_ttl_timeout(void *data, unsigned int event) {
return BELLE_SIP_STOP;
}
static bool_t addrinfo_in_list(const struct addrinfo *ai, const struct addrinfo *list) {
/* returns the addrinfo from list that matches 'ai' in terms of content*/
static const struct addrinfo* addrinfo_in_list(const struct addrinfo *ai, const struct addrinfo *list) {
const struct addrinfo *item = list;
bool_t in_list = FALSE;
while (item != NULL) {
if ((ai->ai_family == item->ai_family) && (bctbx_sockaddr_equals(ai->ai_addr, item->ai_addr))) {
in_list = TRUE;
break;
return item;
}
item = item->ai_next;
}
return in_list;
return NULL;
}
static bool_t addrinfo_is_first(const struct addrinfo *ai, const struct addrinfo *list) {
/* returns the first addrinfo from list, if it is matching 'ai' in terms content*/
static const struct addrinfo * addrinfo_is_first(const struct addrinfo *ai, const struct addrinfo *list) {
if (list != NULL && (ai->ai_family == list->ai_family) && (bctbx_sockaddr_equals(ai->ai_addr, list->ai_addr)))
return TRUE;
return FALSE;
return list;
return NULL;
}
static void channel_res_done(void *data, const char *name, struct addrinfo *ai_list, uint32_t ttl){
static void channel_res_done(void *data, belle_sip_resolver_results_t *results){
belle_sip_channel_t *obj=(belle_sip_channel_t*)data;
const struct addrinfo *ai_list = NULL;
const char *name = NULL;
if (obj->resolver_ctx){
belle_sip_object_unref(obj->resolver_ctx);
obj->resolver_ctx=NULL;
}
if (results){
ai_list = belle_sip_resolver_results_get_addrinfos(results);
SET_OBJECT_PROPERTY(obj, resolver_results, results);
name = belle_sip_resolver_results_get_name(results);
}
if (ai_list){
int ttl = belle_sip_resolver_results_get_ttl(results);
obj->peer_list = ai_list;
if (!obj->current_peer) {
obj->peer_list=obj->current_peer=ai_list;
channel_set_current_peer(obj, ai_list);
channel_set_state(obj,BELLE_SIP_CHANNEL_RES_DONE);
} else {
bool_t check;
const struct addrinfo *existing_peer;
if (belle_sip_stack_reconnect_to_primary_asap_enabled(obj->stack)) {
check = addrinfo_is_first(obj->current_peer, ai_list);
existing_peer = addrinfo_is_first(obj->current_peer, ai_list);
} else {
check = addrinfo_in_list(obj->current_peer, ai_list);
existing_peer = addrinfo_in_list(obj->current_peer, ai_list);
}
if (check) {
if (existing_peer) {
belle_sip_message("channel[%p]: DNS resolution returned the currently used address, continue using it", obj);
obj->peer_list = ai_list;
channel_set_current_peer(obj, existing_peer);
channel_set_state(obj, BELLE_SIP_CHANNEL_READY);
} else {
belle_sip_message("channel[%p]: DNS resolution returned an address different than the one being used, reconnect to the new address", obj);
obj->peer_list = obj->current_peer = ai_list;
channel_set_current_peer(obj, ai_list);
belle_sip_channel_close(obj);
belle_sip_main_loop_do_later(obj->stack->ml, (belle_sip_callback_t)channel_connect_next, belle_sip_object_ref(obj));
channel_set_state(obj, BELLE_SIP_CHANNEL_RETRY);
......
......@@ -94,16 +94,19 @@ struct belle_sip_channel{
belle_sip_list_t *state_listeners;
belle_sip_list_t *full_listeners;
int ai_family;
char *peer_cname;
char *peer_name;
char *peer_cname; /* A or SRV name */
char *peer_name; /* A or SRV name */
int peer_port;
char *local_ip;
int local_port;
char *public_ip;
int public_port;
belle_sip_resolver_context_t* resolver_ctx;
struct addrinfo *peer_list;
struct addrinfo *current_peer;
belle_sip_resolver_results_t* resolver_results;
struct addrinfo *static_peer_list; /*this is the addrinfo when the channel is instanciated from destination IP address directly (no dns resolution)*/
const struct addrinfo *peer_list; /*points to the addrinfo list in resolver_results, or to the static_peer_list*/
const struct addrinfo *current_peer; /*points in the currently used element in peer_list */
const char *current_peer_cname; /*name of the host we are currently connected to. Set only in SRV case*/
belle_sip_list_t *outgoing_messages;
belle_sip_message_t *cur_out_message;
output_stream_state_t out_state;
......
......@@ -414,17 +414,18 @@ static int tls_channel_connect_to(belle_sip_channel_t *obj, const struct addrinf
return -1;
}
static void http_proxy_res_done(void *data, const char *name, struct addrinfo *ai_list, uint32_t ttl){
static void http_proxy_res_done(void *data, belle_sip_resolver_results_t *results){
belle_sip_tls_channel_t *obj=(belle_sip_tls_channel_t*)data;
const struct addrinfo *ai_list;
if (obj->http_proxy_resolver_ctx){
belle_sip_object_unref(obj->http_proxy_resolver_ctx);
obj->http_proxy_resolver_ctx=NULL;
}
ai_list = belle_sip_resolver_results_get_addrinfos(results);
if (ai_list){
tls_channel_connect_to((belle_sip_channel_t *)obj,ai_list);
bctbx_freeaddrinfo(ai_list);
}else{
belle_sip_error("%s: DNS resolution failed for %s", __FUNCTION__, name);
belle_sip_error("%s: DNS resolution failed for %s", __FUNCTION__, belle_sip_resolver_results_get_name(results));
channel_set_state((belle_sip_channel_t*)obj,BELLE_SIP_CHANNEL_ERROR);
}
}
......
......@@ -41,8 +41,9 @@ typedef struct endpoint {
belle_sip_resolver_context_t *resolver_ctx;
int resolve_done;
int resolve_ko;
struct addrinfo *ai_list;
belle_sip_list_t *srv_list; /**< List of struct dns_srv pointers */
bctbx_list_t *srv_list;
belle_sip_resolver_results_t *results;
const struct addrinfo *ai_list;
} endpoint_t;
static unsigned int wait_for(belle_sip_stack_t *stack, int *current_value, int expected_value, int timeout) {
......@@ -68,12 +69,13 @@ static void reset_endpoint(endpoint_t *endpoint) {
endpoint->resolver_ctx = 0;
endpoint->resolve_done = 0;
endpoint->resolve_ko = 0;
if (endpoint->ai_list != NULL) {
bctbx_freeaddrinfo(endpoint->ai_list);
endpoint->ai_list = NULL;
if (endpoint->results) {
belle_sip_object_unref(endpoint->results);
endpoint->results = NULL;
}
if (endpoint->srv_list != NULL) {
belle_sip_list_free_with_data(endpoint->srv_list, belle_sip_object_unref);
endpoint->ai_list = NULL;
if (endpoint->srv_list){
bctbx_list_free_with_data(endpoint->srv_list, belle_sip_object_unref);
endpoint->srv_list = NULL;
}
}
......@@ -85,12 +87,14 @@ static void destroy_endpoint(endpoint_t *endpoint) {
belle_sip_uninit_sockets();
}
static void a_resolve_done(void *data, const char *name, struct addrinfo *ai_list, uint32_t ttl) {
static void a_resolve_done(void *data, belle_sip_resolver_results_t *results) {
endpoint_t *client = (endpoint_t *)data;
BELLESIP_UNUSED(name);
client->resolve_done = 1;
if (ai_list) {
client->ai_list = ai_list;
belle_sip_object_ref(results);
client->results = results;
if (belle_sip_resolver_results_get_addrinfos(results)) {
client->ai_list = belle_sip_resolver_results_get_addrinfos(results);
client->resolve_done = 1;
} else
client->resolve_ko = 1;
......
......@@ -22,23 +22,21 @@
static belle_sip_stack_t *stack;
static void resolver_callback(void *data, const char *queried_name, struct addrinfo *ai_list, unsigned int ttl){
static void resolver_callback(void *data, belle_sip_resolver_results_t *results){
int err;
struct addrinfo *ai_it;
const struct addrinfo *ai_it;
char name[NI_MAXHOST];
char port[NI_MAXSERV];
const struct addrinfo *ai_list = belle_sip_resolver_results_get_addrinfos(results);
for(ai_it=ai_list;ai_it!=NULL;ai_it=ai_it->ai_next){
err=bctbx_getnameinfo(ai_it->ai_addr,ai_list->ai_addrlen,name,sizeof(name),port,sizeof(port),NI_NUMERICSERV|NI_NUMERICHOST);
if (err!=0){
fprintf(stderr,"getnameinfo error: %s",gai_strerror(err));
}else{
printf("\t%s %s (ttl:%u)\n",name,port,ttl);
printf("\t%s %s (ttl:%u)\n",name,port,belle_sip_resolver_results_get_ttl(results));
}
}
if (ai_list){
bctbx_freeaddrinfo(ai_list);
}
belle_sip_main_loop_quit(belle_sip_stack_get_main_loop(stack));
}
......
Markdown is supported