Mbed library for ENC28J60 Ethernet modules. Full support for TCP/IP and UDP Server, Client and HTTP server (webserver). DHCP and DNS is included.

Dependents:   mBuino_ENC28_MQTT Nucleo_Web_ENC28J60 Nucleo_Web_ENC28J60_ADC Serial_over_Ethernet ... more

Library for ENC28J60 Ethernet modules.

/media/uploads/hudakz/enc28j60_module01.jpg

Ported to mbed from Norbert Truchsess's UIPEthernet library for Arduino. Thank you Norbert!

  • Full support for persistent (streaming) TCP/IP and UDP connections Client and Server each, ARP, ICMP, DHCP and DNS.
  • Works with both Mbed OS 2 and Mbed OS 5.

Usage:

  • Import the library into your project.
  • Add #include "UipEthernet.h" to main.cpp
  • Create one instance of the UipEthernet class initialized with the MAC address you'd like to use and SPI pins of the connected Mbed board.

Example programs:

Import programWebSwitch_ENC28J60

HTTP Server serving a simple webpage which enables to remotely turn a digital output on/off. Compile, download, run and type 'IP_address/secret/' (don't forget the last '/') into your web browser and hit ENTER.

Import programHTTPServer_Echo_ENC28J60

A simple HTTP server echoing received requests. Ethernet connection is over an ENC28J60 board. Usage: Type the server's IP address into you web browser and hit <ENTER>.

Import programTcpServer_ENC28J60

Simple TCP/IP Server using the UIPEthernet library for ENC28J60 Ethernet boards.

Import programTcpClient_ENC28J60

Simple TCP/IP Client using the UIPEthernet library for ENC28J60 Ethernet boards.

Import programUdpServer_ENC28J60

Simple UDP Server using the UIPEthernet library for ENC28J60 Ethernet boards.

Import programUdpClient_ENC28J60

Simple UDP Client using the UIPEthernet library for ENC28J60 Ethernet boards.

Import programMQTT_Hello_ENC28J60

MQTT Client example program. Ethernet connection is via an ENC28J60 module.

Files at this revision

API Documentation at this revision

Comitter:
hudakz
Date:
Tue Sep 03 09:16:55 2019 +0000
Parent:
13:95c00132cd98
Child:
15:53715cc81c63
Commit message:
UDP socket improved.

Changed in this revision

SocketAddress.cpp Show annotated file Show diff for this revision Revisions of this file
SocketAddress.h Show annotated file Show diff for this revision Revisions of this file
UdpSocket.cpp Show annotated file Show diff for this revision Revisions of this file
UdpSocket.h Show annotated file Show diff for this revision Revisions of this file
UipEthernet.cpp Show annotated file Show diff for this revision Revisions of this file
UipEthernet.h Show annotated file Show diff for this revision Revisions of this file
utility/Enc28j60Eth.cpp Show annotated file Show diff for this revision Revisions of this file
utility/Enc28j60Eth.h Show annotated file Show diff for this revision Revisions of this file
utility/Udp.h Show annotated file Show diff for this revision Revisions of this file
utility/common_functions.c Show annotated file Show diff for this revision Revisions of this file
utility/common_functions.h Show annotated file Show diff for this revision Revisions of this file
utility/ip4string.h Show annotated file Show diff for this revision Revisions of this file
utility/ip4tos.c Show annotated file Show diff for this revision Revisions of this file
utility/ip6string.h Show annotated file Show diff for this revision Revisions of this file
utility/ip6tos.c Show annotated file Show diff for this revision Revisions of this file
utility/ns_types.h Show annotated file Show diff for this revision Revisions of this file
utility/nsapi_types.h Show annotated file Show diff for this revision Revisions of this file
utility/stoip4.c Show annotated file Show diff for this revision Revisions of this file
utility/stoip6.c Show annotated file Show diff for this revision Revisions of this file
utility/uip.h Show annotated file Show diff for this revision Revisions of this file
utility/uipethernet-conf.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SocketAddress.cpp	Tue Sep 03 09:16:55 2019 +0000
@@ -0,0 +1,349 @@
+/* Socket
+ * Copyright (c) 2015 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.
+ */
+
+#include "mbed_version.h"
+
+#if MBED_MAJOR_VERSION == 2
+
+#include "SocketAddress.h"
+//#include "NetworkInterface.h"
+//#include "NetworkStack.h"
+#include <string.h>
+#include <stdio.h>
+#include "ip4string.h"
+#include "ip6string.h"
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+SocketAddress::SocketAddress(nsapi_addr_t addr, uint16_t port)
+{
+    mem_init();
+    _ip_address = NULL;
+    set_addr(addr);
+    set_port(port);
+}
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+SocketAddress::SocketAddress(const char* addr, uint16_t port)
+{
+    mem_init();
+    _ip_address = NULL;
+    set_ip_address(addr);
+    set_port(port);
+}
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+SocketAddress::SocketAddress(const void* bytes, nsapi_version_t version, uint16_t port)
+{
+    mem_init();
+    _ip_address = NULL;
+    set_ip_bytes(bytes, version);
+    set_port(port);
+}
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+SocketAddress::SocketAddress(const SocketAddress& addr)
+{
+    mem_init();
+    _ip_address = NULL;
+    set_addr(addr.get_addr());
+    set_port(addr.get_port());
+}
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+void SocketAddress::mem_init(void)
+{
+    _addr.version = NSAPI_UNSPEC;
+    memset(_addr.bytes, 0, NSAPI_IP_BYTES);
+    _port = 0;
+}
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+bool SocketAddress::set_ip_address(const char* addr)
+{
+    delete[] _ip_address;
+    _ip_address = NULL;
+
+    if (addr && stoip4(addr, strlen(addr), _addr.bytes)) {
+        _addr.version = NSAPI_IPv4;
+        return true;
+    }
+    else
+    if (addr && stoip6(addr, strlen(addr), _addr.bytes)) {
+        _addr.version = NSAPI_IPv6;
+        return true;
+    }
+    else {
+        _addr = nsapi_addr_t();
+        return false;
+    }
+}
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+void SocketAddress::set_ip_bytes(const void* bytes, nsapi_version_t version)
+{
+    nsapi_addr_t    addr;
+
+    addr = nsapi_addr_t();
+    addr.version = version;
+    if (version == NSAPI_IPv6) {
+        memcpy(addr.bytes, bytes, NSAPI_IPv6_BYTES);
+    }
+    else
+    if (version == NSAPI_IPv4) {
+        memcpy(addr.bytes, bytes, NSAPI_IPv4_BYTES);
+    }
+
+    set_addr(addr);
+}
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+void SocketAddress::set_addr(nsapi_addr_t addr)
+{
+    delete[] _ip_address;
+    _ip_address = NULL;
+    _addr = addr;
+}
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+void SocketAddress::set_port(uint16_t port)
+{
+    _port = port;
+}
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+const char* SocketAddress::get_ip_address() const
+{
+    if (_addr.version == NSAPI_UNSPEC) {
+        return NULL;
+    }
+
+    if (!_ip_address) {
+        _ip_address = new char[NSAPI_IP_SIZE];
+        if (_addr.version == NSAPI_IPv4) {
+            ip4tos(_addr.bytes, _ip_address);
+        }
+        else
+        if (_addr.version == NSAPI_IPv6) {
+            ip6tos(_addr.bytes, _ip_address);
+        }
+    }
+
+    return _ip_address;
+}
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+const void* SocketAddress::get_ip_bytes() const
+{
+    return _addr.bytes;
+}
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+nsapi_version_t SocketAddress::get_ip_version() const
+{
+    return _addr.version;
+}
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+nsapi_addr_t SocketAddress::get_addr() const
+{
+    return _addr;
+}
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+uint16_t SocketAddress::get_port() const
+{
+    return _port;
+}
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+SocketAddress::operator bool() const
+{
+    if (_addr.version == NSAPI_IPv4) {
+        for (int i = 0; i < NSAPI_IPv4_BYTES; i++) {
+            if (_addr.bytes[i]) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+    else
+    if (_addr.version == NSAPI_IPv6) {
+        for (int i = 0; i < NSAPI_IPv6_BYTES; i++) {
+            if (_addr.bytes[i]) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+    else {
+        return false;
+    }
+}
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+SocketAddress &SocketAddress::operator=(const SocketAddress& addr)
+{
+    delete[] _ip_address;
+    _ip_address = NULL;
+    set_addr(addr.get_addr());
+    set_port(addr.get_port());
+    return *this;
+}
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+bool operator==(const SocketAddress& a, const SocketAddress& b)
+{
+    if (!a && !b) {
+        return true;
+    }
+    else
+    if (a._addr.version != b._addr.version) {
+        return false;
+    }
+    else
+    if (a._addr.version == NSAPI_IPv4) {
+        return memcmp(a._addr.bytes, b._addr.bytes, NSAPI_IPv4_BYTES) == 0;
+    }
+    else
+    if (a._addr.version == NSAPI_IPv6) {
+        return memcmp(a._addr.bytes, b._addr.bytes, NSAPI_IPv6_BYTES) == 0;
+    }
+
+    MBED_UNREACHABLE;
+}
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+bool operator!=(const SocketAddress& a, const SocketAddress& b)
+{
+    return !(a == b);
+}
+
+//void SocketAddress::_SocketAddress(NetworkStack *iface, const char *host, uint16_t port)
+//{
+//    _ip_address = NULL;
+//    // gethostbyname must check for literals, so can call it directly
+//    int err = iface->gethostbyname(host, this);
+//    _port = port;
+//    if (err) {
+//        _addr = nsapi_addr_t();
+//        _port = 0;
+//    }
+//}
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+SocketAddress::~SocketAddress()
+{
+    delete[] _ip_address;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SocketAddress.h	Tue Sep 03 09:16:55 2019 +0000
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+/** @file SocketAddress.h SocketAddress class */
+/** \addtogroup netsocket
+ * @{*/
+
+#ifndef SOCKET_ADDRESS_H
+#define SOCKET_ADDRESS_H
+
+#include "nsapi_types.h"
+#include "mbed_toolchain.h"
+
+// Predeclared classes
+class NetworkStack;
+class NetworkInterface;
+
+/** SocketAddress class
+ *
+ *  Representation of an IP address and port pair.
+ */
+class SocketAddress {
+public:
+    /** Create a SocketAddress from a hostname and port
+     *
+     *  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.
+     *
+     *  On failure, the IP address and port will be set to zero
+     *
+     *  @tparam S       Type of the Network stack
+     *  @param stack    Network stack to use for DNS resolution
+     *  @param host     Hostname to resolve
+     *  @param port     Optional 16-bit port, defaults to 0
+     *  @deprecated
+     *      Constructors hide possible errors. Replaced by
+     *      NetworkInterface::gethostbyname.
+     */
+    template <typename S>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1.3",
+                          "Constructors hide possible errors. Replaced by "
+                          "NetworkInterface::gethostbyname.")
+    SocketAddress(S *stack, const char *host, uint16_t port = 0)
+    {
+        _SocketAddress(nsapi_create_stack(stack), host, port);
+    }
+
+    /** Create a SocketAddress from a raw IP address and port
+     *
+     *  @note To construct from a host name, use NetworkInterface::gethostbyname
+     *
+     *  @param addr     Raw IP address
+     *  @param port     Optional 16-bit port, defaults to 0
+     */
+    SocketAddress(nsapi_addr_t addr = nsapi_addr_t(), uint16_t port = 0);
+
+    /** Create a SocketAddress from an IP address and port
+     *
+     *  @param addr     Null-terminated representation of the IP address
+     *  @param port     Optional 16-bit port, defaults to 0
+     */
+    SocketAddress(const char *addr, uint16_t port = 0);
+
+    /** Create a SocketAddress from raw IP bytes, IP version, and port
+     *
+     *  @param bytes    Raw IP address in big-endian order
+     *  @param version  IP address version, NSAPI_IPv4 or NSAPI_IPv6
+     *  @param port     Optional 16-bit port, defaults to 0
+     */
+    SocketAddress(const void *bytes, nsapi_version_t version, uint16_t port = 0);
+
+    /** Create a SocketAddress from another SocketAddress
+     *
+     *  @param addr  SocketAddress to copy
+     */
+    SocketAddress(const SocketAddress &addr);
+
+    /** Destructor */
+    ~SocketAddress();
+
+    /** Set the IP address
+     *
+     *  @param addr     Null-terminated represention of the IP address
+     *  @return         True if address is a valid representation of an IP address,
+     *                  otherwise False and SocketAddress is set to null
+     */
+    bool set_ip_address(const char *addr);
+
+    /** Set the raw IP bytes and IP version
+     *
+     *  @param bytes    Raw IP address in big-endian order
+     *  @param version  IP address version, NSAPI_IPv4 or NSAPI_IPv6
+     */
+    void set_ip_bytes(const void *bytes, nsapi_version_t version);
+
+    /** Set the raw IP address
+     *
+     *  @param addr     Raw IP address
+     */
+    void set_addr(nsapi_addr_t addr);
+
+    /** Set the port
+     *
+     *  @param port     16-bit port
+     */
+    void set_port(uint16_t port);
+
+    /** Get the human-readable IP address
+     *
+     *  Allocates memory for a string and converts binary address to
+     *  human-readable format. String is freed in the destructor.
+     *
+     *  @return         Null-terminated representation of the IP Address
+     */
+    const char *get_ip_address() const;
+
+    /** Get the raw IP bytes
+     *
+     *  @return         Raw IP address in big-endian order
+     */
+    const void *get_ip_bytes() const;
+
+    /** Get the IP address version
+     *
+     *  @return         IP address version, NSAPI_IPv4 or NSAPI_IPv6
+     */
+    nsapi_version_t get_ip_version() const;
+
+    /** Get the raw IP address
+     *
+     *  @return         Raw IP address
+     */
+    nsapi_addr_t get_addr() const;
+
+    /** Get the port
+     *
+     *  @return         The 16-bit port
+     */
+    uint16_t get_port() const;
+
+    /** Test if address is zero
+     *
+     *  @return         True if address is not zero
+     */
+    operator bool() const;
+
+    /** Copy address from another SocketAddress
+     *
+     * @param addr  SocketAddress to copy
+     */
+    SocketAddress &operator=(const SocketAddress &addr);
+
+    /** Compare two addresses for equality
+     *
+     *  @return         True if both addresses are equal
+     */
+    friend bool operator==(const SocketAddress &a, const SocketAddress &b);
+
+    /** Compare two addresses for equality
+     *
+     *  @return         True if both addresses are not equal
+     */
+    friend bool operator!=(const SocketAddress &a, const SocketAddress &b);
+
+private:
+    //void _SocketAddress(NetworkStack *iface, const char *host, uint16_t port);
+
+    /** Initialize memory */
+    void mem_init(void);
+
+    mutable char *_ip_address;
+    nsapi_addr_t _addr;
+    uint16_t _port;
+};
+
+
+#endif
+
+/** @}*/
--- a/UdpSocket.cpp	Sat Aug 31 20:34:52 2019 +0000
+++ b/UdpSocket.cpp	Tue Sep 03 09:16:55 2019 +0000
@@ -30,13 +30,47 @@
 #define UIP_ARPHDRSIZE  42
 #define UDPBUF          ((struct uip_udpip_hdr*) &uip_buf[UIP_LLH_LEN])
 
-// Constructor
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
 UdpSocket::UdpSocket() :
-    _uip_udp_conn(NULL)
+    _uip_udp_conn(NULL),
+    _timeout_ms(1000)
 {
     memset(&appdata, 0, sizeof(appdata));
 }
 
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+UdpSocket::UdpSocket(int timeout_ms) :
+    _uip_udp_conn(NULL),
+    _timeout_ms(timeout_ms)
+{
+    memset(&appdata, 0, sizeof(appdata));
+}
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+UdpSocket::UdpSocket(UipEthernet* net, int timeout_ms /*= 1000*/ ) :
+    _uip_udp_conn(NULL),
+    _timeout_ms(timeout_ms)
+{
+    memset(&appdata, 0, sizeof(appdata));
+    if (UipEthernet::ethernet != net)
+        UipEthernet::ethernet = net;
+}
+
 // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use
 uint8_t UdpSocket::begin(uint16_t port)
 {
@@ -67,6 +101,17 @@
     }
 }
 
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+void UdpSocket::close()
+{
+    stop();
+}
+
 // Sending UDP packets
 // Start building up a packet to send to the remote host specific in ip and port
 
@@ -222,13 +267,13 @@
 }
 
 // Number of bytes remaining in the current packet
-int UdpSocket::available()
+size_t UdpSocket::available()
 {
     UipEthernet::ethernet->tick();
     return UipEthernet::ethernet->enc28j60Eth.blockSize(appdata.packet_in);
 }
 
-// Read a single byte from the current packet
+// Read a single byte from the current packet. Returns -1 if no byte is available.
 int UdpSocket::read()
 {
     static unsigned char    c;
@@ -242,7 +287,7 @@
 // Read up to len bytes from the current packet and place them into buffer
 
 // Returns the number of bytes read, or 0 if none are available
-int UdpSocket::read(unsigned char* buffer, size_t len)
+size_t UdpSocket::read(unsigned char* buffer, size_t len)
 {
     UipEthernet::ethernet->tick();
     if (appdata.packet_in != NOBLOCK) {
@@ -372,3 +417,116 @@
     UipEthernet::ethernet->network_send();
 }
 #endif
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+nsapi_size_or_error_t UdpSocket::sendto(const char* host, uint16_t port, const void* data, size_t size)
+{
+    DnsClient   dns;
+    IpAddress   address;
+    uint32_t    address_bytes;
+
+    dns.begin(UipEthernet::ethernet->dnsServerIP());
+    if (dns.getHostByName(host, address) == 1) {
+        address_bytes = address;
+        _remote_addr = SocketAddress(&address_bytes, NSAPI_IPv4, port);
+    }
+    else {
+        _remote_addr = SocketAddress(host, port);
+    }
+
+    if (beginPacket(host, port) == 0) {
+        stop();
+        return NSAPI_ERROR_NO_ADDRESS;
+    }
+
+    if (write((uint8_t*)data, size) == 0) {
+        stop();
+        return NSAPI_ERROR_WOULD_BLOCK;
+    };
+
+    if (endPacket() <= 0) {
+        stop();
+        return NSAPI_ERROR_WOULD_BLOCK;
+    }
+
+    return NSAPI_ERROR_OK;
+}
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+nsapi_size_or_error_t UdpSocket::sendto(const SocketAddress& address, const void* data, size_t size)
+{
+    IpAddress   ip_addr(address.get_addr().bytes);
+    uint16_t    port = address.get_port();
+
+    _remote_addr = address;
+
+    if (beginPacket(ip_addr, port) == 0) {
+        stop();
+        return NSAPI_ERROR_NO_ADDRESS;
+    }
+
+    if (write((uint8_t*)data, size) == 0) {
+        stop();
+        return NSAPI_ERROR_WOULD_BLOCK;
+    };
+
+    if (endPacket() <= 0) {
+        stop();
+        return NSAPI_ERROR_WOULD_BLOCK;
+    }
+
+    return NSAPI_ERROR_OK;
+}
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+nsapi_size_or_error_t UdpSocket::recvfrom(SocketAddress* address, void* data, size_t size)
+{
+    *address = _remote_addr;
+
+    Timer   timer;
+    int     success;
+
+    timer.start();
+    do {
+        success = parsePacket();
+    } while (!success && (timer.read_ms() < _timeout_ms));
+
+    if (!success) {
+        stop();
+        return NSAPI_ERROR_WOULD_BLOCK;
+    }
+
+    size_t      n;
+    size_t      recv_count = 0;
+    uint8_t*    pos = (uint8_t*)data;
+
+    do {
+        if (recv_count + available() <= size) {
+            n = read(pos, available());
+            pos += n;
+            recv_count += n;
+        }
+        else {
+            return NSAPI_ERROR_NO_MEMORY;
+        }
+    } while ((available() > 0) && (recv_count < size));
+
+    flush();
+
+    return NSAPI_ERROR_OK;
+}
--- a/UdpSocket.h	Sat Aug 31 20:34:52 2019 +0000
+++ b/UdpSocket.h	Tue Sep 03 09:16:55 2019 +0000
@@ -22,6 +22,7 @@
 #define UDPSOCKET_h
 
 #include "mbed.h"
+#include "SocketAddress.h"
 #include "utility/Udp.h"
 #include "IpAddress.h"
 #include "utility/MemPool.h"
@@ -42,16 +43,23 @@
     bool        send;
 } uip_udp_userdata_t;
 
+class UipEthernet;
+
 class UdpSocket :  public Udp
 {
 private:
+    uip_udp_userdata_t      appdata;
     struct uip_udp_conn*    _uip_udp_conn;
-    uip_udp_userdata_t      appdata;
+    SocketAddress           _remote_addr;
+    int                     _timeout_ms;
 public:
-    UdpSocket();                    // Constructor
-    virtual     ~UdpSocket()    { } // Virtual destructor
-    uint8_t     begin(uint16_t);    // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use
-    void        stop();             // Finish with the UDP socket
+    UdpSocket();                        // Constructor
+    UdpSocket(int timeout_ms);          // Constructor
+    UdpSocket(UipEthernet* ethernet, int timeout_ms = 1000);
+    virtual     ~UdpSocket()    { }     // Virtual destructor
+    uint8_t     begin(uint16_t port);   // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use
+    void        stop();                 // Finish with the UDP socket
+    void        close();                // Close the UDP socket
     // Sending UDP packets
     // Start building up a packet to send to the remote host specific in ip and port
     // Returns 1 if successful, 0 if there was a problem with the supplied IP address or port
@@ -77,18 +85,18 @@
     int         parsePacket();
 
     // Number of bytes remaining in the current packet
-    int         available();
+    size_t      available();
 
     // Read a single byte from the current packet
     int         read();
 
     // Read up to len bytes from the current packet and place them into buffer
     // Returns the number of bytes read, or 0 if none are available
-    int         read(unsigned char* buffer, size_t len);
+    size_t      read(unsigned char* buffer, size_t len);
     // Read up to len characters from the current packet and place them into buffer
 
     // Returns the number of characters read, or 0 if none are available
-    int         read(char* buffer, size_t len)  { return read((unsigned char*)buffer, len); }
+    size_t      read(char* buffer, size_t len)  { return read((unsigned char*)buffer, len); }
 
     // Return the next byte from the current packet without moving on to the next byte
     int         peek();
@@ -99,6 +107,14 @@
 
     // Return the port of the host who sent the current incoming packet
     uint16_t    remotePort();
+
+    // Send data to the specified host and port.
+    nsapi_size_or_error_t sendto (const char *host, uint16_t port, const void *data, size_t size);
+    // Send data to the specified address.
+    nsapi_size_or_error_t sendto (const SocketAddress &address, const void *data, size_t size);
+    // Receive a datagram and store the source address in address if it's not NULL.
+    nsapi_size_or_error_t recvfrom (SocketAddress *address, void *data, size_t size);
+
 private:
     friend void     uipudp_appcall();
 
--- a/UipEthernet.cpp	Sat Aug 31 20:34:52 2019 +0000
+++ b/UipEthernet.cpp	Tue Sep 03 09:16:55 2019 +0000
@@ -136,12 +136,14 @@
                 dhcpClient.getGatewayIp(),
                 dhcpClient.getSubnetMask()
             );
+
+            return 0;
         }
 
-        return ret;
+        return -1;
     }
     else {
-        return 1;
+        return 0;
     }
 }
 
--- a/UipEthernet.h	Sat Aug 31 20:34:52 2019 +0000
+++ b/UipEthernet.h	Tue Sep 03 09:16:55 2019 +0000
@@ -37,6 +37,7 @@
 {
 #include "utility/uip_timer.h"
 #include "utility/uip.h"
+#include "utility/util.h"
 }
 #define UIPETHERNET_FREEPACKET  1
 #define UIPETHERNET_SENDPACKET  2
--- a/utility/Enc28j60Eth.cpp	Sat Aug 31 20:34:52 2019 +0000
+++ b/utility/Enc28j60Eth.cpp	Tue Sep 03 09:16:55 2019 +0000
@@ -244,7 +244,7 @@
  * @param
  * @retval
  */
-memaddress Enc28j60Eth::blockSize(memhandle handle)
+size_t Enc28j60Eth::blockSize(memhandle handle)
 {
     return handle == NOBLOCK ? 0 : handle == UIP_RECEIVEBUFFERHANDLE ? receivePkt.size : blocks[handle].size;
 }
--- a/utility/Enc28j60Eth.h	Sat Aug 31 20:34:52 2019 +0000
+++ b/utility/Enc28j60Eth.h	Tue Sep 03 09:16:55 2019 +0000
@@ -65,7 +65,7 @@
     void        init(uint8_t* macaddr);
     memhandle   receivePacket();
     void        freePacket();
-    memaddress  blockSize(memhandle handle);
+    size_t      blockSize(memhandle handle);
     void        sendPacket(memhandle handle);
     uint16_t    readPacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len);
     uint16_t    writePacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len);
--- a/utility/Udp.h	Sat Aug 31 20:34:52 2019 +0000
+++ b/utility/Udp.h	Tue Sep 03 09:16:55 2019 +0000
@@ -67,21 +67,21 @@
     virtual int         parsePacket(void) = 0;
 
     // Number of bytes remaining in the current packet
-    virtual int         available(void) = 0;
+    virtual size_t      available(void) = 0;
 
-    // Read a single byte from the current packet
+    // Read a single byte from the current packet. Returns -1 if no byte is available.
     virtual int         read(void) = 0;
 
     // Read up to len bytes from the current packet and place them into buffer
     // Returns the number of bytes read, or 0 if none are available
-    virtual int         read(unsigned char* buffer, size_t len) = 0;
+    virtual size_t      read(unsigned char* buffer, size_t len) = 0;
 
     // Read up to len characters from the current packet and place them into buffer
     // Returns the number of characters read, or 0 if none are available
-    virtual int         read(char* buffer, size_t len) = 0;
+    virtual size_t      read(char* buffer, size_t len) = 0;
 
     // Return the next byte from the current packet without moving on to the next byte
-    virtual int         peek(void) = 0;
+    virtual int         peek(void) = 0;         // returns -1 if fails
     virtual void        flush(void) = 0;        // Finish reading the current packet
 
     // Return the IP address of the host who sent the current incoming packet
@@ -90,6 +90,6 @@
     // Return the port of the host who sent the current incoming packet
     virtual uint16_t    remotePort(void) = 0;
 protected:
-    uint8_t*    rawIPAddress(IpAddress& addr)   { return addr.rawAddress(); };
+    uint8_t*    rawIPAddress(IpAddress& addr)   { return addr.rawAddress(); }
 };
 #endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utility/common_functions.c	Tue Sep 03 09:16:55 2019 +0000
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2014-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Most functions can be inlined, and definitions are in common_functions.h.
+ * Define COMMON_FUNCTIONS_FN before including it to generate external definitions.
+ */
+
+#include "mbed_version.h"
+
+#if MBED_MAJOR_VERSION == 2
+
+#define COMMON_FUNCTIONS_FN extern
+
+#include "common_functions.h"
+
+#include <string.h>
+
+/* Returns mask for <split_value> (0-8) most-significant bits of a byte */
+static inline uint8_t context_split_mask(uint_fast8_t split_value)
+{
+    return (uint8_t) - (0x100u >> split_value);
+}
+
+bool bitsequal(const uint8_t *a, const uint8_t *b, uint_fast8_t bits)
+{
+    uint_fast8_t bytes = bits / 8;
+    bits %= 8;
+
+    if (bytes && memcmp(a, b, bytes)) {
+        return false;
+    }
+
+    if (bits) {
+        uint_fast8_t split_bit = context_split_mask(bits);
+        if ((a[bytes] & split_bit) != (b[bytes] & split_bit)) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+uint8_t *bitcopy(uint8_t *restrict dst, const uint8_t *restrict src, uint_fast8_t bits)
+{
+    uint_fast8_t bytes = bits / 8;
+    bits %= 8;
+
+    if (bytes) {
+        dst = (uint8_t *) memcpy(dst, src, bytes) + bytes;
+        src += bytes;
+    }
+
+    if (bits) {
+        uint_fast8_t split_bit = context_split_mask(bits);
+        *dst = (*src & split_bit) | (*dst & ~ split_bit);
+    }
+
+    return dst;
+}
+
+uint8_t *bitcopy0(uint8_t *restrict dst, const uint8_t *restrict src, uint_fast8_t bits)
+{
+    uint_fast8_t bytes = bits / 8;
+    bits %= 8;
+
+    if (bytes) {
+        dst = (uint8_t *) memcpy(dst, src, bytes) + bytes;
+        src += bytes;
+    }
+
+    if (bits) {
+        uint_fast8_t split_bit = context_split_mask(bits);
+        *dst = (*src & split_bit);
+    }
+
+    return dst;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utility/common_functions.h	Tue Sep 03 09:16:55 2019 +0000
@@ -0,0 +1,638 @@
+/*
+ * Copyright (c) 2014-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef COMMON_FUNCTIONS_H_
+#define COMMON_FUNCTIONS_H_
+
+#include "ns_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Common write 64-bit variable to 8-bit pointer.
+ *
+ * Write 64 bits in big-endian (network) byte order.
+ *
+ * \param value 64-bit variable
+ * \param ptr pointer where data to be written
+ *
+ * \return updated pointer
+ */
+NS_INLINE uint8_t *common_write_64_bit(uint64_t value, uint8_t ptr[__static 8]);
+
+/*
+ * Common read 64-bit variable from 8-bit pointer.
+ *
+ * Read 64 bits in big-endian (network) byte order.
+ *
+ * \param data_buf pointer where data to be read
+ *
+ * \return 64-bit variable
+ */
+NS_INLINE uint64_t common_read_64_bit(const uint8_t data_buf[__static 8]);
+
+/*
+ * Common write 32-bit variable to 8-bit pointer.
+ *
+ * Write 32 bits in big-endian (network) byte order.
+ *
+ * \param value 32-bit variable
+ * \param ptr pointer where data to be written
+ *
+ * \return updated pointer
+ */
+NS_INLINE uint8_t *common_write_32_bit(uint32_t value, uint8_t ptr[__static 4]);
+
+/*
+ * Common read 32-bit variable from 8-bit pointer.
+ *
+ * Read 32 bits in big-endian (network) byte order.
+ *
+ * \param data_buf pointer where data to be read
+ *
+ * \return 32-bit variable
+ */
+NS_INLINE uint32_t common_read_32_bit(const uint8_t data_buf[__static 4]);
+
+/*
+ * Common write 32-bit variable to 8-bit pointer.
+ *
+ * Write 32 bits in little-endian byte order.
+ *
+ * \param value 32-bit variable
+ * \param ptr pointer where data to be written
+ *
+ * \return updated pointer
+ */
+NS_INLINE uint8_t *common_write_32_bit_inverse(uint32_t value, uint8_t ptr[__static 4]);
+
+/*
+ * Common read 32-bit variable from 8-bit pointer.
+ *
+ * Read 32 bits in little-endian byte order.
+ *
+ * \param data_buf pointer where data to be read
+ *
+ * \return 32-bit variable
+ */
+NS_INLINE uint32_t common_read_32_bit_inverse(const uint8_t data_buf[__static 4]);
+
+/*
+ * Common write 24-bit variable to 8-bit pointer.
+ *
+ * Write 24 bits in big-endian (network) byte order.
+ *
+ * \param value 24-bit variable
+ * \param ptr pointer where data to be written
+ *
+ * \return updated pointer
+ */
+NS_INLINE uint8_t *common_write_24_bit(uint_fast24_t value, uint8_t ptr[__static 3]);
+
+/*
+ * Common read 24-bit variable from 8-bit pointer.
+ *
+ * Read 24 bits in big-endian (network) byte order.
+ *
+ * \param data_buf pointer where data to be read
+ *
+ * \return 24-bit variable
+ */
+NS_INLINE uint_fast24_t common_read_24_bit(const uint8_t data_buf[__static 3]);
+
+/*
+ * Common write 24-bit variable to 8-bit pointer.
+ *
+ * Write 24 bits in little-endian byte order.
+ *
+ * \param value 24-bit variable
+ * \param ptr pointer where data to be written
+ *
+ * \return updated pointer
+ */
+NS_INLINE uint8_t *common_write_24_bit_inverse(uint_fast24_t value, uint8_t ptr[__static 3]);
+
+/*
+ * Common read 24-bit variable from 8-bit pointer.
+ *
+ * Read 24 bits in little-endian byte order.
+ *
+ * \param data_buf pointer where data to be read
+ *
+ * \return 24-bit variable
+ */
+NS_INLINE uint_fast24_t common_read_24_bit_inverse(const uint8_t data_buf[__static 3]);
+
+/*
+ * Common write 16-bit variable to 8-bit pointer.
+ *
+ * Write 16 bits in big-endian (network) byte order.
+ *
+ * \param value 16-bit variable
+ * \param ptr pointer where data to be written
+ *
+ * \return updated pointer
+ */
+NS_INLINE uint8_t *common_write_16_bit(uint16_t value, uint8_t ptr[__static 2]);
+
+/*
+ * Common read 16-bit variable from 8-bit pointer.
+ *
+ * Read 16 bits in big-endian (network) byte order.
+ *
+ * \param data_buf pointer where data to be read
+ *
+ * \return 16-bit variable
+ */
+NS_INLINE uint16_t common_read_16_bit(const uint8_t data_buf[__static 2]);
+
+/*
+ * Common write 16-bit variable to 8-bit pointer.
+ *
+ * Write 16 bits in little-endian byte order.
+ *
+ * \param value 16-bit variable
+ * \param ptr pointer where data to be written
+ *
+ * \return updated pointer
+ */
+NS_INLINE uint8_t *common_write_16_bit_inverse(uint16_t value, uint8_t ptr[__static 2]);
+
+/*
+ * Common read 16-bit variable from 8-bit pointer.
+ *
+ * Read 16 bits in little-endian byte order.
+ *
+ * \param data_buf pointer where data to be read
+ *
+ * \return 16-bit variable
+ */
+NS_INLINE uint16_t common_read_16_bit_inverse(const uint8_t data_buf[__static 2]);
+
+/*
+ * Count bits in a byte
+ *
+ * \param value byte to inspect
+ *
+ * \return number of 1-bits in byte
+ */
+NS_INLINE uint_fast8_t common_count_bits(uint8_t value);
+
+/*
+ * Count leading zeros in a byte
+ *
+ * \deprecated Use common_count_leading_zeros_8
+ *
+ * \param value byte to inspect
+ *
+ * \return number of leading zeros in byte (0-8)
+ */
+NS_INLINE uint_fast8_t common_count_leading_zeros(uint8_t value);
+
+/*
+ * Count leading zeros in a byte
+ *
+ * \param value byte to inspect
+ *
+ * \return number of leading zeros in byte (0-8)
+ */
+NS_INLINE uint_fast8_t common_count_leading_zeros_8(uint8_t value);
+
+/*
+ * Count leading zeros in a 16-bit value
+ *
+ * \param value value to inspect
+ *
+ * \return number of leading zeros in byte (0-16)
+ */
+NS_INLINE uint_fast8_t common_count_leading_zeros_16(uint16_t value);
+
+/*
+ * Count leading zeros in a 32-bit value
+ *
+ * \param value value to inspect
+ *
+ * \return number of leading zeros in byte (0-32)
+ */
+NS_INLINE uint_fast8_t common_count_leading_zeros_32(uint32_t value);
+
+/*
+ * Compare 8-bit serial numbers
+ *
+ * Compare two 8-bit serial numbers, according to RFC 1982 Serial Number
+ * Arithmetic.
+ *
+ * \param s1 first serial number
+ * \param s2 second serial number
+ *
+ * \return true if s1 > s2
+ * \return false if s1 <= s2, or the comparison is undefined
+ */
+NS_INLINE bool common_serial_number_greater_8(uint8_t s1, uint8_t s2);
+
+/*
+ * Compare 16-bit serial numbers
+ *
+ * Compare two 16-bit serial numbers, according to RFC 1982 Serial Number
+ * Arithmetic.
+ *
+ * \param s1 first serial number
+ * \param s2 second serial number
+ *
+ * \return true if s1 > s2
+ * \return false if s1 <= s2, or the comparison is undefined
+ */
+NS_INLINE bool common_serial_number_greater_16(uint16_t s1, uint16_t s2);
+
+/*
+ * Compare 32-bit serial numbers
+ *
+ * Compare two 32-bit serial numbers, according to RFC 1982 Serial Number
+ * Arithmetic.
+ *
+ * \param s1 first serial number
+ * \param s2 second serial number
+ *
+ * \return true if s1 > s2
+ * \return false if s1 <= s2, or the comparison is undefined
+ */
+NS_INLINE bool common_serial_number_greater_32(uint32_t s1, uint32_t s2);
+
+/*
+ * Test a bit in an bit array.
+ *
+ * Check whether a particular bit is set in a bit string. The bit array
+ * is in big-endian (network) bit order.
+ *
+ * \param bitset pointer to bit array
+ * \param bit index of bit - 0 is the most significant bit of the first byte
+ *
+ * \return true if the bit is set
+ */
+NS_INLINE bool bit_test(const uint8_t *bitset, uint_fast8_t bit);
+
+/*
+ * Set a bit in an bit array.
+ *
+ * Set a bit in a bit array. The array is in big-endian (network) bit order.
+ *
+ * \param bitset pointer to bit array
+ * \param bit index of bit - 0 is the most significant bit of the first byte
+ */
+NS_INLINE void bit_set(uint8_t *bitset, uint_fast8_t bit);
+
+/*
+ * Clear a bit in an bit array.
+ *
+ * Clear a bit in a bit array. The bit array is in big-endian (network) bit order.
+ *
+ * \param bitset pointer to bit array
+ * \param bit index of bit - 0 is the most significant bit of the first byte
+ */
+NS_INLINE void bit_clear(uint8_t *bitset, uint_fast8_t bit);
+
+/*
+ * Compare two bitstrings.
+ *
+ * Compare two bitstrings of specified length. The bit strings are in
+ * big-endian (network) bit order.
+ *
+ * \param a pointer to first string
+ * \param b pointer to second string
+ * \param bits number of bits to compare
+ *
+ * \return true if the strings compare equal
+ */
+bool bitsequal(const uint8_t *a, const uint8_t *b, uint_fast8_t bits);
+
+/*
+ * Copy a bitstring
+ *
+ * Copy a bitstring of specified length. The bit string is in big-endian
+ * (network) bit order. Bits beyond the bitlength at the destination are not
+ * modified.
+ *
+ * For example, copying 4 bits sets the first 4 bits of dst[0] from src[0],
+ * the lower 4 bits of dst[0] are unmodified.
+ *
+ * \param dst destination pointer
+ * \param src source pointer
+ * \param bits number of bits to copy
+ *
+ * \return the value of dst
+ */
+uint8_t *bitcopy(uint8_t *restrict dst, const uint8_t *restrict src, uint_fast8_t bits);
+
+/*
+ * Copy a bitstring and pad last byte with zeros
+ *
+ * Copy a bitstring of specified length. The bit string is in big-endian
+ * (network) bit order. Bits beyond the bitlength in the last destination byte are
+ * zeroed.
+ *
+ * For example, copying 4 bits sets the first 4 bits of dst[0] from src[0], and
+ * the lower 4 bits of dst[0] are set to 0.
+ *
+ * \param dst destination pointer
+ * \param src source pointer
+ * \param bits number of bits to copy
+ *
+ * \return the value of dst
+ */
+uint8_t *bitcopy0(uint8_t *restrict dst, const uint8_t *restrict src, uint_fast8_t bits);
+
+/* Provide definitions, either for inlining, or for common_functions.c */
+#if defined NS_ALLOW_INLINING || defined COMMON_FUNCTIONS_FN
+#ifndef COMMON_FUNCTIONS_FN
+#define COMMON_FUNCTIONS_FN NS_INLINE
+#endif
+
+COMMON_FUNCTIONS_FN uint8_t *common_write_64_bit(uint64_t value, uint8_t ptr[__static 8])
+{
+    *ptr++ = value >> 56;
+    *ptr++ = value >> 48;
+    *ptr++ = value >> 40;
+    *ptr++ = value >> 32;
+    *ptr++ = value >> 24;
+    *ptr++ = value >> 16;
+    *ptr++ = value >> 8;
+    *ptr++ = value;
+    return ptr;
+}
+
+COMMON_FUNCTIONS_FN uint64_t common_read_64_bit(const uint8_t data_buf[__static 8])
+{
+    uint64_t temp_64;
+    temp_64 = (uint64_t)(*data_buf++) << 56;
+    temp_64 += (uint64_t)(*data_buf++) << 48;
+    temp_64 += (uint64_t)(*data_buf++) << 40;
+    temp_64 += (uint64_t)(*data_buf++) << 32;
+    temp_64 += (uint64_t)(*data_buf++) << 24;
+    temp_64 += (uint64_t)(*data_buf++) << 16;
+    temp_64 += (uint64_t)(*data_buf++) << 8;
+    temp_64 += *data_buf++;
+    return temp_64;
+}
+
+COMMON_FUNCTIONS_FN uint8_t *common_write_32_bit(uint32_t value, uint8_t ptr[__static 4])
+{
+    *ptr++ = value >> 24;
+    *ptr++ = value >> 16;
+    *ptr++ = value >> 8;
+    *ptr++ = value;
+    return ptr;
+}
+
+COMMON_FUNCTIONS_FN uint32_t common_read_32_bit(const uint8_t data_buf[__static 4])
+{
+    uint32_t temp_32;
+    temp_32 = (uint32_t)(*data_buf++) << 24;
+    temp_32 += (uint32_t)(*data_buf++) << 16;
+    temp_32 += (uint32_t)(*data_buf++) << 8;
+    temp_32 += *data_buf++;
+    return temp_32;
+}
+
+COMMON_FUNCTIONS_FN uint8_t *common_write_32_bit_inverse(uint32_t value, uint8_t ptr[__static 4])
+{
+    *ptr++ = value;
+    *ptr++ = value >> 8;
+    *ptr++ = value >> 16;
+    *ptr++ = value >> 24;
+    return ptr;
+}
+
+COMMON_FUNCTIONS_FN uint32_t common_read_32_bit_inverse(const uint8_t data_buf[__static 4])
+{
+    uint32_t temp_32;
+    temp_32 =  *data_buf++;
+    temp_32 += (uint32_t)(*data_buf++) << 8;
+    temp_32 += (uint32_t)(*data_buf++) << 16;
+    temp_32 += (uint32_t)(*data_buf++) << 24;
+    return temp_32;
+}
+
+COMMON_FUNCTIONS_FN uint8_t *common_write_24_bit(uint_fast24_t value, uint8_t ptr[__static 3])
+{
+    *ptr++ = value >> 16;
+    *ptr++ = value >> 8;
+    *ptr++ = value;
+    return ptr;
+}
+
+COMMON_FUNCTIONS_FN uint_fast24_t common_read_24_bit(const uint8_t data_buf[__static 3])
+{
+    uint_fast24_t temp_24;
+    temp_24 = (uint_fast24_t)(*data_buf++) << 16;
+    temp_24 += (uint_fast24_t)(*data_buf++) << 8;
+    temp_24 += *data_buf++;
+    return temp_24;
+}
+
+COMMON_FUNCTIONS_FN uint8_t *common_write_24_bit_inverse(uint_fast24_t value, uint8_t ptr[__static 3])
+{
+    *ptr++ = value;
+    *ptr++ = value >> 8;
+    *ptr++ = value >> 16;
+    return ptr;
+}
+
+COMMON_FUNCTIONS_FN uint_fast24_t common_read_24_bit_inverse(const uint8_t data_buf[__static 3])
+{
+    uint_fast24_t temp_24;
+    temp_24 =  *data_buf++;
+    temp_24 += (uint_fast24_t)(*data_buf++) << 8;
+    temp_24 += (uint_fast24_t)(*data_buf++) << 16;
+    return temp_24;
+}
+
+COMMON_FUNCTIONS_FN uint8_t *common_write_16_bit(uint16_t value, uint8_t ptr[__static 2])
+{
+    *ptr++ = value >> 8;
+    *ptr++ = value;
+    return ptr;
+}
+
+COMMON_FUNCTIONS_FN uint16_t common_read_16_bit(const uint8_t data_buf[__static 2])
+{
+    uint16_t temp_16;
+    temp_16 = (uint16_t)(*data_buf++) << 8;
+    temp_16 += *data_buf++;
+    return temp_16;
+}
+
+COMMON_FUNCTIONS_FN uint8_t *common_write_16_bit_inverse(uint16_t value, uint8_t ptr[__static 2])
+{
+    *ptr++ = value;
+    *ptr++ = value >> 8;
+    return ptr;
+}
+
+COMMON_FUNCTIONS_FN uint16_t common_read_16_bit_inverse(const uint8_t data_buf[__static 2])
+{
+    uint16_t temp_16;
+    temp_16 = *data_buf++;
+    temp_16 += (uint16_t)(*data_buf++) << 8;
+    return temp_16;
+}
+
+COMMON_FUNCTIONS_FN uint_fast8_t common_count_bits(uint8_t value)
+{
+    /* First step sets each bit pair to be count of bits (00,01,10) */
+    /* [00-00 = 00, 01-00 = 01, 10-01 = 01, 11-01 = 10] */
+    uint_fast8_t count = value - ((value >> 1) & 0x55);
+    /* Add bit pairs to make each nibble contain count of bits (0-4) */
+    count = (count & 0x33) + ((count >> 2) & 0x33);
+    /* Final result is sum of nibbles (0-8) */
+    count = (count >> 4) + (count & 0x0F);
+    return count;
+}
+
+COMMON_FUNCTIONS_FN uint_fast8_t common_count_leading_zeros(uint8_t value)
+{
+    return common_count_leading_zeros_8(value);
+}
+
+COMMON_FUNCTIONS_FN uint_fast8_t common_count_leading_zeros_8(uint8_t value)
+{
+#ifdef  __CC_ARM
+    return value ? __clz((unsigned int) value << 24) : 8;
+#elif defined __GNUC__
+    return value ? __builtin_clz((unsigned int) value << 24) : 8;
+#else
+    uint_fast8_t cnt = 0;
+    if (value == 0) {
+        return 8;
+    }
+    if ((value & 0xF0) == 0) {
+        value <<= 4;
+        cnt += 4;
+    }
+    if ((value & 0xC0) == 0) {
+        value <<= 2;
+        cnt += 2;
+    }
+    if ((value & 0x80) == 0) {
+        cnt += 1;
+    }
+
+    return cnt;
+#endif
+}
+
+COMMON_FUNCTIONS_FN uint_fast8_t common_count_leading_zeros_16(uint16_t value)
+{
+#ifdef  __CC_ARM
+    return value ? __clz((unsigned int) value << 16) : 16;
+#elif defined __GNUC__
+    return value ? __builtin_clz((unsigned int) value << 16) : 16;
+#else
+    uint_fast8_t cnt = 0;
+    if (value == 0) {
+        return 16;
+    }
+    if ((value & 0xFF00) == 0) {
+        value <<= 8;
+        cnt += 8;
+    }
+    if ((value & 0xF000) == 0) {
+        value <<= 4;
+        cnt += 4;
+    }
+    if ((value & 0xC000) == 0) {
+        value <<= 2;
+        cnt += 2;
+    }
+    if ((value & 0x8000) == 0) {
+        cnt += 1;
+    }
+
+    return cnt;
+#endif
+}
+
+COMMON_FUNCTIONS_FN uint_fast8_t common_count_leading_zeros_32(uint32_t value)
+{
+#ifdef  __CC_ARM
+    return __clz(value);
+#elif defined __GNUC__
+    return value ? __builtin_clz(value) : 32;
+#else
+    uint_fast8_t cnt = 0;
+    if (value == 0) {
+        return 32;
+    }
+    if ((value & 0xFFFF0000) == 0) {
+        value <<= 16;
+        cnt += 16;
+    }
+    if ((value & 0xFF000000) == 0) {
+        value <<= 8;
+        cnt += 8;
+    }
+    if ((value & 0xF0000000) == 0) {
+        value <<= 4;
+        cnt += 4;
+    }
+    if ((value & 0xC0000000) == 0) {
+        value <<= 2;
+        cnt += 2;
+    }
+    if ((value & 0x80000000) == 0) {
+        cnt += 1;
+    }
+
+    return cnt;
+#endif
+}
+
+COMMON_FUNCTIONS_FN bool common_serial_number_greater_8(uint8_t s1, uint8_t s2)
+{
+    return (s1 > s2 && s1 - s2 < UINT8_C(0x80)) || (s1 < s2 && s2 - s1 > UINT8_C(0x80));
+}
+
+COMMON_FUNCTIONS_FN bool common_serial_number_greater_16(uint16_t s1, uint16_t s2)
+{
+    return (s1 > s2 && s1 - s2 < UINT16_C(0x8000)) || (s1 < s2 && s2 - s1 > UINT16_C(0x8000));
+}
+
+COMMON_FUNCTIONS_FN bool common_serial_number_greater_32(uint32_t s1, uint32_t s2)
+{
+    return (s1 > s2 && s1 - s2 < UINT32_C(0x80000000)) || (s1 < s2 && s2 - s1 > UINT32_C(0x80000000));
+}
+
+COMMON_FUNCTIONS_FN bool bit_test(const uint8_t *bitset, uint_fast8_t bit)
+{
+    return bitset[bit >> 3] & (0x80 >> (bit & 7));
+}
+
+COMMON_FUNCTIONS_FN void bit_set(uint8_t *bitset, uint_fast8_t bit)
+{
+    bitset[bit >> 3] |= (0x80 >> (bit & 7));
+}
+
+COMMON_FUNCTIONS_FN void bit_clear(uint8_t *bitset, uint_fast8_t bit)
+{
+    bitset[bit >> 3] &= ~(0x80 >> (bit & 7));
+}
+
+#endif /* defined NS_ALLOW_INLINING || defined COMMON_FUNCTIONS_FN */
+
+#ifdef __cplusplus
+}
+#endif
+#endif /*__COMMON_FUNCTIONS_H_*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utility/ip4string.h	Tue Sep 03 09:16:55 2019 +0000
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2014-2018 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef IP4STRING_H
+#define IP4STRING_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "ns_types.h"
+
+/**
+ * Print binary IPv4 address to a string.
+ *
+ * String must contain enough room for full address, 16 bytes exact.
+ *
+ * \param ip4addr IPv4 address.
+ * \param p buffer to write string to.
+ * \return length of generated string excluding the terminating null character
+ */
+uint_fast8_t ip4tos(const void *ip4addr, char *p);
+
+/**
+ * Convert numeric IPv4 address string to a binary.
+ *
+ * \param ip4addr IPv4 address in string format.
+ * \param len Length of IPv4 string, maximum of 16..
+ * \param dest buffer for address. MUST be 4 bytes.
+ * \return boolean set to true if conversion succeed, false if it didn't
+ */
+bool stoip4(const char *ip4addr, size_t len, void *dest);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utility/ip4tos.c	Tue Sep 03 09:16:55 2019 +0000
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2014-2018 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "mbed_version.h"
+
+#if MBED_MAJOR_VERSION == 2
+
+#include <stdio.h>
+#include <string.h>
+#include "common_functions.h"
+#include "ip4string.h"
+
+static void ipv4_itoa(char *string, uint8_t byte);
+
+/**
+ * Print binary IPv4 address to a string.
+ * String must contain enough room for full address, 16 bytes exact.
+ * \param addr IPv4 address.
+ * \p buffer to write string to.
+ */
+uint_fast8_t ip4tos(const void *ip4addr, char *p)
+{
+    uint_fast8_t outputPos = 0;
+    const uint8_t *byteArray = ip4addr;
+
+    for (uint_fast8_t component = 0; component < 4; ++component) {
+        //Convert the byte to string
+        ipv4_itoa(&p[outputPos], byteArray[component]);
+
+        //Move outputPos to the end of the string
+        while (p[outputPos] != '\0') {
+            outputPos += 1;
+        }
+
+        //Append a dot if this is not the last digit
+        if (component < 3) {
+            p[outputPos++] = '.';
+        }
+    }
+
+    // Return length of generated string, excluding the terminating null character
+    return outputPos;
+}
+
+static void ipv4_itoa(char *string, uint8_t byte)
+{
+    char *baseString = string;
+
+    //Write the digits to the buffer from the least significant to the most
+    //  This is the incorrect order but we will swap later
+    do {
+        *string++ = '0' + byte % 10;
+        byte /= 10;
+    } while (byte);
+
+    //We put the final \0, then go back one step on the last digit for the swap
+    *string-- = '\0';
+
+    //We now swap the digits
+    while (baseString < string) {
+        uint8_t tmp = *string;
+        *string-- = *baseString;
+        *baseString++ = tmp;
+    }
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utility/ip6string.h	Tue Sep 03 09:16:55 2019 +0000
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2014-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef IP6STRING_H
+#define IP6STRING_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "ns_types.h"
+
+#define MAX_IPV6_STRING_LEN_WITH_TRAILING_NULL 40
+
+/**
+ * Print binary IPv6 address to a string.
+ *
+ * String must contain enough room for full address, 40 bytes exact.
+ * IPv4 tunneling addresses are not covered.
+ *
+ * \param ip6addr IPv6 address.
+ * \param p buffer to write string to.
+ * \return length of generated string excluding the terminating null character
+ */
+uint_fast8_t ip6tos(const void *ip6addr, char *p);
+
+/**
+ * Print binary IPv6 prefix to a string.
+ *
+ * String buffer `p` must contain enough room for a full address and prefix length, 44 bytes exact.
+ * Bits in the `prefix` buffer beyond `prefix_len` bits are not shown and only the bytes containing the
+ * prefix bits are read. I.e. for a 20 bit prefix 3 bytes are read, and for a 0 bit prefix 0 bytes are
+ * read (thus if `prefix_len` is zero, `prefix` can be NULL).
+ * `prefix_len` must be 0 to 128.
+ *
+ * \param prefix IPv6 prefix.
+ * \param prefix_len length of `prefix` in bits.
+ * \param p buffer to write string to.
+ * \return length of generated string excluding the terminating null character, or 0 for an error, such as 'prefix_len' > 128
+ */
+uint_fast8_t ip6_prefix_tos(const void *prefix, uint_fast8_t prefix_len, char *p);
+
+/**
+ * Convert numeric IPv6 address string to a binary.
+ *
+ * IPv4 tunneling addresses are not covered.
+ *
+ * \param ip6addr IPv6 address in string format.
+ * \param len Lenght of ipv6 string, maximum of 41.
+ * \param dest buffer for address. MUST be 16 bytes. Filled with 0 on error.
+ * \return boolean set to true if conversion succeed, false if it didn't
+ */
+bool stoip6(const char *ip6addr, size_t len, void *dest);
+/**
+ * Find out numeric IPv6 address prefix length.
+ *
+ * \param ip6addr  IPv6 address in string format
+ * \return prefix length or 0 if it not given
+ */
+unsigned char sipv6_prefixlength(const char *ip6addr);
+
+/**
+ * Convert numeric IPv6 address string with prefix to a binary.
+ *
+ * IPv4 tunneling addresses are not covered.
+ *
+ * \param ip6addr IPv6 address in string format.
+ * \param dest buffer for address. MUST be 16 bytes.
+ * \param prefix_len_out length of prefix, is set to -1 if no prefix given
+ *
+ * \return 0 on success, negative value otherwise. prefix_len_out contains prefix length.
+  */
+int stoip6_prefix(const char *ip6addr, void *dest, int_fast16_t *prefix_len_out);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utility/ip6tos.c	Tue Sep 03 09:16:55 2019 +0000
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2014-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "mbed_version.h"
+
+#if MBED_MAJOR_VERSION == 2
+
+#include <stdio.h>
+#include <string.h>
+#include "common_functions.h"
+#include "ip6string.h"
+
+/**
+ * Print binary IPv6 address to a string.
+ * String must contain enough room for full address, 40 bytes exact.
+ * IPv4 tunneling addresses are not covered.
+ * \param addr IPv6 address.
+ * \p buffer to write string to.
+ */
+uint_fast8_t ip6tos(const void *ip6addr, char *p)
+{
+    char *p_orig = p;
+    uint_fast8_t zero_start = 255, zero_len = 1;
+    const uint8_t *addr = ip6addr;
+    uint_fast16_t part;
+
+    /* Follow RFC 5952 - pre-scan for longest run of zeros */
+    for (uint_fast8_t n = 0; n < 8; n++) {
+        part = *addr++;
+        part = (part << 8) | *addr++;
+        if (part != 0) {
+            continue;
+        }
+
+        /* We're at the start of a run of zeros - scan to non-zero (or end) */
+        uint_fast8_t n0 = n;
+        for (n = n0 + 1; n < 8; n++) {
+            part = *addr++;
+            part = (part << 8) | *addr++;
+            if (part != 0) {
+                break;
+            }
+        }
+
+        /* Now n0->initial zero of run, n->after final zero in run. Is this the
+         * longest run yet? If equal, we stick with the previous one - RFC 5952
+         * S4.2.3. Note that zero_len being initialised to 1 stops us
+         * shortening a 1-part run (S4.2.2.)
+         */
+        if (n - n0 > zero_len) {
+            zero_start = n0;
+            zero_len = n - n0;
+        }
+
+        /* Continue scan for initial zeros from part n+1 - we've already
+         * consumed part n, and know it's non-zero. */
+    }
+
+    /* Now go back and print, jumping over any zero run */
+    addr = ip6addr;
+    for (uint_fast8_t n = 0; n < 8;) {
+        if (n == zero_start) {
+            if (n == 0) {
+                *p++ = ':';
+            }
+            *p++ = ':';
+            addr += 2 * zero_len;
+            n += zero_len;
+            continue;
+        }
+
+        part = *addr++;
+        part = (part << 8) | *addr++;
+        n++;
+
+        p += sprintf(p, "%"PRIxFAST16, part);
+
+        /* One iteration writes "part:" rather than ":part", and has the
+         * explicit check for n == 8 below, to allow easy extension for
+         * IPv4-in-IPv6-type addresses ("xxxx::xxxx:a.b.c.d"): we'd just
+         * run the same loop for 6 parts, and output would then finish with the
+         * required : or ::, ready for "a.b.c.d" to be tacked on.
+         */
+        if (n != 8) {
+            *p++ = ':';
+        }
+    }
+    *p = '\0';
+
+    // Return length of generated string, excluding the terminating null character
+    return p - p_orig;
+}
+
+uint_fast8_t ip6_prefix_tos(const void *prefix, uint_fast8_t prefix_len, char *p)
+{
+    char *wptr = p;
+    uint8_t addr[16] = {0};
+
+    if (prefix_len > 128) {
+        return 0;
+    }
+
+    // Generate prefix part of the string
+    bitcopy(addr, prefix, prefix_len);
+    wptr += ip6tos(addr, wptr);
+    // Add the prefix length part of the string
+    wptr += sprintf(wptr, "/%"PRIuFAST8, prefix_len);
+
+    // Return total length of generated string
+    return wptr - p;
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utility/ns_types.h	Tue Sep 03 09:16:55 2019 +0000
@@ -0,0 +1,411 @@
+/*
+ * Copyright (c) 2014-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * ns_types.h - Basic compiler and type setup for Nanostack libraries.
+ */
+#ifndef NS_TYPES_H_
+#define NS_TYPES_H_
+
+/** \file
+ * \brief Basic compiler and type setup
+ *
+ * We currently assume C99 or later.
+ *
+ * C99 features being relied on:
+ *
+ *   - <inttypes.h> and <stdbool.h>
+ *   - inline (with C99 semantics, not C++ as per default GCC);
+ *   - designated initialisers;
+ *   - compound literals;
+ *   - restrict;
+ *   - [static N] in array parameters;
+ *   - declarations in for statements;
+ *   - mixing declarations and statements
+ *
+ * Compilers should be set to C99 or later mode when building Nanomesh source.
+ * For GCC this means "-std=gnu99" (C99 with usual GNU extensions).
+ *
+ * Also, a little extra care is required for public header files that could be
+ * included from C++, especially as C++ lacks some C99 features.
+ *
+ * (TODO: as this is exposed to API users, do we need a predefine to distinguish
+ * internal and external use, for finer control? Not yet, but maybe...)
+ */
+
+/* Make sure <stdint.h> defines its macros if C++ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS
+#endif
+#ifndef __STDC_CONSTANT_MACROS
+#define __STDC_CONSTANT_MACROS
+#endif
+
+#include <stddef.h>
+#include <inttypes.h> // includes <stdint.h>; debugf() users need PRIu32 etc
+#include <stdbool.h>
+
+/*
+ * Create the optional <stdint.h> 24-bit types if they don't exist (worth trying
+ * to use them, as they could exist and be more efficient than 32-bit on 8-bit
+ * systems...)
+ */
+#ifndef UINT_LEAST24_MAX
+typedef uint_least32_t uint_least24_t;
+#define UINT_LEAST24_MAX UINT_LEAST32_MAX
+#define UINT24_C(x) UINT32_C(x)
+#define PRIoLEAST24 PRIoLEAST32
+#define PRIuLEAST24 PRIuLEAST32
+#define PRIxLEAST24 PRIxLEAST32
+#define PRIXLEAST24 PRIXLEAST32
+#endif
+
+#ifndef INT_LEAST24_MAX
+typedef int_least32_t int_least24_t;
+#define INT_LEAST24_MIN INT_LEAST32_MIN
+#define INT_LEAST24_MAX INT_LEAST32_MAX
+#define INT24_C(x) INT32_C(x)
+#define PRIdLEAST24 PRIdLEAST32
+#define PRIiLEAST24 PRIiLEAST32
+#endif
+
+#ifndef UINT_FAST24_MAX
+typedef uint_fast32_t uint_fast24_t;
+#define UINT_FAST24_MAX UINT_FAST32_MAX
+#define PRIoFAST24 PRIoFAST32
+#define PRIuFAST24 PRIuFAST32
+#define PRIxFAST24 PRIxFAST32
+#define PRIXFAST24 PRIXFAST32
+#endif
+
+#ifndef INT_FAST24_MAX
+typedef int_fast32_t int_fast24_t;
+#define INT_FAST24_MIN INT_FAST32_MIN
+#define INT_FAST24_MAX INT_FAST32_MAX
+#define PRIdFAST24 PRIdFAST32
+#define PRIiFAST24 PRIiFAST32
+#endif
+
+/* Function attribute - C11 "noreturn" or C++11 "[[noreturn]]" */
+#ifndef NS_NORETURN
+#if defined  __cplusplus && __cplusplus >= 201103L
+#define NS_NORETURN [[noreturn]]
+#elif !defined  __cplusplus && __STDC_VERSION__ >= 201112L
+#define NS_NORETURN _Noreturn
+#elif defined __GNUC__
+#define NS_NORETURN __attribute__((__noreturn__))
+#elif defined __CC_ARM
+#define NS_NORETURN __declspec(noreturn)
+#elif defined __IAR_SYSTEMS_ICC__
+#define NS_NORETURN __noreturn
+#else
+#define NS_NORETURN
+#endif
+#endif
+
+/* C11's "alignas" macro, emulated for integer expressions if necessary */
+#ifndef __alignas_is_defined
+#if defined __CC_ARM || defined __TASKING__
+#define alignas(n) __align(n)
+#define __alignas_is_defined 1
+#elif (defined __STDC_VERSION__ && __STDC_VERSION__ >= 201112L) || (defined __cplusplus && __cplusplus >= 201103L)
+# if defined __ARMCC_VERSION && __ARMCC_VERSION < 6120000
+/* Workaround for Arm Compiler versions prior to 6.12 */
+#   if !defined __cplusplus
+#     define alignas _Alignas
+#   endif
+#   define __alignas_is_defined 1
+# else
+#   include <stdalign.h>
+# endif
+#elif defined __GNUC__
+#define alignas(n) __attribute__((__aligned__(n)))
+#define __alignas_is_defined 1
+#elif defined __IAR_SYSTEMS_ICC__
+/* Does this really just apply to the next variable? */
+#define alignas(n) __Alignas(data_alignment=n)
+#define __Alignas(x) _Pragma(#x)
+#define __alignas_is_defined 1
+#endif
+#endif
+
+/**
+ * Marker for functions or objects that may be unused, suppressing warnings.
+ * Place after the identifier:
+ * ~~~
+ *    static int X MAYBE_UNUSED = 3;
+ *    static int foo(void) MAYBE_UNUSED;
+ * ~~~
+ */
+#if defined __CC_ARM || defined __GNUC__
+#define MAYBE_UNUSED __attribute__((unused))
+#else
+#define MAYBE_UNUSED
+#endif
+
+/*
+ * C++ (even C++11) doesn't provide restrict: define away or provide
+ * alternative.
+ */
+#ifdef __cplusplus
+#ifdef __GNUC__
+#define restrict __restrict
+#else
+#define restrict
+#endif
+#endif /* __cplusplus */
+
+
+/**
+ * C++ doesn't allow "static" in function parameter types: ie
+ * ~~~
+ *    entry_t *find_entry(const uint8_t address[static 16])
+ * ~~~
+ * If a header file may be included from C++, use this __static define instead.
+ *
+ * (Syntax introduced in C99 - `uint8_t address[16]` in a prototype was always
+ * equivalent to `uint8_t *address`, but the C99 addition of static tells the
+ * compiler that address is never NULL, and always points to at least 16
+ * elements. This adds no new type-checking, but the information could aid
+ * compiler optimisation, and it can serve as documentation).
+ */
+#ifdef __cplusplus
+#define __static
+#else
+#define __static static
+#endif
+
+#ifdef __GNUC__
+#define NS_GCC_VERSION (__GNUC__ * 10000 \
+                   + __GNUC_MINOR__ * 100 \
+                   + __GNUC_PATCHLEVEL__)
+#endif
+
+/** \brief Compile-time assertion
+ *
+ * C11 provides _Static_assert, as does GCC even in C99 mode (and
+ * as a freestanding implementation, we can't rely on <assert.h> to get
+ * the static_assert macro).
+ * C++11 provides static_assert as a keyword, as does G++ in C++0x mode.
+ *
+ * The assertion acts as a declaration that can be placed at file scope, in a
+ * code block (except after a label), or as a member of a struct/union. It
+ * produces a compiler error if "test" evaluates to 0.
+ *
+ * Note that this *includes* the required semicolon when defined, else it
+ * is totally empty, permitting use in structs. (If the user provided the `;`,
+ * it would leave an illegal stray `;` if unavailable).
+ */
+#ifdef __cplusplus
+# if __cplusplus >= 201103L || __cpp_static_assert >= 200410
+# define NS_STATIC_ASSERT(test, str) static_assert(test, str);
+# elif defined __GXX_EXPERIMENTAL_CXX0X__  && NS_GCC_VERSION >= 40300
+# define NS_STATIC_ASSERT(test, str) __extension__ static_assert(test, str);
+# else
+# define NS_STATIC_ASSERT(test, str)
+# endif
+#else /* C */
+# if __STDC_VERSION__ >= 201112L
+# define NS_STATIC_ASSERT(test, str) _Static_assert(test, str);
+# elif defined __GNUC__ && NS_GCC_VERSION >= 40600 && !defined __CC_ARM
+# ifdef _Static_assert
+/*
+ * Some versions of glibc cdefs.h (which comes in via <stdint.h> above)
+ * attempt to define their own _Static_assert (if GCC < 4.6 or
+ * __STRICT_ANSI__) using an extern declaration, which doesn't work in a
+ * struct/union.
+ *
+ * For GCC >= 4.6 and __STRICT_ANSI__, we can do better - just use
+ * the built-in _Static_assert with __extension__. We have to do this, as
+ * ns_list.h needs to use it in a union. No way to get at it though, without
+ * overriding their define.
+ */
+#   undef _Static_assert
+#   define _Static_assert(x, y) __extension__ _Static_assert(x, y)
+# endif
+# define NS_STATIC_ASSERT(test, str) __extension__ _Static_assert(test, str);
+# else
+# define NS_STATIC_ASSERT(test, str)
+#endif
+#endif
+
+/** \brief Pragma to suppress warnings about unusual pointer values.
+ *
+ * Useful if using "poison" values.
+ */
+#ifdef __IAR_SYSTEMS_ICC__
+#define NS_FUNNY_INTPTR_OK      _Pragma("diag_suppress=Pe1053")
+#define NS_FUNNY_INTPTR_RESTORE _Pragma("diag_default=Pe1053")
+#else
+#define NS_FUNNY_INTPTR_OK
+#define NS_FUNNY_INTPTR_RESTORE
+#endif
+
+/** \brief Pragma to suppress warnings about always true/false comparisons
+ */
+#if defined __GNUC__ && NS_GCC_VERSION >= 40600 && !defined __CC_ARM
+#define NS_FUNNY_COMPARE_OK         _Pragma("GCC diagnostic push") \
+                                    _Pragma("GCC diagnostic ignored \"-Wtype-limits\"")
+#define NS_FUNNY_COMPARE_RESTORE    _Pragma("GCC diagnostic pop")
+#else
+#define NS_FUNNY_COMPARE_OK
+#define NS_FUNNY_COMPARE_RESTORE
+#endif
+
+/** \brief Pragma to suppress warnings arising from dummy definitions.
+ *
+ * Useful when you have function-like macros that returning constants
+ * in cut-down builds. Can be fairly cavalier about disabling as we
+ * do not expect every build to use this macro. Generic builds of
+ * components should ensure this is not included by only using it in
+ * a ifdef blocks providing dummy definitions.
+ */
+#ifdef __CC_ARM
+// statement is unreachable(111),  controlling expression is constant(236), expression has no effect(174),
+// function was declared but never referenced(177), variable was set but never used(550)
+#define NS_DUMMY_DEFINITIONS_OK _Pragma("diag_suppress=111,236,174,177,550")
+#elif defined __IAR_SYSTEMS_ICC__
+// controlling expression is constant
+#define NS_DUMMY_DEFINITIONS_OK _Pragma("diag_suppress=Pe236")
+#else
+#define NS_DUMMY_DEFINITIONS_OK
+#endif
+
+/** \brief Convert pointer to member to pointer to containing structure */
+#define NS_CONTAINER_OF(ptr, type, member) \
+    ((type *) ((char *) (ptr) - offsetof(type, member)))
+
+/*
+ * Inlining could cause problems when mixing with C++; provide a mechanism to
+ * disable it. This could also be turned off for other reasons (although
+ * this can usually be done through a compiler flag, eg -O0 on gcc).
+ */
+#ifndef __cplusplus
+#define NS_ALLOW_INLINING
+#endif
+
+/* There is inlining problem in GCC version 4.1.x and we know it works in 4.6.3 */
+#if defined __GNUC__ && NS_GCC_VERSION < 40600
+#undef NS_ALLOW_INLINING
+#endif
+
+/** \brief Mark a potentially-inlineable function.
+ *
+ * We follow C99 semantics, which requires precisely one external definition.
+ * To also allow inlining to be totally bypassed under control of
+ * NS_ALLOW_INLINING, code can be structured as per the example of ns_list:
+ *
+ * foo.h
+ * -----
+ * ~~~
+ *    NS_INLINE int my_func(int);
+ *
+ *    #if defined NS_ALLOW_INLINING || defined FOO_FN
+ *    #ifndef FOO_FN
+ *    #define FOO_FN NS_INLINE
+ *    #endif
+ *    FOO_FN int my_func(int a)
+ *    {
+ *        definition;
+ *    }
+ *    #endif
+ * ~~~
+ * foo.c
+ * -----
+ * ~~~
+ *    #define FOO_FN extern
+ *    #include "foo.h"
+ * ~~~
+ * Which generates:
+ * ~~~
+ *                 NS_ALLOW_INLINING set          NS_ALLOW_INLINING unset
+ *                 =====================          =======================
+ *                 Include foo.h                  Include foo.h
+ *                 -------------                  -------------
+ *                 inline int my_func(int);       int my_func(int);
+ *
+ *                 // inline definition
+ *                 inline int my_func(int a)
+ *                 {
+ *                     definition;
+ *                 }
+ *
+ *                 Compile foo.c                  Compile foo.c
+ *                 -------------                  -------------
+ *    (from .h)    inline int my_func(int);       int my_func(int);
+ *
+ *                 // external definition
+ *                 // because of no "inline"      // normal external definition
+ *                 extern int my_func(int a)      extern int my_func(int a)
+ *                 {                              {
+ *                     definition;                    definition;
+ *                 }                              }
+ * ~~~
+ *
+ * Note that even with inline keywords, whether the compiler inlines or not is
+ * up to it. For example, gcc at "-O0" will not inline at all, and will always
+ * call the real functions in foo.o, just as if NS_ALLOW_INLINING was unset.
+ * At "-O2", gcc could potentially inline everything, meaning that foo.o is not
+ * referenced at all.
+ *
+ * Alternatively, you could use "static inline", which gives every caller its
+ * own internal definition. This is compatible with C++ inlining (which expects
+ * the linker to eliminate duplicates), but in C it's less efficient if the code
+ * ends up non-inlined, and it's harder to breakpoint. I don't recommend it
+ * except for the most trivial functions (which could then probably be macros).
+ */
+#ifdef NS_ALLOW_INLINING
+#define NS_INLINE inline
+#else
+#define NS_INLINE
+#endif
+
+#if defined __SDCC_mcs51 || defined __ICC8051__ || defined __C51__
+
+/* The 8051 environments: SDCC (historic), IAR (current), Keil (future?) */
+
+#define NS_LARGE            __xdata
+#define NS_LARGE_PTR        __xdata
+#ifdef __ICC8051__
+#define NS_REENTRANT
+#define NS_REENTRANT_PREFIX __idata_reentrant
+#else
+#define NS_REENTRANT        __reentrant
+#define NS_REENTRANT_PREFIX
+#endif
+#define NS_NEAR_FUNC        __near_func
+
+#else
+
+/* "Normal" systems. Define it all away. */
+#define NS_LARGE
+#define NS_LARGE_PTR
+#define NS_REENTRANT
+#define NS_REENTRANT_PREFIX
+#define NS_NEAR_FUNC
+
+#endif
+
+/** \brief Scatter-gather descriptor
+ *
+ * Slightly optimised for small platforms - we assume we won't need any
+ * element bigger than 64K.
+ */
+typedef struct ns_iovec {
+    void *iov_base;
+    uint_fast16_t iov_len;
+} ns_iovec_t;
+
+#endif /* NS_TYPES_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utility/nsapi_types.h	Tue Sep 03 09:16:55 2019 +0000
@@ -0,0 +1,624 @@
+
+/** \addtogroup netsocket */
+/** @{*/
+/* nsapi.h - The network socket API
+ * Copyright (c) 2015 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 NSAPI_TYPES_H
+#define NSAPI_TYPES_H
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/** Enum of standardized error codes
+ *
+ *  Valid error codes have negative values and may
+ *  be returned by any network operation.
+ *
+ *  @enum nsapi_error
+ */
+enum nsapi_error {
+    NSAPI_ERROR_OK                  =  0,        /*!< no error */
+    NSAPI_ERROR_WOULD_BLOCK         = -3001,     /*!< no data is not available but call is non-blocking */
+    NSAPI_ERROR_UNSUPPORTED         = -3002,     /*!< unsupported functionality */
+    NSAPI_ERROR_PARAMETER           = -3003,     /*!< invalid configuration */
+    NSAPI_ERROR_NO_CONNECTION       = -3004,     /*!< not connected to a network */
+    NSAPI_ERROR_NO_SOCKET           = -3005,     /*!< socket not available for use */
+    NSAPI_ERROR_NO_ADDRESS          = -3006,     /*!< IP address is not known */
+    NSAPI_ERROR_NO_MEMORY           = -3007,     /*!< memory resource not available */
+    NSAPI_ERROR_NO_SSID             = -3008,     /*!< ssid not found */
+    NSAPI_ERROR_DNS_FAILURE         = -3009,     /*!< DNS failed to complete successfully */
+    NSAPI_ERROR_DHCP_FAILURE        = -3010,     /*!< DHCP failed to complete successfully */
+    NSAPI_ERROR_AUTH_FAILURE        = -3011,     /*!< connection to access point failed */
+    NSAPI_ERROR_DEVICE_ERROR        = -3012,     /*!< failure interfacing with the network processor */
+    NSAPI_ERROR_IN_PROGRESS         = -3013,     /*!< operation (eg connect) in progress */
+    NSAPI_ERROR_ALREADY             = -3014,     /*!< operation (eg connect) already in progress */
+    NSAPI_ERROR_IS_CONNECTED        = -3015,     /*!< socket is already connected */
+    NSAPI_ERROR_CONNECTION_LOST     = -3016,     /*!< connection lost */
+    NSAPI_ERROR_CONNECTION_TIMEOUT  = -3017,     /*!< connection timed out */
+    NSAPI_ERROR_ADDRESS_IN_USE      = -3018,     /*!< Address already in use */
+    NSAPI_ERROR_TIMEOUT             = -3019,     /*!< operation timed out */
+    NSAPI_ERROR_BUSY                = -3020,     /*!< device is busy and cannot accept new operation */
+};
+
+
+/** Enum of connection status types
+ *
+ *  Valid error codes have negative values.
+ *
+ *  @enum nsapi_connection_status
+ */
+typedef enum nsapi_connection_status {
+    NSAPI_STATUS_LOCAL_UP           = 0,        /*!< local IP address set */
+    NSAPI_STATUS_GLOBAL_UP          = 1,        /*!< global IP address set */
+    NSAPI_STATUS_DISCONNECTED       = 2,        /*!< no connection to network */
+    NSAPI_STATUS_CONNECTING         = 3,        /*!< connecting to network */
+    NSAPI_STATUS_ERROR_UNSUPPORTED  = NSAPI_ERROR_UNSUPPORTED
+} nsapi_connection_status_t;
+
+
+/** Enum of event types
+ *
+ *  Event callbacks are accompanied with an event-dependent parameter passed as an intptr_t.
+ *
+ *  @enum nsapi_event
+ */
+typedef enum nsapi_event {
+    NSAPI_EVENT_CONNECTION_STATUS_CHANGE = 0, /*!< network connection status has changed, the parameter = new status (nsapi_connection_status_t) */
+    NSAPI_EVENT_CELLULAR_STATUS_BASE     = 0x1000,  /*!< Cellular modem status has changed, See the enum values from enum cellular_connection_status_t in /features/cellular/framework/common/CellularCommon.h */
+    NSAPI_EVENT_CELLULAR_STATUS_END      = 0x1FFF   /*!< cellular modem status has changed, See the enum values from enum cellular_connection_status_t in /features/cellular/framework/common/CellularCommon.h */
+} nsapi_event_t;
+
+
+/** Type used to represent error codes
+ *
+ *  This is a separate type from enum nsapi_error to avoid breaking
+ *  compatibility in type-sensitive overloads
+ */
+typedef signed int nsapi_error_t;
+
+/** Type used to represent the size of data passed through sockets
+ */
+typedef unsigned int nsapi_size_t;
+
+/** Type used to represent either a size or error passed through sockets
+ *
+ *  A valid nsapi_size_or_error_t is either a non-negative size or a
+ *  negative error code from the nsapi_error_t
+ */
+typedef signed int nsapi_size_or_error_t;
+
+/** Type used to represent either a value or error
+ *
+ *  A valid nsapi_value_or_error_t is either a non-negative value or a
+ *  negative error code from the nsapi_error_t
+ */
+typedef signed int nsapi_value_or_error_t;
+
+/** Enum of encryption types
+ *
+ *  The security type specifies a particular security to use when
+ *  connected to a WiFi network
+ */
+typedef enum nsapi_security {
+    NSAPI_SECURITY_NONE         = 0x0,      /*!< open access point */
+    NSAPI_SECURITY_WEP          = 0x1,      /*!< phrase conforms to WEP */
+    NSAPI_SECURITY_WPA          = 0x2,      /*!< phrase conforms to WPA */
+    NSAPI_SECURITY_WPA2         = 0x3,      /*!< phrase conforms to WPA2 */
+    NSAPI_SECURITY_WPA_WPA2     = 0x4,      /*!< phrase conforms to WPA/WPA2 */
+    NSAPI_SECURITY_PAP          = 0x5,      /*!< phrase conforms to PPP authentication context */
+    NSAPI_SECURITY_CHAP         = 0x6,      /*!< phrase conforms to PPP authentication context */
+    NSAPI_SECURITY_EAP_TLS      = 0x7,      /*!< phrase conforms to EAP-TLS */
+    NSAPI_SECURITY_PEAP         = 0x8,      /*!< phrase conforms to PEAP */
+    NSAPI_SECURITY_UNKNOWN      = 0xFF,     /*!< unknown/unsupported security in scan results */
+} nsapi_security_t;
+
+/** Size of  2 char network interface name from driver
+ */
+#define NSAPI_INTERFACE_PREFIX_SIZE 2
+
+/** Maximum size of network interface name
+ */
+#define NSAPI_INTERFACE_NAME_MAX_SIZE 6
+
+/** Maximum size of IP address representation
+ */
+#define NSAPI_IP_SIZE NSAPI_IPv6_SIZE
+
+/** Maximum number of bytes for IP address
+ */
+#define NSAPI_IP_BYTES NSAPI_IPv6_BYTES
+
+/** Maximum size of MAC address representation
+ */
+#define NSAPI_MAC_SIZE 18
+
+/** Maximum number of bytes for MAC address
+ */
+#define NSAPI_MAC_BYTES 6
+
+/** Size of IPv4 representation
+ */
+#define NSAPI_IPv4_SIZE 16
+
+/** Number of bytes in IPv4 address
+ */
+#define NSAPI_IPv4_BYTES 4
+
+/** Size of IPv6 representation
+ */
+#define NSAPI_IPv6_SIZE 40
+
+/** Number of bytes in IPv6 address
+ */
+#define NSAPI_IPv6_BYTES 16
+
+/** Enum of IP address versions
+ *
+ *  The IP version specifies the type of an IP address.
+ *
+ *  @enum nsapi_version
+ */
+typedef enum nsapi_version {
+    NSAPI_UNSPEC,   /*!< Address is unspecified */
+    NSAPI_IPv4,     /*!< Address is IPv4 */
+    NSAPI_IPv6,     /*!< Address is IPv6 */
+} nsapi_version_t;
+
+/** IP address structure for passing IP addresses by value
+ */
+typedef struct nsapi_addr {
+    /** IP version
+     *  - NSAPI_IPv4
+     *  - NSAPI_IPv6
+     *  - NSAPI_UNSPEC
+     */
+    nsapi_version_t version;
+
+    /** IP address
+     *  The raw bytes of the IP address stored in big-endian format
+     */
+    uint8_t bytes[NSAPI_IP_BYTES];
+} nsapi_addr_t;
+
+
+/** Opaque handle for network sockets
+ */
+typedef void *nsapi_socket_t;
+
+
+/** Enum of socket protocols
+ *
+ *  The socket protocol specifies a particular protocol to
+ *  be used with a newly created socket.
+ *
+ *  @enum nsapi_protocol
+ */
+typedef enum nsapi_protocol {
+    NSAPI_TCP, /*!< Socket is of TCP type */
+    NSAPI_UDP, /*!< Socket is of UDP type */
+} nsapi_protocol_t;
+
+/** Enum of standardized stack option levels
+ *  for use with NetworkStack::setstackopt and getstackopt.
+ *
+ *  @enum nsapi_stack_level
+ */
+typedef enum nsapi_stack_level {
+    NSAPI_STACK     = 5000, /*!< Stack option level - see nsapi_stack_option_t for options */
+} nsapi_stack_level_t;
+
+/** Enum of standardized stack option names for level NSAPI_STACK
+ *  of NetworkStack::setstackopt and getstackopt.
+ *
+ *  These options may not be supported on all stacks, in which
+ *  case NSAPI_ERROR_UNSUPPORTED may be returned.
+ *
+ *  @enum nsapi_stack_option
+ */
+typedef enum nsapi_stack_option {
+    NSAPI_IPV4_MRU, /*!< Sets/gets size of largest IPv4 fragmented datagram to reassemble */
+    NSAPI_IPV6_MRU, /*!< Sets/gets size of largest IPv6 fragmented datagram to reassemble */
+} nsapi_stack_option_t;
+
+/** Enum of standardized socket option levels
+ *  for use with Socket::setsockopt and getsockopt.
+ *
+ *  @enum nsapi_socket_level
+ */
+typedef enum nsapi_socket_level {
+    NSAPI_SOCKET    = 7000, /*!< Socket option level - see nsapi_socket_option_t for options */
+} nsapi_socket_level_t;
+
+/** Enum of standardized socket option names for level NSAPI_SOCKET
+ *  of Socket::setsockopt and getsockopt.
+ *
+ *  These options may not be supported on all stacks, in which
+ *  case NSAPI_ERROR_UNSUPPORTED may be returned.
+ *
+ *  @enum nsapi_socket_option
+ */
+typedef enum nsapi_socket_option {
+    NSAPI_REUSEADDR,         /*!< Allow bind to reuse local addresses */
+    NSAPI_KEEPALIVE,         /*!< Enables sending of keepalive messages */
+    NSAPI_KEEPIDLE,          /*!< Sets timeout value to initiate keepalive */
+    NSAPI_KEEPINTVL,         /*!< Sets timeout value for keepalive */
+    NSAPI_LINGER,            /*!< Keeps close from returning until queues empty */
+    NSAPI_SNDBUF,            /*!< Sets send buffer size */
+    NSAPI_RCVBUF,            /*!< Sets recv buffer size */
+    NSAPI_ADD_MEMBERSHIP,    /*!< Add membership to multicast address */
+    NSAPI_DROP_MEMBERSHIP,   /*!< Drop membership to multicast address */
+    NSAPI_BIND_TO_DEVICE,        /*!< Bind socket network interface name*/
+} nsapi_socket_option_t;
+
+/** Supported IP protocol versions of IP stack
+ *
+ *  @enum nsapi_ip_stack
+ */
+typedef enum nsapi_ip_stack {
+    DEFAULT_STACK = 0,
+    IPV4_STACK,
+    IPV6_STACK,
+    IPV4V6_STACK
+} nsapi_ip_stack_t;
+
+/* Backwards compatibility - previously didn't distinguish stack and socket options */
+typedef nsapi_socket_level_t nsapi_level_t;
+typedef nsapi_socket_option_t nsapi_option_t;
+
+/** nsapi_wifi_ap structure
+ *
+ *  Structure representing a WiFi Access Point
+ */
+typedef struct nsapi_wifi_ap {
+    char ssid[33]; /* 32 is what 802.11 defines as longest possible name; +1 for the \0 */
+    uint8_t bssid[6];
+    nsapi_security_t security;
+    int8_t rssi;
+    uint8_t channel;
+} nsapi_wifi_ap_t;
+
+
+/** nsapi_stack structure
+ *
+ *  Stack structure representing a specific instance of a stack.
+ */
+typedef struct nsapi_stack {
+    /** Network stack operation table
+     *
+     *  Provides access to the underlying api of the stack. This is not
+     *  flattened into the nsapi_stack to allow allocation in read-only
+     *  memory.
+     */
+    const struct nsapi_stack_api *stack_api;
+
+    /** Opaque handle for network stacks
+     */
+    void *stack;
+
+    // Internal nsapi buffer
+    unsigned _stack_buffer[16];
+} nsapi_stack_t;
+
+/** nsapi_ip_mreq structure
+ */
+typedef struct nsapi_ip_mreq {
+    nsapi_addr_t imr_multiaddr; /* IP multicast address of group */
+    nsapi_addr_t imr_interface; /* local IP address of interface */
+} nsapi_ip_mreq_t;
+
+/** nsapi_stack_api structure
+ *
+ *  Common api structure for network stack operations. A network stack
+ *  can provide a nsapi_stack_api structure filled out with the
+ *  appropriate implementation.
+ *
+ *  Unsupported operations can be left as null pointers.
+ */
+typedef struct nsapi_stack_api {
+    /** Get the local IP address
+     *
+     *  @param stack    Stack handle
+     *  @return         Local IP Address or null address if not connected
+     */
+    nsapi_addr_t (*get_ip_address)(nsapi_stack_t *stack);
+
+    /** Translates a hostname to an IP address
+     *
+     *  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 stack    Stack handle
+     *  @param addr     Destination for the host IP address
+     *  @param host     Hostname to resolve
+     *  @param version  Address family
+     *  @return         0 on success, negative error code on failure
+     */
+    nsapi_error_t (*gethostbyname)(nsapi_stack_t *stack, const char *host, nsapi_addr_t *addr, nsapi_version_t version);
+
+    /** Add a domain name server to list of servers to query
+     *
+     *  @param addr     Destination for the host address
+     *  @return         0 on success, negative error code on failure
+     */
+    nsapi_error_t (*add_dns_server)(nsapi_stack_t *stack, nsapi_addr_t addr);
+
+    /** Set stack-specific stack options
+     *
+     *  The setstackopt allow an application to pass stack-specific hints
+     *  to the underlying stack. For unsupported options,
+     *  NSAPI_ERROR_UNSUPPORTED is returned and the stack is unmodified.
+     *
+     *  @param stack    Stack handle
+     *  @param level    Stack-specific protocol level
+     *  @param optname  Stack-specific option identifier
+     *  @param optval   Option value
+     *  @param optlen   Length of the option value
+     *  @return         0 on success, negative error code on failure
+     */
+    nsapi_error_t (*setstackopt)(nsapi_stack_t *stack, int level,
+                                 int optname, const void *optval, unsigned optlen);
+
+    /** Get stack-specific stack options
+     *
+     *  The getstackopt allow an application to retrieve stack-specific hints
+     *  from the underlying stack. For unsupported options,
+     *  NSAPI_ERROR_UNSUPPORTED is returned and optval is unmodified.
+     *
+     *  @param stack    Stack handle
+     *  @param level    Stack-specific protocol level
+     *  @param optname  Stack-specific option identifier
+     *  @param optval   Destination for option value
+     *  @param optlen   Length of the option value
+     *  @return         0 on success, negative error code on failure
+     */
+    nsapi_error_t (*getstackopt)(nsapi_stack_t *stack, int level,
+                                 int optname, void *optval, unsigned *optlen);
+
+    /** Opens a socket
+     *
+     *  Creates a network socket and stores it in the specified handle.
+     *  The handle must be passed to following calls on the socket.
+     *
+     *  A stack may have a finite number of sockets, in this case
+     *  NSAPI_ERROR_NO_SOCKET is returned if no socket is available.
+     *
+     *  @param stack    Stack context
+     *  @param socket   Destination for the handle to a newly created socket
+     *  @param proto    Protocol of socket to open, NSAPI_TCP or NSAPI_UDP
+     *  @return         0 on success, negative error code on failure
+     */
+    nsapi_error_t (*socket_open)(nsapi_stack_t *stack, nsapi_socket_t *socket,
+                                 nsapi_protocol_t proto);
+
+    /** Close the socket
+     *
+     *  Closes any open connection and deallocates any memory associated
+     *  with the socket.
+     *
+     *  @param stack    Stack handle
+     *  @param socket   Socket handle
+     *  @return         0 on success, negative error code on failure
+     */
+    nsapi_error_t (*socket_close)(nsapi_stack_t *stack, nsapi_socket_t socket);
+
+    /** Bind a specific address to a socket
+     *
+     *  Binding a socket specifies the address and port on which to receive
+     *  data. If the IP address is zeroed, only the port is bound.
+     *
+     *  @param stack    Stack handle
+     *  @param socket   Socket handle
+     *  @param addr     Local address to bind, may be null
+     *  @param port     Local port to bind
+     *  @return         0 on success, negative error code on failure.
+     */
+    nsapi_error_t (*socket_bind)(nsapi_stack_t *stack, nsapi_socket_t socket,
+                                 nsapi_addr_t addr, uint16_t port);
+
+    /** Listen for connections on a TCP socket
+     *
+     *  Marks the socket as a passive socket that can be used to accept
+     *  incoming connections.
+     *
+     *  @param stack    Stack handle
+     *  @param socket   Socket handle
+     *  @param backlog  Number of pending connections that can be queued
+     *                  simultaneously
+     *  @return         0 on success, negative error code on failure
+     */
+    nsapi_error_t (*socket_listen)(nsapi_stack_t *stack, nsapi_socket_t socket, int backlog);
+
+    /** Connects TCP socket to a remote host
+     *
+     *  Initiates a connection to a remote server specified by the
+     *  indicated address.
+     *
+     *  @param stack    Stack handle
+     *  @param socket   Socket handle
+     *  @param addr     The address of the remote host
+     *  @param port     The port of the remote host
+     *  @return         0 on success, negative error code on failure
+     */
+    nsapi_error_t (*socket_connect)(nsapi_stack_t *stack, nsapi_socket_t socket,
+                                    nsapi_addr_t addr, uint16_t port);
+
+    /** Accepts a connection on a TCP socket
+     *
+     *  The server socket must be bound and set to listen for connections.
+     *  On a new connection, creates a network socket and stores it in the
+     *  specified handle. The handle must be passed to following calls on
+     *  the socket.
+     *
+     *  A stack may have a finite number of sockets, in this case
+     *  NSAPI_ERROR_NO_SOCKET is returned if no socket is available.
+     *
+     *  This call is non-blocking. If accept would block,
+     *  NSAPI_ERROR_WOULD_BLOCK is returned immediately.
+     *
+     *  @param stack    Stack handle
+     *  @param server   Socket handle to server to accept from
+     *  @param socket   Destination for a handle to the newly created socket
+     *  @param addr     Destination for the address of the remote host
+     *  @param port     Destination for the port of the remote host
+     *  @return         0 on success, negative error code on failure
+     */
+    nsapi_error_t (*socket_accept)(nsapi_stack_t *stack, nsapi_socket_t server,
+                                   nsapi_socket_t *socket, nsapi_addr_t *addr, uint16_t *port);
+
+    /** Send data over a TCP socket
+     *
+     *  The socket must be connected to a remote host. Returns the number of
+     *  bytes sent from the buffer.
+     *
+     *  This call is non-blocking. If send would block,
+     *  NSAPI_ERROR_WOULD_BLOCK is returned immediately.
+     *
+     *  @param stack    Stack handle
+     *  @param socket   Socket handle
+     *  @param data     Buffer of data to send to the host
+     *  @param size     Size of the buffer in bytes
+     *  @return         Number of sent bytes on success, negative error
+     *                  code on failure
+     */
+    nsapi_size_or_error_t (*socket_send)(nsapi_stack_t *stack, nsapi_socket_t socket,
+                                         const void *data, nsapi_size_t size);
+
+    /** Receive data over a TCP socket
+     *
+     *  The socket must be connected to a remote host. Returns the number of
+     *  bytes received into the buffer.
+     *
+     *  This call is non-blocking. If recv would block,
+     *  NSAPI_ERROR_WOULD_BLOCK is returned immediately.
+     *
+     *  @param stack    Stack handle
+     *  @param socket   Socket handle
+     *  @param data     Destination buffer for data received from the host
+     *  @param size     Size of the buffer in bytes
+     *  @return         Number of received bytes on success, negative error
+     *                  code on failure
+     */
+    nsapi_size_or_error_t (*socket_recv)(nsapi_stack_t *stack, nsapi_socket_t socket,
+                                         void *data, nsapi_size_t size);
+
+    /** Send a packet over a UDP socket
+     *
+     *  Sends data to the specified address. Returns the number of bytes
+     *  sent from the buffer.
+     *
+     *  This call is non-blocking. If sendto would block,
+     *  NSAPI_ERROR_WOULD_BLOCK is returned immediately.
+     *
+     *  @param stack    Stack handle
+     *  @param socket   Socket handle
+     *  @param addr     The address of the remote host
+     *  @param port     The port of the remote host
+     *  @param data     Buffer of data to send to the host
+     *  @param size     Size of the buffer in bytes
+     *  @return         Number of sent bytes on success, negative error
+     *                  code on failure
+     */
+    nsapi_size_or_error_t (*socket_sendto)(nsapi_stack_t *stack, nsapi_socket_t socket,
+                                           nsapi_addr_t addr, uint16_t port, const void *data, nsapi_size_t size);
+
+    /** Receive a packet over a UDP socket
+     *
+     *  Receives data and stores the source address in address if address
+     *  is not NULL. Returns the number of bytes received into the buffer.
+     *
+     *  This call is non-blocking. If recvfrom would block,
+     *  NSAPI_ERROR_WOULD_BLOCK is returned immediately.
+     *
+     *  @param stack    Stack handle
+     *  @param socket   Socket handle
+     *  @param addr     Destination for the address of the remote host
+     *  @param port     Destination for the port of the remote host
+     *  @param data     Destination buffer for data received from the host
+     *  @param size     Size of the buffer in bytes
+     *  @return         Number of received bytes on success, negative error
+     *                  code on failure
+     */
+    nsapi_size_or_error_t (*socket_recvfrom)(nsapi_stack_t *stack, nsapi_socket_t socket,
+                                             nsapi_addr_t *addr, uint16_t *port, void *buffer, nsapi_size_t size);
+
+    /** Register a callback on state change of the socket
+     *
+     *  The specified callback will be called on state changes such as when
+     *  the socket can recv/send/accept successfully and on when an error
+     *  occurs. The callback may also be called spuriously without reason.
+     *
+     *  The callback may be called in an interrupt context and should not
+     *  perform expensive operations such as recv/send calls.
+     *
+     *  @param stack    Stack handle
+     *  @param socket   Socket handle
+     *  @param callback Function to call on state change
+     *  @param data     Argument to pass to callback
+     */
+    void (*socket_attach)(nsapi_stack_t *stack, nsapi_socket_t socket,
+                          void (*callback)(void *), void *data);
+
+    /** Set stack-specific socket options
+     *
+     *  The setsockopt allow an application to pass stack-specific hints
+     *  to the underlying stack. For unsupported options,
+     *  NSAPI_ERROR_UNSUPPORTED is returned and the socket is unmodified.
+     *
+     *  @param stack    Stack handle
+     *  @param socket   Socket handle
+     *  @param level    Stack-specific protocol level
+     *  @param optname  Stack-specific option identifier
+     *  @param optval   Option value
+     *  @param optlen   Length of the option value
+     *  @return         0 on success, negative error code on failure
+     */
+    nsapi_error_t (*setsockopt)(nsapi_stack_t *stack, nsapi_socket_t socket, int level,
+                                int optname, const void *optval, unsigned optlen);
+
+    /** Get stack-specific socket options
+     *
+     *  The getstackopt allow an application to retrieve stack-specific hints
+     *  from the underlying stack. For unsupported options,
+     *  NSAPI_ERROR_UNSUPPORTED is returned and optval is unmodified.
+     *
+     *  @param stack    Stack handle
+     *  @param socket   Socket handle
+     *  @param level    Stack-specific protocol level
+     *  @param optname  Stack-specific option identifier
+     *  @param optval   Destination for option value
+     *  @param optlen   Length of the option value
+     *  @return         0 on success, negative error code on failure
+     */
+    nsapi_error_t (*getsockopt)(nsapi_stack_t *stack, nsapi_socket_t socket, int level,
+                                int optname, void *optval, unsigned *optlen);
+} nsapi_stack_api_t;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/** @}*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utility/stoip4.c	Tue Sep 03 09:16:55 2019 +0000
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2014-2018 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "mbed_version.h"
+
+#if MBED_MAJOR_VERSION == 2
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "common_functions.h"
+#include "ip4string.h"
+
+/**
+ * Convert numeric IPv4 address string to a binary.
+ * \param ip4addr IPv4 address in string format.
+ * \param len Length of IPv4 string, maximum of 16..
+ * \param dest buffer for address. MUST be 4 bytes.
+ * \return boolean set to true if conversion succeded, false if it didn't
+ */
+bool stoip4(const char *ip4addr, size_t len, void *dest)
+{
+    uint8_t *addr = dest;
+
+    if (len > 16) { // Too long, not possible
+        return false;
+    }
+
+    uint_fast8_t stringLength = 0, byteCount = 0;
+
+    //Iterate over each component of the IP. The exit condition is in the middle of the loop
+    while (true) {
+
+        //No valid character (IPv4 addresses don't have implicit 0, that is x.y..z being read as x.y.0.z)
+        if (stringLength == len || ip4addr[stringLength] < '0' || ip4addr[stringLength] > '9') {
+            return false;
+        }
+
+        //For each component, we convert it to the raw value
+        uint_fast16_t byte = 0;
+        while (stringLength < len && ip4addr[stringLength] >= '0' && ip4addr[stringLength] <= '9') {
+            byte *= 10;
+            byte += ip4addr[stringLength++] - '0';
+
+            //We go over the maximum value for an IPv4 component
+            if (byte > 0xff) {
+                return false;
+            }
+        }
+
+        //Append the component
+        addr[byteCount++] = (uint8_t) byte;
+
+        //If we're at the end, we leave the loop. It's the only way to reach the `true` output
+        if (byteCount == 4) {
+            break;
+        }
+
+        //If the next character is invalid, we return false
+        if (stringLength == len || ip4addr[stringLength++] != '.') {
+            return false;
+        }
+    }
+
+    return stringLength == len || ip4addr[stringLength] == '\0';
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utility/stoip6.c	Tue Sep 03 09:16:55 2019 +0000
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2014-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "mbed_version.h"
+
+#if MBED_MAJOR_VERSION == 2
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "common_functions.h"
+#include "ip6string.h"
+
+static uint16_t hex(const char *p);
+static bool is_hex(char c);
+
+/**
+ * Convert numeric IPv6 address string to a binary.
+ * IPv4 tunnelling addresses are not covered.
+ * \param ip6addr IPv6 address in string format.
+ * \param len Length of ipv6 string.
+ * \param dest buffer for address. MUST be 16 bytes.
+ * \return boolean set to true if conversion succeed, false if it didn't
+ */
+bool stoip6(const char *ip6addr, size_t len, void *dest)
+{
+    uint8_t *addr;
+    const char *p, *q;
+    int_fast8_t field_no, coloncolon = -1;
+
+    addr = dest;
+
+    if (len > 39) { // Too long, not possible. We do not support IPv4-mapped IPv6 addresses
+        goto error;
+    }
+
+    // First go forward the string, until end, noting :: position if any
+    // We're decrementing `len` as we go forward, and stop when it reaches 0
+    for (field_no = 0, p = ip6addr; len && *p; p = q + 1) {
+
+        for (q = p; len && *q && (*q != ':'); len -= 1) { // Seek for ':' or end
+            if (!is_hex(*q++)) { // There must only be hex characters besides ':'
+                goto error;
+            }
+        }
+
+        if ((q - p) > 4) { // We can't have more than 4 hex digits per segment
+            goto error;
+        }
+
+        if (field_no == 8) { // If the address goes farther than 8 segments
+            goto error;
+        }
+
+        // Convert and write this part, (high-endian AKA network byte order)
+        addr = common_write_16_bit(hex(p), addr);
+        field_no++;
+
+        // We handle the colons
+        if (len) {
+            // Check if we reached "::"
+            if (q[0] == ':' && q[1] == ':') {
+                if (coloncolon != -1) { // We are not supposed to see "::" more than once per address
+                    goto error;
+                }
+                coloncolon = field_no;
+                q++;
+                len -= 2;
+            } else {
+                len -= 1;
+            }
+        }
+    }
+
+    if (coloncolon != -1) {
+        /* Insert zeros in the appropriate place */
+        uint_fast8_t head_size = 2 * coloncolon;
+        uint_fast8_t inserted_size = 2 * (8 - field_no);
+        uint_fast8_t tail_size = 16 - head_size - inserted_size;
+        addr = dest;
+        memmove(addr + head_size + inserted_size, addr + head_size, tail_size);
+        memset(addr + head_size, 0, inserted_size);
+    } else if (field_no != 8) { // Report an error if we didn't get 8 fields
+        goto error;
+    }
+    return true;
+
+error:
+    // Fill the output buffer with 0 so we stick to the old failure behavior.
+    // We are however more agressive and wipe the entire address, and do so more often.
+    memset(dest, 0, 16);
+    return false;
+}
+
+unsigned char sipv6_prefixlength(const char *ip6addr)
+{
+    char *ptr = strchr(ip6addr, '/');
+    if (ptr) {
+        return (unsigned char)strtoul(ptr + 1, 0, 10);
+    }
+    return 0;
+}
+
+int stoip6_prefix(const char *ip6addr, void *dest, int_fast16_t *prefix_len_out)
+{
+    size_t addr_len, total_len;
+    int_fast16_t prefix_length;
+
+    if (prefix_len_out) {
+        *prefix_len_out = -1;
+    }
+
+    total_len = addr_len = strlen(ip6addr);
+    const char *ptr = strchr(ip6addr, '/');
+    if (ptr) {
+        addr_len = ptr - ip6addr;
+        if (prefix_len_out) {
+            if (total_len - addr_len > 3) {
+                /* too many digits in prefix */
+                return -1;
+            }
+
+            prefix_length = strtoul(ptr + 1, 0, 10);
+            if (prefix_length <  0 || prefix_length > 128) {
+                /* prefix value illegal */
+                return -1;
+            }
+
+            *prefix_len_out = prefix_length;
+        }
+    }
+
+    if (!stoip6(ip6addr, addr_len, dest)) {
+        /* parser failure */
+        return -1;
+    }
+
+    return 0;
+}
+
+static bool is_hex(char c)
+{
+    // 'A' (0x41) and 'a' (0x61) are mapped in the ASCII table in such a way that masking the 0x20 bit turn 'a' in 'A'
+    if ((c & ~0x20) >= 'A' && (c & ~0x20) <= 'F') {
+        return true;
+    }
+
+    if (c >= '0' && c <= '9') {
+        return true;
+    }
+
+    return false;
+}
+
+static uint16_t hex(const char *p)
+{
+    uint16_t val = 0;
+
+    for (;;) {
+        char c = *p++;
+        if ((c >= '0') && (c <= '9')) {
+            val = (val << 4) | (c - '0');
+        } else if ((c >= 'A') && (c <= 'F')) {
+            val = (val << 4) | (10 + (c - 'A'));
+        } else if ((c >= 'a') && (c <= 'f')) {
+            val = (val << 4) | (10 + (c - 'a'));
+        } else {
+            break; // Non hex character
+        }
+    }
+    return val;
+}
+#endif
--- a/utility/uip.h	Sat Aug 31 20:34:52 2019 +0000
+++ b/utility/uip.h	Tue Sep 03 09:16:55 2019 +0000
@@ -1203,29 +1203,19 @@
 struct uip_conn
 {
     uip_ipaddr_t        ripaddr;        /**< The IP address of the remote host. */
-
     u16_t               lport;          /**< The local TCP port, in network byte order. */
-    u16_t               rport;          /**< The local remote TCP port, in network byte
-			 order. */
-
-    u8_t                rcv_nxt[4];     /**< The sequence number that we expect to
-			 receive next. */
-    u8_t                snd_nxt[4];     /**< The sequence number that was last sent by
-                         us. */
+    u16_t               rport;          /**< The local remote TCP port, in network byte order. */
+    u8_t                rcv_nxt[4];     /**< The sequence number that we expect to receive next. */
+    u8_t                snd_nxt[4];     /**< The sequence number that was last sent by us. */
     u16_t               len;            /**< Length of the data that was previously sent. */
-    u16_t               mss;            /**< Current maximum segment size for the
-			 connection. */
-    u16_t               initialmss;     /**< Initial maximum segment size for the
-			 connection. */
-    u8_t                sa;             /**< Retransmission time-out calculation state
-			 variable. */
-    u8_t                sv;             /**< Retransmission time-out calculation state
-			 variable. */
+    u16_t               mss;            /**< Current maximum segment size for the connection. */
+    u16_t               initialmss;     /**< Initial maximum segment size for the connection. */
+    u8_t                sa;             /**< Retransmission time-out calculation state variable. */
+    u8_t                sv;             /**< Retransmission time-out calculation state variable. */
     u8_t                rto;            /**< Retransmission time-out. */
     u8_t                tcpstateflags;  /**< TCP state and flags. */
     u8_t                timer;          /**< The retransmission timer. */
-    u8_t                nrtx;           /**< The number of retransmissions for the last
-			 segment sent. */
+    u8_t                nrtx;           /**< The number of retransmissions for the last segment sent. */
 
     /** The application state. */
     uip_tcp_appstate_t  appstate;
@@ -1286,48 +1276,34 @@
 {
     struct
     {
-        uip_stats_t drop;       /**< Number of dropped packets at the IP
-			     layer. */
-        uip_stats_t recv;       /**< Number of received packets at the IP
-			     layer. */
-        uip_stats_t sent;       /**< Number of sent packets at the IP
-			     layer. */
-        uip_stats_t vhlerr;     /**< Number of packets dropped due to wrong
-			     IP version or header length. */
-        uip_stats_t hblenerr;   /**< Number of packets dropped due to wrong
-			     IP length, high byte. */
-        uip_stats_t lblenerr;   /**< Number of packets dropped due to wrong
-			     IP length, low byte. */
-        uip_stats_t fragerr;    /**< Number of packets dropped since they
-			     were IP fragments. */
-        uip_stats_t chkerr;     /**< Number of packets dropped due to IP
-			     checksum errors. */
-        uip_stats_t protoerr;   /**< Number of packets dropped since they
-			     were neither ICMP, UDP nor TCP. */
+        uip_stats_t drop;       /**< Number of dropped packets at the IP layer. */
+        uip_stats_t recv;       /**< Number of received packets at the IP layer. */
+        uip_stats_t sent;       /**< Number of sent packets at the IP layer. */
+        uip_stats_t vhlerr;     /**< Number of packets dropped due to wrong IP version or header length. */
+        uip_stats_t hblenerr;   /**< Number of packets dropped due to wrong IP length, high byte. */
+        uip_stats_t lblenerr;   /**< Number of packets dropped due to wrong IP length, low byte. */
+        uip_stats_t fragerr;    /**< Number of packets dropped since they were IP fragments. */
+        uip_stats_t chkerr;     /**< Number of packets dropped due to IP checksum errors. */
+        uip_stats_t protoerr;   /**< Number of packets dropped since they were neither ICMP, UDP nor TCP. */
     } ip;   /**< IP statistics. */
     struct
     {
         uip_stats_t drop;       /**< Number of dropped ICMP packets. */
         uip_stats_t recv;       /**< Number of received ICMP packets. */
         uip_stats_t sent;       /**< Number of sent ICMP packets. */
-        uip_stats_t typeerr;    /**< Number of ICMP packets with a wrong
-			     type. */
+        uip_stats_t typeerr;    /**< Number of ICMP packets with a wrong type. */
     } icmp; /**< ICMP statistics. */
     struct
     {
         uip_stats_t drop;       /**< Number of dropped TCP segments. */
         uip_stats_t recv;       /**< Number of recived TCP segments. */
         uip_stats_t sent;       /**< Number of sent TCP segments. */
-        uip_stats_t chkerr;     /**< Number of TCP segments with a bad
-			     checksum. */
-        uip_stats_t ackerr;     /**< Number of TCP segments with a bad ACK
-			     number. */
+        uip_stats_t chkerr;     /**< Number of TCP segments with a bad checksum. */
+        uip_stats_t ackerr;     /**< Number of TCP segments with a bad ACK number. */
         uip_stats_t rst;        /**< Number of recevied TCP RST (reset) segments. */
         uip_stats_t rexmit;     /**< Number of retransmitted TCP segments. */
-        uip_stats_t syndrop;    /**< Number of dropped SYNs due to too few
-			     connections was avaliable. */
-        uip_stats_t synrst;     /**< Number of SYNs for closed ports,
-			     triggering a RST. */
+        uip_stats_t syndrop;    /**< Number of dropped SYNs due to too few connections was avaliable. */
+        uip_stats_t synrst;     /**< Number of SYNs for closed ports, triggering a RST. */
     } tcp;  /**< TCP statistics. */
 #if UIP_UDP
     struct
@@ -1335,8 +1311,7 @@
         uip_stats_t drop;   /**< Number of dropped UDP segments. */
         uip_stats_t recv;   /**< Number of recived UDP segments. */
         uip_stats_t sent;   /**< Number of sent UDP segments. */
-        uip_stats_t chkerr; /**< Number of UDP segments with a bad
-			     checksum. */
+        uip_stats_t chkerr; /**< Number of UDP segments with a bad checksum. */
     } udp;  /**< UDP statistics. */
 #endif /* UIP_UDP */
 };
@@ -1368,40 +1343,40 @@
    should *NOT* be accessed directly, but only through the UIP
    functions/macros. */
 
-#define UIP_ACKDATA     1       /* Signifies that the outstanding data was
-			       acked and the application should send
-			       out new data instead of retransmitting
-			       the last data. */
+#define UIP_ACKDATA     1        /* Signifies that the outstanding data was
+                                    acked and the application should send
+                                    out new data instead of retransmitting
+                                    the last data. */
 
-#define UIP_NEWDATA     2       /* Flags the fact that the peer has sent
-			       us new data. */
+#define UIP_NEWDATA     2        /* Flags the fact that the peer has sent
+                                    us new data. */
 
-#define UIP_REXMIT      4       /* Tells the application to retransmit the
-			       data that was last sent. */
+#define UIP_REXMIT      4        /* Tells the application to retransmit the
+                                    ata that was last sent. */
 
-#define UIP_POLL        8       /* Used for polling the application, to
-			       check if the application has data that
-			       it wants to send. */
+#define UIP_POLL        8        /* Used for polling the application, to
+                                    check if the application has data that
+                                    it wants to send. */
 
-#define UIP_CLOSE       16      /* The remote host has closed the
-			       connection, thus the connection has
-			       gone away. Or the application signals
-			       that it wants to close the
-			       connection. */
+#define UIP_CLOSE       16       /* The remote host has closed the
+                                    connection, thus the connection has
+                                    gone away. Or the application signals
+                                    that it wants to close the
+                                    connection. */
 
-#define UIP_ABORT       32      /* The remote host has aborted the
-			       connection, thus the connection has
-			       gone away. Or the application signals
-			       that it wants to abort the
-			       connection. */
+#define UIP_ABORT       32       /* The remote host has aborted the
+                                    connection, thus the connection has
+                                    gone away. Or the application signals
+                                    that it wants to abort the
+                                    connection. */
 
-#define UIP_CONNECTED   64      /* We have got a connection from a remote
-                               host and have set up a new connection
-                               for it, or an active connection has
-                               been successfully established. */
+#define UIP_CONNECTED   64       /* We have got a connection from a remote
+                                    host and have set up a new connection
+                                    for it, or an active connection has
+                                    been successfully established. */
 
-#define UIP_TIMEDOUT    128     /* The connection has been aborted due to
-			       too many retransmissions. */
+#define UIP_TIMEDOUT    128      /* The connection has been aborted due to
+                                    too many retransmissions. */
 
 /* uip_process(flag):
  *
@@ -1416,14 +1391,15 @@
    timer has fired. These values are never used directly, but only in
    the macrose defined in this file. */
 
-#define UIP_DATA            1   /*  Tells UIP that there is incoming
+#define UIP_DATA            1    /* Tells UIP that there is incoming
                                     data in the uip_buf buffer. The
                                     length of the data is stored in the
                                     global variable uip_len.
-                                */
-#define UIP_TIMER           2   /* Tells UIP that the periodic timer has fired. */
-#define UIP_POLL_REQUEST    3   /* Tells UIP that a connection should be polled. */
-#define UIP_UDP_SEND_CONN   4   /* Tells UIP that a UDP datagram should be constructed in the uip_buf buffer. */
+                                 */
+#define UIP_TIMER           2    /* Tells UIP that the periodic timer has fired. */
+#define UIP_POLL_REQUEST    3    /* Tells UIP that a connection should be polled. */
+#define UIP_UDP_SEND_CONN   4    /* Tells UIP that a UDP datagram should be constructed
+                                    in the uip_buf buffer. */
 
 #if UIP_UDP
 #define UIP_UDP_TIMER   5
--- a/utility/uipethernet-conf.h	Sat Aug 31 20:34:52 2019 +0000
+++ b/utility/uipethernet-conf.h	Tue Sep 03 09:16:55 2019 +0000
@@ -4,14 +4,14 @@
 /* for TCP */
 
 #define UIP_SOCKET_NUMPACKETS   5
-#define UIP_MAX_CONNECTIONS     4
+#define UIP_MAX_CONNECTIONS     5
 
 /* for UDP
  * set UIP_CONF_UDP to 0 to disable UDP (saves aprox. 5kb flash) */
 
 #define UIP_CONF_UDP            1
 #define UIP_CONF_BROADCAST      1
-#define UIP_CONF_UDP_CONNS      4
+#define UIP_CONF_UDP_CONNS      5
 
 /* number of attempts on write before returning number of bytes sent so far
  * set to -1 to block until connection is closed by timeout */