Skip to content

Commit b7e8400

Browse files
Mika Leppänenkjbracey
authored andcommitted
Added non-blocking DNS functionality to network interface
- Added non-blocking DNS interface to network interface and network stack. - Added caching of DNS replies. - Added a network stack function to get DNS addresses from stack. - Added call and call_in hooks to onboard network stack to allow calling functions from onboard stack context. - Added support to call and call_in functions to LWIP and Nanostack. - Disabled LWIP DNS translator with the exception of DNS address storage used in DNS address get.
1 parent bad530a commit b7e8400

File tree

18 files changed

+984
-107
lines changed

18 files changed

+984
-107
lines changed

features/FEATURE_LWIP/lwip-interface/LWIPStack.cpp

Lines changed: 73 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "lwip/dns.h"
3434
#include "lwip/udp.h"
3535
#include "lwip/lwip_errno.h"
36+
#include "lwip-sys/arch/sys_arch.h"
3637

3738
#include "LWIPStack.h"
3839

@@ -47,10 +48,10 @@ void LWIP::socket_callback(struct netconn *nc, enum netconn_evt eh, u16_t len)
4748
return;
4849
}
4950

50-
sys_prot_t prot = sys_arch_protect();
51-
5251
LWIP &lwip = LWIP::get_instance();
5352

53+
lwip.adaptation.lock();
54+
5455
for (int i = 0; i < MEMP_NUM_NETCONN; i++) {
5556
if (lwip.arena[i].in_use
5657
&& lwip.arena[i].conn == nc
@@ -59,7 +60,7 @@ void LWIP::socket_callback(struct netconn *nc, enum netconn_evt eh, u16_t len)
5960
}
6061
}
6162

62-
sys_arch_unprotect(prot);
63+
lwip.adaptation.unlock();
6364
}
6465

6566
#if !LWIP_IPV4 || !LWIP_IPV6
@@ -149,6 +150,7 @@ void LWIP::tcpip_init_irq(void *eh)
149150
{
150151
LWIP *lwip = static_cast<LWIP *>(eh);
151152
lwip->tcpip_inited.release();
153+
sys_tcpip_thread_set();
152154
}
153155

154156
/* LWIP network stack implementation */
@@ -173,80 +175,84 @@ LWIP::LWIP()
173175
arena_init();
174176
}
175177

176-
nsapi_error_t LWIP::gethostbyname(const char *host, SocketAddress *address, nsapi_version_t version)
178+
nsapi_error_t LWIP::get_dns_server(int index, SocketAddress *address)
177179
{
178-
ip_addr_t lwip_addr;
179-
180-
#if LWIP_IPV4 && LWIP_IPV6
181-
u8_t addr_type;
182-
if (version == NSAPI_UNSPEC) {
183-
const ip_addr_t *ip_addr = NULL;
184-
if (default_interface) {
185-
ip_addr = get_ip_addr(true, &default_interface->netif);
186-
}
187-
// Prefer IPv6
188-
if (IP_IS_V6(ip_addr)) {
189-
// If IPv4 is available use it as backup
190-
if (get_ipv4_addr(&default_interface->netif)) {
191-
addr_type = NETCONN_DNS_IPV6_IPV4;
192-
} else {
193-
addr_type = NETCONN_DNS_IPV6;
194-
}
195-
// Prefer IPv4
196-
} else {
197-
// If IPv6 is available use it as backup
198-
if (get_ipv6_addr(&default_interface->netif)) {
199-
addr_type = NETCONN_DNS_IPV4_IPV6;
200-
} else {
201-
addr_type = NETCONN_DNS_IPV4;
180+
int dns_entries = 0;
181+
182+
for (int i = 0; i < DNS_MAX_SERVERS; i++) {
183+
const ip_addr_t *ip_addr = dns_getserver(i);
184+
if (!ip_addr_isany(ip_addr)) {
185+
if (index == dns_entries) {
186+
nsapi_addr_t addr;
187+
convert_lwip_addr_to_mbed(&addr, ip_addr);
188+
address->set_addr(addr);
189+
return NSAPI_ERROR_OK;
202190
}
191+
dns_entries++;
203192
}
204-
} else if (version == NSAPI_IPv4) {
205-
addr_type = NETCONN_DNS_IPV4;
206-
} else if (version == NSAPI_IPv6) {
207-
addr_type = NETCONN_DNS_IPV6;
208-
} else {
209-
return NSAPI_ERROR_DNS_FAILURE;
210193
}
211-
err_t err = netconn_gethostbyname_addrtype(host, &lwip_addr, addr_type);
212-
#elif LWIP_IPV4
213-
if (version != NSAPI_IPv4 && version != NSAPI_UNSPEC) {
214-
return NSAPI_ERROR_DNS_FAILURE;
215-
}
216-
err_t err = netconn_gethostbyname(host, &lwip_addr);
217-
#elif LWIP_IPV6
218-
if (version != NSAPI_IPv6 && version != NSAPI_UNSPEC) {
219-
return NSAPI_ERROR_DNS_FAILURE;
194+
return NSAPI_ERROR_NO_ADDRESS;
195+
}
196+
197+
void LWIP::tcpip_thread_callback(void *ptr)
198+
{
199+
lwip_callback *cb = static_cast<lwip_callback *>(ptr);
200+
201+
if (cb->delay) {
202+
sys_timeout(cb->delay, LWIP::tcpip_thread_callback, ptr);
203+
cb->delay = 0;
204+
} else {
205+
cb->callback();
206+
delete cb;
220207
}
221-
err_t err = netconn_gethostbyname(host, &lwip_addr);
222-
#endif
208+
}
223209

224-
if (err != ERR_OK) {
225-
return NSAPI_ERROR_DNS_FAILURE;
210+
nsapi_error_t LWIP::call(mbed::Callback<void()> func)
211+
{
212+
return call_in(0, func);
213+
}
214+
215+
nsapi_error_t LWIP::call_in(int delay, mbed::Callback<void()> func)
216+
{
217+
lwip_callback *cb = new lwip_callback;
218+
if (!cb) {
219+
return NSAPI_ERROR_NO_MEMORY;
226220
}
227221

228-
nsapi_addr_t addr;
229-
convert_lwip_addr_to_mbed(&addr, &lwip_addr);
230-
address->set_addr(addr);
222+
cb->delay = delay;
223+
cb->callback = func;
231224

232-
return 0;
225+
if (tcpip_callback_with_block(LWIP::tcpip_thread_callback, cb, 1) != ERR_OK) {
226+
return NSAPI_ERROR_NO_MEMORY;
227+
}
228+
229+
return NSAPI_ERROR_OK;
233230
}
234231

235-
nsapi_error_t LWIP::add_dns_server(const SocketAddress &address)
232+
const char *LWIP::get_ip_address()
236233
{
237-
// Shift all dns servers down to give precedence to new server
238-
for (int i = DNS_MAX_SERVERS-1; i > 0; i--) {
239-
dns_setserver(i, dns_getserver(i-1));
234+
if (!default_interface) {
235+
return NULL;
240236
}
241237

242-
nsapi_addr_t addr = address.get_addr();
243-
ip_addr_t ip_addr;
244-
if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) {
245-
return NSAPI_ERROR_PARAMETER;
246-
}
238+
const ip_addr_t *addr = get_ip_addr(true, &default_interface->netif);
247239

248-
dns_setserver(0, &ip_addr);
249-
return 0;
240+
if (!addr) {
241+
return NULL;
242+
}
243+
#if LWIP_IPV6
244+
if (IP_IS_V6(addr)) {
245+
return ip6addr_ntoa_r(ip_2_ip6(addr), ip_address, sizeof(ip_address));
246+
}
247+
#endif
248+
#if LWIP_IPV4
249+
if (IP_IS_V4(addr)) {
250+
return ip4addr_ntoa_r(ip_2_ip4(addr), ip_address, sizeof(ip_address));
251+
}
252+
#endif
253+
#if LWIP_IPV6 && LWIP_IPV4
254+
return NULL;
255+
#endif
250256
}
251257

252258
nsapi_error_t LWIP::socket_open(nsapi_socket_t *handle, nsapi_protocol_t proto)
@@ -439,6 +445,7 @@ nsapi_size_or_error_t LWIP::socket_sendto(nsapi_socket_t handle, const SocketAdd
439445
}
440446

441447
struct netbuf *buf = netbuf_new();
448+
442449
err_t err = netbuf_ref(buf, data, (u16_t)size);
443450
if (err != ERR_OK) {
444451
netbuf_free(buf);
@@ -588,7 +595,7 @@ nsapi_error_t LWIP::setsockopt(nsapi_socket_t handle, int level, int optname, co
588595

589596
member_pair_index = next_free_multicast_member(s, 0);
590597

591-
sys_prot_t prot = sys_arch_protect();
598+
adaptation.lock();
592599

593600
#if LWIP_IPV4
594601
if (IP_IS_V4(&if_addr)) {
@@ -601,7 +608,7 @@ nsapi_error_t LWIP::setsockopt(nsapi_socket_t handle, int level, int optname, co
601608
}
602609
#endif
603610

604-
sys_arch_unprotect(prot);
611+
adaptation.unlock();
605612

606613
if (igmp_err == ERR_OK) {
607614
set_multicast_member_registry_bit(s, member_pair_index);
@@ -616,7 +623,7 @@ nsapi_error_t LWIP::setsockopt(nsapi_socket_t handle, int level, int optname, co
616623
clear_multicast_member_registry_bit(s, member_pair_index);
617624
s->multicast_memberships_count--;
618625

619-
sys_prot_t prot = sys_arch_protect();
626+
adaptation.lock();
620627

621628
#if LWIP_IPV4
622629
if (IP_IS_V4(&if_addr)) {
@@ -629,7 +636,7 @@ nsapi_error_t LWIP::setsockopt(nsapi_socket_t handle, int level, int optname, co
629636
}
630637
#endif
631638

632-
sys_arch_unprotect(prot);
639+
adaptation.unlock();
633640
}
634641

635642
return err_remap(igmp_err);

features/FEATURE_LWIP/lwip-interface/LWIPStack.h

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -198,29 +198,44 @@ class LWIP : public OnboardNetworkStack, private mbed::NonCopyable<LWIP> {
198198
*/
199199
nsapi_error_t _add_ppp_interface(void *pcb, bool default_if, LWIP::Interface **interface_out);
200200

201-
/** Translates a hostname to an IP address with specific version
201+
/** Get a domain name server from a list of servers to query
202202
*
203-
* The hostname may be either a domain name or an IP address. If the
204-
* hostname is an IP address, no network transactions will be performed.
203+
* Returns a DNS server address for a index. If returns error no more
204+
* DNS servers to read.
205205
*
206-
* If no stack-specific DNS resolution is provided, the hostname
207-
* will be resolve using a UDP socket on the stack.
206+
* @param index Index of the DNS server, starts from zero
207+
* @param address Destination for the host address
208+
* @return 0 on success, negative error code on failure
209+
*/
210+
virtual nsapi_error_t get_dns_server(int index, SocketAddress *address);
211+
212+
/** Call a callback
208213
*
209-
* @param host Hostname to resolve
210-
* @param address Destination for the host SocketAddress
211-
* @param version IP version of address to resolve, NSAPI_UNSPEC indicates
212-
* version is chosen by the stack (defaults to NSAPI_UNSPEC)
214+
* Call a callback from the network stack context. If returns error
215+
* callback will not be called.
216+
*
217+
* @param func Callback to be called
213218
* @return 0 on success, negative error code on failure
214219
*/
215-
virtual nsapi_error_t gethostbyname(const char *host,
216-
SocketAddress *address, nsapi_version_t version = NSAPI_UNSPEC);
220+
virtual nsapi_error_t call(mbed::Callback<void()> func);
217221

218-
/** Add a domain name server to list of servers to query
222+
/** Call a callback after a delay
219223
*
220-
* @param address Destination for the host address
224+
* Call a callback from the network stack context after a delay. If
225+
* returns error callback will not be called.
226+
*
227+
* @param delay Delay in milliseconds
228+
* @param func Callback to be called
221229
* @return 0 on success, negative error code on failure
222230
*/
223-
virtual nsapi_error_t add_dns_server(const SocketAddress &address);
231+
virtual nsapi_error_t call_in(int delay, mbed::Callback<void()> func);
232+
233+
/** Get the local IP address
234+
*
235+
* @return Null-terminated representation of the local IP address
236+
* or null if not yet connected
237+
*/
238+
virtual const char *get_ip_address();
224239

225240
protected:
226241
LWIP();
@@ -439,6 +454,11 @@ class LWIP : public OnboardNetworkStack, private mbed::NonCopyable<LWIP> {
439454
uint32_t multicast_memberships_registry;
440455
};
441456

457+
struct lwip_callback {
458+
unsigned int delay;
459+
mbed::Callback<void()> callback;
460+
};
461+
442462
static nsapi_error_t err_remap(err_t err);
443463
static bool is_local_addr(const ip_addr_t *ip_addr);
444464
static const ip_addr_t *get_ip_addr(bool any_addr, const struct netif *netif);
@@ -475,9 +495,14 @@ class LWIP : public OnboardNetworkStack, private mbed::NonCopyable<LWIP> {
475495
static void socket_callback(struct netconn *nc, enum netconn_evt eh, u16_t len);
476496

477497
static void tcpip_init_irq(void *handle);
498+
static void tcpip_thread_callback(void *ptr);
499+
500+
char ip_address[40];
478501
rtos::Semaphore tcpip_inited;
479502
Interface *default_interface;
480503
LWIPMemoryManager memory_manager;
504+
osThreadId tcpip_thread_id;
505+
rtos::Mutex adaptation;
481506
};
482507

483508
#endif /* LWIPSTACK_H_ */

features/FEATURE_LWIP/lwip-interface/lwip-sys/arch/lwip_sys_arch.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,24 @@ void sys_msleep(u32_t ms) {
480480
osDelay(ms);
481481
}
482482

483+
osThreadId_t lwip_tcpip_thread_id = 0;
484+
485+
bool sys_tcpip_thread_set(void)
486+
{
487+
lwip_tcpip_thread_id = osThreadGetId();
488+
}
489+
490+
bool sys_tcpip_thread_check(void)
491+
{
492+
osThreadId_t thread_id = osThreadGetId();
493+
494+
if (thread_id == lwip_tcpip_thread_id) {
495+
return true;
496+
} else {
497+
return false;
498+
}
499+
}
500+
483501
// Keep a pool of thread structures
484502
static int thread_pool_index = 0;
485503
static sys_thread_data_t thread_pool[SYS_THREAD_POOL_N];

features/FEATURE_LWIP/lwip-interface/lwip-sys/arch/sys_arch.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ typedef sys_thread_data_t* sys_thread_t;
8585
// === PROTECTION ===
8686
typedef int sys_prot_t;
8787

88+
bool sys_tcpip_thread_set(void);
89+
bool sys_tcpip_thread_check(void);
90+
8891
#else
8992
#ifdef __cplusplus
9093
extern "C" {

features/FEATURE_LWIP/lwip-interface/lwip/src/api/lwip_api_lib.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,11 +102,18 @@ netconn_apimsg(tcpip_callback_fn fn, struct api_msg *apimsg)
102102
apimsg->op_completed_sem = LWIP_NETCONN_THREAD_SEM_GET();
103103
#endif /* LWIP_NETCONN_SEM_PER_THREAD */
104104

105-
err = tcpip_send_msg_wait_sem(fn, apimsg, LWIP_API_MSG_SEM(apimsg));
106-
if (err == ERR_OK) {
107-
return apimsg->err;
105+
if (sys_tcpip_thread_check()) {
106+
fn(apimsg);
107+
return ERR_OK;
108+
} else {
109+
err = tcpip_send_msg_wait_sem(fn, apimsg, LWIP_API_MSG_SEM(apimsg));
110+
111+
if (err == ERR_OK) {
112+
return apimsg->err;
113+
}
114+
115+
return err;
108116
}
109-
return err;
110117
}
111118

112119
/**

0 commit comments

Comments
 (0)