mirror of https://github.com/ARMmbed/mbed-os.git
				
				
				
			Corrected defects
- Changed call_in/call methods of the stack to callback provided by the stack - Specified what are limitations for operations that are made in callback - Added pure virtual class DNS that defines DNS operations - Added cancel operation and unique ID to DNS request used in cancel - Added DNS configuration options to netsocket/mbed_lib.json for retries, response wait time and cache size - Changed host name to use dynamic memory in DNS query list and cache, set maximum length for the name to 255 bytes. - Added mutex to asynchronous DNS - Reworked retries: there is now total retry count and a server specific count - Ignores invalid incoming UDP socket messages (DNS header is not valid), and retries DNS query - Reworked DNS module asynchronous operation functions - Corrected other review issues (nothrow new, missing free, missing mutex unlock etc.)pull/6847/head
							parent
							
								
									b7e8400c2c
								
							
						
					
					
						commit
						1c01f5dda4
					
				| 
						 | 
					@ -207,11 +207,6 @@ void LWIP::tcpip_thread_callback(void *ptr)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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)
 | 
					nsapi_error_t LWIP::call_in(int delay, mbed::Callback<void()> func)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    lwip_callback *cb = new lwip_callback;
 | 
					    lwip_callback *cb = new lwip_callback;
 | 
				
			||||||
| 
						 | 
					@ -229,6 +224,12 @@ nsapi_error_t LWIP::call_in(int delay, mbed::Callback<void()> func)
 | 
				
			||||||
    return NSAPI_ERROR_OK;
 | 
					    return NSAPI_ERROR_OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					LWIP::call_in_callback_cb_t LWIP::get_call_in_callback()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    call_in_callback_cb_t cb(this, &LWIP::call_in);
 | 
				
			||||||
 | 
					    return cb;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const char *LWIP::get_ip_address()
 | 
					const char *LWIP::get_ip_address()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (!default_interface) {
 | 
					    if (!default_interface) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -209,27 +209,6 @@ public:
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    virtual nsapi_error_t get_dns_server(int index, 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
 | 
					    /** Get the local IP address
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     *  @return         Null-terminated representation of the local IP address
 | 
					     *  @return         Null-terminated representation of the local IP address
 | 
				
			||||||
| 
						 | 
					@ -438,6 +417,37 @@ protected:
 | 
				
			||||||
                                     int optname, void *optval, unsigned *optlen);
 | 
					                                     int optname, void *optval, unsigned *optlen);
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Call in callback
 | 
				
			||||||
 | 
					      *
 | 
				
			||||||
 | 
					      *  Callback is used to call the call in method of the network stack.
 | 
				
			||||||
 | 
					      */
 | 
				
			||||||
 | 
					    typedef mbed::Callback<nsapi_error_t (int delay_ms, mbed::Callback<void()> user_cb)> call_in_callback_cb_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Get a call in callback
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  Get a call in callback from the network stack context.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  Callback should not take more than 10ms to execute, otherwise it might
 | 
				
			||||||
 | 
					     *  prevent underlying thread processing. A portable user of the callback
 | 
				
			||||||
 | 
					     *  should not make calls to network operations due to stack size limitations.
 | 
				
			||||||
 | 
					     *  The callback should not perform expensive operations such as socket recv/send
 | 
				
			||||||
 | 
					     *  calls or blocking operations.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  @return         Call in callback
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    virtual call_in_callback_cb_t get_call_in_callback();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Call a callback after a delay
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  Call a callback from the network stack context after a delay. If function
 | 
				
			||||||
 | 
					     *  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
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    nsapi_error_t call_in(int delay, mbed::Callback<void()> func);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    struct mbed_lwip_socket {
 | 
					    struct mbed_lwip_socket {
 | 
				
			||||||
        bool in_use;
 | 
					        bool in_use;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -482,20 +482,14 @@ void sys_msleep(u32_t ms) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
osThreadId_t lwip_tcpip_thread_id = 0;
 | 
					osThreadId_t lwip_tcpip_thread_id = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool sys_tcpip_thread_set(void)
 | 
					void sys_tcpip_thread_set(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    lwip_tcpip_thread_id = osThreadGetId();
 | 
					    lwip_tcpip_thread_id = osThreadGetId();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool sys_tcpip_thread_check(void)
 | 
					bool sys_tcpip_thread_check(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    osThreadId_t thread_id = osThreadGetId();
 | 
					    return osThreadGetId() == lwip_tcpip_thread_id;
 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (thread_id == lwip_tcpip_thread_id) {
 | 
					 | 
				
			||||||
        return true;
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        return false;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Keep a pool of thread structures
 | 
					// Keep a pool of thread structures
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -85,7 +85,7 @@ 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);
 | 
					void sys_tcpip_thread_set(void);
 | 
				
			||||||
bool sys_tcpip_thread_check(void);
 | 
					bool sys_tcpip_thread_check(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -910,6 +910,8 @@ netconn_join_leave_group(struct netconn *conn,
 | 
				
			||||||
#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */
 | 
					#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if LWIP_DNS
 | 
					#if LWIP_DNS
 | 
				
			||||||
 | 
					#if LWIP_FULL_DNS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @ingroup netconn_common
 | 
					 * @ingroup netconn_common
 | 
				
			||||||
 * Execute a DNS query, only one IP address is returned
 | 
					 * Execute a DNS query, only one IP address is returned
 | 
				
			||||||
| 
						 | 
					@ -989,6 +991,8 @@ netconn_gethostbyname(const char *name, ip_addr_t *addr)
 | 
				
			||||||
  API_VAR_FREE(MEMP_DNS_API_MSG, msg);
 | 
					  API_VAR_FREE(MEMP_DNS_API_MSG, msg);
 | 
				
			||||||
  return err;
 | 
					  return err;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* LWIP_FULL_DNS */
 | 
				
			||||||
#endif /* LWIP_DNS*/
 | 
					#endif /* LWIP_DNS*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if LWIP_NETCONN_SEM_PER_THREAD
 | 
					#if LWIP_NETCONN_SEM_PER_THREAD
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1892,6 +1892,7 @@ lwip_netconn_do_join_leave_group(void *m)
 | 
				
			||||||
#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */
 | 
					#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if LWIP_DNS
 | 
					#if LWIP_DNS
 | 
				
			||||||
 | 
					#if LWIP_FULL_DNS
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Callback function that is called when DNS name is resolved
 | 
					 * Callback function that is called when DNS name is resolved
 | 
				
			||||||
 * (or on timeout). A waiting application thread is waked up by
 | 
					 * (or on timeout). A waiting application thread is waked up by
 | 
				
			||||||
| 
						 | 
					@ -1943,5 +1944,6 @@ lwip_netconn_do_gethostbyname(void *arg)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif /* LWIP_DNS */
 | 
					#endif /* LWIP_DNS */
 | 
				
			||||||
 | 
					#endif /* LWIP_FULL_DNS */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* LWIP_NETCONN */
 | 
					#endif /* LWIP_NETCONN */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -461,11 +461,6 @@ void Nanostack::call_event_tasklet_main(arm_event_s *event)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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)
 | 
					nsapi_error_t Nanostack::call_in(int delay, mbed::Callback<void()> func)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (call_event_tasklet < 0) {
 | 
					    if (call_event_tasklet < 0) {
 | 
				
			||||||
| 
						 | 
					@ -494,10 +489,12 @@ nsapi_error_t Nanostack::call_in(int delay, mbed::Callback<void()> func)
 | 
				
			||||||
    if (delay) {
 | 
					    if (delay) {
 | 
				
			||||||
        uint32_t ticks = eventOS_event_timer_ms_to_ticks(delay);
 | 
					        uint32_t ticks = eventOS_event_timer_ms_to_ticks(delay);
 | 
				
			||||||
        if (!eventOS_event_send_in(&event, ticks)) {
 | 
					        if (!eventOS_event_send_in(&event, ticks)) {
 | 
				
			||||||
 | 
					            delete cb;
 | 
				
			||||||
            return NSAPI_ERROR_NO_MEMORY;
 | 
					            return NSAPI_ERROR_NO_MEMORY;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        if (eventOS_event_send(&event) < 0) {
 | 
					        if (eventOS_event_send(&event) < 0) {
 | 
				
			||||||
 | 
					            delete cb;
 | 
				
			||||||
            return NSAPI_ERROR_NO_MEMORY;
 | 
					            return NSAPI_ERROR_NO_MEMORY;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -505,6 +502,12 @@ nsapi_error_t Nanostack::call_in(int delay, mbed::Callback<void()> func)
 | 
				
			||||||
    return NSAPI_ERROR_OK;
 | 
					    return NSAPI_ERROR_OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Nanostack::call_in_callback_cb_t Nanostack::get_call_in_callback()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    call_in_callback_cb_t cb(this, &Nanostack::call_in);
 | 
				
			||||||
 | 
					    return cb;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const char * Nanostack::get_ip_address()
 | 
					const char * Nanostack::get_ip_address()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    NanostackLockGuard lock;
 | 
					    NanostackLockGuard lock;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -44,27 +44,6 @@ 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();
 | 
					    Nanostack();
 | 
				
			||||||
| 
						 | 
					@ -266,6 +245,38 @@ 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:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Call in callback
 | 
				
			||||||
 | 
					      *
 | 
				
			||||||
 | 
					      *  Callback is used to call the call in method of the network stack.
 | 
				
			||||||
 | 
					      */
 | 
				
			||||||
 | 
					    typedef mbed::Callback<nsapi_error_t (int delay_ms, mbed::Callback<void()> user_cb)> call_in_callback_cb_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Get a call in callback
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  Get a call in callback from the network stack context.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  Callback should not take more than 10ms to execute, otherwise it might
 | 
				
			||||||
 | 
					     *  prevent underlying thread processing. A portable user of the callback
 | 
				
			||||||
 | 
					     *  should not make calls to network operations due to stack size limitations.
 | 
				
			||||||
 | 
					     *  The callback should not perform expensive operations such as socket recv/send
 | 
				
			||||||
 | 
					     *  calls or blocking operations.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  @return         Call in callback
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    virtual call_in_callback_cb_t get_call_in_callback();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Call a callback after a delay
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  Call a callback from the network stack context after a delay. If function
 | 
				
			||||||
 | 
					     *  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
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    nsapi_error_t call_in(int delay, mbed::Callback<void()> func);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    struct nanostack_callback {
 | 
					    struct nanostack_callback {
 | 
				
			||||||
        mbed::Callback<void()> callback;
 | 
					        mbed::Callback<void()> callback;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,96 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2018 ARM Limited
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					 * you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					 * You may obtain a copy of the License at
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					 * See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					 * limitations under the License.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef DNS_H
 | 
				
			||||||
 | 
					#define DNS_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DNS {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Translates a hostname to an IP address with specific version
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  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.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  @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) = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Hostname translation callback (asynchronous)
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  Callback will be called after DNS resolution completes or a failure occurs.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  Callback should not take more than 10ms to execute, otherwise it might
 | 
				
			||||||
 | 
					     *  prevent underlying thread processing. A portable user of the callback
 | 
				
			||||||
 | 
					     *  should not make calls to network operations due to stack size limitations.
 | 
				
			||||||
 | 
					     *  The callback should not perform expensive operations such as socket recv/send
 | 
				
			||||||
 | 
					     *  calls or blocking operations.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  @param status  0 on success, negative error code on failure
 | 
				
			||||||
 | 
					     *  @param address On success, destination for the host SocketAddress
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    typedef mbed::Callback<void (nsapi_error_t result, SocketAddress *address)> 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. In case result
 | 
				
			||||||
 | 
					     *  is success (IP address was found from DNS cache), callback will be called
 | 
				
			||||||
 | 
					     *  before function returns.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  @param host     Hostname to resolve
 | 
				
			||||||
 | 
					     *  @param callback Callback that is called for result
 | 
				
			||||||
 | 
					     *  @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 or an unique id that
 | 
				
			||||||
 | 
					     *                  represents the hostname translation operation and can be passed to
 | 
				
			||||||
 | 
					     *                  cancel
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    virtual nsapi_error_t gethostbyname_async(const char *host, hostbyname_cb_t callback,
 | 
				
			||||||
 | 
					            nsapi_version_t version = NSAPI_UNSPEC) = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Cancels asynchronous hostname translation
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  When translation is cancelled, callback will not be called.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  @param id       Unique id of the hostname translation operation
 | 
				
			||||||
 | 
					     *  @return         0 on success, negative error code on failure
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    virtual nsapi_error_t gethostbyname_async_cancel(nsapi_error_t id) = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Add a domain name server to list of servers to query
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  @param address  Destination for the host address
 | 
				
			||||||
 | 
					     *  @return         0 on success, negative error code on failure
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    virtual nsapi_error_t add_dns_server(const SocketAddress &address) = 0;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					@ -60,9 +60,14 @@ 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)
 | 
					nsapi_error_t NetworkInterface::gethostbyname_async(const char *host, hostbyname_cb_t callback, nsapi_version_t version)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return get_stack()->gethostbyname_async(host, callback, data, version);
 | 
					    return get_stack()->gethostbyname_async(host, callback, version);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					nsapi_error_t NetworkInterface::gethostbyname_async_cancel(nsapi_error_t handle)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return get_stack()->gethostbyname_async_cancel(handle);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
nsapi_error_t NetworkInterface::add_dns_server(const SocketAddress &address)
 | 
					nsapi_error_t NetworkInterface::add_dns_server(const SocketAddress &address)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,6 +20,8 @@
 | 
				
			||||||
#include "netsocket/nsapi_types.h"
 | 
					#include "netsocket/nsapi_types.h"
 | 
				
			||||||
#include "netsocket/SocketAddress.h"
 | 
					#include "netsocket/SocketAddress.h"
 | 
				
			||||||
#include "Callback.h"
 | 
					#include "Callback.h"
 | 
				
			||||||
 | 
					#include "DNS.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Predeclared classes
 | 
					// Predeclared classes
 | 
				
			||||||
class NetworkStack;
 | 
					class NetworkStack;
 | 
				
			||||||
| 
						 | 
					@ -34,7 +36,7 @@ class EMACInterface;
 | 
				
			||||||
 *  Common interface that is shared between network devices
 | 
					 *  Common interface that is shared between network devices
 | 
				
			||||||
 *  @addtogroup netsocket
 | 
					 *  @addtogroup netsocket
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
class NetworkInterface {
 | 
					class NetworkInterface: public DNS {
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -118,8 +120,8 @@ public:
 | 
				
			||||||
     *  If no stack-specific DNS resolution is provided, the hostname
 | 
					     *  If no stack-specific DNS resolution is provided, the hostname
 | 
				
			||||||
     *  will be resolve using a UDP socket on the stack.
 | 
					     *  will be resolve using a UDP socket on the stack.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     *  @param address  Destination for the host SocketAddress
 | 
					 | 
				
			||||||
     *  @param host     Hostname to resolve
 | 
					     *  @param host     Hostname to resolve
 | 
				
			||||||
 | 
					     *  @param address  Destination for the host SocketAddress
 | 
				
			||||||
     *  @param version  IP version of address to resolve, NSAPI_UNSPEC indicates
 | 
					     *  @param version  IP version of address to resolve, NSAPI_UNSPEC indicates
 | 
				
			||||||
     *                  version is chosen by the stack (defaults to NSAPI_UNSPEC)
 | 
					     *                  version is chosen by the stack (defaults to NSAPI_UNSPEC)
 | 
				
			||||||
     *  @return         0 on success, negative error code on failure
 | 
					     *  @return         0 on success, negative error code on failure
 | 
				
			||||||
| 
						 | 
					@ -129,14 +131,18 @@ public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** Hostname translation callback (asynchronous)
 | 
					    /** Hostname translation callback (asynchronous)
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     *  Callback will be called after DNS resolution completes or a failure
 | 
					     *  Callback will be called after DNS resolution completes or a failure occurs.
 | 
				
			||||||
     *  occurs.
 | 
					     *
 | 
				
			||||||
 | 
					     *  Callback should not take more than 10ms to execute, otherwise it might
 | 
				
			||||||
 | 
					     *  prevent underlying thread processing. A portable user of the callback
 | 
				
			||||||
 | 
					     *  should not make calls to network operations due to stack size limitations.
 | 
				
			||||||
 | 
					     *  The callback should not perform expensive operations such as socket recv/send
 | 
				
			||||||
 | 
					     *  calls or blocking operations.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     *  @param status  0 on success, negative error code on failure
 | 
					     *  @param status  0 on success, negative error code on failure
 | 
				
			||||||
     *  @param address On success, destination for the host SocketAddress
 | 
					     *  @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;
 | 
					    typedef mbed::Callback<void (nsapi_error_t result, SocketAddress *address)> hostbyname_cb_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** Translates a hostname to an IP address (asynchronous)
 | 
					    /** Translates a hostname to an IP address (asynchronous)
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
| 
						 | 
					@ -147,17 +153,29 @@ public:
 | 
				
			||||||
     *  will be resolve using a UDP socket on the stack.
 | 
					     *  will be resolve using a UDP socket on the stack.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     *  Call is non-blocking. Result of the DNS operation is returned by the callback.
 | 
					     *  Call is non-blocking. Result of the DNS operation is returned by the callback.
 | 
				
			||||||
     *  If this function returns failure, callback will not be called.
 | 
					     *  If this function returns failure, callback will not be called. In case result
 | 
				
			||||||
 | 
					     *  is success (IP address was found from DNS cache), callback will be called
 | 
				
			||||||
 | 
					     *  before function returns.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     *  @param host     Hostname to resolve
 | 
					     *  @param host     Hostname to resolve
 | 
				
			||||||
     *  @param callback Callback that is called for result
 | 
					     *  @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
 | 
					     *  @param version  IP version of address to resolve, NSAPI_UNSPEC indicates
 | 
				
			||||||
     *                  version is chosen by the stack (defaults to NSAPI_UNSPEC)
 | 
					     *                  version is chosen by the stack (defaults to NSAPI_UNSPEC)
 | 
				
			||||||
 | 
					     *  @return         0 on success, negative error code on failure or an unique id that
 | 
				
			||||||
 | 
					     *                  represents the hostname translation operation and can be passed to
 | 
				
			||||||
 | 
					     *                  cancel
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    virtual nsapi_error_t gethostbyname_async(const char *host, hostbyname_cb_t callback,
 | 
				
			||||||
 | 
					            nsapi_version_t version = NSAPI_UNSPEC);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Cancels asynchronous hostname translation
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  When translation is cancelled, callback will not be called.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  @param id       Unique id of the hostname translation operation
 | 
				
			||||||
     *  @return         0 on success, negative error code on failure
 | 
					     *  @return         0 on success, negative error code on failure
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    virtual nsapi_error_t gethostbyname_async(const char *host, hostbyname_cb_t callback, void *data,
 | 
					    virtual nsapi_error_t gethostbyname_async_cancel(nsapi_error_t id);
 | 
				
			||||||
            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
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -49,7 +49,7 @@ 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)
 | 
					nsapi_error_t NetworkStack::gethostbyname_async(const char *name, hostbyname_cb_t callback, nsapi_version_t version)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    SocketAddress address;
 | 
					    SocketAddress address;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -59,6 +59,7 @@ nsapi_error_t NetworkStack::gethostbyname_async(const char *name, hostbyname_cb_
 | 
				
			||||||
            return NSAPI_ERROR_DNS_FAILURE;
 | 
					            return NSAPI_ERROR_DNS_FAILURE;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        callback(NSAPI_ERROR_OK, &address);
 | 
				
			||||||
        return NSAPI_ERROR_OK;
 | 
					        return NSAPI_ERROR_OK;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -71,7 +72,14 @@ nsapi_error_t NetworkStack::gethostbyname_async(const char *name, hostbyname_cb_
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return nsapi_dns_query_async(this, name, callback, data, version);
 | 
					    call_in_callback_cb_t call_in_cb = get_call_in_callback();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return nsapi_dns_query_async(this, name, callback, call_in_cb, version);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					nsapi_error_t NetworkStack::gethostbyname_async_cancel(nsapi_error_t handle)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return nsapi_dns_query_async_cancel(handle);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
nsapi_error_t NetworkStack::add_dns_server(const SocketAddress &address)
 | 
					nsapi_error_t NetworkStack::add_dns_server(const SocketAddress &address)
 | 
				
			||||||
| 
						 | 
					@ -104,6 +112,39 @@ nsapi_error_t NetworkStack::getsockopt(void *handle, int level, int optname, voi
 | 
				
			||||||
    return NSAPI_ERROR_UNSUPPORTED;
 | 
					    return NSAPI_ERROR_UNSUPPORTED;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					nsapi_error_t NetworkStack::call_in(int delay, mbed::Callback<void()> func)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    events::EventQueue *event_queue = mbed::mbed_event_queue();
 | 
				
			||||||
 | 
					    if (!event_queue) {
 | 
				
			||||||
 | 
					        return NSAPI_ERROR_NO_MEMORY;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (delay > 0) {
 | 
				
			||||||
 | 
					        if (event_queue->call_in(delay, func) == 0) {
 | 
				
			||||||
 | 
					            return NSAPI_ERROR_NO_MEMORY;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        if (event_queue->call(func) == 0) {
 | 
				
			||||||
 | 
					            return NSAPI_ERROR_NO_MEMORY;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return NSAPI_ERROR_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef mbed::Callback<nsapi_error_t (int delay_ms, mbed::Callback<void()> user_cb)> call_in_callback_cb_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					call_in_callback_cb_t NetworkStack::get_call_in_callback()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    events::EventQueue *event_queue = mbed::mbed_event_queue();
 | 
				
			||||||
 | 
					    if (!event_queue) {
 | 
				
			||||||
 | 
					        return NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    call_in_callback_cb_t cb(this, &NetworkStack::call_in);
 | 
				
			||||||
 | 
					    return cb;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NetworkStackWrapper class for encapsulating the raw nsapi_stack structure
 | 
					// NetworkStackWrapper class for encapsulating the raw nsapi_stack structure
 | 
				
			||||||
class NetworkStackWrapper : public NetworkStack
 | 
					class NetworkStackWrapper : public NetworkStack
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,6 +21,7 @@
 | 
				
			||||||
#include "nsapi_types.h"
 | 
					#include "nsapi_types.h"
 | 
				
			||||||
#include "netsocket/SocketAddress.h"
 | 
					#include "netsocket/SocketAddress.h"
 | 
				
			||||||
#include "netsocket/NetworkInterface.h"
 | 
					#include "netsocket/NetworkInterface.h"
 | 
				
			||||||
 | 
					#include "DNS.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Predeclared classes
 | 
					// Predeclared classes
 | 
				
			||||||
class OnboardNetworkStack;
 | 
					class OnboardNetworkStack;
 | 
				
			||||||
| 
						 | 
					@ -33,7 +34,7 @@ class OnboardNetworkStack;
 | 
				
			||||||
 *  for instantiating network sockets.
 | 
					 *  for instantiating network sockets.
 | 
				
			||||||
 *  @addtogroup netsocket
 | 
					 *  @addtogroup netsocket
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
class NetworkStack
 | 
					class NetworkStack: public DNS
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
    virtual ~NetworkStack() {};
 | 
					    virtual ~NetworkStack() {};
 | 
				
			||||||
| 
						 | 
					@ -64,14 +65,18 @@ public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** Hostname translation callback (asynchronous)
 | 
					    /** Hostname translation callback (asynchronous)
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     *  Callback will be called after DNS resolution completes or a failure
 | 
					     *  Callback will be called after DNS resolution completes or a failure occurs.
 | 
				
			||||||
     *  occurs.
 | 
					     *
 | 
				
			||||||
 | 
					     *  Callback should not take more than 10ms to execute, otherwise it might
 | 
				
			||||||
 | 
					     *  prevent underlying thread processing. A portable user of the callback
 | 
				
			||||||
 | 
					     *  should not make calls to network operations due to stack size limitations.
 | 
				
			||||||
 | 
					     *  The callback should not perform expensive operations such as socket recv/send
 | 
				
			||||||
 | 
					     *  calls or blocking operations.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     *  @param status  0 on success, negative error code on failure
 | 
					     *  @param status  0 on success, negative error code on failure
 | 
				
			||||||
     *  @param address On success, destination for the host SocketAddress
 | 
					     *  @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;
 | 
					    typedef mbed::Callback<void (nsapi_error_t result, SocketAddress *address)> hostbyname_cb_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** Translates a hostname to an IP address (asynchronous)
 | 
					    /** Translates a hostname to an IP address (asynchronous)
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
| 
						 | 
					@ -82,17 +87,29 @@ public:
 | 
				
			||||||
     *  will be resolve using a UDP socket on the stack.
 | 
					     *  will be resolve using a UDP socket on the stack.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     *  Call is non-blocking. Result of the DNS operation is returned by the callback.
 | 
					     *  Call is non-blocking. Result of the DNS operation is returned by the callback.
 | 
				
			||||||
     *  If this function returns failure, callback will not be called.
 | 
					     *  If this function returns failure, callback will not be called. In case result
 | 
				
			||||||
 | 
					     *  is success (IP address was found from DNS cache), callback will be called
 | 
				
			||||||
 | 
					     *  before function returns.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     *  @param host     Hostname to resolve
 | 
					     *  @param host     Hostname to resolve
 | 
				
			||||||
     *  @param callback Callback that is called for result
 | 
					     *  @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
 | 
					     *  @param version  IP version of address to resolve, NSAPI_UNSPEC indicates
 | 
				
			||||||
     *                  version is chosen by the stack (defaults to NSAPI_UNSPEC)
 | 
					     *                  version is chosen by the stack (defaults to NSAPI_UNSPEC)
 | 
				
			||||||
 | 
					     *  @return         0 on success, negative error code on failure or an unique id that
 | 
				
			||||||
 | 
					     *                  represents the hostname translation operation and can be passed to
 | 
				
			||||||
 | 
					     *                  cancel
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    virtual nsapi_error_t gethostbyname_async(const char *host, hostbyname_cb_t callback,
 | 
				
			||||||
 | 
					            nsapi_version_t version = NSAPI_UNSPEC);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Cancels asynchronous hostname translation
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  When translation is cancelled, callback will not be called.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  @param id       Unique id of the hostname translation operation
 | 
				
			||||||
     *  @return         0 on success, negative error code on failure
 | 
					     *  @return         0 on success, negative error code on failure
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    virtual nsapi_error_t gethostbyname_async(const char *host, hostbyname_cb_t callback, void *data,
 | 
					    virtual nsapi_error_t gethostbyname_async_cancel(nsapi_error_t id);
 | 
				
			||||||
            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
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
| 
						 | 
					@ -347,8 +364,40 @@ protected:
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    virtual nsapi_error_t getsockopt(nsapi_socket_t handle, int level,
 | 
					    virtual nsapi_error_t getsockopt(nsapi_socket_t handle, int level,
 | 
				
			||||||
            int optname, void *optval, unsigned *optlen);
 | 
					            int optname, void *optval, unsigned *optlen);
 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Call in callback
 | 
				
			||||||
 | 
					      *
 | 
				
			||||||
 | 
					      *  Callback is used to call the call in method of the network stack.
 | 
				
			||||||
 | 
					      */
 | 
				
			||||||
 | 
					    typedef mbed::Callback<nsapi_error_t (int delay_ms, mbed::Callback<void()> user_cb)> call_in_callback_cb_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Get a call in callback
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  Get a call in callback from the network stack context.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  Callback should not take more than 10ms to execute, otherwise it might
 | 
				
			||||||
 | 
					     *  prevent underlying thread processing. A portable user of the callback
 | 
				
			||||||
 | 
					     *  should not make calls to network operations due to stack size limitations.
 | 
				
			||||||
 | 
					     *  The callback should not perform expensive operations such as socket recv/send
 | 
				
			||||||
 | 
					     *  calls or blocking operations.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  @return         Call in callback
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    virtual call_in_callback_cb_t get_call_in_callback();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Call a callback after a delay
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  Call a callback from the network stack context after a delay. If function
 | 
				
			||||||
 | 
					     *  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);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Convert a raw nsapi_stack_t object into a C++ NetworkStack object
 | 
					/** Convert a raw nsapi_stack_t object into a C++ NetworkStack object
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -39,8 +39,6 @@ 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
 | 
				
			||||||
| 
						 | 
					@ -123,27 +121,6 @@ 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
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * Connects EMAC layer with the IP stack and initializes all the required infrastructure.
 | 
					     * Connects EMAC layer with the IP stack and initializes all the required infrastructure.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,22 @@
 | 
				
			||||||
    "name": "nsapi",
 | 
					    "name": "nsapi",
 | 
				
			||||||
    "config": {
 | 
					    "config": {
 | 
				
			||||||
        "present": 1,
 | 
					        "present": 1,
 | 
				
			||||||
        "default-stack": "LWIP"
 | 
					        "default-stack": "LWIP",
 | 
				
			||||||
 | 
					        "dns-response-wait-time": {
 | 
				
			||||||
 | 
					            "help": "How long the DNS translator waits for a reply from a server",
 | 
				
			||||||
 | 
					            "value": 5000
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "dns-total-retries": {
 | 
				
			||||||
 | 
					            "help": "Number of total DNS query retries that the DNS translator makes",
 | 
				
			||||||
 | 
					            "value": 3
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "dns-retries": {
 | 
				
			||||||
 | 
					            "help": "Number of DNS query retries that the DNS translator makes per server",
 | 
				
			||||||
 | 
					            "value": 0
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "dns-cache-size": {
 | 
				
			||||||
 | 
					            "help": "Number of cached host name resolutions",
 | 
				
			||||||
 | 
					            "value": 3
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -31,17 +31,32 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DNS options
 | 
					// DNS options
 | 
				
			||||||
#define DNS_BUFFER_SIZE 512
 | 
					#define DNS_BUFFER_SIZE 512
 | 
				
			||||||
#define DNS_TIMEOUT 5000
 | 
					 | 
				
			||||||
#define DNS_SERVERS_SIZE 5
 | 
					#define DNS_SERVERS_SIZE 5
 | 
				
			||||||
#define DNS_RESPONSE_MIN_SIZE 12
 | 
					#define DNS_RESPONSE_MIN_SIZE 12
 | 
				
			||||||
#define DNS_MAX_TTL 604800
 | 
					#define DNS_MAX_TTL 604800
 | 
				
			||||||
#define DNS_CACHE_SIZE 3
 | 
					 | 
				
			||||||
#define DNS_STACK_SERVERS_NUM 5
 | 
					#define DNS_STACK_SERVERS_NUM 5
 | 
				
			||||||
#define DNS_QUERY_QUEUE_SIZE 5
 | 
					#define DNS_QUERY_QUEUE_SIZE 5
 | 
				
			||||||
 | 
					#define DNS_HOST_NAME_MAX_LEN 255
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef MBED_CONF_NSAPI_DNS_RESPONSE_WAIT_TIME
 | 
				
			||||||
 | 
					#define MBED_CONF_NSAPI_DNS_RESPONSE_WAIT_TIME   5000
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef MBED_CONF_NSAPI_DNS_TOTAL_RETRIES
 | 
				
			||||||
 | 
					#define MBED_CONF_NSAPI_DNS_TOTAL_RETRIES        3
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef MBED_CONF_NSAPI_DNS_RETRIES
 | 
				
			||||||
 | 
					#define MBED_CONF_NSAPI_DNS_RETRIES              0
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef MBED_CONF_NSAPI_DNS_CACHE_SIZE
 | 
				
			||||||
 | 
					#define MBED_CONF_NSAPI_DNS_CACHE_SIZE           3
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct DNS_CACHE {
 | 
					struct DNS_CACHE {
 | 
				
			||||||
    SocketAddress address;
 | 
					    nsapi_addr_t address;
 | 
				
			||||||
    char host[128];
 | 
					    char *host;
 | 
				
			||||||
    uint64_t expires;      /*!< time to live in milliseconds */
 | 
					    uint64_t expires;      /*!< time to live in milliseconds */
 | 
				
			||||||
    uint64_t accessed;     /*!< last accessed */
 | 
					    uint64_t accessed;     /*!< last accessed */
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -49,33 +64,35 @@ struct DNS_CACHE {
 | 
				
			||||||
struct DNS_QUERY {
 | 
					struct DNS_QUERY {
 | 
				
			||||||
    int unique_id;
 | 
					    int unique_id;
 | 
				
			||||||
    NetworkStack *stack;
 | 
					    NetworkStack *stack;
 | 
				
			||||||
    char host[128];
 | 
					    char *host;
 | 
				
			||||||
    NetworkStack::hostbyname_cb_t callback;
 | 
					    NetworkStack::hostbyname_cb_t callback;
 | 
				
			||||||
    void *cb_data;
 | 
					    call_in_callback_cb_t call_in_cb;
 | 
				
			||||||
    nsapi_size_t addr_count;
 | 
					    nsapi_size_t addr_count;
 | 
				
			||||||
    nsapi_version_t version;
 | 
					    nsapi_version_t version;
 | 
				
			||||||
    UDPSocket *socket;
 | 
					    UDPSocket *socket;
 | 
				
			||||||
 | 
					    nsapi_addr_t *addrs;
 | 
				
			||||||
    int dns_server;
 | 
					    int dns_server;
 | 
				
			||||||
    int retries;
 | 
					    int retries;
 | 
				
			||||||
 | 
					    int total_retries;
 | 
				
			||||||
    int dns_message_id;
 | 
					    int dns_message_id;
 | 
				
			||||||
 | 
					    int count;
 | 
				
			||||||
 | 
					    uint32_t ttl;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef nsapi_error_t (*nsapi_dns_call_t)(mbed::Callback<void()> func);
 | 
					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);
 | 
					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 void nsapi_dns_cache_add(const char *host, nsapi_addr_t *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_size_or_error_t nsapi_dns_cache_find(const char *host, nsapi_version_t version, nsapi_addr_t *address);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static nsapi_error_t nsapi_dns_get_server_addr(NetworkStack *stack, int *index, SocketAddress *dns_addr);
 | 
					static nsapi_error_t nsapi_dns_get_server_addr(NetworkStack *stack, int *index, int *total_retries, SocketAddress *dns_addr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void nsapi_dns_query_async_create(DNS_QUERY *query);
 | 
					static void nsapi_dns_query_async_create(void *ptr);
 | 
				
			||||||
 | 
					static nsapi_error_t nsapi_dns_query_async_delete(int unique_id);
 | 
				
			||||||
static void nsapi_dns_query_async_send(void *ptr);
 | 
					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_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(NetworkStack *stack);
 | 
				
			||||||
static void nsapi_dns_query_async_socket_callback_handle(NetworkStack *stack);
 | 
					static void nsapi_dns_query_async_response(void *ptr);
 | 
				
			||||||
 | 
					 | 
				
			||||||
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] = {
 | 
					static nsapi_addr_t dns_servers[DNS_SERVERS_SIZE] = {
 | 
				
			||||||
    {NSAPI_IPv4, {8, 8, 8, 8}},                             // Google
 | 
					    {NSAPI_IPv4, {8, 8, 8, 8}},                             // Google
 | 
				
			||||||
| 
						 | 
					@ -87,13 +104,15 @@ static 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 DNS_CACHE *dns_cache[MBED_CONF_NSAPI_DNS_CACHE_SIZE];
 | 
				
			||||||
static uint16_t dns_message_id = 0;
 | 
					static uint16_t dns_message_id = 0;
 | 
				
			||||||
static int dns_unique_id = 0;
 | 
					static int dns_unique_id = 1;
 | 
				
			||||||
static DNS_QUERY *dns_query_queue[DNS_QUERY_QUEUE_SIZE];
 | 
					static DNS_QUERY *dns_query_queue[DNS_QUERY_QUEUE_SIZE];
 | 
				
			||||||
 | 
					// Protects cache shared between blocking and asynchronous calls
 | 
				
			||||||
static rtos::Mutex dns_cache_mutex;
 | 
					static rtos::Mutex dns_cache_mutex;
 | 
				
			||||||
static nsapi_dns_call_t dns_call = nsapi_dns_call_default;
 | 
					// Protects from several threads running asynchronous DNS
 | 
				
			||||||
static nsapi_dns_call_in_t dns_call_in = nsapi_dns_call_in_default;
 | 
					static rtos::Mutex dns_mutex;
 | 
				
			||||||
 | 
					static nsapi_dns_call_in_t dns_call_in = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 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)
 | 
				
			||||||
| 
						 | 
					@ -199,7 +218,7 @@ static int dns_scan_response(const uint8_t *ptr, uint16_t exp_id, uint32_t *ttl,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // verify header is response to query
 | 
					    // verify header is response to query
 | 
				
			||||||
    if (!(id == exp_id && qr && opcode == 0 && rcode == 0)) {
 | 
					    if (!(id == exp_id && qr && opcode == 0 && rcode == 0)) {
 | 
				
			||||||
        return 0;
 | 
					        return -1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // skip questions
 | 
					    // skip questions
 | 
				
			||||||
| 
						 | 
					@ -273,7 +292,7 @@ static int dns_scan_response(const uint8_t *ptr, uint16_t exp_id, uint32_t *ttl,
 | 
				
			||||||
    return count;
 | 
					    return count;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void nsapi_dns_cache_add(const char *host, SocketAddress *address, uint32_t ttl)
 | 
					static void nsapi_dns_cache_add(const char *host, nsapi_addr_t *address, uint32_t ttl)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    // RFC 1034: if TTL is zero, entry is not added to cache
 | 
					    // RFC 1034: if TTL is zero, entry is not added to cache
 | 
				
			||||||
    if (!ttl) {
 | 
					    if (!ttl) {
 | 
				
			||||||
| 
						 | 
					@ -281,17 +300,17 @@ static void nsapi_dns_cache_add(const char *host, SocketAddress *address, uint32
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Checks if already cached
 | 
					    // Checks if already cached
 | 
				
			||||||
    if (nsapi_dns_cache_find(host, address->get_ip_version(), NULL) == NSAPI_ERROR_OK) {
 | 
					    if (nsapi_dns_cache_find(host, address->version, NULL) == NSAPI_ERROR_OK) {
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    dns_cache_mutex.lock();
 | 
					    dns_cache_mutex.lock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int index = -1;
 | 
					    int index = -1;
 | 
				
			||||||
    uint64_t accessed = -1;
 | 
					    uint64_t accessed = ~0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Finds free or last accessed entry
 | 
					    // Finds free or last accessed entry
 | 
				
			||||||
    for (int i = 0; i < DNS_CACHE_SIZE; i++) {
 | 
					    for (int i = 0; i < MBED_CONF_NSAPI_DNS_CACHE_SIZE; i++) {
 | 
				
			||||||
        if (!dns_cache[i]) {
 | 
					        if (!dns_cache[i]) {
 | 
				
			||||||
            index = i;
 | 
					            index = i;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
| 
						 | 
					@ -302,17 +321,21 @@ static void nsapi_dns_cache_add(const char *host, SocketAddress *address, uint32
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (index < 0) {
 | 
					    if (index < 0) {
 | 
				
			||||||
 | 
					        dns_cache_mutex.unlock();
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Allocates in case entry is free, otherwise reuses
 | 
					    // Allocates in case entry is free, otherwise reuses
 | 
				
			||||||
    if (!dns_cache[index]) {
 | 
					    if (!dns_cache[index]) {
 | 
				
			||||||
        dns_cache[index] = new DNS_CACHE;
 | 
					        dns_cache[index] = new (std::nothrow) DNS_CACHE;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        free(dns_cache[index]->host);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (dns_cache[index]) {
 | 
					    if (dns_cache[index]) {
 | 
				
			||||||
        dns_cache[index]->address = *address;
 | 
					        dns_cache[index]->address = *address;
 | 
				
			||||||
        strncpy(dns_cache[index]->host, host, 127);
 | 
					        dns_cache[index]->host = (char *) malloc(strlen(host) + 1);
 | 
				
			||||||
 | 
					        strcpy(dns_cache[index]->host, host);
 | 
				
			||||||
        uint64_t ms_count = rtos::Kernel::get_ms_count();
 | 
					        uint64_t ms_count = rtos::Kernel::get_ms_count();
 | 
				
			||||||
        dns_cache[index]->expires = ms_count + ttl * 1000;
 | 
					        dns_cache[index]->expires = ms_count + ttl * 1000;
 | 
				
			||||||
        dns_cache[index]->accessed = ms_count;
 | 
					        dns_cache[index]->accessed = ms_count;
 | 
				
			||||||
| 
						 | 
					@ -321,21 +344,22 @@ static void nsapi_dns_cache_add(const char *host, SocketAddress *address, uint32
 | 
				
			||||||
    dns_cache_mutex.unlock();
 | 
					    dns_cache_mutex.unlock();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static nsapi_error_t nsapi_dns_cache_find(const char *host, nsapi_version_t version, SocketAddress *address)
 | 
					static nsapi_error_t nsapi_dns_cache_find(const char *host, nsapi_version_t version, nsapi_addr_t *address)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    nsapi_error_t ret_val = NSAPI_ERROR_NO_ADDRESS;
 | 
					    nsapi_error_t ret_val = NSAPI_ERROR_NO_ADDRESS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    dns_cache_mutex.lock();
 | 
					    dns_cache_mutex.lock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (int i = 0; i < DNS_CACHE_SIZE; i++) {
 | 
					    for (int i = 0; i < MBED_CONF_NSAPI_DNS_CACHE_SIZE; i++) {
 | 
				
			||||||
        if (dns_cache[i]) {
 | 
					        if (dns_cache[i]) {
 | 
				
			||||||
            uint64_t ms_count = rtos::Kernel::get_ms_count();
 | 
					            uint64_t ms_count = rtos::Kernel::get_ms_count();
 | 
				
			||||||
            // Checks all entries for expired entries
 | 
					            // Checks all entries for expired entries
 | 
				
			||||||
            if (ms_count > dns_cache[i]->expires) {
 | 
					            if (ms_count > dns_cache[i]->expires) {
 | 
				
			||||||
 | 
					                free(dns_cache[i]->host);
 | 
				
			||||||
                delete dns_cache[i];
 | 
					                delete dns_cache[i];
 | 
				
			||||||
                dns_cache[i] = NULL;
 | 
					                dns_cache[i] = NULL;
 | 
				
			||||||
            } else if (((version == NSAPI_UNSPEC) || (version == dns_cache[i]->address.get_ip_version())) &&
 | 
					            } else if ((version == NSAPI_UNSPEC || version == dns_cache[i]->address.version) &&
 | 
				
			||||||
                (strncmp(dns_cache[i]->host, host, 127) == 0)) {
 | 
					                strcmp(dns_cache[i]->host, host) == 0) {
 | 
				
			||||||
                if (address) {
 | 
					                if (address) {
 | 
				
			||||||
                    *address = dns_cache[i]->address;
 | 
					                    *address = dns_cache[i]->address;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
| 
						 | 
					@ -350,14 +374,22 @@ static nsapi_error_t nsapi_dns_cache_find(const char *host, nsapi_version_t vers
 | 
				
			||||||
    return ret_val;
 | 
					    return ret_val;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static nsapi_error_t nsapi_dns_get_server_addr(NetworkStack *stack, int *index, SocketAddress *dns_addr)
 | 
					static nsapi_error_t nsapi_dns_get_server_addr(NetworkStack *stack, int *index, int *total_retries, SocketAddress *dns_addr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    bool dns_addr_set = false;
 | 
					    bool dns_addr_set = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (*index >= DNS_SERVERS_SIZE + DNS_STACK_SERVERS_NUM) {
 | 
					    if (*total_retries == 0) {
 | 
				
			||||||
        return NSAPI_ERROR_NO_ADDRESS;
 | 
					        return NSAPI_ERROR_NO_ADDRESS;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (*index >= DNS_SERVERS_SIZE + DNS_STACK_SERVERS_NUM) {
 | 
				
			||||||
 | 
					        if (*total_retries) {
 | 
				
			||||||
 | 
					            *index = 0;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            return NSAPI_ERROR_NO_ADDRESS;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (*index < DNS_STACK_SERVERS_NUM) {
 | 
					    if (*index < DNS_STACK_SERVERS_NUM) {
 | 
				
			||||||
        nsapi_error_t ret = stack->get_dns_server(*index, dns_addr);
 | 
					        nsapi_error_t ret = stack->get_dns_server(*index, dns_addr);
 | 
				
			||||||
        if (ret < 0) {
 | 
					        if (ret < 0) {
 | 
				
			||||||
| 
						 | 
					@ -382,14 +414,12 @@ static nsapi_size_or_error_t nsapi_dns_query_multiple(NetworkStack *stack, const
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    // check for valid host name
 | 
					    // check for valid host name
 | 
				
			||||||
    int host_len = host ? strlen(host) : 0;
 | 
					    int host_len = host ? strlen(host) : 0;
 | 
				
			||||||
    if (host_len > 128 || host_len == 0) {
 | 
					    if (host_len > DNS_HOST_NAME_MAX_LEN || host_len == 0) {
 | 
				
			||||||
        return NSAPI_ERROR_PARAMETER;
 | 
					        return NSAPI_ERROR_PARAMETER;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // check cache
 | 
					    // check cache
 | 
				
			||||||
    SocketAddress address;
 | 
					    if (nsapi_dns_cache_find(host, version, addr) == NSAPI_ERROR_OK) {
 | 
				
			||||||
    if (nsapi_dns_cache_find(host, version, &address) == NSAPI_ERROR_OK) {
 | 
					 | 
				
			||||||
        *addr = address.get_addr();
 | 
					 | 
				
			||||||
        return 1;
 | 
					        return 1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -400,7 +430,7 @@ static nsapi_size_or_error_t nsapi_dns_query_multiple(NetworkStack *stack, const
 | 
				
			||||||
        return err;
 | 
					        return err;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    socket.set_timeout(DNS_TIMEOUT);
 | 
					    socket.set_timeout(MBED_CONF_NSAPI_DNS_RESPONSE_WAIT_TIME);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // create network packet
 | 
					    // create network packet
 | 
				
			||||||
    uint8_t * const packet = (uint8_t *)malloc(DNS_BUFFER_SIZE);
 | 
					    uint8_t * const packet = (uint8_t *)malloc(DNS_BUFFER_SIZE);
 | 
				
			||||||
| 
						 | 
					@ -410,14 +440,15 @@ 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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool retry = false;
 | 
					    int retries = MBED_CONF_NSAPI_DNS_RETRIES;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int index = 0;
 | 
					    int index = 0;
 | 
				
			||||||
 | 
					    int total_retries = MBED_CONF_NSAPI_DNS_TOTAL_RETRIES;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // check against each dns server
 | 
					    // check against each dns server
 | 
				
			||||||
    while (true) {
 | 
					    while (true) {
 | 
				
			||||||
        SocketAddress dns_addr;
 | 
					        SocketAddress dns_addr;
 | 
				
			||||||
        err = nsapi_dns_get_server_addr(stack, &index, &dns_addr);
 | 
					        err = nsapi_dns_get_server_addr(stack, &index, &total_retries, &dns_addr);
 | 
				
			||||||
        if (err != NSAPI_ERROR_OK) {
 | 
					        if (err != NSAPI_ERROR_OK) {
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -429,20 +460,24 @@ static nsapi_size_or_error_t nsapi_dns_query_multiple(NetworkStack *stack, const
 | 
				
			||||||
        // 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
 | 
					            // goes to next dns server
 | 
				
			||||||
            retry = false;
 | 
					            retries = MBED_CONF_NSAPI_DNS_RETRIES;
 | 
				
			||||||
            index++;
 | 
					            index++;
 | 
				
			||||||
            continue;
 | 
					            continue;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (total_retries) {
 | 
				
			||||||
 | 
					            total_retries--;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // 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) {
 | 
					            if (retries) {
 | 
				
			||||||
                // retries once
 | 
					                // retries
 | 
				
			||||||
                retry = true;
 | 
					                retries--;
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                // goes to next dns server
 | 
					                // goes to next dns server
 | 
				
			||||||
                retry = false;
 | 
					                retries = MBED_CONF_NSAPI_DNS_RETRIES;
 | 
				
			||||||
                index++;
 | 
					                index++;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            continue;
 | 
					            continue;
 | 
				
			||||||
| 
						 | 
					@ -453,13 +488,12 @@ static nsapi_size_or_error_t nsapi_dns_query_multiple(NetworkStack *stack, const
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const uint8_t *response = packet;
 | 
					        const uint8_t *response = packet;
 | 
				
			||||||
        uint32_t ttl;
 | 
					        uint32_t ttl;
 | 
				
			||||||
        int count = dns_scan_response(response, 1, &ttl, addr, addr_count);
 | 
					        int resp = dns_scan_response(response, 1, &ttl, addr, addr_count);
 | 
				
			||||||
        if (count > 0) {
 | 
					        if (resp > 0) {
 | 
				
			||||||
            // Adds address to cache
 | 
					            nsapi_dns_cache_add(host, addr, ttl);
 | 
				
			||||||
            SocketAddress address(*addr);
 | 
					            result = resp;
 | 
				
			||||||
            nsapi_dns_cache_add(host, &address, ttl);
 | 
					        } else if (resp < 0) {
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
            result = count;
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* The DNS response is final, no need to check other servers */
 | 
					        /* The DNS response is final, no need to check other servers */
 | 
				
			||||||
| 
						 | 
					@ -490,7 +524,7 @@ extern "C" nsapi_size_or_error_t nsapi_dns_query_multiple(nsapi_stack_t *stack,
 | 
				
			||||||
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 *addresses, nsapi_size_t addr_count, nsapi_version_t version)
 | 
					        SocketAddress *addresses, nsapi_size_t addr_count, nsapi_version_t version)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    nsapi_addr_t *addrs = new nsapi_addr_t[addr_count];
 | 
					    nsapi_addr_t *addrs = new (std::nothrow) nsapi_addr_t[addr_count];
 | 
				
			||||||
    nsapi_size_or_error_t result = nsapi_dns_query_multiple(stack, host, addrs, addr_count, version);
 | 
					    nsapi_size_or_error_t result = nsapi_dns_query_multiple(stack, host, addrs, addr_count, version);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (result > 0) {
 | 
					    if (result > 0) {
 | 
				
			||||||
| 
						 | 
					@ -521,39 +555,10 @@ nsapi_error_t nsapi_dns_query(NetworkStack *stack, const char *host,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
nsapi_error_t nsapi_dns_query_async(NetworkStack *stack, const char *host,
 | 
					nsapi_error_t nsapi_dns_query_async(NetworkStack *stack, const char *host,
 | 
				
			||||||
        NetworkStack::hostbyname_cb_t callback, void *data, nsapi_version_t version)
 | 
					        NetworkStack::hostbyname_cb_t callback, call_in_callback_cb_t call_in_cb,
 | 
				
			||||||
 | 
					        nsapi_version_t version)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    nsapi_size_or_error_t result = nsapi_dns_query_multiple_async(stack, host, callback, data, 1, version);
 | 
					    return nsapi_dns_query_multiple_async(stack, host, callback, 0, call_in_cb, 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)
 | 
					void nsapi_dns_call_in_set(nsapi_dns_call_in_t callback)
 | 
				
			||||||
| 
						 | 
					@ -561,32 +566,19 @@ void nsapi_dns_call_in_set(nsapi_dns_call_in_t callback)
 | 
				
			||||||
    dns_call_in = callback;
 | 
					    dns_call_in = callback;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static nsapi_error_t nsapi_dns_call(NetworkStack *stack, mbed::Callback<void()> func)
 | 
					nsapi_error_t nsapi_dns_call_in(call_in_callback_cb_t cb, int delay, mbed::Callback<void()> func)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (stack->onboardNetworkStack()) {
 | 
					    if (dns_call_in) {
 | 
				
			||||||
        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);
 | 
					        dns_call_in(delay, func);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        return cb(delay, func);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    return NSAPI_ERROR_OK;
 | 
					    return NSAPI_ERROR_OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
nsapi_error_t nsapi_dns_query_multiple_async(NetworkStack *stack, const char *host,
 | 
					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)
 | 
					    NetworkStack::hostbyname_cb_t callback, nsapi_size_t addr_count,
 | 
				
			||||||
 | 
					    call_in_callback_cb_t call_in_cb, nsapi_version_t version)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (!stack) {
 | 
					    if (!stack) {
 | 
				
			||||||
        return NSAPI_ERROR_PARAMETER;
 | 
					        return NSAPI_ERROR_PARAMETER;
 | 
				
			||||||
| 
						 | 
					@ -594,129 +586,87 @@ nsapi_error_t nsapi_dns_query_multiple_async(NetworkStack *stack, const char *ho
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // check for valid host name
 | 
					    // check for valid host name
 | 
				
			||||||
    int host_len = host ? strlen(host) : 0;
 | 
					    int host_len = host ? strlen(host) : 0;
 | 
				
			||||||
    if (host_len > 128 || host_len == 0) {
 | 
					    if (host_len > DNS_HOST_NAME_MAX_LEN || host_len == 0) {
 | 
				
			||||||
        return NSAPI_ERROR_PARAMETER;
 | 
					        return NSAPI_ERROR_PARAMETER;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    DNS_QUERY *query = new DNS_QUERY;
 | 
					    nsapi_addr address;
 | 
				
			||||||
 | 
					    if (nsapi_dns_cache_find(host, version, &address) == NSAPI_ERROR_OK) {
 | 
				
			||||||
 | 
					        SocketAddress addr(address);
 | 
				
			||||||
 | 
					        callback(NSAPI_ERROR_OK, &addr);
 | 
				
			||||||
 | 
					        return NSAPI_ERROR_OK;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!query) {
 | 
					    dns_mutex.lock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int index = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (int i = 0; i < DNS_QUERY_QUEUE_SIZE; i++) {
 | 
				
			||||||
 | 
					        if (!dns_query_queue[i]) {
 | 
				
			||||||
 | 
					            index = i;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (index < 0) {
 | 
				
			||||||
 | 
					        dns_mutex.unlock();
 | 
				
			||||||
        return NSAPI_ERROR_NO_MEMORY;
 | 
					        return NSAPI_ERROR_NO_MEMORY;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    query->unique_id = 0;
 | 
					    DNS_QUERY *query = new (std::nothrow) DNS_QUERY;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!query) {
 | 
				
			||||||
 | 
					        dns_mutex.unlock();
 | 
				
			||||||
 | 
					        return NSAPI_ERROR_NO_MEMORY;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    query->host = (char *) malloc(host_len + 1);
 | 
				
			||||||
    strcpy(query->host, host);
 | 
					    strcpy(query->host, host);
 | 
				
			||||||
    query->callback = callback;
 | 
					    query->callback = callback;
 | 
				
			||||||
    query->cb_data = data;
 | 
					    query->call_in_cb = call_in_cb;
 | 
				
			||||||
    query->stack = stack;
 | 
					    query->stack = stack;
 | 
				
			||||||
    query->addr_count = addr_count;
 | 
					    query->addr_count = addr_count;
 | 
				
			||||||
    query->version = version;
 | 
					    query->version = version;
 | 
				
			||||||
    query->socket = NULL;
 | 
					    query->socket = NULL;
 | 
				
			||||||
 | 
					    query->addrs = NULL;
 | 
				
			||||||
    query->dns_server = 0;
 | 
					    query->dns_server = 0;
 | 
				
			||||||
    query->retries = 2;
 | 
					    query->retries = MBED_CONF_NSAPI_DNS_RETRIES + 1;
 | 
				
			||||||
 | 
					    query->total_retries =  MBED_CONF_NSAPI_DNS_TOTAL_RETRIES;
 | 
				
			||||||
    query->dns_message_id = -1;
 | 
					    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++;
 | 
					    query->unique_id = dns_unique_id++;
 | 
				
			||||||
 | 
					    if (query->unique_id > 0x7FFF) {
 | 
				
			||||||
 | 
					        query->unique_id = 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    dns_query_queue[index] = query;
 | 
					    dns_query_queue[index] = query;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    nsapi_dns_query_async_send(reinterpret_cast<void *>(query->unique_id));
 | 
					    if (nsapi_dns_call_in(query->call_in_cb, 0, mbed::callback(nsapi_dns_query_async_create, reinterpret_cast<void *>(query->unique_id))) != NSAPI_ERROR_OK) {
 | 
				
			||||||
}
 | 
					        delete query;
 | 
				
			||||||
 | 
					        dns_mutex.unlock();
 | 
				
			||||||
 | 
					        return NSAPI_ERROR_NO_MEMORY;
 | 
				
			||||||
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) {
 | 
					    dns_mutex.unlock();
 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (close_socket) {
 | 
					    return query->unique_id;
 | 
				
			||||||
        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)
 | 
					nsapi_error_t nsapi_dns_query_async_cancel(nsapi_error_t id)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    query->callback(status, address, query->cb_data);
 | 
					    dns_mutex.lock();
 | 
				
			||||||
    nsapi_dns_query_async_delete(query);
 | 
					
 | 
				
			||||||
 | 
					    nsapi_error_t ret = nsapi_dns_query_async_delete(id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dns_mutex.unlock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void nsapi_dns_query_async_send(void *ptr)
 | 
					static void nsapi_dns_query_async_create(void *ptr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    dns_mutex.lock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int unique_id = reinterpret_cast<int>(ptr);
 | 
					    int unique_id = reinterpret_cast<int>(ptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    DNS_QUERY *query = NULL;
 | 
					    DNS_QUERY *query = NULL;
 | 
				
			||||||
| 
						 | 
					@ -729,7 +679,114 @@ static void nsapi_dns_query_async_send(void *ptr)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!query) {
 | 
					    if (!query) {
 | 
				
			||||||
        nsapi_dns_query_async_resp(query, NSAPI_ERROR_NO_MEMORY, NULL);
 | 
					        // Cancel has been called
 | 
				
			||||||
 | 
					        dns_mutex.unlock();
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (int i = 0; i < DNS_QUERY_QUEUE_SIZE; i++) {
 | 
				
			||||||
 | 
					        if (dns_query_queue[i] && dns_query_queue[i] != query) {
 | 
				
			||||||
 | 
					            if (dns_query_queue[i]->socket && dns_query_queue[i]->stack == query->stack) {
 | 
				
			||||||
 | 
					                query->socket = dns_query_queue[i]->socket;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    UDPSocket *socket;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (query->socket) {
 | 
				
			||||||
 | 
					        socket = query->socket;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        socket = new (std::nothrow) UDPSocket;
 | 
				
			||||||
 | 
					        if (!socket) {
 | 
				
			||||||
 | 
					            nsapi_dns_query_async_resp(query, NSAPI_ERROR_NO_MEMORY, NULL);
 | 
				
			||||||
 | 
					            dns_mutex.unlock();
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        int err = socket->open(query->stack);
 | 
				
			||||||
 | 
					        if (err) {
 | 
				
			||||||
 | 
					            delete socket;
 | 
				
			||||||
 | 
					            nsapi_dns_query_async_resp(query, err, NULL);
 | 
				
			||||||
 | 
					            dns_mutex.unlock();
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        socket->set_timeout(0);
 | 
				
			||||||
 | 
					        socket->sigio(mbed::callback(nsapi_dns_query_async_socket_callback, query->stack));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        query->socket = socket;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dns_mutex.unlock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    nsapi_dns_query_async_send(reinterpret_cast<void *>(query->unique_id));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static nsapi_error_t nsapi_dns_query_async_delete(int unique_id)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int index = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (int i = 0; i < DNS_QUERY_QUEUE_SIZE; i++) {
 | 
				
			||||||
 | 
					        if (dns_query_queue[i] && dns_query_queue[i]->unique_id == unique_id) {
 | 
				
			||||||
 | 
					            index = i;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (index < 0) {
 | 
				
			||||||
 | 
					        return NSAPI_ERROR_DEVICE_ERROR;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool close_socket = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (int i = 0; i < DNS_QUERY_QUEUE_SIZE; i++) {
 | 
				
			||||||
 | 
					        if (i != index && dns_query_queue[i] && dns_query_queue[i]->socket &&
 | 
				
			||||||
 | 
					            dns_query_queue[i]->stack == dns_query_queue[index]->stack) {
 | 
				
			||||||
 | 
					            close_socket = false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (close_socket && dns_query_queue[index]->socket) {
 | 
				
			||||||
 | 
					        dns_query_queue[index]->socket->close();
 | 
				
			||||||
 | 
					        delete dns_query_queue[index]->socket;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (dns_query_queue[index]->addrs) {
 | 
				
			||||||
 | 
					        delete[] dns_query_queue[index]->addrs;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    free(dns_query_queue[index]->host);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    delete dns_query_queue[index];
 | 
				
			||||||
 | 
					    dns_query_queue[index] = NULL;
 | 
				
			||||||
 | 
					    return NSAPI_ERROR_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void nsapi_dns_query_async_resp(DNS_QUERY *query, nsapi_error_t status, SocketAddress *address)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    query->callback(status, address);
 | 
				
			||||||
 | 
					    nsapi_dns_query_async_delete(query->unique_id);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void nsapi_dns_query_async_send(void *ptr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    dns_mutex.lock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    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) {
 | 
				
			||||||
 | 
					        // Cancel has been called
 | 
				
			||||||
 | 
					        dns_mutex.unlock();
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -737,7 +794,7 @@ static void nsapi_dns_query_async_send(void *ptr)
 | 
				
			||||||
        query->retries--;
 | 
					        query->retries--;
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        query->dns_server++;
 | 
					        query->dns_server++;
 | 
				
			||||||
        query->retries = 1;
 | 
					        query->retries = MBED_CONF_NSAPI_DNS_RETRIES;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    query->dns_message_id = dns_message_id++;
 | 
					    query->dns_message_id = dns_message_id++;
 | 
				
			||||||
| 
						 | 
					@ -746,6 +803,7 @@ static void nsapi_dns_query_async_send(void *ptr)
 | 
				
			||||||
    uint8_t *packet = (uint8_t *)malloc(DNS_BUFFER_SIZE);
 | 
					    uint8_t *packet = (uint8_t *)malloc(DNS_BUFFER_SIZE);
 | 
				
			||||||
    if (!packet) {
 | 
					    if (!packet) {
 | 
				
			||||||
        nsapi_dns_query_async_resp(query, NSAPI_ERROR_NO_MEMORY, NULL);
 | 
					        nsapi_dns_query_async_resp(query, NSAPI_ERROR_NO_MEMORY, NULL);
 | 
				
			||||||
 | 
					        dns_mutex.unlock();
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -754,10 +812,11 @@ static void nsapi_dns_query_async_send(void *ptr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    while (true) {
 | 
					    while (true) {
 | 
				
			||||||
        SocketAddress dns_addr;
 | 
					        SocketAddress dns_addr;
 | 
				
			||||||
        nsapi_size_or_error_t err = nsapi_dns_get_server_addr(query->stack, &(query->dns_server), &dns_addr);
 | 
					        nsapi_size_or_error_t err = nsapi_dns_get_server_addr(query->stack, &(query->dns_server), &(query->total_retries), &dns_addr);
 | 
				
			||||||
        if (err != NSAPI_ERROR_OK) {
 | 
					        if (err != NSAPI_ERROR_OK) {
 | 
				
			||||||
            nsapi_dns_query_async_resp(query, NSAPI_ERROR_DNS_FAILURE, NULL);
 | 
					            nsapi_dns_query_async_resp(query, NSAPI_ERROR_DNS_FAILURE, NULL);
 | 
				
			||||||
            free(packet);
 | 
					            free(packet);
 | 
				
			||||||
 | 
					            dns_mutex.unlock();
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -770,23 +829,26 @@ static void nsapi_dns_query_async_send(void *ptr)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (query->total_retries) {
 | 
				
			||||||
 | 
					        query->total_retries--;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    free(packet);
 | 
					    free(packet);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (nsapi_dns_call_in(query->stack, DNS_TIMEOUT,
 | 
					    if (nsapi_dns_call_in(query->call_in_cb, MBED_CONF_NSAPI_DNS_RESPONSE_WAIT_TIME,
 | 
				
			||||||
        mbed::callback(nsapi_dns_query_async_send, reinterpret_cast<void *>(unique_id))) != NSAPI_ERROR_OK) {
 | 
					        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);
 | 
					        nsapi_dns_query_async_resp(query, NSAPI_ERROR_NO_MEMORY, NULL);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dns_mutex.unlock();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void nsapi_dns_query_async_socket_callback(NetworkStack *stack)
 | 
					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;
 | 
					    UDPSocket *socket = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dns_mutex.lock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (int i = 0; i < DNS_QUERY_QUEUE_SIZE; i++) {
 | 
					    for (int i = 0; i < DNS_QUERY_QUEUE_SIZE; i++) {
 | 
				
			||||||
        if (dns_query_queue[i] && dns_query_queue[i]->stack == stack) {
 | 
					        if (dns_query_queue[i] && dns_query_queue[i]->stack == stack) {
 | 
				
			||||||
            socket = dns_query_queue[i]->socket;
 | 
					            socket = dns_query_queue[i]->socket;
 | 
				
			||||||
| 
						 | 
					@ -798,58 +860,95 @@ static void nsapi_dns_query_async_socket_callback_handle(NetworkStack *stack)
 | 
				
			||||||
        // create network packet
 | 
					        // create network packet
 | 
				
			||||||
        uint8_t *packet = (uint8_t *)malloc(DNS_BUFFER_SIZE);
 | 
					        uint8_t *packet = (uint8_t *)malloc(DNS_BUFFER_SIZE);
 | 
				
			||||||
        if (!packet) {
 | 
					        if (!packet) {
 | 
				
			||||||
 | 
					            dns_mutex.unlock();
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // recv the response
 | 
					        while (true) {
 | 
				
			||||||
        nsapi_size_or_error_t size = socket->recvfrom(NULL, packet, DNS_BUFFER_SIZE);
 | 
					            // recv the response
 | 
				
			||||||
 | 
					            nsapi_size_or_error_t size = socket->recvfrom(NULL, packet, DNS_BUFFER_SIZE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (size < DNS_RESPONSE_MIN_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;
 | 
					                break;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // gets id from response to associate with correct query
 | 
				
			||||||
 | 
					            uint16_t id = (packet[0] << 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) {
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            int requested_count = 1;
 | 
				
			||||||
 | 
					            if (query->addr_count > 1) {
 | 
				
			||||||
 | 
					                requested_count = query->addr_count;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            query->addrs = new (std::nothrow) nsapi_addr_t[requested_count];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            int resp = dns_scan_response(packet, id, &(query->ttl), query->addrs, requested_count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Ignore invalid responses
 | 
				
			||||||
 | 
					            if (resp < 0) {
 | 
				
			||||||
 | 
					                delete[] query->addrs;
 | 
				
			||||||
 | 
					                query->addrs = 0;
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                query->count = resp;
 | 
				
			||||||
 | 
					                nsapi_dns_call_in(query->call_in_cb, 0, mbed::callback(nsapi_dns_query_async_response, reinterpret_cast<void *>(query->unique_id)));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        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);
 | 
					        free(packet);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (count > 0) {
 | 
					    dns_mutex.unlock();
 | 
				
			||||||
            SocketAddress *addresses = new SocketAddress[count];
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            for (int i = 0; i < count; i++) {
 | 
					static void nsapi_dns_query_async_response(void *ptr)
 | 
				
			||||||
                addresses[i].set_addr(addrs[i]);
 | 
					{
 | 
				
			||||||
 | 
					    dns_mutex.lock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    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) {
 | 
				
			||||||
 | 
					        if (query->count > 0) {
 | 
				
			||||||
 | 
					            SocketAddress *addresses = new (std::nothrow) SocketAddress[query->count];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for (int i = 0; i < query->count; i++) {
 | 
				
			||||||
 | 
					                addresses[i].set_addr(query->addrs[i]);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Adds address to cache
 | 
					            // Adds address to cache
 | 
				
			||||||
            nsapi_dns_cache_add(query->host, addresses, ttl);
 | 
					            nsapi_dns_cache_add(query->host, &(query->addrs[0]), query->ttl);
 | 
				
			||||||
 | 
					 | 
				
			||||||
            nsapi_dns_query_async_resp(query, NSAPI_ERROR_OK, addresses);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            nsapi_error_t status = NSAPI_ERROR_OK;
 | 
				
			||||||
 | 
					            if (query->addr_count > 0) {
 | 
				
			||||||
 | 
					                status = query->count;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            nsapi_dns_query_async_resp(query, status, addresses);
 | 
				
			||||||
            delete[] addresses;
 | 
					            delete[] addresses;
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            nsapi_dns_query_async_resp(query, NSAPI_ERROR_DNS_FAILURE, NULL);
 | 
					            nsapi_dns_query_async_resp(query, NSAPI_ERROR_DNS_FAILURE, NULL);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					 | 
				
			||||||
        delete[] addrs;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    dns_mutex.unlock();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -63,6 +63,7 @@ nsapi_error_t nsapi_dns_add_server(nsapi_addr_t addr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef mbed::Callback<nsapi_error_t (int delay_ms, mbed::Callback<void()> user_cb)> call_in_callback_cb_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** 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
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
| 
						 | 
					@ -80,14 +81,15 @@ nsapi_error_t nsapi_dns_query(NetworkStack *stack, const char *host,
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *  @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
 | 
				
			||||||
 *  @param callback Callback that is called for result*
 | 
					 *  @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)
 | 
					 *  @param version  IP version to resolve (defaults to NSAPI_IPv4)
 | 
				
			||||||
 *  @return         0 on success, negative error code on failure
 | 
					 *  @return         0 on success, negative error code on failure or an unique id that
 | 
				
			||||||
 *                  NSAPI_ERROR_DNS_FAILURE indicates the host could not be found
 | 
					 *                  represents the hostname translation operation and can be passed to
 | 
				
			||||||
 | 
					 *                  cancel, NSAPI_ERROR_DNS_FAILURE indicates the host could not be found
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
nsapi_error_t nsapi_dns_query_async(NetworkStack *stack, const char *host,
 | 
					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);
 | 
					        NetworkStack::hostbyname_cb_t callback, call_in_callback_cb_t call_in_cb,
 | 
				
			||||||
 | 
					        nsapi_version_t version = NSAPI_IPv4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Query a domain name server for an IP address of a given hostname (asynchronous)
 | 
					/** Query a domain name server for an IP address of a given hostname (asynchronous)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
| 
						 | 
					@ -135,14 +137,15 @@ nsapi_size_or_error_t nsapi_dns_query_multiple(NetworkStack *stack, const char *
 | 
				
			||||||
 *  @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
 | 
				
			||||||
 *  @param callback   Callback that is called for result
 | 
					 *  @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 addr_count Number of addresses allocated in the array
 | 
				
			||||||
 *  @param version    IP version to resolve (defaults to NSAPI_IPv4)
 | 
					 *  @param version    IP version to resolve (defaults to NSAPI_IPv4)
 | 
				
			||||||
 *  @return           0 on success, negative error code on failure
 | 
					 *  @return           0 on success, negative error code on failure or an unique id that
 | 
				
			||||||
 *                    NSAPI_ERROR_DNS_FAILURE indicates the host could not be found
 | 
					                      represents the hostname translation operation and can be passed to
 | 
				
			||||||
 | 
					 *                    cancel, 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,
 | 
					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);
 | 
					        NetworkStack::hostbyname_cb_t callback, nsapi_size_t addr_count,
 | 
				
			||||||
 | 
					        call_in_callback_cb_t call_in_cb, 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
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
| 
						 | 
					@ -176,6 +179,15 @@ nsapi_size_or_error_t nsapi_dns_query_multiple(S *stack, const char *host,
 | 
				
			||||||
                host, addr, addr_count, version);
 | 
					                host, addr, addr_count, version);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Cancels asynchronous hostname translation
 | 
				
			||||||
 | 
					  *
 | 
				
			||||||
 | 
					  *  When translation is cancelled, callback will not be called.
 | 
				
			||||||
 | 
					  *
 | 
				
			||||||
 | 
					  *  @param id       Unique id of the hostname translation operation
 | 
				
			||||||
 | 
					  *  @return         0 on success, negative error code on failure
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					nsapi_error_t nsapi_dns_query_async_cancel(nsapi_error_t id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Add a domain name server to list of servers to query
 | 
					/** Add a domain name server to list of servers to query
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *  @param addr     Destination for the host address
 | 
					 *  @param addr     Destination for the host address
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue