mirror of https://github.com/ARMmbed/mbed-os.git
				
				
				
			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.pull/6847/head
							parent
							
								
									bad530ab0d
								
							
						
					
					
						commit
						b7e8400c2c
					
				| 
						 | 
					@ -33,6 +33,7 @@
 | 
				
			||||||
#include "lwip/dns.h"
 | 
					#include "lwip/dns.h"
 | 
				
			||||||
#include "lwip/udp.h"
 | 
					#include "lwip/udp.h"
 | 
				
			||||||
#include "lwip/lwip_errno.h"
 | 
					#include "lwip/lwip_errno.h"
 | 
				
			||||||
 | 
					#include "lwip-sys/arch/sys_arch.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "LWIPStack.h"
 | 
					#include "LWIPStack.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -47,10 +48,10 @@ void LWIP::socket_callback(struct netconn *nc, enum netconn_evt eh, u16_t len)
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sys_prot_t prot = sys_arch_protect();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    LWIP &lwip = LWIP::get_instance();
 | 
					    LWIP &lwip = LWIP::get_instance();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    lwip.adaptation.lock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (int i = 0; i < MEMP_NUM_NETCONN; i++) {
 | 
					    for (int i = 0; i < MEMP_NUM_NETCONN; i++) {
 | 
				
			||||||
        if (lwip.arena[i].in_use
 | 
					        if (lwip.arena[i].in_use
 | 
				
			||||||
            && lwip.arena[i].conn == nc
 | 
					            && lwip.arena[i].conn == nc
 | 
				
			||||||
| 
						 | 
					@ -59,7 +60,7 @@ void LWIP::socket_callback(struct netconn *nc, enum netconn_evt eh, u16_t len)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sys_arch_unprotect(prot);
 | 
					    lwip.adaptation.unlock();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if !LWIP_IPV4 || !LWIP_IPV6
 | 
					#if !LWIP_IPV4 || !LWIP_IPV6
 | 
				
			||||||
| 
						 | 
					@ -149,6 +150,7 @@ void LWIP::tcpip_init_irq(void *eh)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    LWIP *lwip = static_cast<LWIP *>(eh);
 | 
					    LWIP *lwip = static_cast<LWIP *>(eh);
 | 
				
			||||||
    lwip->tcpip_inited.release();
 | 
					    lwip->tcpip_inited.release();
 | 
				
			||||||
 | 
					    sys_tcpip_thread_set();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* LWIP network stack implementation */
 | 
					/* LWIP network stack implementation */
 | 
				
			||||||
| 
						 | 
					@ -173,80 +175,84 @@ LWIP::LWIP()
 | 
				
			||||||
    arena_init();
 | 
					    arena_init();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
nsapi_error_t LWIP::gethostbyname(const char *host, SocketAddress *address, nsapi_version_t version)
 | 
					nsapi_error_t LWIP::get_dns_server(int index, SocketAddress *address)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    ip_addr_t lwip_addr;
 | 
					    int dns_entries = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if LWIP_IPV4 && LWIP_IPV6
 | 
					    for (int i = 0; i < DNS_MAX_SERVERS; i++) {
 | 
				
			||||||
    u8_t addr_type;
 | 
					        const ip_addr_t *ip_addr = dns_getserver(i);
 | 
				
			||||||
    if (version == NSAPI_UNSPEC) {
 | 
					        if (!ip_addr_isany(ip_addr)) {
 | 
				
			||||||
        const ip_addr_t *ip_addr = NULL;
 | 
					            if (index == dns_entries) {
 | 
				
			||||||
        if (default_interface) {
 | 
					                nsapi_addr_t addr;
 | 
				
			||||||
            ip_addr = get_ip_addr(true, &default_interface->netif);
 | 
					                convert_lwip_addr_to_mbed(&addr, ip_addr);
 | 
				
			||||||
        }
 | 
					                address->set_addr(addr);
 | 
				
			||||||
        // Prefer IPv6
 | 
					                return NSAPI_ERROR_OK;
 | 
				
			||||||
        if (IP_IS_V6(ip_addr)) {
 | 
					 | 
				
			||||||
            // If IPv4 is available use it as backup
 | 
					 | 
				
			||||||
            if (get_ipv4_addr(&default_interface->netif)) {
 | 
					 | 
				
			||||||
                addr_type = NETCONN_DNS_IPV6_IPV4;
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                addr_type = NETCONN_DNS_IPV6;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        // Prefer IPv4
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            // If IPv6 is available use it as backup
 | 
					 | 
				
			||||||
            if (get_ipv6_addr(&default_interface->netif)) {
 | 
					 | 
				
			||||||
                addr_type = NETCONN_DNS_IPV4_IPV6;
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                addr_type = NETCONN_DNS_IPV4;
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            dns_entries++;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    } else if (version == NSAPI_IPv4) {
 | 
					 | 
				
			||||||
        addr_type = NETCONN_DNS_IPV4;
 | 
					 | 
				
			||||||
    } else if (version == NSAPI_IPv6) {
 | 
					 | 
				
			||||||
        addr_type = NETCONN_DNS_IPV6;
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        return NSAPI_ERROR_DNS_FAILURE;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    err_t err = netconn_gethostbyname_addrtype(host, &lwip_addr, addr_type);
 | 
					    return NSAPI_ERROR_NO_ADDRESS;
 | 
				
			||||||
#elif LWIP_IPV4
 | 
					 | 
				
			||||||
     if (version != NSAPI_IPv4 && version != NSAPI_UNSPEC) {
 | 
					 | 
				
			||||||
        return NSAPI_ERROR_DNS_FAILURE;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    err_t err = netconn_gethostbyname(host, &lwip_addr);
 | 
					 | 
				
			||||||
#elif LWIP_IPV6
 | 
					 | 
				
			||||||
    if (version != NSAPI_IPv6 && version != NSAPI_UNSPEC) {
 | 
					 | 
				
			||||||
        return NSAPI_ERROR_DNS_FAILURE;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    err_t err = netconn_gethostbyname(host, &lwip_addr);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (err != ERR_OK) {
 | 
					 | 
				
			||||||
        return NSAPI_ERROR_DNS_FAILURE;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    nsapi_addr_t addr;
 | 
					 | 
				
			||||||
    convert_lwip_addr_to_mbed(&addr, &lwip_addr);
 | 
					 | 
				
			||||||
    address->set_addr(addr);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
nsapi_error_t LWIP::add_dns_server(const SocketAddress &address)
 | 
					void LWIP::tcpip_thread_callback(void *ptr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    // Shift all dns servers down to give precedence to new server
 | 
					    lwip_callback *cb = static_cast<lwip_callback *>(ptr);
 | 
				
			||||||
    for (int i = DNS_MAX_SERVERS-1; i > 0; i--) {
 | 
					
 | 
				
			||||||
        dns_setserver(i, dns_getserver(i-1));
 | 
					    if (cb->delay) {
 | 
				
			||||||
 | 
					        sys_timeout(cb->delay, LWIP::tcpip_thread_callback, ptr);
 | 
				
			||||||
 | 
					        cb->delay = 0;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        cb->callback();
 | 
				
			||||||
 | 
					        delete cb;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					nsapi_error_t LWIP::call(mbed::Callback<void()> func)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return call_in(0, func);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					nsapi_error_t LWIP::call_in(int delay, mbed::Callback<void()> func)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    lwip_callback *cb = new lwip_callback;
 | 
				
			||||||
 | 
					    if (!cb) {
 | 
				
			||||||
 | 
					        return NSAPI_ERROR_NO_MEMORY;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    nsapi_addr_t addr = address.get_addr();
 | 
					    cb->delay = delay;
 | 
				
			||||||
    ip_addr_t ip_addr;
 | 
					    cb->callback = func;
 | 
				
			||||||
    if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) {
 | 
					
 | 
				
			||||||
        return NSAPI_ERROR_PARAMETER;
 | 
					    if (tcpip_callback_with_block(LWIP::tcpip_thread_callback, cb, 1) != ERR_OK) {
 | 
				
			||||||
 | 
					        return NSAPI_ERROR_NO_MEMORY;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    dns_setserver(0, &ip_addr);
 | 
					    return NSAPI_ERROR_OK;
 | 
				
			||||||
    return 0;
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char *LWIP::get_ip_address()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (!default_interface) {
 | 
				
			||||||
 | 
					        return NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const ip_addr_t *addr = get_ip_addr(true, &default_interface->netif);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!addr) {
 | 
				
			||||||
 | 
					        return NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#if LWIP_IPV6
 | 
				
			||||||
 | 
					    if (IP_IS_V6(addr)) {
 | 
				
			||||||
 | 
					        return ip6addr_ntoa_r(ip_2_ip6(addr), ip_address, sizeof(ip_address));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#if LWIP_IPV4
 | 
				
			||||||
 | 
					    if (IP_IS_V4(addr)) {
 | 
				
			||||||
 | 
					        return ip4addr_ntoa_r(ip_2_ip4(addr), ip_address, sizeof(ip_address));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#if LWIP_IPV6 && LWIP_IPV4
 | 
				
			||||||
 | 
					    return NULL;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
nsapi_error_t LWIP::socket_open(nsapi_socket_t *handle, nsapi_protocol_t proto)
 | 
					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
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    struct netbuf *buf = netbuf_new();
 | 
					    struct netbuf *buf = netbuf_new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    err_t err = netbuf_ref(buf, data, (u16_t)size);
 | 
					    err_t err = netbuf_ref(buf, data, (u16_t)size);
 | 
				
			||||||
    if (err != ERR_OK) {
 | 
					    if (err != ERR_OK) {
 | 
				
			||||||
        netbuf_free(buf);
 | 
					        netbuf_free(buf);
 | 
				
			||||||
| 
						 | 
					@ -588,7 +595,7 @@ nsapi_error_t LWIP::setsockopt(nsapi_socket_t handle, int level, int optname, co
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                member_pair_index = next_free_multicast_member(s, 0);
 | 
					                member_pair_index = next_free_multicast_member(s, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                sys_prot_t prot = sys_arch_protect();
 | 
					                adaptation.lock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                #if LWIP_IPV4
 | 
					                #if LWIP_IPV4
 | 
				
			||||||
                if (IP_IS_V4(&if_addr)) {
 | 
					                if (IP_IS_V4(&if_addr)) {
 | 
				
			||||||
| 
						 | 
					@ -601,7 +608,7 @@ nsapi_error_t LWIP::setsockopt(nsapi_socket_t handle, int level, int optname, co
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                #endif
 | 
					                #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                sys_arch_unprotect(prot);
 | 
					                adaptation.unlock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (igmp_err == ERR_OK) {
 | 
					                if (igmp_err == ERR_OK) {
 | 
				
			||||||
                    set_multicast_member_registry_bit(s, member_pair_index);
 | 
					                    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
 | 
				
			||||||
                clear_multicast_member_registry_bit(s, member_pair_index);
 | 
					                clear_multicast_member_registry_bit(s, member_pair_index);
 | 
				
			||||||
                s->multicast_memberships_count--;
 | 
					                s->multicast_memberships_count--;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                sys_prot_t prot = sys_arch_protect();
 | 
					                adaptation.lock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                #if LWIP_IPV4
 | 
					                #if LWIP_IPV4
 | 
				
			||||||
                if (IP_IS_V4(&if_addr)) {
 | 
					                if (IP_IS_V4(&if_addr)) {
 | 
				
			||||||
| 
						 | 
					@ -629,7 +636,7 @@ nsapi_error_t LWIP::setsockopt(nsapi_socket_t handle, int level, int optname, co
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                #endif
 | 
					                #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                sys_arch_unprotect(prot);
 | 
					                adaptation.unlock();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return err_remap(igmp_err);
 | 
					            return err_remap(igmp_err);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -198,29 +198,44 @@ public:
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    nsapi_error_t _add_ppp_interface(void *pcb, bool default_if, LWIP::Interface **interface_out);
 | 
					    nsapi_error_t _add_ppp_interface(void *pcb, bool default_if, LWIP::Interface **interface_out);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** Translates a hostname to an IP address with specific version
 | 
					    /** Get a domain name server from a list of servers to query
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     *  The hostname may be either a domain name or an IP address. If the
 | 
					     *  Returns a DNS server address for a index. If returns error no more
 | 
				
			||||||
     *  hostname is an IP address, no network transactions will be performed.
 | 
					     *  DNS servers to read.
 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     *  If no stack-specific DNS resolution is provided, the hostname
 | 
					 | 
				
			||||||
     *  will be resolve using a UDP socket on the stack.
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     *  @param host     Hostname to resolve
 | 
					 | 
				
			||||||
     *  @param address  Destination for the host SocketAddress
 | 
					 | 
				
			||||||
     *  @param version  IP version of address to resolve, NSAPI_UNSPEC indicates
 | 
					 | 
				
			||||||
     *                  version is chosen by the stack (defaults to NSAPI_UNSPEC)
 | 
					 | 
				
			||||||
     *  @return         0 on success, negative error code on failure
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    virtual nsapi_error_t gethostbyname(const char *host,
 | 
					 | 
				
			||||||
            SocketAddress *address, nsapi_version_t version = NSAPI_UNSPEC);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /** Add a domain name server to list of servers to query
 | 
					 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
 | 
					     *  @param index    Index of the DNS server, starts from zero
 | 
				
			||||||
     *  @param address  Destination for the host address
 | 
					     *  @param address  Destination for the host address
 | 
				
			||||||
     *  @return         0 on success, negative error code on failure
 | 
					     *  @return         0 on success, negative error code on failure
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    virtual nsapi_error_t add_dns_server(const SocketAddress &address);
 | 
					    virtual nsapi_error_t get_dns_server(int index, SocketAddress *address);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Call a callback
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  Call a callback from the network stack context. If returns error
 | 
				
			||||||
 | 
					     *  callback will not be called.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  @param func     Callback to be called
 | 
				
			||||||
 | 
					     *  @return         0 on success, negative error code on failure
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    virtual nsapi_error_t call(mbed::Callback<void()> func);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Call a callback after a delay
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  Call a callback from the network stack context after a delay. If
 | 
				
			||||||
 | 
					     *  returns error callback will not be called.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  @param delay    Delay in milliseconds
 | 
				
			||||||
 | 
					     *  @param func     Callback to be called
 | 
				
			||||||
 | 
					     *  @return         0 on success, negative error code on failure
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    virtual nsapi_error_t call_in(int delay, mbed::Callback<void()> func);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Get the local IP address
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  @return         Null-terminated representation of the local IP address
 | 
				
			||||||
 | 
					     *                  or null if not yet connected
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    virtual const char *get_ip_address();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
protected:
 | 
					protected:
 | 
				
			||||||
    LWIP();
 | 
					    LWIP();
 | 
				
			||||||
| 
						 | 
					@ -439,6 +454,11 @@ private:
 | 
				
			||||||
        uint32_t         multicast_memberships_registry;
 | 
					        uint32_t         multicast_memberships_registry;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct lwip_callback {
 | 
				
			||||||
 | 
					        unsigned int delay;
 | 
				
			||||||
 | 
					        mbed::Callback<void()> callback;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static nsapi_error_t err_remap(err_t err);
 | 
					    static nsapi_error_t err_remap(err_t err);
 | 
				
			||||||
    static bool is_local_addr(const ip_addr_t *ip_addr);
 | 
					    static bool is_local_addr(const ip_addr_t *ip_addr);
 | 
				
			||||||
    static const ip_addr_t *get_ip_addr(bool any_addr, const struct netif *netif);
 | 
					    static const ip_addr_t *get_ip_addr(bool any_addr, const struct netif *netif);
 | 
				
			||||||
| 
						 | 
					@ -475,9 +495,14 @@ private:
 | 
				
			||||||
    static void socket_callback(struct netconn *nc, enum netconn_evt eh, u16_t len);
 | 
					    static void socket_callback(struct netconn *nc, enum netconn_evt eh, u16_t len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static void tcpip_init_irq(void *handle);
 | 
					    static void tcpip_init_irq(void *handle);
 | 
				
			||||||
 | 
					    static void tcpip_thread_callback(void *ptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    char ip_address[40];
 | 
				
			||||||
    rtos::Semaphore tcpip_inited;
 | 
					    rtos::Semaphore tcpip_inited;
 | 
				
			||||||
    Interface *default_interface;
 | 
					    Interface *default_interface;
 | 
				
			||||||
    LWIPMemoryManager memory_manager;
 | 
					    LWIPMemoryManager memory_manager;
 | 
				
			||||||
 | 
					    osThreadId tcpip_thread_id;
 | 
				
			||||||
 | 
					    rtos::Mutex adaptation;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* LWIPSTACK_H_ */
 | 
					#endif /* LWIPSTACK_H_ */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -480,6 +480,24 @@ void sys_msleep(u32_t ms) {
 | 
				
			||||||
    osDelay(ms);
 | 
					    osDelay(ms);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					osThreadId_t lwip_tcpip_thread_id = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool sys_tcpip_thread_set(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    lwip_tcpip_thread_id = osThreadGetId();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool sys_tcpip_thread_check(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    osThreadId_t thread_id = osThreadGetId();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (thread_id == lwip_tcpip_thread_id) {
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Keep a pool of thread structures
 | 
					// Keep a pool of thread structures
 | 
				
			||||||
static int thread_pool_index = 0;
 | 
					static int thread_pool_index = 0;
 | 
				
			||||||
static sys_thread_data_t thread_pool[SYS_THREAD_POOL_N];
 | 
					static sys_thread_data_t thread_pool[SYS_THREAD_POOL_N];
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -85,6 +85,9 @@ typedef sys_thread_data_t* sys_thread_t;
 | 
				
			||||||
// === PROTECTION ===
 | 
					// === PROTECTION ===
 | 
				
			||||||
typedef int sys_prot_t;
 | 
					typedef int sys_prot_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool sys_tcpip_thread_set(void);
 | 
				
			||||||
 | 
					bool sys_tcpip_thread_check(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
#ifdef  __cplusplus
 | 
					#ifdef  __cplusplus
 | 
				
			||||||
extern "C" {
 | 
					extern "C" {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -102,11 +102,18 @@ netconn_apimsg(tcpip_callback_fn fn, struct api_msg *apimsg)
 | 
				
			||||||
  apimsg->op_completed_sem = LWIP_NETCONN_THREAD_SEM_GET();
 | 
					  apimsg->op_completed_sem = LWIP_NETCONN_THREAD_SEM_GET();
 | 
				
			||||||
#endif /* LWIP_NETCONN_SEM_PER_THREAD */
 | 
					#endif /* LWIP_NETCONN_SEM_PER_THREAD */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  err = tcpip_send_msg_wait_sem(fn, apimsg, LWIP_API_MSG_SEM(apimsg));
 | 
					  if (sys_tcpip_thread_check()) {
 | 
				
			||||||
  if (err == ERR_OK) {
 | 
					      fn(apimsg);
 | 
				
			||||||
    return apimsg->err;
 | 
					      return ERR_OK;
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					      err = tcpip_send_msg_wait_sem(fn, apimsg, LWIP_API_MSG_SEM(apimsg));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (err == ERR_OK) {
 | 
				
			||||||
 | 
					        return apimsg->err;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return err;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  return err;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -283,16 +283,18 @@ static void dns_init_local(void);
 | 
				
			||||||
static err_t dns_lookup_local(const char *hostname, ip_addr_t *addr LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype));
 | 
					static err_t dns_lookup_local(const char *hostname, ip_addr_t *addr LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype));
 | 
				
			||||||
#endif /* DNS_LOCAL_HOSTLIST */
 | 
					#endif /* DNS_LOCAL_HOSTLIST */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if LWIP_FULL_DNS
 | 
				
			||||||
/* forward declarations */
 | 
					/* forward declarations */
 | 
				
			||||||
static void dns_recv(void *s, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port);
 | 
					static void dns_recv(void *s, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port);
 | 
				
			||||||
static void dns_check_entries(void);
 | 
					static void dns_check_entries(void);
 | 
				
			||||||
static void dns_call_found(u8_t idx, ip_addr_t* addr);
 | 
					static void dns_call_found(u8_t idx, ip_addr_t* addr);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*-----------------------------------------------------------------------------
 | 
					/*-----------------------------------------------------------------------------
 | 
				
			||||||
 * Globals
 | 
					 * Globals
 | 
				
			||||||
 *----------------------------------------------------------------------------*/
 | 
					 *----------------------------------------------------------------------------*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if LWIP_FULL_DNS
 | 
				
			||||||
/* DNS variables */
 | 
					/* DNS variables */
 | 
				
			||||||
static struct udp_pcb        *dns_pcbs[DNS_MAX_SOURCE_PORTS];
 | 
					static struct udp_pcb        *dns_pcbs[DNS_MAX_SOURCE_PORTS];
 | 
				
			||||||
#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0)
 | 
					#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0)
 | 
				
			||||||
| 
						 | 
					@ -301,6 +303,7 @@ static u8_t                   dns_last_pcb_idx;
 | 
				
			||||||
static u8_t                   dns_seqno;
 | 
					static u8_t                   dns_seqno;
 | 
				
			||||||
static struct dns_table_entry dns_table[DNS_TABLE_SIZE];
 | 
					static struct dns_table_entry dns_table[DNS_TABLE_SIZE];
 | 
				
			||||||
static struct dns_req_entry   dns_requests[DNS_MAX_REQUESTS];
 | 
					static struct dns_req_entry   dns_requests[DNS_MAX_REQUESTS];
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
static ip_addr_t              dns_servers[DNS_MAX_SERVERS];
 | 
					static ip_addr_t              dns_servers[DNS_MAX_SERVERS];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if LWIP_IPV4
 | 
					#if LWIP_IPV4
 | 
				
			||||||
| 
						 | 
					@ -324,6 +327,7 @@ dns_init(void)
 | 
				
			||||||
  dns_setserver(0, &dnsserver);
 | 
					  dns_setserver(0, &dnsserver);
 | 
				
			||||||
#endif /* DNS_SERVER_ADDRESS */
 | 
					#endif /* DNS_SERVER_ADDRESS */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if LWIP_FULL_DNS
 | 
				
			||||||
  LWIP_ASSERT("sanity check SIZEOF_DNS_QUERY",
 | 
					  LWIP_ASSERT("sanity check SIZEOF_DNS_QUERY",
 | 
				
			||||||
    sizeof(struct dns_query) == SIZEOF_DNS_QUERY);
 | 
					    sizeof(struct dns_query) == SIZEOF_DNS_QUERY);
 | 
				
			||||||
  LWIP_ASSERT("sanity check SIZEOF_DNS_ANSWER",
 | 
					  LWIP_ASSERT("sanity check SIZEOF_DNS_ANSWER",
 | 
				
			||||||
| 
						 | 
					@ -351,6 +355,7 @@ dns_init(void)
 | 
				
			||||||
#if DNS_LOCAL_HOSTLIST
 | 
					#if DNS_LOCAL_HOSTLIST
 | 
				
			||||||
  dns_init_local();
 | 
					  dns_init_local();
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					#endif /* LWIP_FULL_DNS */
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -397,10 +402,14 @@ dns_getserver(u8_t numdns)
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
dns_tmr(void)
 | 
					dns_tmr(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					#if LWIP_FULL_DNS
 | 
				
			||||||
  LWIP_DEBUGF(DNS_DEBUG, ("dns_tmr: dns_check_entries\n"));
 | 
					  LWIP_DEBUGF(DNS_DEBUG, ("dns_tmr: dns_check_entries\n"));
 | 
				
			||||||
  dns_check_entries();
 | 
					  dns_check_entries();
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if LWIP_FULL_DNS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if DNS_LOCAL_HOSTLIST
 | 
					#if DNS_LOCAL_HOSTLIST
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
dns_init_local(void)
 | 
					dns_init_local(void)
 | 
				
			||||||
| 
						 | 
					@ -1570,4 +1579,6 @@ dns_gethostbyname_addrtype(const char *hostname, ip_addr_t *addr, dns_found_call
 | 
				
			||||||
     LWIP_DNS_ISMDNS_ARG(is_mdns));
 | 
					     LWIP_DNS_ISMDNS_ARG(is_mdns));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* LWIP_FULL_DNS */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* LWIP_DNS */
 | 
					#endif /* LWIP_DNS */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -290,8 +290,8 @@ struct netconn {
 | 
				
			||||||
/** @ingroup netconn_common
 | 
					/** @ingroup netconn_common
 | 
				
			||||||
 * Create new netconn connection
 | 
					 * Create new netconn connection
 | 
				
			||||||
 * @param t @ref netconn_type */
 | 
					 * @param t @ref netconn_type */
 | 
				
			||||||
#define netconn_new(t)                  netconn_new_with_proto_and_callback(t, 0, NULL)
 | 
					#define netconn_new(t)                             netconn_new_with_proto_and_callback(t, 0, NULL)
 | 
				
			||||||
#define netconn_new_with_callback(t, c) netconn_new_with_proto_and_callback(t, 0, c)
 | 
					#define netconn_new_with_callback(t, c)            netconn_new_with_proto_and_callback(t, 0, c)
 | 
				
			||||||
struct netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto,
 | 
					struct netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto,
 | 
				
			||||||
                                             netconn_callback callback);
 | 
					                                             netconn_callback callback);
 | 
				
			||||||
err_t   netconn_delete(struct netconn *conn);
 | 
					err_t   netconn_delete(struct netconn *conn);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -157,19 +157,22 @@ void LWIP::arena_init(void)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct LWIP::mbed_lwip_socket *LWIP::arena_alloc()
 | 
					struct LWIP::mbed_lwip_socket *LWIP::arena_alloc()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    sys_prot_t prot = sys_arch_protect();
 | 
					    LWIP &lwip = LWIP::get_instance();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    lwip.adaptation.lock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (int i = 0; i < MEMP_NUM_NETCONN; i++) {
 | 
					    for (int i = 0; i < MEMP_NUM_NETCONN; i++) {
 | 
				
			||||||
        if (!arena[i].in_use) {
 | 
					        if (!arena[i].in_use) {
 | 
				
			||||||
            struct mbed_lwip_socket *s = &arena[i];
 | 
					            struct mbed_lwip_socket *s = &arena[i];
 | 
				
			||||||
            memset(s, 0, sizeof(*s));
 | 
					            memset(s, 0, sizeof(*s));
 | 
				
			||||||
            s->in_use = true;
 | 
					            s->in_use = true;
 | 
				
			||||||
            sys_arch_unprotect(prot);
 | 
					            lwip.adaptation.unlock();
 | 
				
			||||||
            return s;
 | 
					            return s;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sys_arch_unprotect(prot);
 | 
					    lwip.adaptation.unlock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -213,6 +213,8 @@
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define LWIP_DNS                    1
 | 
					#define LWIP_DNS                    1
 | 
				
			||||||
 | 
					// Only DNS address storage is enabled
 | 
				
			||||||
 | 
					#define LWIP_FULL_DNS               0
 | 
				
			||||||
#define LWIP_SOCKET                 0
 | 
					#define LWIP_SOCKET                 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define SO_REUSE                    1
 | 
					#define SO_REUSE                    1
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,6 +25,7 @@
 | 
				
			||||||
#include "ns_address.h"
 | 
					#include "ns_address.h"
 | 
				
			||||||
#include "nsdynmemLIB.h"
 | 
					#include "nsdynmemLIB.h"
 | 
				
			||||||
#include "eventOS_scheduler.h"
 | 
					#include "eventOS_scheduler.h"
 | 
				
			||||||
 | 
					#include "eventOS_event_timer.h"
 | 
				
			||||||
#include "randLIB.h"
 | 
					#include "randLIB.h"
 | 
				
			||||||
#include "ip6string.h"
 | 
					#include "ip6string.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -57,6 +58,7 @@ enum socket_mode_t {
 | 
				
			||||||
    SOCKET_MODE_LISTENING,  // Socket is listening for connections
 | 
					    SOCKET_MODE_LISTENING,  // Socket is listening for connections
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CALL_EVENT   0x12
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class NanostackSocket {
 | 
					class NanostackSocket {
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
| 
						 | 
					@ -444,6 +446,65 @@ void NanostackSocket::event_connection_reset(socket_callback_t *sock_cb)
 | 
				
			||||||
    close();
 | 
					    close();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Nanostack::Nanostack()
 | 
				
			||||||
 | 
					    : call_event_tasklet(-1)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Nanostack::call_event_tasklet_main(arm_event_s *event)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (event->event_id == CALL_EVENT) {
 | 
				
			||||||
 | 
					        nanostack_callback *cb = static_cast<nanostack_callback *>(event->data_ptr);
 | 
				
			||||||
 | 
					        cb->callback();
 | 
				
			||||||
 | 
					        delete cb;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					nsapi_error_t Nanostack::call(mbed::Callback<void()> func)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return call_in(0, func);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					nsapi_error_t Nanostack::call_in(int delay, mbed::Callback<void()> func)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (call_event_tasklet < 0) {
 | 
				
			||||||
 | 
					        call_event_tasklet = eventOS_event_handler_create(&call_event_tasklet_main, 0);
 | 
				
			||||||
 | 
					        if (call_event_tasklet < 0) {
 | 
				
			||||||
 | 
					            return NSAPI_ERROR_NO_MEMORY;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    nanostack_callback *cb = new nanostack_callback;
 | 
				
			||||||
 | 
					    if (!cb) {
 | 
				
			||||||
 | 
					        return NSAPI_ERROR_NO_MEMORY;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    cb->callback = func;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    arm_event_s event;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    event.sender =  call_event_tasklet,
 | 
				
			||||||
 | 
					    event.event_id = CALL_EVENT,
 | 
				
			||||||
 | 
					    event.receiver = call_event_tasklet,
 | 
				
			||||||
 | 
					    event.data_ptr = cb;
 | 
				
			||||||
 | 
					    event.event_type = APPLICATION_EVENT;
 | 
				
			||||||
 | 
					    event.priority = ARM_LIB_LOW_PRIORITY_EVENT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (delay) {
 | 
				
			||||||
 | 
					        uint32_t ticks = eventOS_event_timer_ms_to_ticks(delay);
 | 
				
			||||||
 | 
					        if (!eventOS_event_send_in(&event, ticks)) {
 | 
				
			||||||
 | 
					            return NSAPI_ERROR_NO_MEMORY;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        if (eventOS_event_send(&event) < 0) {
 | 
				
			||||||
 | 
					            return NSAPI_ERROR_NO_MEMORY;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return NSAPI_ERROR_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const char * Nanostack::get_ip_address()
 | 
					const char * Nanostack::get_ip_address()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    NanostackLockGuard lock;
 | 
					    NanostackLockGuard lock;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,6 +23,7 @@
 | 
				
			||||||
#include "NanostackMemoryManager.h"
 | 
					#include "NanostackMemoryManager.h"
 | 
				
			||||||
#include "MeshInterface.h"
 | 
					#include "MeshInterface.h"
 | 
				
			||||||
#include "mesh_interface_types.h"
 | 
					#include "mesh_interface_types.h"
 | 
				
			||||||
 | 
					#include "eventOS_event.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct ns_address;
 | 
					struct ns_address;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -43,8 +44,31 @@ public:
 | 
				
			||||||
    /* Local variant with stronger typing and manual address specification */
 | 
					    /* Local variant with stronger typing and manual address specification */
 | 
				
			||||||
    nsapi_error_t add_ethernet_interface(EMAC &emac, bool default_if, Nanostack::EthernetInterface **interface_out, const uint8_t *mac_addr = NULL);
 | 
					    nsapi_error_t add_ethernet_interface(EMAC &emac, bool default_if, Nanostack::EthernetInterface **interface_out, const uint8_t *mac_addr = NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Call a callback
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  Call a callback from the network stack context. If returns error
 | 
				
			||||||
 | 
					     *  callback will not be called.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  @param func     Callback to be called
 | 
				
			||||||
 | 
					     *  @return         0 on success, negative error code on failure
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    virtual nsapi_error_t call(mbed::Callback<void()> func);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Call a callback after a delay
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  Call a callback from the network stack context after a delay. If
 | 
				
			||||||
 | 
					     *  returns error callback will not be called.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  @param delay    Delay in milliseconds
 | 
				
			||||||
 | 
					     *  @param func     Callback to be called
 | 
				
			||||||
 | 
					     *  @return         0 on success, negative error code on failure
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    virtual nsapi_error_t call_in(int delay, mbed::Callback<void()> func);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
protected:
 | 
					protected:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Nanostack();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** Get the local IP address
 | 
					    /** Get the local IP address
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     *  @return         Null-terminated representation of the local IP address
 | 
					     *  @return         Null-terminated representation of the local IP address
 | 
				
			||||||
| 
						 | 
					@ -242,9 +266,15 @@ protected:
 | 
				
			||||||
    virtual nsapi_error_t getsockopt(void *handle, int level, int optname, void *optval, unsigned *optlen);
 | 
					    virtual nsapi_error_t getsockopt(void *handle, int level, int optname, void *optval, unsigned *optlen);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
 | 
					    struct nanostack_callback {
 | 
				
			||||||
 | 
					        mbed::Callback<void()> callback;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    nsapi_size_or_error_t do_sendto(void *handle, const struct ns_address *address, const void *data, nsapi_size_t size);
 | 
					    nsapi_size_or_error_t do_sendto(void *handle, const struct ns_address *address, const void *data, nsapi_size_t size);
 | 
				
			||||||
 | 
					    static void call_event_tasklet_main(arm_event_s *event);
 | 
				
			||||||
    char text_ip_address[40];
 | 
					    char text_ip_address[40];
 | 
				
			||||||
    NanostackMemoryManager memory_manager;
 | 
					    NanostackMemoryManager memory_manager;
 | 
				
			||||||
 | 
					    int8_t call_event_tasklet;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
nsapi_error_t map_mesh_error(mesh_error_t err);
 | 
					nsapi_error_t map_mesh_error(mesh_error_t err);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -60,6 +60,11 @@ nsapi_error_t NetworkInterface::gethostbyname(const char *name, SocketAddress *a
 | 
				
			||||||
    return get_stack()->gethostbyname(name, address, version);
 | 
					    return get_stack()->gethostbyname(name, address, version);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					nsapi_error_t NetworkInterface::gethostbyname_async(const char *host, hostbyname_cb_t callback, void *data, nsapi_version_t version)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return get_stack()->gethostbyname_async(host, callback, data, version);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
nsapi_error_t NetworkInterface::add_dns_server(const SocketAddress &address)
 | 
					nsapi_error_t NetworkInterface::add_dns_server(const SocketAddress &address)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return get_stack()->add_dns_server(address);
 | 
					    return get_stack()->add_dns_server(address);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -127,6 +127,38 @@ public:
 | 
				
			||||||
    virtual nsapi_error_t gethostbyname(const char *host,
 | 
					    virtual nsapi_error_t gethostbyname(const char *host,
 | 
				
			||||||
            SocketAddress *address, nsapi_version_t version = NSAPI_UNSPEC);
 | 
					            SocketAddress *address, nsapi_version_t version = NSAPI_UNSPEC);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Hostname translation callback (asynchronous)
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  Callback will be called after DNS resolution completes or a failure
 | 
				
			||||||
 | 
					     *  occurs.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  @param status  0 on success, negative error code on failure
 | 
				
			||||||
 | 
					     *  @param address On success, destination for the host SocketAddress
 | 
				
			||||||
 | 
					     *  @param data    Caller defined data
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    typedef mbed::Callback<void (nsapi_error_t result, SocketAddress *address, void *data)> hostbyname_cb_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Translates a hostname to an IP address (asynchronous)
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  The hostname may be either a domain name or an IP address. If the
 | 
				
			||||||
 | 
					     *  hostname is an IP address, no network transactions will be performed.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  If no stack-specific DNS resolution is provided, the hostname
 | 
				
			||||||
 | 
					     *  will be resolve using a UDP socket on the stack.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  Call is non-blocking. Result of the DNS operation is returned by the callback.
 | 
				
			||||||
 | 
					     *  If this function returns failure, callback will not be called.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  @param host     Hostname to resolve
 | 
				
			||||||
 | 
					     *  @param callback Callback that is called for result
 | 
				
			||||||
 | 
					     *  @param data     Caller defined data returned in callback
 | 
				
			||||||
 | 
					     *  @param version  IP version of address to resolve, NSAPI_UNSPEC indicates
 | 
				
			||||||
 | 
					     *                  version is chosen by the stack (defaults to NSAPI_UNSPEC)
 | 
				
			||||||
 | 
					     *  @return         0 on success, negative error code on failure
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    virtual nsapi_error_t gethostbyname_async(const char *host, hostbyname_cb_t callback, void *data,
 | 
				
			||||||
 | 
					            nsapi_version_t version = NSAPI_UNSPEC);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** Add a domain name server to list of servers to query
 | 
					    /** Add a domain name server to list of servers to query
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     *  @param address  Destination for the host address
 | 
					     *  @param address  Destination for the host address
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -49,11 +49,41 @@ nsapi_error_t NetworkStack::gethostbyname(const char *name, SocketAddress *addre
 | 
				
			||||||
    return nsapi_dns_query(this, name, address, version);
 | 
					    return nsapi_dns_query(this, name, address, version);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					nsapi_error_t NetworkStack::gethostbyname_async(const char *name, hostbyname_cb_t callback, void *data, nsapi_version_t version)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    SocketAddress address;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // check for simple ip addresses
 | 
				
			||||||
 | 
					    if (address.set_ip_address(name)) {
 | 
				
			||||||
 | 
					        if (version != NSAPI_UNSPEC && address.get_ip_version() != version) {
 | 
				
			||||||
 | 
					            return NSAPI_ERROR_DNS_FAILURE;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return NSAPI_ERROR_OK;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // if the version is unspecified, try to guess the version from the
 | 
				
			||||||
 | 
					    // ip address of the underlying stack
 | 
				
			||||||
 | 
					    if (version == NSAPI_UNSPEC) {
 | 
				
			||||||
 | 
					        SocketAddress testaddress;
 | 
				
			||||||
 | 
					        if (testaddress.set_ip_address(this->get_ip_address())) {
 | 
				
			||||||
 | 
					            version = testaddress.get_ip_version();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return nsapi_dns_query_async(this, name, callback, data, version);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
nsapi_error_t NetworkStack::add_dns_server(const SocketAddress &address)
 | 
					nsapi_error_t NetworkStack::add_dns_server(const SocketAddress &address)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return nsapi_dns_add_server(address);
 | 
					    return nsapi_dns_add_server(address);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					nsapi_error_t NetworkStack::get_dns_server(int index, SocketAddress *address)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return NSAPI_ERROR_UNSUPPORTED;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
nsapi_error_t NetworkStack::setstackopt(int level, int optname, const void *optval, unsigned optlen)
 | 
					nsapi_error_t NetworkStack::setstackopt(int level, int optname, const void *optval, unsigned optlen)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return NSAPI_ERROR_UNSUPPORTED;
 | 
					    return NSAPI_ERROR_UNSUPPORTED;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,6 +22,8 @@
 | 
				
			||||||
#include "netsocket/SocketAddress.h"
 | 
					#include "netsocket/SocketAddress.h"
 | 
				
			||||||
#include "netsocket/NetworkInterface.h"
 | 
					#include "netsocket/NetworkInterface.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Predeclared classes
 | 
				
			||||||
 | 
					class OnboardNetworkStack;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** NetworkStack class
 | 
					/** NetworkStack class
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
| 
						 | 
					@ -37,13 +39,10 @@ public:
 | 
				
			||||||
    virtual ~NetworkStack() {};
 | 
					    virtual ~NetworkStack() {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** Get the local IP address
 | 
					    /** Get the local IP address
 | 
				
			||||||
     *  @deprecated
 | 
					 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     *  @return         Null-terminated representation of the local IP address
 | 
					     *  @return         Null-terminated representation of the local IP address
 | 
				
			||||||
     *                  or null if not yet connected
 | 
					     *                  or null if not yet connected
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    MBED_DEPRECATED_SINCE("mbed-os-5.7",
 | 
					 | 
				
			||||||
        "Use NetworkInterface::get_ip_address()")
 | 
					 | 
				
			||||||
    virtual const char *get_ip_address();
 | 
					    virtual const char *get_ip_address();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** Translates a hostname to an IP address with specific version
 | 
					    /** Translates a hostname to an IP address with specific version
 | 
				
			||||||
| 
						 | 
					@ -63,6 +62,38 @@ public:
 | 
				
			||||||
    virtual nsapi_error_t gethostbyname(const char *host,
 | 
					    virtual nsapi_error_t gethostbyname(const char *host,
 | 
				
			||||||
            SocketAddress *address, nsapi_version_t version = NSAPI_UNSPEC);
 | 
					            SocketAddress *address, nsapi_version_t version = NSAPI_UNSPEC);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Hostname translation callback (asynchronous)
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  Callback will be called after DNS resolution completes or a failure
 | 
				
			||||||
 | 
					     *  occurs.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  @param status  0 on success, negative error code on failure
 | 
				
			||||||
 | 
					     *  @param address On success, destination for the host SocketAddress
 | 
				
			||||||
 | 
					     *  @param data    Caller defined data
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    typedef mbed::Callback<void (nsapi_error_t result, SocketAddress *address, void *data)> hostbyname_cb_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Translates a hostname to an IP address (asynchronous)
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  The hostname may be either a domain name or an IP address. If the
 | 
				
			||||||
 | 
					     *  hostname is an IP address, no network transactions will be performed.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  If no stack-specific DNS resolution is provided, the hostname
 | 
				
			||||||
 | 
					     *  will be resolve using a UDP socket on the stack.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  Call is non-blocking. Result of the DNS operation is returned by the callback.
 | 
				
			||||||
 | 
					     *  If this function returns failure, callback will not be called.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  @param host     Hostname to resolve
 | 
				
			||||||
 | 
					     *  @param callback Callback that is called for result
 | 
				
			||||||
 | 
					     *  @param data     Caller defined data returned in callback
 | 
				
			||||||
 | 
					     *  @param version  IP version of address to resolve, NSAPI_UNSPEC indicates
 | 
				
			||||||
 | 
					     *                  version is chosen by the stack (defaults to NSAPI_UNSPEC)
 | 
				
			||||||
 | 
					     *  @return         0 on success, negative error code on failure
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    virtual nsapi_error_t gethostbyname_async(const char *host, hostbyname_cb_t callback, void *data,
 | 
				
			||||||
 | 
					            nsapi_version_t version = NSAPI_UNSPEC);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** Add a domain name server to list of servers to query
 | 
					    /** Add a domain name server to list of servers to query
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     *  @param address  Destination for the host address
 | 
					     *  @param address  Destination for the host address
 | 
				
			||||||
| 
						 | 
					@ -70,6 +101,17 @@ public:
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    virtual nsapi_error_t add_dns_server(const SocketAddress &address);
 | 
					    virtual nsapi_error_t add_dns_server(const SocketAddress &address);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Get a domain name server from a list of servers to query
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  Returns a DNS server address for a index. If returns error no more
 | 
				
			||||||
 | 
					     *  DNS servers to read.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  @param index    Index of the DNS server, starts from zero
 | 
				
			||||||
 | 
					     *  @param address  Destination for the host address
 | 
				
			||||||
 | 
					     *  @return         0 on success, negative error code on failure
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    virtual nsapi_error_t get_dns_server(int index, SocketAddress *address);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /*  Set stack options
 | 
					    /*  Set stack options
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     *  setstackopt allows an application to pass stack-specific options
 | 
					     *  setstackopt allows an application to pass stack-specific options
 | 
				
			||||||
| 
						 | 
					@ -101,6 +143,9 @@ public:
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    virtual nsapi_error_t getstackopt(int level, int optname, void *optval, unsigned *optlen);
 | 
					    virtual nsapi_error_t getstackopt(int level, int optname, void *optval, unsigned *optlen);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Dynamic downcast to a OnboardNetworkStack */
 | 
				
			||||||
 | 
					    virtual OnboardNetworkStack *onboardNetworkStack() { return 0; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
protected:
 | 
					protected:
 | 
				
			||||||
    friend class Socket;
 | 
					    friend class Socket;
 | 
				
			||||||
    friend class UDPSocket;
 | 
					    friend class UDPSocket;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -39,6 +39,8 @@ public:
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    static OnboardNetworkStack &get_default_instance();
 | 
					    static OnboardNetworkStack &get_default_instance();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    virtual OnboardNetworkStack *onboardNetworkStack() { return this; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** Representation of a stack's view of an interface.
 | 
					    /** Representation of a stack's view of an interface.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * Provides facilities required by a driver to implement the application
 | 
					     * Provides facilities required by a driver to implement the application
 | 
				
			||||||
| 
						 | 
					@ -121,6 +123,26 @@ public:
 | 
				
			||||||
        virtual char *get_gateway(char *buf, nsapi_size_t buflen) = 0;
 | 
					        virtual char *get_gateway(char *buf, nsapi_size_t buflen) = 0;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Call a callback
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  Call a callback from the network stack context. If returns error
 | 
				
			||||||
 | 
					     *  callback will not be called.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  @param func     Callback to be called
 | 
				
			||||||
 | 
					     *  @return         0 on success, negative error code on failure
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    virtual nsapi_error_t call(mbed::Callback<void()> func) = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Call a callback after a delay
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  Call a callback from the network stack context after a delay. If
 | 
				
			||||||
 | 
					     *  returns error callback will not be called.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  @param delay    Delay in milliseconds
 | 
				
			||||||
 | 
					     *  @param func     Callback to be called
 | 
				
			||||||
 | 
					     *  @return         0 on success, negative error code on failure
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    virtual nsapi_error_t call_in(int delay, mbed::Callback<void()> func) = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** Register a network interface with the IP stack
 | 
					    /** Register a network interface with the IP stack
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,6 +19,10 @@
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include "mbed_shared_queues.h"
 | 
				
			||||||
 | 
					#include "EventQueue.h"
 | 
				
			||||||
 | 
					#include "OnboardNetworkStack.h"
 | 
				
			||||||
 | 
					#include "Kernel.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define CLASS_IN 1
 | 
					#define CLASS_IN 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,8 +33,51 @@
 | 
				
			||||||
#define DNS_BUFFER_SIZE 512
 | 
					#define DNS_BUFFER_SIZE 512
 | 
				
			||||||
#define DNS_TIMEOUT 5000
 | 
					#define DNS_TIMEOUT 5000
 | 
				
			||||||
#define DNS_SERVERS_SIZE 5
 | 
					#define DNS_SERVERS_SIZE 5
 | 
				
			||||||
 | 
					#define DNS_RESPONSE_MIN_SIZE 12
 | 
				
			||||||
 | 
					#define DNS_MAX_TTL 604800
 | 
				
			||||||
 | 
					#define DNS_CACHE_SIZE 3
 | 
				
			||||||
 | 
					#define DNS_STACK_SERVERS_NUM 5
 | 
				
			||||||
 | 
					#define DNS_QUERY_QUEUE_SIZE 5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
nsapi_addr_t dns_servers[DNS_SERVERS_SIZE] = {
 | 
					struct DNS_CACHE {
 | 
				
			||||||
 | 
					    SocketAddress address;
 | 
				
			||||||
 | 
					    char host[128];
 | 
				
			||||||
 | 
					    uint64_t expires;      /*!< time to live in milliseconds */
 | 
				
			||||||
 | 
					    uint64_t accessed;     /*!< last accessed */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct DNS_QUERY {
 | 
				
			||||||
 | 
					    int unique_id;
 | 
				
			||||||
 | 
					    NetworkStack *stack;
 | 
				
			||||||
 | 
					    char host[128];
 | 
				
			||||||
 | 
					    NetworkStack::hostbyname_cb_t callback;
 | 
				
			||||||
 | 
					    void *cb_data;
 | 
				
			||||||
 | 
					    nsapi_size_t addr_count;
 | 
				
			||||||
 | 
					    nsapi_version_t version;
 | 
				
			||||||
 | 
					    UDPSocket *socket;
 | 
				
			||||||
 | 
					    int dns_server;
 | 
				
			||||||
 | 
					    int retries;
 | 
				
			||||||
 | 
					    int dns_message_id;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef nsapi_error_t (*nsapi_dns_call_t)(mbed::Callback<void()> func);
 | 
				
			||||||
 | 
					typedef nsapi_error_t (*nsapi_dns_call_in_t)(int delay, mbed::Callback<void()> func);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void nsapi_dns_cache_add(const char *host, SocketAddress *address, uint32_t ttl);
 | 
				
			||||||
 | 
					static nsapi_size_or_error_t nsapi_dns_cache_find(const char *host, nsapi_version_t version, SocketAddress *address);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static nsapi_error_t nsapi_dns_get_server_addr(NetworkStack *stack, int *index, SocketAddress *dns_addr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void nsapi_dns_query_async_create(DNS_QUERY *query);
 | 
				
			||||||
 | 
					static void nsapi_dns_query_async_send(void *ptr);
 | 
				
			||||||
 | 
					static void nsapi_dns_query_async_resp(DNS_QUERY *query, nsapi_error_t status, SocketAddress *address);
 | 
				
			||||||
 | 
					static void nsapi_dns_query_async_socket_callback(NetworkStack *stack);
 | 
				
			||||||
 | 
					static void nsapi_dns_query_async_socket_callback_handle(NetworkStack *stack);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static nsapi_error_t nsapi_dns_call_default(mbed::Callback<void()> func);
 | 
				
			||||||
 | 
					static nsapi_error_t nsapi_dns_call_in_default(int delay, mbed::Callback<void()> func);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static nsapi_addr_t dns_servers[DNS_SERVERS_SIZE] = {
 | 
				
			||||||
    {NSAPI_IPv4, {8, 8, 8, 8}},                             // Google
 | 
					    {NSAPI_IPv4, {8, 8, 8, 8}},                             // Google
 | 
				
			||||||
    {NSAPI_IPv4, {209, 244, 0, 3}},                         // Level 3
 | 
					    {NSAPI_IPv4, {209, 244, 0, 3}},                         // Level 3
 | 
				
			||||||
    {NSAPI_IPv4, {84, 200, 69, 80}},                        // DNS.WATCH
 | 
					    {NSAPI_IPv4, {84, 200, 69, 80}},                        // DNS.WATCH
 | 
				
			||||||
| 
						 | 
					@ -40,6 +87,14 @@ nsapi_addr_t dns_servers[DNS_SERVERS_SIZE] = {
 | 
				
			||||||
                  0,0, 0,0, 0x1c,0x04, 0xb1,0x2f}},
 | 
					                  0,0, 0,0, 0x1c,0x04, 0xb1,0x2f}},
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static DNS_CACHE *dns_cache[DNS_CACHE_SIZE];
 | 
				
			||||||
 | 
					static uint16_t dns_message_id = 0;
 | 
				
			||||||
 | 
					static int dns_unique_id = 0;
 | 
				
			||||||
 | 
					static DNS_QUERY *dns_query_queue[DNS_QUERY_QUEUE_SIZE];
 | 
				
			||||||
 | 
					static rtos::Mutex dns_cache_mutex;
 | 
				
			||||||
 | 
					static nsapi_dns_call_t dns_call = nsapi_dns_call_default;
 | 
				
			||||||
 | 
					static nsapi_dns_call_in_t dns_call_in = nsapi_dns_call_in_default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DNS server configuration
 | 
					// DNS server configuration
 | 
				
			||||||
extern "C" nsapi_error_t nsapi_dns_add_server(nsapi_addr_t addr)
 | 
					extern "C" nsapi_error_t nsapi_dns_add_server(nsapi_addr_t addr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -83,11 +138,23 @@ static uint16_t dns_scan_word(const uint8_t **p)
 | 
				
			||||||
    return (a << 8) | b;
 | 
					    return (a << 8) | b;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static uint32_t dns_scan_word32(const uint8_t **p)
 | 
				
			||||||
static void dns_append_question(uint8_t **p, const char *host, nsapi_version_t version)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    uint32_t value = dns_scan_byte(p) << 24;
 | 
				
			||||||
 | 
					    value |= dns_scan_byte(p) << 16;
 | 
				
			||||||
 | 
					    value |= dns_scan_byte(p) << 8;
 | 
				
			||||||
 | 
					    value |= dns_scan_byte(p);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return value;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int dns_append_question(uint8_t *ptr, uint16_t id, const char *host, nsapi_version_t version)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint8_t *s_ptr = ptr;
 | 
				
			||||||
 | 
					    uint8_t **p = &ptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // fill the header
 | 
					    // fill the header
 | 
				
			||||||
    dns_append_word(p, 1);      // id      = 1
 | 
					    dns_append_word(p, id);     // id      = 1
 | 
				
			||||||
    dns_append_word(p, 0x0100); // flags   = recursion required
 | 
					    dns_append_word(p, 0x0100); // flags   = recursion required
 | 
				
			||||||
    dns_append_word(p, 1);      // qdcount = 1
 | 
					    dns_append_word(p, 1);      // qdcount = 1
 | 
				
			||||||
    dns_append_word(p, 0);      // ancount = 0
 | 
					    dns_append_word(p, 0);      // ancount = 0
 | 
				
			||||||
| 
						 | 
					@ -110,10 +177,14 @@ static void dns_append_question(uint8_t **p, const char *host, nsapi_version_t v
 | 
				
			||||||
        dns_append_word(p, RR_AAAA);    // qtype  = ipv6
 | 
					        dns_append_word(p, RR_AAAA);    // qtype  = ipv6
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    dns_append_word(p, CLASS_IN);
 | 
					    dns_append_word(p, CLASS_IN);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return *p - s_ptr;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int dns_scan_response(const uint8_t **p, nsapi_addr_t *addr, unsigned addr_count)
 | 
					static int dns_scan_response(const uint8_t *ptr, uint16_t exp_id, uint32_t *ttl, nsapi_addr_t *addr, unsigned addr_count)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    const uint8_t **p = &ptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // scan header
 | 
					    // scan header
 | 
				
			||||||
    uint16_t id    = dns_scan_word(p);
 | 
					    uint16_t id    = dns_scan_word(p);
 | 
				
			||||||
    uint16_t flags = dns_scan_word(p);
 | 
					    uint16_t flags = dns_scan_word(p);
 | 
				
			||||||
| 
						 | 
					@ -127,7 +198,7 @@ static int dns_scan_response(const uint8_t **p, nsapi_addr_t *addr, unsigned add
 | 
				
			||||||
    dns_scan_word(p);                    // arcount
 | 
					    dns_scan_word(p);                    // arcount
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // verify header is response to query
 | 
					    // verify header is response to query
 | 
				
			||||||
    if (!(id == 1 && qr && opcode == 0 && rcode == 0)) {
 | 
					    if (!(id == exp_id && qr && opcode == 0 && rcode == 0)) {
 | 
				
			||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -162,10 +233,18 @@ static int dns_scan_response(const uint8_t **p, nsapi_addr_t *addr, unsigned add
 | 
				
			||||||
            *p += len;
 | 
					            *p += len;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        uint16_t rtype    = dns_scan_word(p); // rtype
 | 
					        uint16_t rtype    = dns_scan_word(p);    // rtype
 | 
				
			||||||
        uint16_t rclass   = dns_scan_word(p); // rclass
 | 
					        uint16_t rclass   = dns_scan_word(p);    // rclass
 | 
				
			||||||
        *p += 4;                              // ttl
 | 
					        uint32_t ttl_val  = dns_scan_word32(p);  // ttl
 | 
				
			||||||
        uint16_t rdlength = dns_scan_word(p); // rdlength
 | 
					        uint16_t rdlength = dns_scan_word(p);    // rdlength
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (i == 0) {
 | 
				
			||||||
 | 
					            // Is interested only on first address that is stored to cache
 | 
				
			||||||
 | 
					            if (ttl_val > DNS_MAX_TTL) {
 | 
				
			||||||
 | 
					                ttl_val = DNS_MAX_TTL;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            *ttl = ttl_val;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (rtype == RR_A && rclass == CLASS_IN && rdlength == NSAPI_IPv4_BYTES) {
 | 
					        if (rtype == RR_A && rclass == CLASS_IN && rdlength == NSAPI_IPv4_BYTES) {
 | 
				
			||||||
            // accept A record
 | 
					            // accept A record
 | 
				
			||||||
| 
						 | 
					@ -194,6 +273,109 @@ static int dns_scan_response(const uint8_t **p, nsapi_addr_t *addr, unsigned add
 | 
				
			||||||
    return count;
 | 
					    return count;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void nsapi_dns_cache_add(const char *host, SocketAddress *address, uint32_t ttl)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    // RFC 1034: if TTL is zero, entry is not added to cache
 | 
				
			||||||
 | 
					    if (!ttl) {
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Checks if already cached
 | 
				
			||||||
 | 
					    if (nsapi_dns_cache_find(host, address->get_ip_version(), NULL) == NSAPI_ERROR_OK) {
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dns_cache_mutex.lock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int index = -1;
 | 
				
			||||||
 | 
					    uint64_t accessed = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Finds free or last accessed entry
 | 
				
			||||||
 | 
					    for (int i = 0; i < DNS_CACHE_SIZE; i++) {
 | 
				
			||||||
 | 
					        if (!dns_cache[i]) {
 | 
				
			||||||
 | 
					            index = i;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        } else if (dns_cache[i]->accessed <= accessed) {
 | 
				
			||||||
 | 
					            accessed = dns_cache[i]->accessed;
 | 
				
			||||||
 | 
					            index = i;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (index < 0) {
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Allocates in case entry is free, otherwise reuses
 | 
				
			||||||
 | 
					    if (!dns_cache[index]) {
 | 
				
			||||||
 | 
					        dns_cache[index] = new DNS_CACHE;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (dns_cache[index]) {
 | 
				
			||||||
 | 
					        dns_cache[index]->address = *address;
 | 
				
			||||||
 | 
					        strncpy(dns_cache[index]->host, host, 127);
 | 
				
			||||||
 | 
					        uint64_t ms_count = rtos::Kernel::get_ms_count();
 | 
				
			||||||
 | 
					        dns_cache[index]->expires = ms_count + ttl * 1000;
 | 
				
			||||||
 | 
					        dns_cache[index]->accessed = ms_count;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dns_cache_mutex.unlock();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static nsapi_error_t nsapi_dns_cache_find(const char *host, nsapi_version_t version, SocketAddress *address)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    nsapi_error_t ret_val = NSAPI_ERROR_NO_ADDRESS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dns_cache_mutex.lock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (int i = 0; i < DNS_CACHE_SIZE; i++) {
 | 
				
			||||||
 | 
					        if (dns_cache[i]) {
 | 
				
			||||||
 | 
					            uint64_t ms_count = rtos::Kernel::get_ms_count();
 | 
				
			||||||
 | 
					            // Checks all entries for expired entries
 | 
				
			||||||
 | 
					            if (ms_count > dns_cache[i]->expires) {
 | 
				
			||||||
 | 
					                delete dns_cache[i];
 | 
				
			||||||
 | 
					                dns_cache[i] = NULL;
 | 
				
			||||||
 | 
					            } else if (((version == NSAPI_UNSPEC) || (version == dns_cache[i]->address.get_ip_version())) &&
 | 
				
			||||||
 | 
					                (strncmp(dns_cache[i]->host, host, 127) == 0)) {
 | 
				
			||||||
 | 
					                if (address) {
 | 
				
			||||||
 | 
					                    *address = dns_cache[i]->address;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                dns_cache[i]->accessed = ms_count;
 | 
				
			||||||
 | 
					                ret_val = NSAPI_ERROR_OK;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dns_cache_mutex.unlock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return ret_val;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static nsapi_error_t nsapi_dns_get_server_addr(NetworkStack *stack, int *index, SocketAddress *dns_addr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    bool dns_addr_set = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (*index >= DNS_SERVERS_SIZE + DNS_STACK_SERVERS_NUM) {
 | 
				
			||||||
 | 
					        return NSAPI_ERROR_NO_ADDRESS;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (*index < DNS_STACK_SERVERS_NUM) {
 | 
				
			||||||
 | 
					        nsapi_error_t ret = stack->get_dns_server(*index, dns_addr);
 | 
				
			||||||
 | 
					        if (ret < 0) {
 | 
				
			||||||
 | 
					            *index = DNS_STACK_SERVERS_NUM;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            dns_addr_set = true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!dns_addr_set) {
 | 
				
			||||||
 | 
					        dns_addr->set_addr(dns_servers[*index - DNS_STACK_SERVERS_NUM]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dns_addr->set_port(53);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return NSAPI_ERROR_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// core query function
 | 
					// core query function
 | 
				
			||||||
static nsapi_size_or_error_t nsapi_dns_query_multiple(NetworkStack *stack, const char *host,
 | 
					static nsapi_size_or_error_t nsapi_dns_query_multiple(NetworkStack *stack, const char *host,
 | 
				
			||||||
        nsapi_addr_t *addr, unsigned addr_count, nsapi_version_t version)
 | 
					        nsapi_addr_t *addr, unsigned addr_count, nsapi_version_t version)
 | 
				
			||||||
| 
						 | 
					@ -204,6 +386,13 @@ static nsapi_size_or_error_t nsapi_dns_query_multiple(NetworkStack *stack, const
 | 
				
			||||||
        return NSAPI_ERROR_PARAMETER;
 | 
					        return NSAPI_ERROR_PARAMETER;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // check cache
 | 
				
			||||||
 | 
					    SocketAddress address;
 | 
				
			||||||
 | 
					    if (nsapi_dns_cache_find(host, version, &address) == NSAPI_ERROR_OK) {
 | 
				
			||||||
 | 
					        *addr = address.get_addr();
 | 
				
			||||||
 | 
					        return 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // create a udp socket
 | 
					    // create a udp socket
 | 
				
			||||||
    UDPSocket socket;
 | 
					    UDPSocket socket;
 | 
				
			||||||
    int err = socket.open(stack);
 | 
					    int err = socket.open(stack);
 | 
				
			||||||
| 
						 | 
					@ -221,21 +410,41 @@ static nsapi_size_or_error_t nsapi_dns_query_multiple(NetworkStack *stack, const
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    nsapi_size_or_error_t result = NSAPI_ERROR_DNS_FAILURE;
 | 
					    nsapi_size_or_error_t result = NSAPI_ERROR_DNS_FAILURE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // check against each dns server
 | 
					    bool retry = false;
 | 
				
			||||||
    for (unsigned i = 0; i < DNS_SERVERS_SIZE; i++) {
 | 
					 | 
				
			||||||
        // send the question
 | 
					 | 
				
			||||||
        uint8_t *question = packet;
 | 
					 | 
				
			||||||
        dns_append_question(&question, host, version);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        err = socket.sendto(SocketAddress(dns_servers[i], 53), packet, question - packet);
 | 
					    int index = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // check against each dns server
 | 
				
			||||||
 | 
					    while (true) {
 | 
				
			||||||
 | 
					        SocketAddress dns_addr;
 | 
				
			||||||
 | 
					        err = nsapi_dns_get_server_addr(stack, &index, &dns_addr);
 | 
				
			||||||
 | 
					        if (err != NSAPI_ERROR_OK) {
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // send the question
 | 
				
			||||||
 | 
					        int len = dns_append_question(packet, 1, host, version);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        err = socket.sendto(dns_addr, packet, len);
 | 
				
			||||||
        // send may fail for various reasons, including wrong address type - move on
 | 
					        // send may fail for various reasons, including wrong address type - move on
 | 
				
			||||||
        if (err < 0) {
 | 
					        if (err < 0) {
 | 
				
			||||||
 | 
					            // goes to next dns server
 | 
				
			||||||
 | 
					            retry = false;
 | 
				
			||||||
 | 
					            index++;
 | 
				
			||||||
            continue;
 | 
					            continue;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // recv the response
 | 
					        // recv the response
 | 
				
			||||||
        err = socket.recvfrom(NULL, packet, DNS_BUFFER_SIZE);
 | 
					        err = socket.recvfrom(NULL, packet, DNS_BUFFER_SIZE);
 | 
				
			||||||
        if (err == NSAPI_ERROR_WOULD_BLOCK) {
 | 
					        if (err == NSAPI_ERROR_WOULD_BLOCK) {
 | 
				
			||||||
 | 
					            if (!retry) {
 | 
				
			||||||
 | 
					                // retries once
 | 
				
			||||||
 | 
					                retry = true;
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                // goes to next dns server
 | 
				
			||||||
 | 
					                retry = false;
 | 
				
			||||||
 | 
					                index++;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            continue;
 | 
					            continue;
 | 
				
			||||||
        } else if (err < 0) {
 | 
					        } else if (err < 0) {
 | 
				
			||||||
            result = err;
 | 
					            result = err;
 | 
				
			||||||
| 
						 | 
					@ -243,8 +452,13 @@ static nsapi_size_or_error_t nsapi_dns_query_multiple(NetworkStack *stack, const
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const uint8_t *response = packet;
 | 
					        const uint8_t *response = packet;
 | 
				
			||||||
        int count = dns_scan_response(&response, addr, addr_count);
 | 
					        uint32_t ttl;
 | 
				
			||||||
 | 
					        int count = dns_scan_response(response, 1, &ttl, addr, addr_count);
 | 
				
			||||||
        if (count > 0) {
 | 
					        if (count > 0) {
 | 
				
			||||||
 | 
					            // Adds address to cache
 | 
				
			||||||
 | 
					            SocketAddress address(*addr);
 | 
				
			||||||
 | 
					            nsapi_dns_cache_add(host, &address, ttl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            result = count;
 | 
					            result = count;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -305,3 +519,337 @@ nsapi_error_t nsapi_dns_query(NetworkStack *stack, const char *host,
 | 
				
			||||||
    address->set_addr(addr);
 | 
					    address->set_addr(addr);
 | 
				
			||||||
    return (nsapi_error_t)((result > 0) ? 0 : result);
 | 
					    return (nsapi_error_t)((result > 0) ? 0 : result);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					nsapi_error_t nsapi_dns_query_async(NetworkStack *stack, const char *host,
 | 
				
			||||||
 | 
					        NetworkStack::hostbyname_cb_t callback, void *data, nsapi_version_t version)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    nsapi_size_or_error_t result = nsapi_dns_query_multiple_async(stack, host, callback, data, 1, version);
 | 
				
			||||||
 | 
					    return (nsapi_error_t)((result > 0) ? 0 : result);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static nsapi_error_t nsapi_dns_call_default(mbed::Callback<void()> func)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    events::EventQueue *event_queue = mbed::mbed_event_queue();
 | 
				
			||||||
 | 
					    if (!event_queue) {
 | 
				
			||||||
 | 
					        return NSAPI_ERROR_NO_MEMORY;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (event_queue->call(func) == 0) {
 | 
				
			||||||
 | 
					        return NSAPI_ERROR_NO_MEMORY;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return NSAPI_ERROR_OK ;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static nsapi_error_t nsapi_dns_call_in_default(int delay, mbed::Callback<void()> func)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    events::EventQueue *event_queue = mbed::mbed_event_queue();
 | 
				
			||||||
 | 
					    if (!event_queue) {
 | 
				
			||||||
 | 
					        return NSAPI_ERROR_NO_MEMORY;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (event_queue->call_in(delay, func) == 0) {
 | 
				
			||||||
 | 
					        return NSAPI_ERROR_NO_MEMORY;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return NSAPI_ERROR_OK ;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void nsapi_dns_call_set(nsapi_dns_call_t callback)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    dns_call = callback;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void nsapi_dns_call_in_set(nsapi_dns_call_in_t callback)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    dns_call_in = callback;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static nsapi_error_t nsapi_dns_call(NetworkStack *stack, mbed::Callback<void()> func)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (stack->onboardNetworkStack()) {
 | 
				
			||||||
 | 
					        OnboardNetworkStack *onboard_stack = reinterpret_cast<OnboardNetworkStack *>(stack);
 | 
				
			||||||
 | 
					        return onboard_stack->call(func);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        dns_call(func);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return NSAPI_ERROR_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static nsapi_error_t nsapi_dns_call_in(NetworkStack *stack, int delay, mbed::Callback<void()> func)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (stack->onboardNetworkStack()) {
 | 
				
			||||||
 | 
					        OnboardNetworkStack *onboard_stack = reinterpret_cast<OnboardNetworkStack *>(stack);
 | 
				
			||||||
 | 
					        return onboard_stack->call_in(delay, func);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        dns_call_in(delay, func);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return NSAPI_ERROR_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					nsapi_error_t nsapi_dns_query_multiple_async(NetworkStack *stack, const char *host,
 | 
				
			||||||
 | 
					    NetworkStack::hostbyname_cb_t callback, void *data, nsapi_size_t addr_count, nsapi_version_t version)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (!stack) {
 | 
				
			||||||
 | 
					        return NSAPI_ERROR_PARAMETER;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // check for valid host name
 | 
				
			||||||
 | 
					    int host_len = host ? strlen(host) : 0;
 | 
				
			||||||
 | 
					    if (host_len > 128 || host_len == 0) {
 | 
				
			||||||
 | 
					        return NSAPI_ERROR_PARAMETER;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    DNS_QUERY *query = new DNS_QUERY;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!query) {
 | 
				
			||||||
 | 
					        return NSAPI_ERROR_NO_MEMORY;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    query->unique_id = 0;
 | 
				
			||||||
 | 
					    strcpy(query->host, host);
 | 
				
			||||||
 | 
					    query->callback = callback;
 | 
				
			||||||
 | 
					    query->cb_data = data;
 | 
				
			||||||
 | 
					    query->stack = stack;
 | 
				
			||||||
 | 
					    query->addr_count = addr_count;
 | 
				
			||||||
 | 
					    query->version = version;
 | 
				
			||||||
 | 
					    query->socket = NULL;
 | 
				
			||||||
 | 
					    query->dns_server = 0;
 | 
				
			||||||
 | 
					    query->retries = 2;
 | 
				
			||||||
 | 
					    query->dns_message_id = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (nsapi_dns_call(stack, mbed::callback(nsapi_dns_query_async_create, query)) != NSAPI_ERROR_OK) {
 | 
				
			||||||
 | 
					        delete query;
 | 
				
			||||||
 | 
					        return NSAPI_ERROR_NO_MEMORY;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return NSAPI_ERROR_IN_PROGRESS ;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void nsapi_dns_query_async_create(DNS_QUERY *query)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    SocketAddress address;
 | 
				
			||||||
 | 
					    if (nsapi_dns_cache_find(query->host, query->version, &address) == NSAPI_ERROR_OK) {
 | 
				
			||||||
 | 
					        nsapi_dns_query_async_resp(query, NSAPI_ERROR_OK, &address);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int index = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (int i = 0; i < DNS_QUERY_QUEUE_SIZE; i++) {
 | 
				
			||||||
 | 
					        if (dns_query_queue[i]) {
 | 
				
			||||||
 | 
					            if (dns_query_queue[i]->stack == query->stack) {
 | 
				
			||||||
 | 
					                query->socket = dns_query_queue[i]->socket;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else if (index < 0) {
 | 
				
			||||||
 | 
					            index = i;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (index < 0) {
 | 
				
			||||||
 | 
					        nsapi_dns_query_async_resp(query, NSAPI_ERROR_NO_MEMORY, NULL);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    UDPSocket *socket;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (query->socket) {
 | 
				
			||||||
 | 
					        socket = query->socket;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        socket = new UDPSocket;
 | 
				
			||||||
 | 
					        if (!socket) {
 | 
				
			||||||
 | 
					            nsapi_dns_query_async_resp(query, NSAPI_ERROR_NO_MEMORY, NULL);
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        int err = socket->open(query->stack);
 | 
				
			||||||
 | 
					        if (err) {
 | 
				
			||||||
 | 
					            delete socket;
 | 
				
			||||||
 | 
					            nsapi_dns_query_async_resp(query, err, NULL);
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        socket->set_timeout(0);
 | 
				
			||||||
 | 
					        socket->sigio(mbed::callback(nsapi_dns_query_async_socket_callback, query->stack));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        query->socket = socket;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    query->unique_id = dns_unique_id++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dns_query_queue[index] = query;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    nsapi_dns_query_async_send(reinterpret_cast<void *>(query->unique_id));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void nsapi_dns_query_async_delete(DNS_QUERY *query)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int index = -1;
 | 
				
			||||||
 | 
					    bool close_socket = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (int i = 0; i < DNS_QUERY_QUEUE_SIZE; i++) {
 | 
				
			||||||
 | 
					        if (dns_query_queue[i]) {
 | 
				
			||||||
 | 
					            if (dns_query_queue[i] == query) {
 | 
				
			||||||
 | 
					                index = i;
 | 
				
			||||||
 | 
					            } else if (dns_query_queue[i]->stack == query->stack) {
 | 
				
			||||||
 | 
					                close_socket = false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (index < 0) {
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (close_socket) {
 | 
				
			||||||
 | 
					        query->socket->close();
 | 
				
			||||||
 | 
					        delete query->socket;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dns_query_queue[index] = NULL;
 | 
				
			||||||
 | 
					    delete query;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void nsapi_dns_query_async_resp(DNS_QUERY *query, nsapi_error_t status, SocketAddress *address)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    query->callback(status, address, query->cb_data);
 | 
				
			||||||
 | 
					    nsapi_dns_query_async_delete(query);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void nsapi_dns_query_async_send(void *ptr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int unique_id = reinterpret_cast<int>(ptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    DNS_QUERY *query = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (int i = 0; i < DNS_QUERY_QUEUE_SIZE; i++) {
 | 
				
			||||||
 | 
					        if (dns_query_queue[i] && dns_query_queue[i]->unique_id == unique_id) {
 | 
				
			||||||
 | 
					            query = dns_query_queue[i];
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!query) {
 | 
				
			||||||
 | 
					        nsapi_dns_query_async_resp(query, NSAPI_ERROR_NO_MEMORY, NULL);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (query->retries) {
 | 
				
			||||||
 | 
					        query->retries--;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        query->dns_server++;
 | 
				
			||||||
 | 
					        query->retries = 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    query->dns_message_id = dns_message_id++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // create network packet
 | 
				
			||||||
 | 
					    uint8_t *packet = (uint8_t *)malloc(DNS_BUFFER_SIZE);
 | 
				
			||||||
 | 
					    if (!packet) {
 | 
				
			||||||
 | 
					        nsapi_dns_query_async_resp(query, NSAPI_ERROR_NO_MEMORY, NULL);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // send the question
 | 
				
			||||||
 | 
					    int len = dns_append_question(packet, query->dns_message_id, query->host, query->version);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    while (true) {
 | 
				
			||||||
 | 
					        SocketAddress dns_addr;
 | 
				
			||||||
 | 
					        nsapi_size_or_error_t err = nsapi_dns_get_server_addr(query->stack, &(query->dns_server), &dns_addr);
 | 
				
			||||||
 | 
					        if (err != NSAPI_ERROR_OK) {
 | 
				
			||||||
 | 
					            nsapi_dns_query_async_resp(query, NSAPI_ERROR_DNS_FAILURE, NULL);
 | 
				
			||||||
 | 
					            free(packet);
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        err = query->socket->sendto(dns_addr, packet, len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (err < 0) {
 | 
				
			||||||
 | 
					            query->dns_server++;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    free(packet);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (nsapi_dns_call_in(query->stack, DNS_TIMEOUT,
 | 
				
			||||||
 | 
					        mbed::callback(nsapi_dns_query_async_send, reinterpret_cast<void *>(unique_id))) != NSAPI_ERROR_OK) {
 | 
				
			||||||
 | 
					        nsapi_dns_query_async_resp(query, NSAPI_ERROR_NO_MEMORY, NULL);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void nsapi_dns_query_async_socket_callback(NetworkStack *stack)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    nsapi_dns_call(stack, mbed::callback(nsapi_dns_query_async_socket_callback_handle, stack));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void nsapi_dns_query_async_socket_callback_handle(NetworkStack *stack)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    UDPSocket *socket = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (int i = 0; i < DNS_QUERY_QUEUE_SIZE; i++) {
 | 
				
			||||||
 | 
					        if (dns_query_queue[i] && dns_query_queue[i]->stack == stack) {
 | 
				
			||||||
 | 
					            socket = dns_query_queue[i]->socket;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (socket) {
 | 
				
			||||||
 | 
					        // create network packet
 | 
				
			||||||
 | 
					        uint8_t *packet = (uint8_t *)malloc(DNS_BUFFER_SIZE);
 | 
				
			||||||
 | 
					        if (!packet) {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // recv the response
 | 
				
			||||||
 | 
					        nsapi_size_or_error_t size = socket->recvfrom(NULL, packet, DNS_BUFFER_SIZE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (size < DNS_RESPONSE_MIN_SIZE) {
 | 
				
			||||||
 | 
					            free(packet);
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // gets id from response to associate with correct query
 | 
				
			||||||
 | 
					        uint16_t id = (*packet << 8) | *(packet + 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        DNS_QUERY *query = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (int i = 0; i < DNS_QUERY_QUEUE_SIZE; i++) {
 | 
				
			||||||
 | 
					            if (dns_query_queue[i] && dns_query_queue[i]->dns_message_id == id) {
 | 
				
			||||||
 | 
					                query = dns_query_queue[i];
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!query) {
 | 
				
			||||||
 | 
					            free(packet);
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        nsapi_addr_t *addrs = new nsapi_addr_t[query->addr_count];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        uint32_t ttl;
 | 
				
			||||||
 | 
					        int count = dns_scan_response((const uint8_t *) packet, id, &ttl, addrs, query->addr_count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        free(packet);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (count > 0) {
 | 
				
			||||||
 | 
					            SocketAddress *addresses = new SocketAddress[count];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for (int i = 0; i < count; i++) {
 | 
				
			||||||
 | 
					                addresses[i].set_addr(addrs[i]);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Adds address to cache
 | 
				
			||||||
 | 
					            nsapi_dns_cache_add(query->host, addresses, ttl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            nsapi_dns_query_async_resp(query, NSAPI_ERROR_OK, addresses);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            delete[] addresses;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            nsapi_dns_query_async_resp(query, NSAPI_ERROR_DNS_FAILURE, NULL);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        delete[] addrs;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -77,6 +77,19 @@ nsapi_error_t nsapi_dns_query(NetworkStack *stack, const char *host,
 | 
				
			||||||
        SocketAddress *addr, nsapi_version_t version = NSAPI_IPv4);
 | 
					        SocketAddress *addr, nsapi_version_t version = NSAPI_IPv4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Query a domain name server for an IP address of a given hostname
 | 
					/** Query a domain name server for an IP address of a given hostname
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  @param stack    Network stack as target for DNS query
 | 
				
			||||||
 | 
					 *  @param host     Hostname to resolve
 | 
				
			||||||
 | 
					 *  @param callback Callback that is called for result*
 | 
				
			||||||
 | 
					 *  @param data     Caller defined data returned in callback
 | 
				
			||||||
 | 
					 *  @param version  IP version to resolve (defaults to NSAPI_IPv4)
 | 
				
			||||||
 | 
					 *  @return         0 on success, negative error code on failure
 | 
				
			||||||
 | 
					 *                  NSAPI_ERROR_DNS_FAILURE indicates the host could not be found
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					nsapi_error_t nsapi_dns_query_async(NetworkStack *stack, const char *host,
 | 
				
			||||||
 | 
					        NetworkStack::hostbyname_cb_t callback, void *data, nsapi_version_t version = NSAPI_IPv4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Query a domain name server for an IP address of a given hostname (asynchronous)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *  @param stack    Network stack as target for DNS query
 | 
					 *  @param stack    Network stack as target for DNS query
 | 
				
			||||||
 *  @param host     Hostname to resolve
 | 
					 *  @param host     Hostname to resolve
 | 
				
			||||||
| 
						 | 
					@ -117,6 +130,20 @@ nsapi_error_t nsapi_dns_query(S *stack, const char *host,
 | 
				
			||||||
nsapi_size_or_error_t nsapi_dns_query_multiple(NetworkStack *stack, const char *host,
 | 
					nsapi_size_or_error_t nsapi_dns_query_multiple(NetworkStack *stack, const char *host,
 | 
				
			||||||
        SocketAddress *addr, nsapi_size_t addr_count, nsapi_version_t version = NSAPI_IPv4);
 | 
					        SocketAddress *addr, nsapi_size_t addr_count, nsapi_version_t version = NSAPI_IPv4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Query a domain name server for an IP address of a given hostname (asynchronous)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  @param stack      Network stack as target for DNS query
 | 
				
			||||||
 | 
					 *  @param host       Hostname to resolve
 | 
				
			||||||
 | 
					 *  @param callback   Callback that is called for result
 | 
				
			||||||
 | 
					 *  @param data       Caller defined data returned in callback
 | 
				
			||||||
 | 
					 *  @param addr_count Number of addresses allocated in the array
 | 
				
			||||||
 | 
					 *  @param version    IP version to resolve (defaults to NSAPI_IPv4)
 | 
				
			||||||
 | 
					 *  @return           0 on success, negative error code on failure
 | 
				
			||||||
 | 
					 *                    NSAPI_ERROR_DNS_FAILURE indicates the host could not be found
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					nsapi_size_or_error_t nsapi_dns_query_multiple_async(NetworkStack *stack, const char *host,
 | 
				
			||||||
 | 
					        NetworkStack::hostbyname_cb_t callback, void *data, nsapi_size_t addr_count, nsapi_version_t version = NSAPI_IPv4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Query a domain name server for multiple IP address of a given hostname
 | 
					/** Query a domain name server for multiple IP address of a given hostname
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *  @param stack      Network stack as target for DNS query
 | 
					 *  @param stack      Network stack as target for DNS query
 | 
				
			||||||
| 
						 | 
					@ -130,6 +157,7 @@ nsapi_size_or_error_t nsapi_dns_query_multiple(NetworkStack *stack, const char *
 | 
				
			||||||
extern "C" nsapi_size_or_error_t nsapi_dns_query_multiple(nsapi_stack_t *stack, const char *host,
 | 
					extern "C" nsapi_size_or_error_t nsapi_dns_query_multiple(nsapi_stack_t *stack, const char *host,
 | 
				
			||||||
        nsapi_addr_t *addr, nsapi_size_t addr_count, nsapi_version_t version = NSAPI_IPv4);
 | 
					        nsapi_addr_t *addr, nsapi_size_t addr_count, nsapi_version_t version = NSAPI_IPv4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Query a domain name server for multiple IP address of a given hostname
 | 
					/** Query a domain name server for multiple IP address of a given hostname
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *  @param stack      Network stack as target for DNS query
 | 
					 *  @param stack      Network stack as target for DNS query
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue