Skip to content

Add Getaddrinfo interface for multiple DNS adresses #11653

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion TESTS/netsocket/dns/asynchronous_dns_cache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "utest.h"
#include "dns_tests.h"

#define RESULTS_NUM 1
using namespace utest::v1;

namespace {
Expand Down Expand Up @@ -53,7 +54,7 @@ void ASYNCHRONOUS_DNS_CACHE()

semaphore.acquire();

TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, data.result);
TEST_ASSERT_EQUAL(RESULTS_NUM, data.result);
TEST_ASSERT(strlen(data.addr.get_ip_address()) > 1);

int delay_ms = (ticker_us - started_us) / 1000;
Expand Down
12 changes: 6 additions & 6 deletions TESTS/netsocket/dns/asynchronous_dns_cancel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ void ASYNCHRONOUS_DNS_CANCEL()
data[i].semaphore = &semaphore;
data[i].req_result = get_interface()->gethostbyname_async(dns_test_hosts[i],
mbed::Callback<void(nsapi_error_t, SocketAddress *)>(hostbyname_cb, (void *) &data[i]));
TEST_ASSERT(data[i].req_result >= 0 || data[i].req_result == NSAPI_ERROR_NO_MEMORY || data[i].req_result == NSAPI_ERROR_BUSY);
TEST_ASSERT(data[i].req_result > 0 || data[i].req_result == NSAPI_ERROR_NO_MEMORY || data[i].req_result == NSAPI_ERROR_BUSY);

if (data[i].req_result >= 0) {
if (data[i].req_result > 0) {
// Callback will be called
count++;
} else {
Expand Down Expand Up @@ -68,10 +68,10 @@ void ASYNCHRONOUS_DNS_CANCEL()
tr_info("DNS: query \"%s\" => cancel", dns_test_hosts[i]);
continue;
}
TEST_ASSERT(data[i].result == NSAPI_ERROR_OK || data[i].result == NSAPI_ERROR_NO_MEMORY || data[i].result == NSAPI_ERROR_BUSY || data[i].result == NSAPI_ERROR_DNS_FAILURE || data[i].result == NSAPI_ERROR_TIMEOUT);
if (data[i].result == NSAPI_ERROR_OK) {
tr_info("DNS: query \"%s\" => \"%s\"",
dns_test_hosts[i], data[i].addr.get_ip_address());
TEST_ASSERT(data[i].result == 1 || data[i].result == NSAPI_ERROR_NO_MEMORY || data[i].result == NSAPI_ERROR_BUSY || data[i].result == NSAPI_ERROR_DNS_FAILURE || data[i].result == NSAPI_ERROR_TIMEOUT);
if (data[i].result == 1) {
printf("DNS: query \"%s\" => \"%s\"\n",
dns_test_hosts[i], data[i].addr.get_ip_address());
} else if (data[i].result == NSAPI_ERROR_DNS_FAILURE) {
tr_error("DNS: query \"%s\" => DNS failure", dns_test_hosts[i]);
} else if (data[i].result == NSAPI_ERROR_TIMEOUT) {
Expand Down
118 changes: 118 additions & 0 deletions TESTS/netsocket/dns/asynchronous_dns_multi_ip.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/*
* Copyright (c) 2018, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "mbed.h"
#include "greentea-client/test_env.h"
#include "unity.h"
#include "utest.h"
#include "dns_tests.h"

using namespace utest::v1;

namespace {
int result_number;
int result_no_mem;
int result_dns_failure;
int result_exp_timeout;
}

// Callback used for asynchronous DNS result
void getaddrinfo_cb(void *data, nsapi_error_t result, SocketAddress *address)
{
dns_application_data_multi_ip *app_data = static_cast<dns_application_data_multi_ip *>(data);
app_data->result = result;
for (unsigned int i = 0; i < result; i++) {
if (address) {
app_data->addr[i] = address[i];
}
}
app_data->semaphore->release();
app_data->value_set = true;
}

void do_getaddrinfo_async(const char hosts[][DNS_TEST_HOST_LEN], unsigned int op_count, int *exp_ok, int *exp_no_mem, int *exp_dns_failure, int *exp_timeout)
{
// Verify that there is enough hosts in the host list
TEST_ASSERT(op_count <= MBED_CONF_APP_DNS_TEST_HOSTS_NUM)

// Reset counters
(*exp_ok) = 0;
(*exp_no_mem) = 0;
(*exp_dns_failure) = 0;
(*exp_timeout) = 0;

// Create callback semaphore and data
rtos::Semaphore semaphore;
dns_application_data_multi_ip *data = new dns_application_data_multi_ip[op_count];
SocketAddress hints{{NSAPI_IPv4}, 80};

unsigned int count = 0;
for (unsigned int i = 0; i < op_count; i++) {
data[i].semaphore = &semaphore;
nsapi_error_t err = NetworkInterface::get_default_instance()->getaddrinfo_async(hosts[i], &hints, mbed::Callback<void(nsapi_error_t, SocketAddress *)>(getaddrinfo_cb, (void *) &data[i]));
TEST_ASSERT(err >= 0 || err == NSAPI_ERROR_NO_MEMORY || err == NSAPI_ERROR_BUSY);
if (err >= 0) {
// Callback will be called
count++;
} else {
// No memory to initiate DNS query, callback will not be called
data[i].result = err;
}
}

// Wait for callback(s) to complete
for (unsigned int i = 0; i < count; i++) {
semaphore.acquire();
}
// Print result
for (unsigned int i = 0; i < op_count; i++) {
TEST_ASSERT(data[i].result > 0 || data[i].result == NSAPI_ERROR_NO_MEMORY || data[i].result == NSAPI_ERROR_BUSY
|| data[i].result == NSAPI_ERROR_DNS_FAILURE || data[i].result == NSAPI_ERROR_TIMEOUT);
if (data[i].result > 0) {
(*exp_ok)++;
for (unsigned int results = 0; results < data[i].result; results++) {
printf("DNS: query \"%s\" => \"%s\"\n",
hosts[i], data[i].addr[results].get_ip_address());
}
} else if (data[i].result == NSAPI_ERROR_DNS_FAILURE) {
(*exp_dns_failure)++;
printf("DNS: query \"%s\" => DNS failure\n", hosts[i]);
} else if (data[i].result == NSAPI_ERROR_TIMEOUT) {
(*exp_timeout)++;
printf("DNS: query \"%s\" => timeout\n", hosts[i]);
} else if (data[i].result == NSAPI_ERROR_NO_MEMORY) {
(*exp_no_mem)++;
printf("DNS: query \"%s\" => no memory\n", hosts[i]);
} else if (data[i].result == NSAPI_ERROR_BUSY) {
(*exp_no_mem)++;
printf("DNS: query \"%s\" => busy\n", hosts[i]);
}
}

delete[] data;
}

void ASYNCHRONOUS_DNS_MULTI_IP()
{
nsapi_dns_reset();
do_getaddrinfo_async(dns_test_hosts_multi_ip, MBED_CONF_APP_DNS_SIMULT_QUERIES, &result_number, &result_no_mem, &result_dns_failure, &result_exp_timeout);

TEST_ASSERT_EQUAL(MBED_CONF_APP_DNS_SIMULT_QUERIES, result_number);
TEST_ASSERT_EQUAL(0, result_no_mem);
TEST_ASSERT_EQUAL(0, result_dns_failure);
TEST_ASSERT_EQUAL(0, result_exp_timeout);
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ void ASYNCHRONOUS_DNS_NON_ASYNC_AND_ASYNC()
get_interface()->gethostbyname_async_cancel(err);
}

TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, data.result);
TEST_ASSERT_EQUAL(1, data.result);

tr_info("DNS: query \"%s\" => \"%s\"",
dns_test_hosts_second[0], data.addr.get_ip_address());
Expand Down
19 changes: 17 additions & 2 deletions TESTS/netsocket/dns/dns_tests.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@
#define MBED_CONF_NSAPI_DNS_CACHE_SIZE 3
#endif

#ifndef MBED_CONF_APP_DNS_TEST_HOSTS_NUM
#define MBED_CONF_APP_DNS_TEST_HOSTS_NUM 6
#endif

// Hostnames for testing against
// Both lists must have A and AAAA records
#ifndef MBED_CONF_APP_DNS_TEST_HOSTS
Expand All @@ -45,8 +49,8 @@
#define MBED_CONF_APP_DNS_TEST_HOSTS_SECOND {"ipv6ready.org", "wireshark.org", "bbc.co.uk", "cnn.com", "www.flickr.com", "www.mozilla.org"}
#endif

#ifndef MBED_CONF_APP_DNS_TEST_HOSTS_NUM
#define MBED_CONF_APP_DNS_TEST_HOSTS_NUM 6
#ifndef MBED_CONF_APP_DNS_TEST_MULTI_IP_HOSTS
#define MBED_CONF_APP_DNS_TEST_MULTI_IP_HOSTS {"google.com", "www.mozilla.org", "yahoo.com", "instagram.com","www.flickr.com"}
#endif

#define DNS_TEST_HOST_LEN 40
Expand All @@ -59,8 +63,17 @@ struct dns_application_data {
bool value_set;
};

struct dns_application_data_multi_ip {
rtos::Semaphore *semaphore;
nsapi_error_t result;
SocketAddress addr[MBED_CONF_NSAPI_DNS_ADDRESSES_LIMIT];
nsapi_error_t req_result;
bool value_set;
};

extern const char dns_test_hosts[MBED_CONF_APP_DNS_TEST_HOSTS_NUM][DNS_TEST_HOST_LEN];
extern const char dns_test_hosts_second[MBED_CONF_APP_DNS_TEST_HOSTS_NUM][DNS_TEST_HOST_LEN];
extern const char dns_test_hosts_multi_ip[MBED_CONF_APP_DNS_SIMULT_QUERIES][DNS_TEST_HOST_LEN];

/*
* Utility functions
Expand Down Expand Up @@ -95,4 +108,6 @@ void SYNCHRONOUS_DNS();
void SYNCHRONOUS_DNS_MULTIPLE();
void SYNCHRONOUS_DNS_CACHE();
void SYNCHRONOUS_DNS_INVALID();
void SYNCHRONOUS_DNS_MULTI_IP();
void ASYNCHRONOUS_DNS_MULTI_IP();
#endif
7 changes: 5 additions & 2 deletions TESTS/netsocket/dns/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ NetworkInterface *net;

const char dns_test_hosts[MBED_CONF_APP_DNS_TEST_HOSTS_NUM][DNS_TEST_HOST_LEN] = MBED_CONF_APP_DNS_TEST_HOSTS;
const char dns_test_hosts_second[MBED_CONF_APP_DNS_TEST_HOSTS_NUM][DNS_TEST_HOST_LEN] = MBED_CONF_APP_DNS_TEST_HOSTS_SECOND;
const char dns_test_hosts_multi_ip[MBED_CONF_APP_DNS_SIMULT_QUERIES][DNS_TEST_HOST_LEN] = MBED_CONF_APP_DNS_TEST_MULTI_IP_HOSTS;

// Callback used for asynchronous DNS result
void hostbyname_cb(void *data, nsapi_error_t result, SocketAddress *address)
Expand Down Expand Up @@ -92,8 +93,8 @@ void do_asynchronous_gethostbyname(const char hosts[][DNS_TEST_HOST_LEN], unsign

// Print result
for (unsigned int i = 0; i < op_count; i++) {
TEST_ASSERT(data[i].result == NSAPI_ERROR_OK || data[i].result == NSAPI_ERROR_NO_MEMORY || data[i].result == NSAPI_ERROR_BUSY || data[i].result == NSAPI_ERROR_DNS_FAILURE || data[i].result == NSAPI_ERROR_TIMEOUT);
if (data[i].result == NSAPI_ERROR_OK) {
TEST_ASSERT(data[i].result > 0 || data[i].result == NSAPI_ERROR_NO_MEMORY || data[i].result == NSAPI_ERROR_BUSY || data[i].result == NSAPI_ERROR_DNS_FAILURE || data[i].result == NSAPI_ERROR_TIMEOUT);
if (data[i].result > 0) {
(*exp_ok)++;
tr_info("DNS: query \"%s\" => \"%s\"",
hosts[i], data[i].addr.get_ip_address());
Expand Down Expand Up @@ -220,6 +221,8 @@ Case cases[] = {
Case("SYNCHRONOUS_DNS", SYNCHRONOUS_DNS),
Case("SYNCHRONOUS_DNS_MULTIPLE", SYNCHRONOUS_DNS_MULTIPLE),
Case("SYNCHRONOUS_DNS_INVALID", SYNCHRONOUS_DNS_INVALID),
Case("SYNCHRONOUS_DNS_MULTI_IP", SYNCHRONOUS_DNS_MULTI_IP),
Case("ASYNCHRONOUS_DNS_MULTI_IP", ASYNCHRONOUS_DNS_MULTI_IP),
};

Specification specification(test_setup, cases, greentea_teardown, greentea_continue_handlers);
Expand Down
86 changes: 86 additions & 0 deletions TESTS/netsocket/dns/synchronous_dns_multi_ip.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* Copyright (c) 2018, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "mbed.h"
#include "greentea-client/test_env.h"
#include "unity.h"
#include "utest.h"
#include "dns_tests.h"

using namespace utest::v1;

namespace {
int result_number;
int result_no_mem;
int result_dns_failure;
int result_exp_timeout;
}


void do_getaddrinfo(const char hosts[][DNS_TEST_HOST_LEN], unsigned int op_count, int *exp_ok, int *exp_no_mem, int *exp_dns_failure, int *exp_timeout)
{
// Verify that there is enough hosts in the host list
TEST_ASSERT(op_count <= MBED_CONF_APP_DNS_TEST_HOSTS_NUM)

// Reset counters
(*exp_ok) = 0;
(*exp_no_mem) = 0;
(*exp_dns_failure) = 0;
(*exp_timeout) = 0;

SocketAddress hints{{NSAPI_IPv4}, 80};
for (unsigned int i = 0; i < op_count; i++) {
SocketAddress *result;
nsapi_error_t err = NetworkInterface::get_default_instance()->get_default_instance()->getaddrinfo(hosts[i], &hints, &result);

if (err == NSAPI_ERROR_DNS_FAILURE) {
(*exp_dns_failure)++;
printf("DNS: query \"%s\" => DNS failure\n", hosts[i]);
} else if (err == NSAPI_ERROR_TIMEOUT) {
(*exp_timeout)++;
printf("DNS: query \"%s\" => timeout\n", hosts[i]);
} else if (err == NSAPI_ERROR_NO_MEMORY) {
(*exp_no_mem)++;
printf("DNS: query \"%s\" => no memory\n", hosts[i]);
} else if (err == NSAPI_ERROR_BUSY) {
(*exp_no_mem)++;
printf("DNS: query \"%s\" => busy\n", hosts[i]);
} else if (err > NSAPI_ERROR_OK) {
(*exp_ok)++;
for (unsigned int results = 0; results < err; results++) {
printf("DNS: query \"%s\" => \"%s\"\n", hosts[i], result[results].get_ip_address());
}
} else if (err == 0) {
printf("DNS: query \"%s\", no results\n", hosts[i]);
TEST_FAIL();
} else if (err < 0) {
printf("DNS: query \"%s\" => %d, unexpected answer\n", hosts[i], err);
TEST_FAIL();
}
}
}

void SYNCHRONOUS_DNS_MULTI_IP()
{
nsapi_dns_reset();
do_getaddrinfo(dns_test_hosts_multi_ip, MBED_CONF_APP_DNS_SIMULT_QUERIES, &result_number, &result_no_mem, &result_dns_failure, &result_exp_timeout);

TEST_ASSERT_EQUAL(MBED_CONF_APP_DNS_SIMULT_QUERIES, result_number);
TEST_ASSERT_EQUAL(0, result_no_mem);
TEST_ASSERT_EQUAL(0, result_dns_failure);
TEST_ASSERT_EQUAL(0, result_exp_timeout);
}
Original file line number Diff line number Diff line change
Expand Up @@ -332,11 +332,14 @@ TEST_F(Test_IfaceDnsSocket, multiple_queries)

SocketAddress *addr_cache;
// Cache will only raturn one address.
EXPECT_EQ(Test_IfaceDnsSocket::query_id, getaddrinfo(&stackMock(), "www.google.com", hints, &addr_cache));
EXPECT_EQ(3, getaddrinfo(&stackMock(), "www.google.com", hints, &addr_cache));

// This is a bug which will be fixed in
EXPECT_EQ(addr_cache[0].get_ip_version(), NSAPI_IPv4);
EXPECT_FALSE(strncmp(addr_cache[0].get_ip_address(), "216.58.207.238", sizeof("216.58.207.238")));
EXPECT_EQ(addr_cache[1].get_ip_version(), NSAPI_IPv4);
EXPECT_FALSE(strncmp(addr_cache[1].get_ip_address(), "222.173.190.239", sizeof("222.173.190.239")));
EXPECT_EQ(addr_cache[2].get_ip_version(), NSAPI_IPv4);
EXPECT_FALSE(strncmp(addr_cache[2].get_ip_address(), "1.2.3.4", sizeof("1.2.3.4")));
delete[] addr_cache;
}

Expand Down Expand Up @@ -400,7 +403,7 @@ TEST_F(Test_IfaceDnsSocket, simultaneous_query_async)
// Run again to execute response_handler
executeEventQueueCallbacks();

EXPECT_EQ(NSAPI_ERROR_OK, Test_IfaceDnsSocket::hostname_cb_result);
EXPECT_EQ(1, Test_IfaceDnsSocket::hostname_cb_result);
EXPECT_EQ(Test_IfaceDnsSocket::hostname_cb_address[0].get_ip_version(), NSAPI_IPv4);
EXPECT_FALSE(strncmp(Test_IfaceDnsSocket::hostname_cb_address[0].get_ip_address(), "216.58.207.238", sizeof("216.58.207.238")));

Expand Down Expand Up @@ -473,11 +476,12 @@ TEST_F(Test_IfaceDnsSocket, single_query_async_multiple)
Test_IfaceDnsSocket::hostname_cb_result = NSAPI_ERROR_DEVICE_ERROR;

// Do not set any return values. Second call should use cache.
// Cache will only return one address!
EXPECT_EQ(0, getaddrinfo_async(&stackMock(), "www.google.com", &Test_IfaceDnsSocket::hostbyname_cb));
EXPECT_EQ(NSAPI_ERROR_OK, Test_IfaceDnsSocket::hostname_cb_result);
EXPECT_EQ(3, getaddrinfo_async(&stackMock(), "www.google.com", &Test_IfaceDnsSocket::hostbyname_cb));
EXPECT_EQ(3, Test_IfaceDnsSocket::hostname_cb_result);
EXPECT_EQ(Test_IfaceDnsSocket::hostname_cb_address[0].get_ip_version(), NSAPI_IPv4);
EXPECT_FALSE(strncmp(Test_IfaceDnsSocket::hostname_cb_address[0].get_ip_address(), "216.58.207.238", sizeof("216.58.207.238")));
EXPECT_FALSE(strncmp(Test_IfaceDnsSocket::hostname_cb_address[1].get_ip_address(), "222.173.190.239", sizeof("222.173.190.239")));
EXPECT_FALSE(strncmp(Test_IfaceDnsSocket::hostname_cb_address[2].get_ip_address(), "1.2.3.4", sizeof("1.2.3.4")));

delete[] Test_IfaceDnsSocket::hostname_cb_address;
}
Expand Down
2 changes: 2 additions & 0 deletions UNITTESTS/features/netsocket/InternetSocket/unittest.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
# UNIT TESTS
####################

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMBED_CONF_NSAPI_DNS_ADDRESSES_LIMIT=10")

set(unittest-sources
../features/netsocket/SocketAddress.cpp
../features/netsocket/NetworkStack.cpp
Expand Down
Loading