Commit 688d4029 authored by Ghislain MARY's avatar Ghislain MARY
Browse files

Add support for IPv6 address resolutions and improve unit tests of the resolver.

parent 1de0552a
...@@ -78,6 +78,8 @@ struct dns_cache *cache(belle_sip_resolver_context_t *ctx) { ...@@ -78,6 +78,8 @@ struct dns_cache *cache(belle_sip_resolver_context_t *ctx) {
} }
static int resolver_process_a_data(belle_sip_resolver_context_t *ctx, unsigned int revents) { static int resolver_process_a_data(belle_sip_resolver_context_t *ctx, unsigned int revents) {
char host[128];
const char *host_ptr;
struct dns_packet *ans; struct dns_packet *ans;
struct dns_rr_i *I; struct dns_rr_i *I;
int error; int error;
...@@ -113,13 +115,24 @@ static int resolver_process_a_data(belle_sip_resolver_context_t *ctx, unsigned i ...@@ -113,13 +115,24 @@ static int resolver_process_a_data(belle_sip_resolver_context_t *ctx, unsigned i
free(ans); free(ans);
return BELLE_SIP_STOP; return BELLE_SIP_STOP;
} }
if ((rr.class == DNS_C_IN) && (rr.type == DNS_T_A)) { if ((ctx->family == AF_INET6) && (rr.class == DNS_C_IN) && (rr.type == DNS_T_AAAA)) {
char host[64]; struct dns_aaaa *aaaa = &any.aaaa;
struct dns_a *a = &any.a; host_ptr = inet_ntop(ctx->family, &aaaa->addr, host, sizeof(host));
ctx->ai = belle_sip_ip_address_to_addrinfo(inet_ntoa(a->addr), ctx->port); if (!host_ptr) continue;
ctx->ai = belle_sip_ip_address_to_addrinfo(host_ptr, ctx->port);
belle_sip_addrinfo_to_ip(ctx->ai, host, sizeof(host), NULL); belle_sip_addrinfo_to_ip(ctx->ai, host, sizeof(host), NULL);
belle_sip_message("%s has address %s", ctx->name, host); belle_sip_message("%s has address %s", ctx->name, host);
break; break;
} else {
if ((rr.class == DNS_C_IN) && (rr.type == DNS_T_A)) {
struct dns_a *a = &any.a;
host_ptr = inet_ntop(ctx->family, &a->addr, host, sizeof(host));
if (!host_ptr) continue;
ctx->ai = belle_sip_ip_address_to_addrinfo(host_ptr, ctx->port);
belle_sip_addrinfo_to_ip(ctx->ai, host, sizeof(host), NULL);
belle_sip_message("%s has address %s", ctx->name, host);
break;
}
} }
} }
} }
...@@ -232,7 +245,10 @@ unsigned long belle_sip_resolve(belle_sip_stack_t *stack, const char *name, int ...@@ -232,7 +245,10 @@ unsigned long belle_sip_resolve(belle_sip_stack_t *stack, const char *name, int
ctx->ai = NULL; ctx->ai = NULL;
if (family == 0) family = AF_UNSPEC; if (family == 0) family = AF_UNSPEC;
ctx->family = family; ctx->family = family;
if (resolver_start_query(ctx, (belle_sip_source_func_t)resolver_process_a_data, DNS_T_A, belle_sip_stack_get_dns_timeout(stack)) < 0) { if (resolver_start_query(ctx,
(belle_sip_source_func_t)resolver_process_a_data,
(ctx->family == AF_INET6) ? DNS_T_AAAA : DNS_T_A,
belle_sip_stack_get_dns_timeout(stack)) < 0) {
belle_sip_object_unref(ctx); belle_sip_object_unref(ctx);
return 0; return 0;
} }
......
...@@ -22,15 +22,18 @@ ...@@ -22,15 +22,18 @@
#include "belle_sip_internal.h" #include "belle_sip_internal.h"
#define SIPDOMAIN "sip.linphone.org" #define IPV4_SIP_DOMAIN "sip.linphone.org"
#define SIPPORT 5060 #define IPV4_SIP_IP "37.59.129.73"
#define IPV6_SIP_DOMAIN "videolan.org"
#define IPV6_SIP_IP "2a01:e0d:1:3:58bf:fa02:0:1"
#define SIP_PORT 5060
typedef struct endpoint { typedef struct endpoint {
belle_sip_stack_t* stack; belle_sip_stack_t* stack;
long unsigned int resolver_id; long unsigned int resolver_id;
int resolve_done; int resolve_done;
int resolve_successful; struct addrinfo *result;
} endpoint_t; } endpoint_t;
static unsigned int wait_for(belle_sip_stack_t *stack, int *current_value, int expected_value, int timeout) { static unsigned int wait_for(belle_sip_stack_t *stack, int *current_value, int expected_value, int timeout) {
...@@ -51,7 +54,13 @@ static endpoint_t* create_endpoint(void) { ...@@ -51,7 +54,13 @@ static endpoint_t* create_endpoint(void) {
return endpoint; return endpoint;
} }
static void destroy_endpoint(endpoint_t* endpoint) { static void reset_endpoint(endpoint_t *endpoint) {
endpoint->resolver_id = 0;
endpoint->resolve_done = 0;
endpoint->result = NULL;
}
static void destroy_endpoint(endpoint_t *endpoint) {
belle_sip_object_unref(endpoint->stack); belle_sip_object_unref(endpoint->stack);
belle_sip_free(endpoint); belle_sip_free(endpoint);
belle_sip_uninit_sockets(); belle_sip_uninit_sockets();
...@@ -61,18 +70,54 @@ static void resolve_done(void *data, const char *name, struct addrinfo *res) { ...@@ -61,18 +70,54 @@ static void resolve_done(void *data, const char *name, struct addrinfo *res) {
endpoint_t *client = (endpoint_t *)data; endpoint_t *client = (endpoint_t *)data;
client->resolve_done = 1; client->resolve_done = 1;
if (res) { if (res) {
client->resolve_successful = 1; client->result = res;
} }
} }
static void resolve(void) { static void resolve(void) {
const char* peer_name = SIPDOMAIN; const char* peer_name;
int peer_port = SIPPORT; int peer_port = SIP_PORT;
struct in_addr ipv4_address;
struct in6_addr ipv6_address;
int family;
int result;
endpoint_t* client = create_endpoint(); endpoint_t* client = create_endpoint();
CU_ASSERT_PTR_NOT_NULL_FATAL(client); CU_ASSERT_PTR_NOT_NULL_FATAL(client);
client->resolver_id = belle_sip_resolve(client->stack, peer_name, peer_port, 0, resolve_done, client, belle_sip_stack_get_main_loop(client->stack));
/* IPv4 A query */
family = AF_INET;
peer_name = IPV4_SIP_DOMAIN;
client->resolver_id = belle_sip_resolve(client->stack, peer_name, peer_port, family, resolve_done, client, belle_sip_stack_get_main_loop(client->stack));
CU_ASSERT_TRUE(wait_for(client->stack, &client->resolve_done, 1, 2000));
CU_ASSERT_PTR_NOT_EQUAL(client->result, NULL);
if (client->result != NULL) {
struct sockaddr_in *sock_in = (struct sockaddr_in *)client->result->ai_addr;
CU_ASSERT_EQUAL(ntohs(sock_in->sin_port), peer_port);
result = inet_pton(family, IPV4_SIP_IP, &ipv4_address);
if (result) {
CU_ASSERT_EQUAL(sock_in->sin_addr.s_addr, ipv4_address.s_addr);
}
}
/* IPv6 AAAA query */
reset_endpoint(client);
family = AF_INET6;
peer_name = IPV6_SIP_DOMAIN;
client->resolver_id = belle_sip_resolve(client->stack, peer_name, peer_port, family, resolve_done, client, belle_sip_stack_get_main_loop(client->stack));
CU_ASSERT_TRUE(wait_for(client->stack, &client->resolve_done, 1, 2000)); CU_ASSERT_TRUE(wait_for(client->stack, &client->resolve_done, 1, 2000));
CU_ASSERT_TRUE((client->resolve_successful == 1)); CU_ASSERT_PTR_NOT_EQUAL(client->result, NULL);
if (client->result != NULL) {
struct sockaddr_in6 *sock_in6 = (struct sockaddr_in6 *)client->result->ai_addr;
CU_ASSERT_EQUAL(ntohs(sock_in6->sin6_port), peer_port);
result = inet_pton(family, IPV6_SIP_IP, &ipv6_address);
if (result) {
CU_ASSERT_EQUAL(sock_in6->sin6_addr.s6_addr32[0], ipv6_address.s6_addr32[0]);
CU_ASSERT_EQUAL(sock_in6->sin6_addr.s6_addr32[1], ipv6_address.s6_addr32[1]);
CU_ASSERT_EQUAL(sock_in6->sin6_addr.s6_addr32[2], ipv6_address.s6_addr32[2]);
CU_ASSERT_EQUAL(sock_in6->sin6_addr.s6_addr32[3], ipv6_address.s6_addr32[3]);
}
}
destroy_endpoint(client); destroy_endpoint(client);
} }
......
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