You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by ad...@apache.org on 2017/04/19 18:18:15 UTC

[19/30] incubator-mynewt-core git commit: net/ip/lwip_base; update to LwIP to tag STABLE-2_0_2_RELEASE

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f52033e9/net/ip/lwip_base/src/apps/httpd/httpd.c
----------------------------------------------------------------------
diff --git a/net/ip/lwip_base/src/apps/httpd/httpd.c b/net/ip/lwip_base/src/apps/httpd/httpd.c
index f8e2e28..43195d7 100644
--- a/net/ip/lwip_base/src/apps/httpd/httpd.c
+++ b/net/ip/lwip_base/src/apps/httpd/httpd.c
@@ -98,11 +98,11 @@
 #include "lwip/ip.h"
 #include "lwip/tcp.h"
 
-#include <string.h>
-#include <stdlib.h>
+#include <string.h> /* memset */
+#include <stdlib.h> /* atoi */
 #include <stdio.h>
 
-#if LWIP_TCP
+#if LWIP_TCP && LWIP_CALLBACK_API
 
 /** Minimum length for a valid HTTP/0.9 request: "GET /\r\n" -> 7 bytes */
 #define MIN_REQ_LEN   7
@@ -335,85 +335,34 @@ char *http_cgi_param_vals[LWIP_HTTPD_MAX_CGI_PARAMETERS]; /* Values for each ext
 /** global list of active HTTP connections, use to kill the oldest when
     running out of memory */
 static struct http_state *http_connections;
-#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */
 
-#if LWIP_HTTPD_STRNSTR_PRIVATE
-/** Like strstr but does not need 'buffer' to be NULL-terminated */
-static char*
-strnstr(const char* buffer, const char* token, size_t n)
+static void
+http_add_connection(struct http_state *hs)
 {
-  const char* p;
-  int tokenlen = (int)strlen(token);
-  if (tokenlen == 0) {
-    return (char *)(size_t)buffer;
-  }
-  for (p = buffer; *p && (p + tokenlen <= buffer + n); p++) {
-    if ((*p == *token) && (strncmp(p, token, tokenlen) == 0)) {
-      return (char *)(size_t)p;
-    }
-  }
-  return NULL;
+  /* add the connection to the list */
+  hs->next = http_connections;
+  http_connections = hs;
 }
-#endif /* LWIP_HTTPD_STRNSTR_PRIVATE */
 
-#if LWIP_HTTPD_STRICMP_PRIVATE
-static int
-stricmp(const char* str1, const char* str2)
+static void
+http_remove_connection(struct http_state *hs)
 {
-  char c1, c2;
-
-  do {
-    c1 = *str1++;
-    c2 = *str2++;
-    if (c1 != c2) {
-      char c1_upc = c1 | 0x20;
-      if ((c1_upc >= 'a') && (c1_upc <= 'z')) {
-        /* characters are not equal an one is in the alphabet range:
-        downcase both chars and check again */
-        char c2_upc = c2 | 0x20;
-        if (c1_upc != c2_upc) {
-          /* still not equal */
-          /* don't care for < or > */
-          return 1;
+  /* take the connection off the list */
+  if (http_connections) {
+    if (http_connections == hs) {
+      http_connections = hs->next;
+    } else {
+      struct http_state *last;
+      for(last = http_connections; last->next != NULL; last = last->next) {
+        if (last->next == hs) {
+          last->next = hs->next;
+          break;
         }
-      } else {
-        /* characters are not equal but none is in the alphabet range */
-        return 1;
       }
     }
-  } while (c1 != 0);
-  return 0;
-}
-#endif /* LWIP_HTTPD_STRICMP_PRIVATE */
-
-#if LWIP_HTTPD_ITOA_PRIVATE && LWIP_HTTPD_DYNAMIC_HEADERS
-static void
-httpd_itoa(int value, char* result)
-{
-  const int base = 10;
-  char* ptr = result, *ptr1 = result, tmp_char;
-  int tmp_value;
-
-  do {
-    tmp_value = value;
-    value /= base;
-    *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz"[35 + (tmp_value - value * base)];
-  } while(value);
-
-   /* Apply negative sign */
-  if (tmp_value < 0) {
-     *ptr++ = '-';
-  }
-  *ptr-- = '\0';
-  while(ptr1 < ptr) {
-    tmp_char = *ptr;
-    *ptr--= *ptr1;
-    *ptr1++ = tmp_char;
   }
 }
-#endif
 
-#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED
 static void
 http_kill_oldest_connection(u8_t ssi_required)
 {
@@ -442,6 +391,11 @@ http_kill_oldest_connection(u8_t ssi_required)
     http_close_or_abort_conn(hs_free_next->next->pcb, hs_free_next->next, 1); /* this also unlinks the http_state from the list */
   }
 }
+#else /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */
+
+#define http_add_connection(hs)
+#define http_remove_connection(hs)
+
 #endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */
 
 #if LWIP_HTTPD_SSI
@@ -498,17 +452,7 @@ http_state_alloc(void)
 #endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */
   if (ret != NULL) {
     http_state_init(ret);
-#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED
-    /* add the connection to the list */
-    if (http_connections == NULL) {
-      http_connections = ret;
-    } else {
-      struct http_state *last;
-      for(last = http_connections; last->next != NULL; last = last->next);
-      LWIP_ASSERT("last != NULL", last != NULL);
-      last->next = ret;
-    }
-#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */
+    http_add_connection(ret);
   }
   return ret;
 }
@@ -557,22 +501,7 @@ http_state_free(struct http_state *hs)
 {
   if (hs != NULL) {
     http_state_eof(hs);
-#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED
-    /* take the connection off the list */
-    if (http_connections) {
-      if (http_connections == hs) {
-        http_connections = hs->next;
-      } else {
-        struct http_state *last;
-        for(last = http_connections; last->next != NULL; last = last->next) {
-          if (last->next == hs) {
-            last->next = hs->next;
-            break;
-          }
-        }
-      }
-    }
-#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */
+    http_remove_connection(hs);
     HTTP_FREE_HTTP_STATE(hs);
   }
 }
@@ -714,17 +643,14 @@ http_eof(struct tcp_pcb *pcb, struct http_state *hs)
   /* HTTP/1.1 persistent connection? (Not supported for SSI) */
 #if LWIP_HTTPD_SUPPORT_11_KEEPALIVE
   if (hs->keepalive) {
-#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED
-    struct http_state* next = hs->next;
-#endif
+    http_remove_connection(hs);
+
     http_state_eof(hs);
     http_state_init(hs);
     /* restore state: */
-#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED
-    hs->next = next;
-#endif
     hs->pcb = pcb;
     hs->keepalive = 1;
+    http_add_connection(hs);
     /* ensure nagle doesn't interfere with sending all data as fast as possible: */
     tcp_nagle_disable(pcb);
   } else
@@ -964,7 +890,7 @@ get_http_headers(struct http_state *hs, const char *uri)
     /* Now determine the content type and add the relevant header for that. */
     for (content_type = 0; content_type < NUM_HTTP_HEADERS; content_type++) {
       /* Have we found a matching extension? */
-      if(!stricmp(g_psHTTPHeaders[content_type].extension, ext)) {
+      if(!lwip_stricmp(g_psHTTPHeaders[content_type].extension, ext)) {
         break;
       }
     }
@@ -1012,7 +938,7 @@ get_http_headers(struct http_state *hs, const char *uri)
   }
   if (add_content_len) {
     size_t len;
-    LWIP_HTTPD_ITOA(hs->hdr_content_len, (size_t)LWIP_HTTPD_MAX_CONTENT_LEN_SIZE,
+    lwip_itoa(hs->hdr_content_len, (size_t)LWIP_HTTPD_MAX_CONTENT_LEN_SIZE,
       hs->handle->len);
     len = strlen(hs->hdr_content_len);
     if (len <= LWIP_HTTPD_MAX_CONTENT_LEN_SIZE - LWIP_HTTPD_MAX_CONTENT_LEN_OFFSET) {
@@ -1553,6 +1479,8 @@ http_send_data_ssi(struct tcp_pcb *pcb, struct http_state *hs)
             }
           }
           break;
+        default:
+          break;
       }
     }
   }
@@ -1764,7 +1692,14 @@ http_post_rxpbuf(struct http_state *hs, struct pbuf *p)
       hs->post_content_len_left -= p->tot_len;
     }
   }
+#if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND
+  /* prevent connection being closed if httpd_post_data_recved() is called nested */
+  hs->unrecved_bytes++;
+#endif
   err = httpd_post_receive_data(hs, p);
+#if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND
+  hs->unrecved_bytes--;
+#endif
   if (err != ERR_OK) {
     /* Ignore remaining content in case of application error */
     hs->post_content_len_left = 0;
@@ -1802,16 +1737,16 @@ http_post_request(struct pbuf *inp, struct http_state *hs,
 {
   err_t err;
   /* search for end-of-header (first double-CRLF) */
-  char* crlfcrlf = strnstr(uri_end + 1, CRLF CRLF, data_len - (uri_end + 1 - data));
+  char* crlfcrlf = lwip_strnstr(uri_end + 1, CRLF CRLF, data_len - (uri_end + 1 - data));
 
   if (crlfcrlf != NULL) {
     /* search for "Content-Length: " */
 #define HTTP_HDR_CONTENT_LEN                "Content-Length: "
 #define HTTP_HDR_CONTENT_LEN_LEN            16
 #define HTTP_HDR_CONTENT_LEN_DIGIT_MAX_LEN  10
-    char *scontent_len = strnstr(uri_end + 1, HTTP_HDR_CONTENT_LEN, crlfcrlf - (uri_end + 1));
+    char *scontent_len = lwip_strnstr(uri_end + 1, HTTP_HDR_CONTENT_LEN, crlfcrlf - (uri_end + 1));
     if (scontent_len != NULL) {
-      char *scontent_len_end = strnstr(scontent_len + HTTP_HDR_CONTENT_LEN_LEN, CRLF, HTTP_HDR_CONTENT_LEN_DIGIT_MAX_LEN);
+      char *scontent_len_end = lwip_strnstr(scontent_len + HTTP_HDR_CONTENT_LEN_LEN, CRLF, HTTP_HDR_CONTENT_LEN_DIGIT_MAX_LEN);
       if (scontent_len_end != NULL) {
         int content_len;
         char *content_len_num = scontent_len + HTTP_HDR_CONTENT_LEN_LEN;
@@ -1825,8 +1760,8 @@ http_post_request(struct pbuf *inp, struct http_state *hs,
         if (content_len >= 0) {
           /* adjust length of HTTP header passed to application */
           const char *hdr_start_after_uri = uri_end + 1;
-          u16_t hdr_len = LWIP_MIN(data_len, crlfcrlf + 4 - data);
-          u16_t hdr_data_len = LWIP_MIN(data_len, crlfcrlf + 4 - hdr_start_after_uri);
+          u16_t hdr_len = (u16_t)LWIP_MIN(data_len, crlfcrlf + 4 - data);
+          u16_t hdr_data_len = (u16_t)LWIP_MIN(data_len, crlfcrlf + 4 - hdr_start_after_uri);
           u8_t post_auto_wnd = 1;
           http_uri_buf[0] = 0;
           /* trim http header */
@@ -1953,7 +1888,7 @@ http_continue(void *connection)
  * When data has been received in the correct state, try to parse it
  * as a HTTP request.
  *
- * @param p the received pbuf
+ * @param inp the received pbuf
  * @param hs the connection state
  * @param pcb the tcp_pcb which received this packet
  * @return ERR_OK if request was OK and hs has been initialized correctly
@@ -2020,7 +1955,7 @@ http_parse_request(struct pbuf *inp, struct http_state *hs, struct tcp_pcb *pcb)
   /* received enough data for minimal request? */
   if (data_len >= MIN_REQ_LEN) {
     /* wait for CRLF before parsing anything */
-    crlf = strnstr(data, CRLF, data_len);
+    crlf = lwip_strnstr(data, CRLF, data_len);
     if (crlf != NULL) {
 #if LWIP_HTTPD_SUPPORT_POST
       int is_post = 0;
@@ -2052,11 +1987,11 @@ http_parse_request(struct pbuf *inp, struct http_state *hs, struct tcp_pcb *pcb)
       }
       /* if we come here, method is OK, parse URI */
       left_len = (u16_t)(data_len - ((sp1 +1) - data));
-      sp2 = strnstr(sp1 + 1, " ", left_len);
+      sp2 = lwip_strnstr(sp1 + 1, " ", left_len);
 #if LWIP_HTTPD_SUPPORT_V09
       if (sp2 == NULL) {
         /* HTTP 0.9: respond with correct protocol version */
-        sp2 = strnstr(sp1 + 1, CRLF, left_len);
+        sp2 = lwip_strnstr(sp1 + 1, CRLF, left_len);
         is_09 = 1;
 #if LWIP_HTTPD_SUPPORT_POST
         if (is_post) {
@@ -2069,13 +2004,13 @@ http_parse_request(struct pbuf *inp, struct http_state *hs, struct tcp_pcb *pcb)
       uri_len = (u16_t)(sp2 - (sp1 + 1));
       if ((sp2 != 0) && (sp2 > sp1)) {
         /* wait for CRLFCRLF (indicating end of HTTP headers) before parsing anything */
-        if (strnstr(data, CRLF CRLF, data_len) != NULL) {
+        if (lwip_strnstr(data, CRLF CRLF, data_len) != NULL) {
           char *uri = sp1 + 1;
 #if LWIP_HTTPD_SUPPORT_11_KEEPALIVE
           /* This is HTTP/1.0 compatible: for strict 1.1, a connection
              would always be persistent unless "close" was specified. */
-          if (!is_09 && (strnstr(data, HTTP11_CONNECTIONKEEPALIVE, data_len) ||
-              strnstr(data, HTTP11_CONNECTIONKEEPALIVE2, data_len))) {
+          if (!is_09 && (lwip_strnstr(data, HTTP11_CONNECTIONKEEPALIVE, data_len) ||
+              lwip_strnstr(data, HTTP11_CONNECTIONKEEPALIVE2, data_len))) {
             hs->keepalive = 1;
           } else {
             hs->keepalive = 0;
@@ -2259,7 +2194,7 @@ http_find_file(struct http_state *hs, const char *uri, int is_09)
       }
       tag_check = 0;
       for (loop = 0; loop < NUM_SHTML_EXTENSIONS; loop++) {
-        if (!stricmp(ext, g_pcSSIExtensions[loop])) {
+        if (!lwip_stricmp(ext, g_pcSSIExtensions[loop])) {
           tag_check = 1;
           break;
         }
@@ -2285,7 +2220,7 @@ http_find_file(struct http_state *hs, const char *uri, int is_09)
  * @param is_09 1 if the request is HTTP/0.9 (no HTTP headers in response)
  * @param uri the HTTP header URI
  * @param tag_check enable SSI tag checking
- * @param uri_has_params != NULL if URI has parameters (separated by '?')
+ * @param params != NULL if URI has parameters (separated by '?')
  * @return ERR_OK if file was found and hs has been initialized correctly
  *         another err_t otherwise
  */
@@ -2334,7 +2269,7 @@ http_init_file(struct http_state *hs, struct fs_file *file, int is_09, const cha
     if (is_09 && ((hs->handle->flags & FS_FILE_FLAGS_HEADER_INCLUDED) != 0)) {
       /* HTTP/0.9 responses are sent without HTTP header,
          search for the end of the header. */
-      char *file_start = strnstr(hs->file, CRLF CRLF, hs->left);
+      char *file_start = lwip_strnstr(hs->file, CRLF CRLF, hs->left);
       if (file_start != NULL) {
         size_t diff = file_start + 4 - hs->file;
         hs->file += diff;
@@ -2637,6 +2572,7 @@ httpd_init(void)
   tcp_setprio(pcb, HTTPD_TCP_PRIO);
   /* set SOF_REUSEADDR here to explicitly bind httpd to multiple interfaces */
   err = tcp_bind(pcb, IP_ANY_TYPE, HTTPD_SERVER_PORT);
+  LWIP_UNUSED_ARG(err); /* in case of LWIP_NOASSERT */
   LWIP_ASSERT("httpd_init: tcp_bind failed", err == ERR_OK);
   pcb = tcp_listen(pcb);
   LWIP_ASSERT("httpd_init: tcp_listen failed", pcb != NULL);
@@ -2690,4 +2626,4 @@ http_set_cgi_handlers(const tCGI *cgis, int num_handlers)
 }
 #endif /* LWIP_HTTPD_CGI */
 
-#endif /* LWIP_TCP */
+#endif /* LWIP_TCP && LWIP_CALLBACK_API */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f52033e9/net/ip/lwip_base/src/apps/httpd/httpd_structs.h
----------------------------------------------------------------------
diff --git a/net/ip/lwip_base/src/apps/httpd/httpd_structs.h b/net/ip/lwip_base/src/apps/httpd/httpd_structs.h
index dc53346..fbd135a 100644
--- a/net/ip/lwip_base/src/apps/httpd/httpd_structs.h
+++ b/net/ip/lwip_base/src/apps/httpd/httpd_structs.h
@@ -3,10 +3,6 @@
 
 #include "lwip/apps/httpd.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #if LWIP_HTTPD_DYNAMIC_HEADERS
 /** This struct is used for a list of HTTP header strings for various
  * filename extensions. */
@@ -115,8 +111,4 @@ static const char * const g_pcSSIExtensions[] = {
 #define NUM_SHTML_EXTENSIONS (sizeof(g_pcSSIExtensions) / sizeof(const char *))
 #endif /* LWIP_HTTPD_SSI */
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* LWIP_HTTPD_STRUCTS_H */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f52033e9/net/ip/lwip_base/src/apps/lwiperf/lwiperf.c
----------------------------------------------------------------------
diff --git a/net/ip/lwip_base/src/apps/lwiperf/lwiperf.c b/net/ip/lwip_base/src/apps/lwiperf/lwiperf.c
index fea2c06..efabe47 100644
--- a/net/ip/lwip_base/src/apps/lwiperf/lwiperf.c
+++ b/net/ip/lwip_base/src/apps/lwiperf/lwiperf.c
@@ -53,7 +53,7 @@
 #include <string.h>
 
 /* Currently, only TCP-over-IPv4 is implemented (does iperf support IPv6 anyway?) */
-#if LWIP_IPV4 && LWIP_TCP
+#if LWIP_IPV4 && LWIP_TCP && LWIP_CALLBACK_API
 
 /** Specify the idle timeout (in seconds) after that the test fails */
 #ifndef LWIPERF_TCP_MAX_IDLE_SEC
@@ -262,7 +262,7 @@ lwiperf_tcp_client_send_more(lwiperf_state_tcp_t* conn)
       /* this session is time-limited */
       u32_t now = sys_now();
       u32_t diff_ms = now - conn->time_started;
-      u32_t time = (u32_t)-(s32_t)htonl(conn->settings.amount);
+      u32_t time = (u32_t)-(s32_t)lwip_htonl(conn->settings.amount);
       u32_t time_ms = time * 10;
       if (diff_ms >= time_ms) {
         /* time specified by the client is over -> close the connection */
@@ -271,7 +271,7 @@ lwiperf_tcp_client_send_more(lwiperf_state_tcp_t* conn)
       }
     } else {
       /* this session is byte-limited */
-      u32_t amount_bytes = htonl(conn->settings.amount);
+      u32_t amount_bytes = lwip_htonl(conn->settings.amount);
       /* @todo: this can send up to 1*MSS more than requested... */
       if (amount_bytes >= conn->bytes_transferred) {
         /* all requested bytes transferred -> close the connection */
@@ -294,7 +294,7 @@ lwiperf_tcp_client_send_more(lwiperf_state_tcp_t* conn)
     } else {
       /* transmit data */
       /* @todo: every x bytes, transmit the settings again */
-      txptr = (void*)(size_t)&lwiperf_txbuf_const[conn->bytes_transferred % 10];
+      txptr = LWIP_CONST_CAST(void*, &lwiperf_txbuf_const[conn->bytes_transferred % 10]);
       txlen_max = TCP_MSS;
       if (conn->bytes_transferred == 48) { /* @todo: fix this for intermediate settings, too */
         txlen_max = TCP_MSS - 24;
@@ -390,7 +390,7 @@ lwiperf_tx_start(lwiperf_state_tcp_t* conn)
   tcp_err(newpcb, lwiperf_tcp_err);
 
   ip_addr_copy(remote_addr, conn->conn_pcb->remote_ip);
-  remote_port = (u16_t)htonl(client_conn->settings.remote_port);
+  remote_port = (u16_t)lwip_htonl(client_conn->settings.remote_port);
 
   err = tcp_connect(newpcb, &remote_addr, remote_port, lwiperf_tcp_client_connected);
   if (err != ERR_OK) {
@@ -494,10 +494,8 @@ lwiperf_tcp_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
         return ERR_VAL;
       }
     }
-    packet_idx += i;
-#else
-    packet_idx += q->len;
 #endif
+    packet_idx += q->len;
   }
   LWIP_ASSERT("count mismatch", packet_idx == p->tot_len);
   conn->bytes_transferred += packet_idx;
@@ -660,4 +658,4 @@ lwiperf_abort(void* lwiperf_session)
   }
 }
 
-#endif /* LWIP_IPV4 && LWIP_TCP */
+#endif /* LWIP_IPV4 && LWIP_TCP && LWIP_CALLBACK_API */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f52033e9/net/ip/lwip_base/src/apps/mdns/mdns.c
----------------------------------------------------------------------
diff --git a/net/ip/lwip_base/src/apps/mdns/mdns.c b/net/ip/lwip_base/src/apps/mdns/mdns.c
index 5da37bc..14334fc 100644
--- a/net/ip/lwip_base/src/apps/mdns/mdns.c
+++ b/net/ip/lwip_base/src/apps/mdns/mdns.c
@@ -52,10 +52,7 @@
  *
  * This file is part of the lwIP TCP/IP stack.
  *
- * Author: Erik Ekman <er...@verisure.com>
- *
- * Please coordinate changes and requests with Erik Ekman
- * <er...@verisure.com>
+ * Author: Erik Ekman <er...@kryo.se>
  *
  */
 
@@ -68,7 +65,6 @@
 #include "lwip/prot/dns.h"
 
 #include <string.h>
-#include <stdlib.h>
 
 #if LWIP_MDNS_RESPONDER
 
@@ -85,13 +81,13 @@
 #if LWIP_IPV4
 #include "lwip/igmp.h"
 /* IPv4 multicast group 224.0.0.251 */
-static const ip_addr_t v4group = IPADDR4_INIT(PP_HTONL(0xE00000FBUL));
+static const ip_addr_t v4group = DNS_MQUERY_IPV4_GROUP_INIT;
 #endif
 
 #if LWIP_IPV6
 #include "lwip/mld6.h"
 /* IPv6 multicast group FF02::FB */
-static const ip_addr_t v6group = IPADDR6_INIT(PP_HTONL(0xFF020000UL), PP_HTONL(0x00000000UL), PP_HTONL(0x00000000UL), PP_HTONL(0x000000FBUL));
+static const ip_addr_t v6group = DNS_MQUERY_IPV6_GROUP_INIT;
 #endif
 
 #define MDNS_PORT 5353
@@ -107,6 +103,8 @@ static const ip_addr_t v6group = IPADDR6_INIT(PP_HTONL(0xFF020000UL), PP_HTONL(0
 static u8_t mdns_netif_client_id;
 static struct udp_pcb *mdns_pcb;
 
+#define NETIF_TO_HOST(netif) (struct mdns_host*)(netif_get_client_data(netif, mdns_netif_client_id))
+
 #define TOPDOMAIN_LOCAL "local"
 
 #define REVERSE_PTR_TOPDOMAIN "arpa"
@@ -263,42 +261,6 @@ struct mdns_answer {
   u16_t rd_offset;
 };
 
-#ifndef LWIP_MDNS_STRNCASECMP
-#define LWIP_MDNS_STRNCASECMP(str1, str2, len) mdns_strncasecmp(str1, str2, len)
-/**
- * A small but sufficient implementation for case insensitive strncmp.
- * This can be defined to e.g. strnicmp for windows or strncasecmp for linux.
- */
-static int
-mdns_strncasecmp(const char* str1, const char* str2, size_t len)
-{
-  char c1, c2;
-
-  do {
-    c1 = *str1++;
-    c2 = *str2++;
-    if (c1 != c2) {
-      char c1_upc = c1 | 0x20;
-      if ((c1_upc >= 'a') && (c1_upc <= 'z')) {
-        /* characters are not equal an one is in the alphabet range:
-        downcase both chars and check again */
-        char c2_upc = c2 | 0x20;
-        if (c1_upc != c2_upc) {
-          /* still not equal */
-          /* don't care for < or > */
-          return 1;
-        }
-      } else {
-        /* characters are not equal but none is in the alphabet range */
-        return 1;
-      }
-    }
-  } while (len-- && c1 != 0);
-  return 0;
-}
-#endif /* LWIP_MDNS_STRNCASECMP */
-
-
 /**
  * Add a label part to a domain
  * @param domain The domain to add a label to
@@ -458,7 +420,7 @@ mdns_domain_eq(struct mdns_domain *a, struct mdns_domain *b)
     len = *ptra;
     ptra++;
     ptrb++;
-    res = LWIP_MDNS_STRNCASECMP((char *) ptra, (char *) ptrb, len);
+    res = lwip_strnicmp((char *) ptra, (char *) ptrb, len);
     if (res != 0) {
       return 0;
     }
@@ -504,15 +466,11 @@ mdns_build_reverse_v4_domain(struct mdns_domain *domain, const ip4_addr_t *addr)
   memset(domain, 0, sizeof(struct mdns_domain));
   ptr = (const u8_t *) addr;
   for (i = sizeof(ip4_addr_t) - 1; i >= 0; i--) {
-    char buf[3];
-    size_t pos = sizeof(buf);
+    char buf[4];
     u8_t val = ptr[i];
-    do {
-      pos--;
-      buf[pos] = '0' + (val % 10);
-      val /= 10;
-    } while (val != 0); /* loop is correct because u8_t needs at most 3 chars */
-    res = mdns_domain_add_label(domain, &buf[pos], (u8_t)(3 - pos));
+
+    lwip_itoa(buf, sizeof(buf), val);
+    res = mdns_domain_add_label(domain, buf, (u8_t)strlen(buf));
     LWIP_ERROR("mdns_build_reverse_v4_domain: Failed to add label", (res == ERR_OK), return res);
   }
   res = mdns_domain_add_label(domain, REVERSE_PTR_V4_DOMAIN, (u8_t)(sizeof(REVERSE_PTR_V4_DOMAIN)-1));
@@ -591,7 +549,7 @@ mdns_build_host_domain(struct mdns_domain *domain, struct mdns_host *mdns)
 {
   err_t res;
   memset(domain, 0, sizeof(struct mdns_domain));
-  LWIP_ERROR("mdns_build_host_domain: Not an mdns netif", (mdns != NULL), return ERR_VAL);
+  LWIP_ERROR("mdns_build_host_domain: mdns != NULL", (mdns != NULL), return ERR_VAL);
   res = mdns_domain_add_label(domain, mdns->name, (u8_t)strlen(mdns->name));
   LWIP_ERROR("mdns_build_host_domain: Failed to add label", (res == ERR_OK), return res);
   return mdns_add_dotlocal(domain);
@@ -611,7 +569,7 @@ mdns_build_dnssd_domain(struct mdns_domain *domain)
   LWIP_ERROR("mdns_build_dnssd_domain: Failed to add label", (res == ERR_OK), return res);
   res = mdns_domain_add_label(domain, "_dns-sd", (u8_t)(sizeof("_dns-sd")-1));
   LWIP_ERROR("mdns_build_dnssd_domain: Failed to add label", (res == ERR_OK), return res);
-  res = mdns_domain_add_label(domain, dnssd_protos[DNSSD_PROTO_UDP], (u8_t)(sizeof(dnssd_protos[DNSSD_PROTO_UDP])-1));
+  res = mdns_domain_add_label(domain, dnssd_protos[DNSSD_PROTO_UDP], (u8_t)strlen(dnssd_protos[DNSSD_PROTO_UDP]));
   LWIP_ERROR("mdns_build_dnssd_domain: Failed to add label", (res == ERR_OK), return res);
   return mdns_add_dotlocal(domain);
 }
@@ -636,7 +594,7 @@ mdns_build_service_domain(struct mdns_domain *domain, struct mdns_service *servi
   }
   res = mdns_domain_add_label(domain, service->service, (u8_t)strlen(service->service));
   LWIP_ERROR("mdns_build_service_domain: Failed to add label", (res == ERR_OK), return res);
-  res = mdns_domain_add_label(domain, dnssd_protos[service->proto], (u8_t)(sizeof(dnssd_protos[DNSSD_PROTO_UDP])-1));
+  res = mdns_domain_add_label(domain, dnssd_protos[service->proto], (u8_t)strlen(dnssd_protos[service->proto]));
   LWIP_ERROR("mdns_build_service_domain: Failed to add label", (res == ERR_OK), return res);
   return mdns_add_dotlocal(domain);
 }
@@ -690,7 +648,7 @@ check_host(struct netif *netif, struct mdns_rr_info *rr, u8_t *reverse_v6_reply)
 #endif
   }
 
-  res = mdns_build_host_domain(&mydomain, (struct mdns_host*)netif->client_data[mdns_netif_client_id]);
+  res = mdns_build_host_domain(&mydomain, NETIF_TO_HOST(netif));
   /* Handle requests for our hostname */
   if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain)) {
     /* TODO return NSEC if unsupported protocol requested */
@@ -858,7 +816,7 @@ mdns_write_domain(struct mdns_outpacket *outpkt, struct mdns_domain *domain)
   }
   if (jump_offset) {
     /* Write jump */
-    jump = htons(DOMAIN_JUMP | jump_offset);
+    jump = lwip_htons(DOMAIN_JUMP | jump_offset);
     res = pbuf_take_at(outpkt->pbuf, &jump, DOMAIN_JUMP_SIZE, outpkt->write_offset);
     if (res != ERR_OK) {
       return res;
@@ -910,7 +868,7 @@ mdns_add_question(struct mdns_outpacket *outpkt, struct mdns_domain *domain, u16
   }
 
   /* Write type */
-  field16 = htons(type);
+  field16 = lwip_htons(type);
   res = pbuf_take_at(outpkt->pbuf, &field16, sizeof(field16), outpkt->write_offset);
   if (res != ERR_OK) {
     return res;
@@ -921,7 +879,7 @@ mdns_add_question(struct mdns_outpacket *outpkt, struct mdns_domain *domain, u16
   if (unicast) {
     klass |= 0x8000;
   }
-  field16 = htons(klass);
+  field16 = lwip_htons(klass);
   res = pbuf_take_at(outpkt->pbuf, &field16, sizeof(field16), outpkt->write_offset);
   if (res != ERR_OK) {
     return res;
@@ -985,7 +943,7 @@ mdns_add_answer(struct mdns_outpacket *reply, struct mdns_domain *domain, u16_t
   mdns_add_question(reply, domain, type, klass, cache_flush);
 
   /* Write TTL */
-  field32 = htonl(ttl);
+  field32 = lwip_htonl(ttl);
   res = pbuf_take_at(reply->pbuf, &field32, sizeof(field32), reply->write_offset);
   if (res != ERR_OK) {
     return res;
@@ -1015,7 +973,7 @@ mdns_add_answer(struct mdns_outpacket *reply, struct mdns_domain *domain, u16_t
   }
 
   /* Write rd_length after when we know the answer size */
-  field16 = htons(reply->write_offset - answer_offset);
+  field16 = lwip_htons(reply->write_offset - answer_offset);
   res = pbuf_take_at(reply->pbuf, &field16, sizeof(field16), rdlen_offset);
 
   return res;
@@ -1043,14 +1001,14 @@ mdns_read_rr_info(struct mdns_packet *pkt, struct mdns_rr_info *info)
     return ERR_VAL;
   }
   pkt->parse_offset += copied;
-  info->type = ntohs(field16);
+  info->type = lwip_ntohs(field16);
 
   copied = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), pkt->parse_offset);
   if (copied != sizeof(field16)) {
     return ERR_VAL;
   }
   pkt->parse_offset += copied;
-  info->klass = ntohs(field16);
+  info->klass = lwip_ntohs(field16);
 
   return ERR_OK;
 }
@@ -1132,14 +1090,14 @@ mdns_read_answer(struct mdns_packet *pkt, struct mdns_answer *answer)
       return ERR_VAL;
     }
     pkt->parse_offset += copied;
-    answer->ttl = ntohl(ttl);
+    answer->ttl = lwip_ntohl(ttl);
 
     copied = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), pkt->parse_offset);
     if (copied != sizeof(field16)) {
       return ERR_VAL;
     }
     pkt->parse_offset += copied;
-    answer->rd_length = ntohs(field16);
+    answer->rd_length = lwip_ntohs(field16);
 
     answer->rd_offset = pkt->parse_offset;
     pkt->parse_offset += answer->rd_length;
@@ -1155,9 +1113,9 @@ static err_t
 mdns_add_a_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct netif *netif)
 {
   struct mdns_domain host;
-  mdns_build_host_domain(&host, (struct mdns_host*)netif->client_data[mdns_netif_client_id]);
+  mdns_build_host_domain(&host, NETIF_TO_HOST(netif));
   LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with A record\n"));
-  return mdns_add_answer(reply, &host, DNS_RRTYPE_A, DNS_RRCLASS_IN, cache_flush, ((struct mdns_host*)netif->client_data[mdns_netif_client_id])->dns_ttl, (const u8_t *) netif_ip4_addr(netif), sizeof(ip4_addr_t), NULL);
+  return mdns_add_answer(reply, &host, DNS_RRTYPE_A, DNS_RRCLASS_IN, cache_flush, (NETIF_TO_HOST(netif))->dns_ttl, (const u8_t *) netif_ip4_addr(netif), sizeof(ip4_addr_t), NULL);
 }
 
 /** Write a 4.3.2.1.in-addr.arpa -> hostname.local PTR RR to outpacket */
@@ -1165,10 +1123,10 @@ static err_t
 mdns_add_hostv4_ptr_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct netif *netif)
 {
   struct mdns_domain host, revhost;
-  mdns_build_host_domain(&host, (struct mdns_host*)netif->client_data[mdns_netif_client_id]);
+  mdns_build_host_domain(&host, NETIF_TO_HOST(netif));
   mdns_build_reverse_v4_domain(&revhost, netif_ip4_addr(netif));
   LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with v4 PTR record\n"));
-  return mdns_add_answer(reply, &revhost, DNS_RRTYPE_PTR, DNS_RRCLASS_IN, cache_flush, ((struct mdns_host*)netif->client_data[mdns_netif_client_id])->dns_ttl, NULL, 0, &host);
+  return mdns_add_answer(reply, &revhost, DNS_RRTYPE_PTR, DNS_RRCLASS_IN, cache_flush, (NETIF_TO_HOST(netif))->dns_ttl, NULL, 0, &host);
 }
 #endif
 
@@ -1178,9 +1136,9 @@ static err_t
 mdns_add_aaaa_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct netif *netif, int addrindex)
 {
   struct mdns_domain host;
-  mdns_build_host_domain(&host, (struct mdns_host*)netif->client_data[mdns_netif_client_id]);
+  mdns_build_host_domain(&host, NETIF_TO_HOST(netif));
   LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with AAAA record\n"));
-  return mdns_add_answer(reply, &host, DNS_RRTYPE_AAAA, DNS_RRCLASS_IN, cache_flush, ((struct mdns_host*)netif->client_data[mdns_netif_client_id])->dns_ttl, (const u8_t *) netif_ip6_addr(netif, addrindex), sizeof(ip6_addr_t), NULL);
+  return mdns_add_answer(reply, &host, DNS_RRTYPE_AAAA, DNS_RRCLASS_IN, cache_flush, (NETIF_TO_HOST(netif))->dns_ttl, (const u8_t *) netif_ip6_addr(netif, addrindex), sizeof(ip6_addr_t), NULL);
 }
 
 /** Write a x.y.z.ip6.arpa -> hostname.local PTR RR to outpacket */
@@ -1188,10 +1146,10 @@ static err_t
 mdns_add_hostv6_ptr_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct netif *netif, int addrindex)
 {
   struct mdns_domain host, revhost;
-  mdns_build_host_domain(&host, (struct mdns_host*)netif->client_data[mdns_netif_client_id]);
+  mdns_build_host_domain(&host, NETIF_TO_HOST(netif));
   mdns_build_reverse_v6_domain(&revhost, netif_ip6_addr(netif, addrindex));
   LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with v6 PTR record\n"));
-  return mdns_add_answer(reply, &revhost, DNS_RRTYPE_PTR, DNS_RRCLASS_IN, cache_flush, ((struct mdns_host*)netif->client_data[mdns_netif_client_id])->dns_ttl, NULL, 0, &host);
+  return mdns_add_answer(reply, &revhost, DNS_RRTYPE_PTR, DNS_RRCLASS_IN, cache_flush, (NETIF_TO_HOST(netif))->dns_ttl, NULL, 0, &host);
 }
 #endif
 
@@ -1232,9 +1190,9 @@ mdns_add_srv_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct mdns
      */
     srvhost.skip_compression = 1;
   }
-  srvdata[0] = htons(SRV_PRIORITY);
-  srvdata[1] = htons(SRV_WEIGHT);
-  srvdata[2] = htons(service->port);
+  srvdata[0] = lwip_htons(SRV_PRIORITY);
+  srvdata[1] = lwip_htons(SRV_WEIGHT);
+  srvdata[2] = lwip_htons(service->port);
   LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with SRV record\n"));
   return mdns_add_answer(reply, &service_instance, DNS_RRTYPE_SRV, DNS_RRCLASS_IN, cache_flush, service->dns_ttl,
                          (const u8_t *) &srvdata, sizeof(srvdata), &srvhost);
@@ -1295,7 +1253,7 @@ mdns_send_outpacket(struct mdns_outpacket *outpkt)
   struct mdns_service *service;
   err_t res;
   int i;
-  struct mdns_host* mdns = (struct mdns_host*)outpkt->netif->client_data[mdns_netif_client_id];
+  struct mdns_host* mdns = NETIF_TO_HOST(outpkt->netif);
 
   /* Write answers to host questions */
 #if LWIP_IPV4
@@ -1449,11 +1407,11 @@ mdns_send_outpacket(struct mdns_outpacket *outpkt)
     /* Write header */
     memset(&hdr, 0, sizeof(hdr));
     hdr.flags1 = DNS_FLAG1_RESPONSE | DNS_FLAG1_AUTHORATIVE;
-    hdr.numanswers = htons(outpkt->answers);
-    hdr.numextrarr = htons(outpkt->additional);
+    hdr.numanswers = lwip_htons(outpkt->answers);
+    hdr.numextrarr = lwip_htons(outpkt->additional);
     if (outpkt->legacy_query) {
-      hdr.numquestions = htons(1);
-      hdr.id = htons(outpkt->tx_id);
+      hdr.numquestions = lwip_htons(1);
+      hdr.id = lwip_htons(outpkt->tx_id);
     }
     pbuf_take(outpkt->pbuf, &hdr, sizeof(hdr));
 
@@ -1495,7 +1453,7 @@ mdns_announce(struct netif *netif, const ip_addr_t *destination)
 {
   struct mdns_outpacket announce;
   int i;
-  struct mdns_host* mdns = (struct mdns_host*)netif->client_data[mdns_netif_client_id];
+  struct mdns_host* mdns = NETIF_TO_HOST(netif);
 
   memset(&announce, 0, sizeof(announce));
   announce.netif = netif;
@@ -1540,7 +1498,7 @@ mdns_handle_question(struct mdns_packet *pkt)
   int replies = 0;
   int i;
   err_t res;
-  struct mdns_host* mdns = (struct mdns_host*)pkt->netif->client_data[mdns_netif_client_id];
+  struct mdns_host* mdns = NETIF_TO_HOST(pkt->netif);
 
   mdns_init_outpacket(&reply, pkt);
 
@@ -1695,19 +1653,19 @@ mdns_handle_question(struct mdns_packet *pkt)
           do {
             /* Check priority field */
             len = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), read_pos);
-            if (len != sizeof(field16) || ntohs(field16) != SRV_PRIORITY) {
+            if (len != sizeof(field16) || lwip_ntohs(field16) != SRV_PRIORITY) {
               break;
             }
             read_pos += len;
             /* Check weight field */
             len = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), read_pos);
-            if (len != sizeof(field16) || ntohs(field16) != SRV_WEIGHT) {
+            if (len != sizeof(field16) || lwip_ntohs(field16) != SRV_WEIGHT) {
               break;
             }
             read_pos += len;
             /* Check port field */
             len = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), read_pos);
-            if (len != sizeof(field16) || ntohs(field16) != service->port) {
+            if (len != sizeof(field16) || lwip_ntohs(field16) != service->port) {
               break;
             }
             read_pos += len;
@@ -1780,8 +1738,6 @@ mdns_handle_response(struct mdns_packet *pkt)
 /**
  * Receive input function for MDNS packets.
  * Handles both IPv4 and IPv6 UDP pcbs.
- *
- * @params see udp.h
  */
 static void
 mdns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
@@ -1796,7 +1752,7 @@ mdns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr,
 
   LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Received IPv%d MDNS packet, len %d\n", IP_IS_V6(addr)? 6 : 4, p->tot_len));
 
-  if (recv_netif->client_data[mdns_netif_client_id] == NULL) {
+  if (NETIF_TO_HOST(recv_netif) == NULL) {
     /* From netif not configured for MDNS */
     goto dealloc;
   }
@@ -1818,9 +1774,9 @@ mdns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr,
   packet.netif = recv_netif;
   packet.pbuf = p;
   packet.parse_offset = offset;
-  packet.tx_id = ntohs(hdr.id);
-  packet.questions = packet.questions_left = ntohs(hdr.numquestions);
-  packet.answers = packet.answers_left = ntohs(hdr.numanswers) + ntohs(hdr.numauthrr) + ntohs(hdr.numextrarr);
+  packet.tx_id = lwip_ntohs(hdr.id);
+  packet.questions = packet.questions_left = lwip_ntohs(hdr.numquestions);
+  packet.answers = packet.answers_left = lwip_ntohs(hdr.numanswers) + lwip_ntohs(hdr.numauthrr) + lwip_ntohs(hdr.numextrarr);
 
 #if LWIP_IPV6
   if (IP_IS_V6(ip_current_dest_addr())) {
@@ -1864,6 +1820,7 @@ mdns_resp_init(void)
   mdns_pcb->ttl = MDNS_TTL;
 #endif
   res = udp_bind(mdns_pcb, IP_ANY_TYPE, MDNS_PORT);
+  LWIP_UNUSED_ARG(res); /* in case of LWIP_NOASSERT */
   LWIP_ASSERT("Failed to bind pcb", res == ERR_OK);
   udp_recv(mdns_pcb, mdns_recv, NULL);
 
@@ -1883,7 +1840,7 @@ mdns_resp_netif_settings_changed(struct netif *netif)
 {
   LWIP_ERROR("mdns_resp_netif_ip_changed: netif != NULL", (netif != NULL), return);
 
-  if (netif->client_data[mdns_netif_client_id] == NULL) {
+  if (NETIF_TO_HOST(netif) == NULL) {
     return;
   }
 
@@ -1892,7 +1849,7 @@ mdns_resp_netif_settings_changed(struct netif *netif)
    mdns_announce(netif, IP6_ADDR_ANY);
 #endif
 #if LWIP_IPV4
-   mdns_announce(netif, IP_ADDR_ANY);
+   mdns_announce(netif, IP4_ADDR_ANY);
 #endif
 }
 
@@ -1915,11 +1872,11 @@ mdns_resp_add_netif(struct netif *netif, const char *hostname, u32_t dns_ttl)
   LWIP_ERROR("mdns_resp_add_netif: netif != NULL", (netif != NULL), return ERR_VAL);
   LWIP_ERROR("mdns_resp_add_netif: Hostname too long", (strlen(hostname) <= MDNS_LABEL_MAXLEN), return ERR_VAL);
 
-  LWIP_ASSERT("mdns_resp_add_netif: Double add", netif->client_data[mdns_netif_client_id] == NULL);
+  LWIP_ASSERT("mdns_resp_add_netif: Double add", NETIF_TO_HOST(netif) == NULL);
   mdns = (struct mdns_host *) mem_malloc(sizeof(struct mdns_host));
   LWIP_ERROR("mdns_resp_add_netif: Alloc failed", (mdns != NULL), return ERR_MEM);
 
-  netif->client_data[mdns_netif_client_id] = mdns;
+  netif_set_client_data(netif, mdns_netif_client_id, mdns);
 
   memset(mdns, 0, sizeof(struct mdns_host));
   MEMCPY(&mdns->name, hostname, LWIP_MIN(MDNS_LABEL_MAXLEN, strlen(hostname)));
@@ -1944,7 +1901,7 @@ mdns_resp_add_netif(struct netif *netif, const char *hostname, u32_t dns_ttl)
 
 cleanup:
   mem_free(mdns);
-  netif->client_data[mdns_netif_client_id] = NULL;
+  netif_set_client_data(netif, mdns_netif_client_id, NULL);
   return res;
 }
 
@@ -1962,7 +1919,7 @@ mdns_resp_remove_netif(struct netif *netif)
   struct mdns_host* mdns;
 
   LWIP_ASSERT("mdns_resp_remove_netif: Null pointer", netif);
-  mdns = (struct mdns_host*)netif->client_data[mdns_netif_client_id];
+  mdns = NETIF_TO_HOST(netif);
   LWIP_ERROR("mdns_resp_remove_netif: Not an active netif", (mdns != NULL), return ERR_VAL);
 
   for (i = 0; i < MDNS_MAX_SERVICES; i++) {
@@ -1981,7 +1938,7 @@ mdns_resp_remove_netif(struct netif *netif)
 #endif
 
   mem_free(mdns);
-  netif->client_data[mdns_netif_client_id] = NULL;
+  netif_set_client_data(netif, mdns_netif_client_id, NULL);
   return ERR_OK;
 }
 
@@ -2009,7 +1966,7 @@ mdns_resp_add_service(struct netif *netif, const char *name, const char *service
   struct mdns_host* mdns;
 
   LWIP_ASSERT("mdns_resp_add_service: netif != NULL", netif);
-  mdns = (struct mdns_host*)netif->client_data[mdns_netif_client_id];
+  mdns = NETIF_TO_HOST(netif);
   LWIP_ERROR("mdns_resp_add_service: Not an mdns netif", (mdns != NULL), return ERR_VAL);
 
   LWIP_ERROR("mdns_resp_add_service: Name too long", (strlen(name) <= MDNS_LABEL_MAXLEN), return ERR_VAL);
@@ -2044,7 +2001,7 @@ mdns_resp_add_service(struct netif *netif, const char *name, const char *service
   mdns_announce(netif, IP6_ADDR_ANY);
 #endif
 #if LWIP_IPV4
-  mdns_announce(netif, IP_ADDR_ANY);
+  mdns_announce(netif, IP4_ADDR_ANY);
 #endif
 
   return ERR_OK;
@@ -2062,7 +2019,7 @@ mdns_resp_add_service(struct netif *netif, const char *name, const char *service
 err_t
 mdns_resp_add_service_txtitem(struct mdns_service *service, const char *txt, u8_t txt_len)
 {
-  LWIP_ASSERT("mdns_resp_add_service: service != NULL", service);
+  LWIP_ASSERT("mdns_resp_add_service_txtitem: service != NULL", service);
 
   /* Use a mdns_domain struct to store txt chunks since it is the same encoding */
   return mdns_domain_add_label(&service->txtdata, txt, txt_len);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f52033e9/net/ip/lwip_base/src/apps/mqtt/mqtt.c
----------------------------------------------------------------------
diff --git a/net/ip/lwip_base/src/apps/mqtt/mqtt.c b/net/ip/lwip_base/src/apps/mqtt/mqtt.c
new file mode 100644
index 0000000..a0e77b9
--- /dev/null
+++ b/net/ip/lwip_base/src/apps/mqtt/mqtt.c
@@ -0,0 +1,1341 @@
+/**
+ * @file
+ * MQTT client
+ *
+ * @defgroup mqtt MQTT client
+ * @ingroup apps
+ * @verbinclude mqtt_client.txt
+ */
+
+/*
+ * Copyright (c) 2016 Erik Andersson <er...@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack
+ *
+ * Author: Erik Andersson <er...@gmail.com>
+ *
+ *
+ * @todo:
+ * - Handle large outgoing payloads for PUBLISH messages
+ * - Fix restriction of a single topic in each (UN)SUBSCRIBE message (protocol has support for multiple topics)
+ * - Add support for legacy MQTT protocol version
+ *
+ * Please coordinate changes and requests with Erik Andersson
+ * Erik Andersson <er...@gmail.com>
+ *
+ */
+#include "lwip/apps/mqtt.h"
+#include "lwip/timeouts.h"
+#include "lwip/ip_addr.h"
+#include "lwip/mem.h"
+#include "lwip/err.h"
+#include "lwip/pbuf.h"
+#include "lwip/tcp.h"
+#include <string.h>
+
+#if LWIP_TCP && LWIP_CALLBACK_API
+
+/**
+ * MQTT_DEBUG: Default is off.
+ */
+#if !defined MQTT_DEBUG || defined __DOXYGEN__
+#define MQTT_DEBUG                  LWIP_DBG_OFF
+#endif
+
+#define MQTT_DEBUG_TRACE        (MQTT_DEBUG | LWIP_DBG_TRACE)
+#define MQTT_DEBUG_STATE        (MQTT_DEBUG | LWIP_DBG_STATE)
+#define MQTT_DEBUG_WARN         (MQTT_DEBUG | LWIP_DBG_LEVEL_WARNING)
+#define MQTT_DEBUG_WARN_STATE   (MQTT_DEBUG | LWIP_DBG_LEVEL_WARNING | LWIP_DBG_STATE)
+#define MQTT_DEBUG_SERIOUS      (MQTT_DEBUG | LWIP_DBG_LEVEL_SERIOUS)
+
+static void mqtt_cyclic_timer(void *arg);
+
+/**
+ * MQTT client connection states
+ */
+enum {
+  TCP_DISCONNECTED,
+  TCP_CONNECTING,
+  MQTT_CONNECTING,
+  MQTT_CONNECTED
+};
+
+/**
+ * MQTT control message types
+ */
+enum mqtt_message_type {
+  MQTT_MSG_TYPE_CONNECT = 1,
+  MQTT_MSG_TYPE_CONNACK = 2,
+  MQTT_MSG_TYPE_PUBLISH = 3,
+  MQTT_MSG_TYPE_PUBACK = 4,
+  MQTT_MSG_TYPE_PUBREC = 5,
+  MQTT_MSG_TYPE_PUBREL = 6,
+  MQTT_MSG_TYPE_PUBCOMP = 7,
+  MQTT_MSG_TYPE_SUBSCRIBE = 8,
+  MQTT_MSG_TYPE_SUBACK = 9,
+  MQTT_MSG_TYPE_UNSUBSCRIBE = 10,
+  MQTT_MSG_TYPE_UNSUBACK = 11,
+  MQTT_MSG_TYPE_PINGREQ = 12,
+  MQTT_MSG_TYPE_PINGRESP = 13,
+  MQTT_MSG_TYPE_DISCONNECT = 14
+};
+
+/** Helpers to extract control packet type and qos from first byte in fixed header */
+#define MQTT_CTL_PACKET_TYPE(fixed_hdr_byte0) ((fixed_hdr_byte0 & 0xf0) >> 4)
+#define MQTT_CTL_PACKET_QOS(fixed_hdr_byte0) ((fixed_hdr_byte0 & 0x6) >> 1)
+
+/**
+ * MQTT connect flags, only used in CONNECT message
+ */
+enum mqtt_connect_flag {
+  MQTT_CONNECT_FLAG_USERNAME = 1 << 7,
+  MQTT_CONNECT_FLAG_PASSWORD = 1 << 6,
+  MQTT_CONNECT_FLAG_WILL_RETAIN = 1 << 5,
+  MQTT_CONNECT_FLAG_WILL = 1 << 2,
+  MQTT_CONNECT_FLAG_CLEAN_SESSION = 1 << 1
+};
+
+
+#if defined(LWIP_DEBUG)
+static const char * const mqtt_message_type_str[15] =
+{
+  "UNDEFINED",
+  "CONNECT",
+  "CONNACK",
+  "PUBLISH",
+  "PUBACK",
+  "PUBREC",
+  "PUBREL",
+  "PUBCOMP",
+  "SUBSCRIBE",
+  "SUBACK",
+  "UNSUBSCRIBE",
+  "UNSUBACK",
+  "PINGREQ",
+  "PINGRESP",
+  "DISCONNECT"
+};
+
+/**
+ * Message type value to string
+ * @param msg_type see enum mqtt_message_type
+ * 
+ * @return Control message type text string
+ */
+static const char *
+mqtt_msg_type_to_str(u8_t msg_type)
+{
+  if (msg_type >= LWIP_ARRAYSIZE(mqtt_message_type_str)) {
+    msg_type = 0;
+  }
+  return mqtt_message_type_str[msg_type];
+}
+
+#endif
+
+
+/**
+ * Generate MQTT packet identifier
+ * @param client MQTT client
+ * @return New packet identifier, range 1 to 65535
+ */
+static u16_t
+msg_generate_packet_id(mqtt_client_t *client)
+{
+  client->pkt_id_seq++;
+  if (client->pkt_id_seq == 0) {
+    client->pkt_id_seq++;
+  }
+  return client->pkt_id_seq;
+}
+
+/*--------------------------------------------------------------------------------------------------------------------- */
+/* Output ring buffer */
+
+
+#define MQTT_RINGBUF_IDX_MASK ((MQTT_OUTPUT_RINGBUF_SIZE) - 1)
+
+/** Add single item to ring buffer */
+#define mqtt_ringbuf_put(rb, item) ((rb)->buf)[(rb)->put++ & MQTT_RINGBUF_IDX_MASK] = (item)
+
+/** Return number of bytes in ring buffer */
+#define mqtt_ringbuf_len(rb) ((u16_t)((rb)->put - (rb)->get))
+
+/** Return number of bytes free in ring buffer */
+#define mqtt_ringbuf_free(rb) (MQTT_OUTPUT_RINGBUF_SIZE - mqtt_ringbuf_len(rb))
+
+/** Return number of bytes possible to read without wrapping around */
+#define mqtt_ringbuf_linear_read_length(rb) LWIP_MIN(mqtt_ringbuf_len(rb), (MQTT_OUTPUT_RINGBUF_SIZE - ((rb)->get & MQTT_RINGBUF_IDX_MASK)))
+
+/** Return pointer to ring buffer get position */
+#define mqtt_ringbuf_get_ptr(rb) (&(rb)->buf[(rb)->get & MQTT_RINGBUF_IDX_MASK])
+
+#define mqtt_ringbuf_advance_get_idx(rb, len) ((rb)->get += (len))
+
+
+/**
+ * Try send as many bytes as possible from output ring buffer
+ * @param rb Output ring buffer
+ * @param tpcb TCP connection handle
+ */
+static void
+mqtt_output_send(struct mqtt_ringbuf_t *rb, struct tcp_pcb *tpcb)
+{
+  err_t err;
+  u8_t wrap = 0;
+  u16_t ringbuf_lin_len = mqtt_ringbuf_linear_read_length(rb);
+  u16_t send_len = tcp_sndbuf(tpcb);
+  LWIP_ASSERT("mqtt_output_send: tpcb != NULL", tpcb != NULL);
+
+  if (send_len == 0 || ringbuf_lin_len == 0) {
+    return;
+  }
+
+  LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_output_send: tcp_sndbuf: %d bytes, ringbuf_linear_available: %d, get %d, put %d\n",
+                                send_len, ringbuf_lin_len, ((rb)->get & MQTT_RINGBUF_IDX_MASK), ((rb)->put & MQTT_RINGBUF_IDX_MASK)));
+
+  if (send_len > ringbuf_lin_len) {
+    /* Space in TCP output buffer is larger than available in ring buffer linear portion */
+    send_len = ringbuf_lin_len;
+    /* Wrap around if more data in ring buffer after linear portion */
+    wrap = (mqtt_ringbuf_len(rb) > ringbuf_lin_len);
+  }
+  err = tcp_write(tpcb, mqtt_ringbuf_get_ptr(rb), send_len, TCP_WRITE_FLAG_COPY | (wrap ? TCP_WRITE_FLAG_MORE : 0));
+  if ((err == ERR_OK) && wrap) {
+    mqtt_ringbuf_advance_get_idx(rb, send_len);
+    /* Use the lesser one of ring buffer linear length and TCP send buffer size */
+    send_len = LWIP_MIN(tcp_sndbuf(tpcb), mqtt_ringbuf_linear_read_length(rb));
+    err = tcp_write(tpcb, mqtt_ringbuf_get_ptr(rb), send_len, TCP_WRITE_FLAG_COPY);
+  }
+
+  if (err == ERR_OK) {
+    mqtt_ringbuf_advance_get_idx(rb, send_len);
+    /* Flush */
+    tcp_output(tpcb);
+  } else {
+    LWIP_DEBUGF(MQTT_DEBUG_WARN, ("mqtt_output_send: Send failed with err %d (\"%s\")\n", err, lwip_strerr(err)));
+  }
+}
+
+
+
+/*--------------------------------------------------------------------------------------------------------------------- */
+/* Request queue */
+
+/**
+ * Create request item
+ * @param r_objs Pointer to request objects
+ * @param pkt_id Packet identifier of request
+ * @param cb Packet callback to call when requests lifetime ends
+ * @param arg Parameter following callback
+ * @return Request or NULL if failed to create
+ */
+static struct mqtt_request_t *
+mqtt_create_request(struct mqtt_request_t *r_objs, u16_t pkt_id, mqtt_request_cb_t cb, void *arg)
+{
+  struct mqtt_request_t *r = NULL;
+  u8_t n;
+  LWIP_ASSERT("mqtt_create_request: r_objs != NULL", r_objs != NULL);
+  for (n = 0; n < MQTT_REQ_MAX_IN_FLIGHT; n++) {
+    /* Item point to itself if not in use */
+    if (r_objs[n].next == &r_objs[n]) {
+      r = &r_objs[n];
+      r->next = NULL;
+      r->cb = cb;
+      r->arg = arg;
+      r->pkt_id = pkt_id;
+      break;
+    }
+  }
+  return r;
+}
+
+
+/**
+ * Append request to pending request queue
+ * @param tail Pointer to request queue tail pointer
+ * @param r Request to append
+ */
+static void
+mqtt_append_request(struct mqtt_request_t **tail, struct mqtt_request_t *r)
+{
+  struct mqtt_request_t *head = NULL;
+  s16_t time_before = 0;
+  struct mqtt_request_t *iter;
+
+  LWIP_ASSERT("mqtt_append_request: tail != NULL", tail != NULL);
+
+  /* Iterate trough queue to find head, and count total timeout time */
+  for (iter = *tail; iter != NULL; iter = iter->next) {
+    time_before += iter->timeout_diff;
+    head = iter;
+  }
+
+  LWIP_ASSERT("mqtt_append_request: time_before <= MQTT_REQ_TIMEOUT", time_before <= MQTT_REQ_TIMEOUT);
+  r->timeout_diff = MQTT_REQ_TIMEOUT - time_before;
+  if (head == NULL) {
+    *tail = r;
+  } else {
+    head->next = r;
+  }
+}
+
+
+/**
+ * Delete request item
+ * @param r Request item to delete
+ */
+static void
+mqtt_delete_request(struct mqtt_request_t *r)
+{
+  if (r != NULL) {
+    r->next = r;
+  }
+}
+
+/**
+ * Remove a request item with a specific packet identifier from request queue
+ * @param tail Pointer to request queue tail pointer
+ * @param pkt_id Packet identifier of request to take
+ * @return Request item if found, NULL if not
+ */
+static struct mqtt_request_t *
+mqtt_take_request(struct mqtt_request_t **tail, u16_t pkt_id)
+{
+  struct mqtt_request_t *iter = NULL, *prev = NULL;
+  LWIP_ASSERT("mqtt_take_request: tail != NULL", tail != NULL);
+  /* Search all request for pkt_id */
+  for (iter = *tail; iter != NULL; iter = iter->next) {
+    if (iter->pkt_id == pkt_id) {
+      break;
+    }
+    prev = iter;
+  }
+
+  /* If request was found */
+  if (iter != NULL) {
+    /* unchain */
+    if (prev == NULL) {
+      *tail= iter->next;
+    } else {
+      prev->next = iter->next;
+    }
+    /* If exists, add remaining timeout time for the request to next */
+    if (iter->next != NULL) {
+      iter->next->timeout_diff += iter->timeout_diff;
+    }
+    iter->next = NULL;
+  }
+  return iter;
+}
+
+/**
+ * Handle requests timeout
+ * @param tail Pointer to request queue tail pointer
+ * @param t Time since last call in seconds
+ */
+static void
+mqtt_request_time_elapsed(struct mqtt_request_t **tail, u8_t t)
+{
+  struct mqtt_request_t *r = *tail;
+  LWIP_ASSERT("mqtt_request_time_elapsed: tail != NULL", tail != NULL);
+  while (t > 0 && r != NULL) {
+    if (t >= r->timeout_diff) {
+      t -= (u8_t)r->timeout_diff;
+      /* Unchain */
+      *tail = r->next;
+      /* Notify upper layer about timeout */
+      if (r->cb != NULL) {
+        r->cb(r->arg, ERR_TIMEOUT);
+      }
+      mqtt_delete_request(r);
+      /* Tail might be be modified in callback, so re-read it in every iteration */
+      r = *(struct mqtt_request_t * const volatile *)tail;
+    } else {
+      r->timeout_diff -= t;
+      t = 0;
+    }
+  }
+}
+
+/**
+ * Free all request items
+ * @param tail Pointer to request queue tail pointer
+ */
+static void
+mqtt_clear_requests(struct mqtt_request_t **tail)
+{
+  struct mqtt_request_t *iter, *next;
+  LWIP_ASSERT("mqtt_clear_requests: tail != NULL", tail != NULL);
+  for (iter = *tail; iter != NULL; iter = next) {
+    next = iter->next;
+    mqtt_delete_request(iter);
+  }
+  *tail = NULL;
+}
+/**
+ * Initialize all request items
+ * @param r_objs Pointer to request objects
+ */
+static void
+mqtt_init_requests(struct mqtt_request_t *r_objs)
+{
+  u8_t n;
+  LWIP_ASSERT("mqtt_init_requests: r_objs != NULL", r_objs != NULL);
+  for (n = 0; n < MQTT_REQ_MAX_IN_FLIGHT; n++) {
+    /* Item pointing to itself indicates unused */
+    r_objs[n].next = &r_objs[n];
+  }
+}
+
+/*--------------------------------------------------------------------------------------------------------------------- */
+/* Output message build helpers */
+
+
+static void
+mqtt_output_append_u8(struct mqtt_ringbuf_t *rb, u8_t value)
+{
+  mqtt_ringbuf_put(rb, value);
+}
+
+static
+void mqtt_output_append_u16(struct mqtt_ringbuf_t *rb, u16_t value)
+{
+  mqtt_ringbuf_put(rb, value >> 8);
+  mqtt_ringbuf_put(rb, value & 0xff);
+}
+
+static void
+mqtt_output_append_buf(struct mqtt_ringbuf_t *rb, const void *data, u16_t length)
+{
+  u16_t n;
+  for (n = 0; n < length; n++) {
+    mqtt_ringbuf_put(rb, ((const u8_t *)data)[n]);
+  }
+}
+
+static void
+mqtt_output_append_string(struct mqtt_ringbuf_t *rb, const char *str, u16_t length)
+{
+  u16_t n;
+  mqtt_ringbuf_put(rb, length >> 8);
+  mqtt_ringbuf_put(rb, length & 0xff);
+  for (n = 0; n < length; n++) {
+    mqtt_ringbuf_put(rb, str[n]);
+  }
+}
+
+/**
+ * Append fixed header
+ * @param rb Output ring buffer
+ * @param msg_type see enum mqtt_message_type
+ * @param dup MQTT DUP flag
+ * @param qos MQTT QoS field
+ * @param retain MQTT retain flag
+ * @param r_length Remaining length after fixed header
+ */
+
+static void
+mqtt_output_append_fixed_header(struct mqtt_ringbuf_t *rb, u8_t msg_type, u8_t dup,
+                 u8_t qos, u8_t retain, u16_t r_length)
+{
+  /* Start with control byte */
+  mqtt_output_append_u8(rb, (((msg_type & 0x0f) << 4) | ((dup & 1) << 3) | ((qos & 3) << 1) | (retain & 1)));
+  /* Encode remaining length field */
+  do {
+    mqtt_output_append_u8(rb, (r_length & 0x7f) | (r_length >= 128 ? 0x80 : 0));
+    r_length >>= 7;
+  } while (r_length > 0);
+}
+
+
+/**
+ * Check output buffer space
+ * @param rb Output ring buffer
+ * @param r_length Remaining length after fixed header
+ * @return 1 if message will fit, 0 if not enough buffer space
+ */
+static u8_t
+mqtt_output_check_space(struct mqtt_ringbuf_t *rb, u16_t r_length)
+{
+  /* Start with length of type byte + remaining length */
+  u16_t total_len = 1 + r_length;
+
+  LWIP_ASSERT("mqtt_output_check_space: rb != NULL", rb != NULL);
+
+ /* Calculate number of required bytes to contain the remaining bytes field and add to total*/
+  do {
+    total_len++;
+    r_length >>= 7;
+  } while (r_length > 0);
+
+  return (total_len <= mqtt_ringbuf_free(rb));
+}
+
+
+/**
+ * Close connection to server
+ * @param client MQTT client
+ * @param reason Reason for disconnection
+ */
+static void
+mqtt_close(mqtt_client_t *client, mqtt_connection_status_t reason)
+{
+  LWIP_ASSERT("mqtt_close: client != NULL", client != NULL);
+
+  /* Bring down TCP connection if not already done */
+  if (client->conn != NULL) {
+    err_t res;
+    tcp_recv(client->conn, NULL);
+    tcp_err(client->conn,  NULL);
+    tcp_sent(client->conn, NULL);
+    res = tcp_close(client->conn);
+    if (res != ERR_OK) {
+      tcp_abort(client->conn);
+      LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_close: Close err=%s\n", lwip_strerr(res)));
+    }
+    client->conn = NULL;
+  }
+
+  /* Remove all pending requests */
+  mqtt_clear_requests(&client->pend_req_queue);
+  /* Stop cyclic timer */
+  sys_untimeout(mqtt_cyclic_timer, client);
+
+  /* Notify upper layer of disconnection if changed state */
+  if (client->conn_state != TCP_DISCONNECTED) {
+
+    client->conn_state = TCP_DISCONNECTED;
+    if (client->connect_cb != NULL) {
+      client->connect_cb(client, client->connect_arg, reason);
+    }
+  }
+}
+
+
+/**
+ * Interval timer, called every MQTT_CYCLIC_TIMER_INTERVAL seconds in MQTT_CONNECTING and MQTT_CONNECTED states
+ * @param arg MQTT client
+ */
+static void
+mqtt_cyclic_timer(void *arg)
+{
+  u8_t restart_timer = 1;
+  mqtt_client_t *client = (mqtt_client_t *)arg;
+  LWIP_ASSERT("mqtt_cyclic_timer: client != NULL", client != NULL);
+
+  if (client->conn_state == MQTT_CONNECTING) {
+    client->cyclic_tick++;
+    if ((client->cyclic_tick * MQTT_CYCLIC_TIMER_INTERVAL) >= MQTT_CONNECT_TIMOUT) {
+      LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_cyclic_timer: CONNECT attempt to server timed out\n"));
+      /* Disconnect TCP */
+      mqtt_close(client, MQTT_CONNECT_TIMEOUT);
+      restart_timer = 0;
+    }
+  } else if (client->conn_state == MQTT_CONNECTED) {
+    /* Handle timeout for pending requests */
+    mqtt_request_time_elapsed(&client->pend_req_queue, MQTT_CYCLIC_TIMER_INTERVAL);
+
+    /* keep_alive > 0 means keep alive functionality shall be used */
+    if (client->keep_alive > 0) {
+
+      client->server_watchdog++;
+      /* If reception from server has been idle for 1.5*keep_alive time, server is considered unresponsive */
+      if ((client->server_watchdog * MQTT_CYCLIC_TIMER_INTERVAL) > (client->keep_alive + client->keep_alive/2)) {
+        LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_cyclic_timer: Server incoming keep-alive timeout\n"));
+        mqtt_close(client, MQTT_CONNECT_TIMEOUT);
+        restart_timer = 0;
+      }
+
+      /* If time for a keep alive message to be sent, transmission has been idle for keep_alive time */
+      if ((client->cyclic_tick * MQTT_CYCLIC_TIMER_INTERVAL) >= client->keep_alive) {
+        LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_cyclic_timer: Sending keep-alive message to server\n"));
+        if (mqtt_output_check_space(&client->output, 0) != 0) {
+          mqtt_output_append_fixed_header(&client->output, MQTT_MSG_TYPE_PINGREQ, 0, 0, 0, 0);
+          client->cyclic_tick = 0;
+        }
+      } else {
+        client->cyclic_tick++;
+      }
+    }
+  } else {
+    LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_cyclic_timer: Timer should not be running in state %d\n", client->conn_state));
+    restart_timer = 0;
+  }
+  if (restart_timer) {
+    sys_timeout(MQTT_CYCLIC_TIMER_INTERVAL*1000, mqtt_cyclic_timer, arg);
+  }
+}
+
+
+/**
+ * Send PUBACK, PUBREC or PUBREL response message
+ * @param client MQTT client
+ * @param msg PUBACK, PUBREC or PUBREL
+ * @param pkt_id Packet identifier
+ * @param qos QoS value
+ * @return ERR_OK if successful, ERR_MEM if out of memory
+ */
+static err_t
+pub_ack_rec_rel_response(mqtt_client_t *client, u8_t msg, u16_t pkt_id, u8_t qos)
+{
+  err_t err = ERR_OK;
+  if (mqtt_output_check_space(&client->output, 2)) {
+    mqtt_output_append_fixed_header(&client->output, msg, 0, qos, 0, 2);
+    mqtt_output_append_u16(&client->output, pkt_id);
+    mqtt_output_send(&client->output, client->conn);
+  } else {
+    LWIP_DEBUGF(MQTT_DEBUG_TRACE,("pub_ack_rec_rel_response: OOM creating response: %s with pkt_id: %d\n",
+                                  mqtt_msg_type_to_str(msg), pkt_id));
+    err = ERR_MEM;
+  }
+  return err;
+}
+
+/**
+ * Subscribe response from server
+ * @param r Matching request
+ * @param result Result code from server
+ */
+static void
+mqtt_incomming_suback(struct mqtt_request_t *r, u8_t result)
+{
+  if (r->cb != NULL) {
+    r->cb(r->arg, result < 3 ? ERR_OK : ERR_ABRT);
+  }
+}
+
+
+/**
+ * Complete MQTT message received or buffer full
+ * @param client MQTT client
+ * @param fixed_hdr_idx header index
+ * @param length length received part
+ * @param remaining_length Remaining length of complete message
+ */
+static mqtt_connection_status_t
+  mqtt_message_received(mqtt_client_t *client, u8_t fixed_hdr_idx, u16_t length, u32_t remaining_length)
+{
+  mqtt_connection_status_t res = MQTT_CONNECT_ACCEPTED;
+
+  u8_t *var_hdr_payload = client->rx_buffer + fixed_hdr_idx;
+
+  /* Control packet type */
+  u8_t pkt_type = MQTT_CTL_PACKET_TYPE(client->rx_buffer[0]);
+  u16_t pkt_id = 0;
+
+  if (pkt_type == MQTT_MSG_TYPE_CONNACK) {
+    if (client->conn_state == MQTT_CONNECTING) {
+      /* Get result code from CONNACK */
+      res = (mqtt_connection_status_t)var_hdr_payload[1];
+      LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_message_received: Connect response code %d\n", res));
+      if (res == MQTT_CONNECT_ACCEPTED) {
+        /* Reset cyclic_tick when changing to connected state */
+        client->cyclic_tick = 0;
+        client->conn_state = MQTT_CONNECTED;
+        /* Notify upper layer */
+        if (client->connect_cb != 0) {
+          client->connect_cb(client, client->connect_arg, res);
+        }
+      }
+    } else {
+      LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_message_received: Received CONNACK in connected state\n"));
+    }
+  } else if (pkt_type == MQTT_MSG_TYPE_PINGRESP) {
+    LWIP_DEBUGF(MQTT_DEBUG_TRACE,( "mqtt_message_received: Received PINGRESP from server\n"));
+
+  } else if (pkt_type == MQTT_MSG_TYPE_PUBLISH) {
+    u16_t payload_offset = 0;
+    u16_t payload_length = length;
+    u8_t qos = MQTT_CTL_PACKET_QOS(client->rx_buffer[0]);
+
+    if (client->msg_idx <= MQTT_VAR_HEADER_BUFFER_LEN) {
+      /* Should have topic and pkt id*/
+      uint8_t *topic;
+      uint16_t after_topic;
+      u8_t bkp;
+      u16_t topic_len = var_hdr_payload[0];
+      topic_len = (topic_len << 8) + (u16_t)(var_hdr_payload[1]);
+
+      topic = var_hdr_payload + 2;
+      after_topic = 2 + topic_len;
+      /* Check length, add one byte even for QoS 0 so that zero termination will fit */
+      if ((after_topic + (qos? 2 : 1)) > length) {
+        LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_message_received: Receive buffer can not fit topic + pkt_id\n"));
+        goto out_disconnect;
+      }
+
+      /* id for QoS 1 and 2 */
+      if (qos > 0) {
+        client->inpub_pkt_id = ((u16_t)var_hdr_payload[after_topic] << 8) + (u16_t)var_hdr_payload[after_topic + 1];
+        after_topic += 2;
+      } else {
+        client->inpub_pkt_id = 0;
+      }
+      /* Take backup of byte after topic */
+      bkp = topic[topic_len];
+      /* Zero terminate string */
+      topic[topic_len] = 0;
+      /* Payload data remaining in receive buffer */
+      payload_length = length - after_topic;
+      payload_offset = after_topic;
+
+      LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_incomming_publish: Received message with QoS %d at topic: %s, payload length %d\n",
+                                    qos, topic, remaining_length + payload_length));
+      if (client->pub_cb != NULL) {
+        client->pub_cb(client->inpub_arg, (const char *)topic, remaining_length + payload_length);
+      }
+      /* Restore byte after topic */
+      topic[topic_len] = bkp;
+    }
+    if (payload_length > 0 || remaining_length == 0) {
+      client->data_cb(client->inpub_arg, var_hdr_payload + payload_offset, payload_length, remaining_length == 0 ? MQTT_DATA_FLAG_LAST : 0);
+      /* Reply if QoS > 0 */
+      if (remaining_length == 0 && qos > 0) {
+        /* Send PUBACK for QoS 1 or PUBREC for QoS 2 */
+        u8_t resp_msg = (qos == 1) ? MQTT_MSG_TYPE_PUBACK : MQTT_MSG_TYPE_PUBREC;
+        LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_incomming_publish: Sending publish response: %s with pkt_id: %d\n",
+                                      mqtt_msg_type_to_str(resp_msg), client->inpub_pkt_id));
+        pub_ack_rec_rel_response(client, resp_msg, client->inpub_pkt_id, 0);
+      }
+    }
+  } else {
+    /* Get packet identifier */
+    pkt_id = (u16_t)var_hdr_payload[0] << 8;
+    pkt_id |= (u16_t)var_hdr_payload[1];
+    if (pkt_id == 0) {
+      LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_message_received: Got message with illegal packet identifier: 0\n"));
+      goto out_disconnect;
+    }
+    if (pkt_type == MQTT_MSG_TYPE_PUBREC) {
+      LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_message_received: PUBREC, sending PUBREL with pkt_id: %d\n",pkt_id));
+      pub_ack_rec_rel_response(client, MQTT_MSG_TYPE_PUBREL, pkt_id, 1);
+
+    } else if (pkt_type == MQTT_MSG_TYPE_PUBREL) {
+      LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_message_received: PUBREL, sending PUBCOMP response with pkt_id: %d\n",pkt_id));
+      pub_ack_rec_rel_response(client, MQTT_MSG_TYPE_PUBCOMP, pkt_id, 0);
+
+    } else if (pkt_type == MQTT_MSG_TYPE_SUBACK || pkt_type == MQTT_MSG_TYPE_UNSUBACK ||
+              pkt_type == MQTT_MSG_TYPE_PUBCOMP || pkt_type == MQTT_MSG_TYPE_PUBACK) {
+      struct mqtt_request_t *r = mqtt_take_request(&client->pend_req_queue, pkt_id);
+      if (r != NULL) {
+        LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_message_received: %s response with id %d\n", mqtt_msg_type_to_str(pkt_type), pkt_id));
+        if (pkt_type == MQTT_MSG_TYPE_SUBACK) {
+          if (length < 3) {
+            LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_message_received: To small SUBACK packet\n"));
+            goto out_disconnect;
+          } else {
+            mqtt_incomming_suback(r, var_hdr_payload[2]);
+          }
+        } else if (r->cb != NULL) {
+          r->cb(r->arg, ERR_OK);
+        }
+        mqtt_delete_request(r);
+      } else {
+        LWIP_DEBUGF(MQTT_DEBUG_WARN,( "mqtt_message_received: Received %s reply, with wrong pkt_id: %d\n", mqtt_msg_type_to_str(pkt_type), pkt_id));
+      }
+    } else {
+      LWIP_DEBUGF(MQTT_DEBUG_WARN,( "mqtt_message_received: Received unknown message type: %d\n", pkt_type));
+      goto out_disconnect;
+    }
+  }
+  return res;
+out_disconnect:
+  return MQTT_CONNECT_DISCONNECTED;
+}
+
+
+/**
+ * MQTT incoming message parser
+ * @param client MQTT client
+ * @param p PBUF chain of received data
+ * @return Connection status
+ */
+static mqtt_connection_status_t
+mqtt_parse_incoming(mqtt_client_t *client, struct pbuf *p)
+{
+  u16_t in_offset = 0;
+  u32_t msg_rem_len = 0;
+  u8_t fixed_hdr_idx = 0;
+  u8_t b = 0;
+
+  while (p->tot_len > in_offset) {
+    if ((fixed_hdr_idx < 2) || ((b & 0x80) != 0)) {
+
+      if (fixed_hdr_idx < client->msg_idx) {
+        b = client->rx_buffer[fixed_hdr_idx];
+      } else {
+        b = pbuf_get_at(p, in_offset++);
+        client->rx_buffer[client->msg_idx++] = b;
+      }
+      fixed_hdr_idx++;
+
+      if (fixed_hdr_idx >= 2) {
+        msg_rem_len |= (u32_t)(b & 0x7f) << ((fixed_hdr_idx - 2) * 7);
+        if ((b & 0x80) == 0) {
+          LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_parse_incoming: Remaining length after fixed header: %d\n", msg_rem_len));
+          if (msg_rem_len == 0) {
+            /* Complete message with no extra headers of payload received */
+            mqtt_message_received(client, fixed_hdr_idx, 0, 0);
+            client->msg_idx = 0;
+            fixed_hdr_idx = 0;
+          } else {
+            /* Bytes remaining in message */
+            msg_rem_len = (msg_rem_len + fixed_hdr_idx) - client->msg_idx;
+          }
+        }
+      }
+    } else {
+      u16_t cpy_len, cpy_start, buffer_space;
+
+      cpy_start = (client->msg_idx - fixed_hdr_idx) % (MQTT_VAR_HEADER_BUFFER_LEN - fixed_hdr_idx) + fixed_hdr_idx;
+
+      /* Allow to copy the lesser one of available length in input data or bytes remaining in message */
+      cpy_len = (u16_t)LWIP_MIN((u16_t)(p->tot_len - in_offset), msg_rem_len);
+
+      /* Limit to available space in buffer */
+      buffer_space = MQTT_VAR_HEADER_BUFFER_LEN - cpy_start;
+      if (cpy_len > buffer_space) {
+        cpy_len = buffer_space;
+      }
+      pbuf_copy_partial(p, client->rx_buffer+cpy_start, cpy_len, in_offset);
+
+      /* Advance get and put indexes  */
+      client->msg_idx += cpy_len;
+      in_offset += cpy_len;
+      msg_rem_len -= cpy_len;
+
+      LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_parse_incoming: msg_idx: %d, cpy_len: %d, remaining %d\n", client->msg_idx, cpy_len, msg_rem_len));
+      if (msg_rem_len == 0 || cpy_len == buffer_space) {
+        /* Whole message received or buffer is full */
+        mqtt_connection_status_t res = mqtt_message_received(client, fixed_hdr_idx, (cpy_start + cpy_len) - fixed_hdr_idx, msg_rem_len);
+        if (res != MQTT_CONNECT_ACCEPTED) {
+          return res;
+        }
+        if (msg_rem_len == 0) {
+          /* Reset parser state */
+          client->msg_idx = 0;
+          /* msg_tot_len = 0; */
+          fixed_hdr_idx = 0;
+        }
+      }
+    }
+  }
+  return MQTT_CONNECT_ACCEPTED;
+}
+
+
+/**
+ * TCP received callback function. @see tcp_recv_fn
+ * @param arg MQTT client
+ * @param p PBUF chain of received data
+ * @param err Passed as return value if not ERR_OK
+ * @return ERR_OK or err passed into callback
+ */
+static err_t
+mqtt_tcp_recv_cb(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
+{
+  mqtt_client_t *client = (mqtt_client_t *)arg;
+  LWIP_ASSERT("mqtt_tcp_recv_cb: client != NULL", client != NULL);
+  LWIP_ASSERT("mqtt_tcp_recv_cb: client->conn == pcb", client->conn == pcb);
+
+  if (p == NULL) {
+    LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_tcp_recv_cb: Recv pbuf=NULL, remote has closed connection\n"));
+    mqtt_close(client, MQTT_CONNECT_DISCONNECTED);
+  } else {
+    mqtt_connection_status_t res;
+    if (err != ERR_OK) {
+      LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_tcp_recv_cb: Recv err=%d\n", err));
+      pbuf_free(p);
+      return err;
+    }
+
+    /* Tell remote that data has been received */
+    tcp_recved(pcb, p->tot_len);
+    res = mqtt_parse_incoming(client, p);
+    pbuf_free(p);
+
+    if (res != MQTT_CONNECT_ACCEPTED) {
+      mqtt_close(client, res);
+    }
+    /* If keep alive functionality is used */
+    if (client->keep_alive != 0) {
+      /* Reset server alive watchdog */
+      client->server_watchdog = 0;
+    }
+
+  }
+  return ERR_OK;
+}
+
+
+/**
+ * TCP data sent callback function. @see tcp_sent_fn
+ * @param arg MQTT client
+ * @param tpcb TCP connection handle
+ * @param len Number of bytes sent
+ * @return ERR_OK
+ */
+static err_t
+mqtt_tcp_sent_cb(void *arg, struct tcp_pcb *tpcb, u16_t len)
+{
+  mqtt_client_t *client = (mqtt_client_t *)arg;
+
+  LWIP_UNUSED_ARG(tpcb);
+  LWIP_UNUSED_ARG(len);
+
+  if (client->conn_state == MQTT_CONNECTED) {
+    struct mqtt_request_t *r;
+
+    /* Reset keep-alive send timer and server watchdog */
+    client->cyclic_tick = 0;
+    client->server_watchdog = 0;
+    /* QoS 0 publish has no response from server, so call its callbacks here */
+    while ((r = mqtt_take_request(&client->pend_req_queue, 0)) != NULL) {
+      LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_tcp_sent_cb: Calling QoS 0 publish complete callback\n"));
+      if (r->cb != NULL) {
+        r->cb(r->arg, ERR_OK);
+      }
+      mqtt_delete_request(r);
+    }
+    /* Try send any remaining buffers from output queue */
+    mqtt_output_send(&client->output, client->conn);
+  }
+  return ERR_OK;
+}
+
+/**
+ * TCP error callback function. @see tcp_err_fn
+ * @param arg MQTT client
+ * @param err Error encountered
+ */
+static void
+mqtt_tcp_err_cb(void *arg, err_t err)
+{
+  mqtt_client_t *client = (mqtt_client_t *)arg;
+  LWIP_UNUSED_ARG(err); /* only used for debug output */
+  LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_tcp_err_cb: TCP error callback: error %d, arg: %p\n", err, arg));
+  LWIP_ASSERT("mqtt_tcp_err_cb: client != NULL", client != NULL);
+  /* Set conn to null before calling close as pcb is already deallocated*/
+  client->conn = 0;
+  mqtt_close(client, MQTT_CONNECT_DISCONNECTED);
+}
+
+/**
+ * TCP poll callback function. @see tcp_poll_fn
+ * @param arg MQTT client
+ * @param tpcb TCP connection handle
+ * @return err ERR_OK
+ */
+static err_t
+mqtt_tcp_poll_cb(void *arg, struct tcp_pcb *tpcb)
+{
+  mqtt_client_t *client = (mqtt_client_t *)arg;
+  if (client->conn_state == MQTT_CONNECTED) {
+    /* Try send any remaining buffers from output queue */
+    mqtt_output_send(&client->output, tpcb);
+  }
+  return ERR_OK;
+}
+
+/**
+ * TCP connect callback function. @see tcp_connected_fn
+ * @param arg MQTT client
+ * @param err Always ERR_OK, mqtt_tcp_err_cb is called in case of error
+ * @return ERR_OK
+ */
+static err_t
+mqtt_tcp_connect_cb(void *arg, struct tcp_pcb *tpcb, err_t err)
+{
+  mqtt_client_t* client = (mqtt_client_t *)arg;
+
+  if (err != ERR_OK) {
+    LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_tcp_connect_cb: TCP connect error %d\n", err));
+    return err;
+  }
+
+  /* Initiate receiver state */
+  client->msg_idx = 0;
+
+  /* Setup TCP callbacks */
+  tcp_recv(tpcb, mqtt_tcp_recv_cb);
+  tcp_sent(tpcb, mqtt_tcp_sent_cb);
+  tcp_poll(tpcb, mqtt_tcp_poll_cb, 2);
+
+  LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_tcp_connect_cb: TCP connection established to server\n"));
+  /* Enter MQTT connect state */
+  client->conn_state = MQTT_CONNECTING;
+
+  /* Start cyclic timer */
+  sys_timeout(MQTT_CYCLIC_TIMER_INTERVAL*1000, mqtt_cyclic_timer, client);
+  client->cyclic_tick = 0;
+
+  /* Start transmission from output queue, connect message is the first one out*/
+  mqtt_output_send(&client->output, client->conn);
+
+  return ERR_OK;
+}
+
+
+
+/*---------------------------------------------------------------------------------------------------- */
+/* Public API */
+
+
+/**
+ * @ingroup mqtt
+ * MQTT publish function.
+ * @param client MQTT client
+ * @param topic Publish topic string
+ * @param payload Data to publish (NULL is allowed)
+ * @param payload_length: Length of payload (0 is allowed)
+ * @param qos Quality of service, 0 1 or 2
+ * @param retain MQTT retain flag
+ * @param cb Callback to call when publish is complete or has timed out
+ * @param arg User supplied argument to publish callback
+ * @return ERR_OK if successful
+ *         ERR_CONN if client is disconnected
+ *         ERR_MEM if short on memory
+ */
+err_t
+mqtt_publish(mqtt_client_t *client, const char *topic, const void *payload, u16_t payload_length, u8_t qos, u8_t retain,
+             mqtt_request_cb_t cb, void *arg)
+{
+  struct mqtt_request_t *r;
+  u16_t pkt_id;
+  size_t topic_strlen;
+  size_t total_len;
+  u16_t topic_len;
+  u16_t remaining_length;
+
+  LWIP_ASSERT("mqtt_publish: client != NULL", client);
+  LWIP_ASSERT("mqtt_publish: topic != NULL", topic);
+  LWIP_ERROR("mqtt_publish: TCP disconnected", (client->conn_state != TCP_DISCONNECTED), return ERR_CONN);
+
+  topic_strlen = strlen(topic);
+  LWIP_ERROR("mqtt_publish: topic length overflow", (topic_strlen <= (0xFFFF - 2)), return ERR_ARG);
+  topic_len = (u16_t)topic_strlen;
+  total_len = 2 + topic_len + payload_length;
+  LWIP_ERROR("mqtt_publish: total length overflow", (total_len <= 0xFFFF), return ERR_ARG);
+  remaining_length = (u16_t)total_len;
+
+  LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_publish: Publish with payload length %d to topic \"%s\"\n", payload_length, topic));
+
+  if (qos > 0) {
+    remaining_length += 2;
+    /* Generate pkt_id id for QoS1 and 2 */
+    pkt_id = msg_generate_packet_id(client);
+  } else {
+    /* Use reserved value pkt_id 0 for QoS 0 in request handle */
+    pkt_id = 0;
+  }
+
+  r = mqtt_create_request(client->req_list, pkt_id, cb, arg);
+  if (r == NULL) {
+    return ERR_MEM;
+  }
+
+  if (mqtt_output_check_space(&client->output, remaining_length) == 0) {
+    mqtt_delete_request(r);
+    return ERR_MEM;
+  }
+  /* Append fixed header */
+  mqtt_output_append_fixed_header(&client->output, MQTT_MSG_TYPE_PUBLISH, 0, qos, retain, remaining_length);
+
+  /* Append Topic */
+  mqtt_output_append_string(&client->output, topic, topic_len);
+
+  /* Append packet if for QoS 1 and 2*/
+  if (qos > 0) {
+    mqtt_output_append_u16(&client->output, pkt_id);
+  }
+
+  /* Append optional publish payload */
+  if ((payload != NULL) && (payload_length > 0)) {
+    mqtt_output_append_buf(&client->output, payload, payload_length);
+  }
+
+  mqtt_append_request(&client->pend_req_queue, r);
+  mqtt_output_send(&client->output, client->conn);
+  return ERR_OK;
+}
+
+
+/**
+ * @ingroup mqtt
+ * MQTT subscribe/unsubscribe function.
+ * @param client MQTT client
+ * @param topic topic to subscribe to
+ * @param qos Quality of service, 0 1 or 2 (only used for subscribe)
+ * @param cb Callback to call when subscribe/unsubscribe reponse is received
+ * @param arg User supplied argument to publish callback
+ * @param sub 1 for subscribe, 0 for unsubscribe
+ * @return ERR_OK if successful, @see err_t enum for other results
+ */
+err_t
+mqtt_sub_unsub(mqtt_client_t *client, const char *topic, u8_t qos, mqtt_request_cb_t cb, void *arg, u8_t sub)
+{
+  size_t topic_strlen;
+  size_t total_len;
+  u16_t topic_len;
+  u16_t remaining_length;
+  u16_t pkt_id;
+  struct mqtt_request_t *r;
+
+  LWIP_ASSERT("mqtt_sub_unsub: client != NULL", client);
+  LWIP_ASSERT("mqtt_sub_unsub: topic != NULL", topic);
+
+  topic_strlen = strlen(topic);
+  LWIP_ERROR("mqtt_sub_unsub: topic length overflow", (topic_strlen <= (0xFFFF - 2)), return ERR_ARG);
+  topic_len = (u16_t)topic_strlen;
+  /* Topic string, pkt_id, qos for subscribe */
+  total_len =  topic_len + 2 + 2 + (sub != 0);
+  LWIP_ERROR("mqtt_sub_unsub: total length overflow", (total_len <= 0xFFFF), return ERR_ARG);
+  remaining_length = (u16_t)total_len;
+
+  LWIP_ASSERT("mqtt_sub_unsub: qos < 3", qos < 3);
+  if (client->conn_state == TCP_DISCONNECTED) {
+    LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_sub_unsub: Can not (un)subscribe in disconnected state\n"));
+    return ERR_CONN;
+  }
+
+  pkt_id = msg_generate_packet_id(client);
+  r = mqtt_create_request(client->req_list, pkt_id, cb, arg);
+  if (r == NULL) {
+    return ERR_MEM;
+  }
+
+  if (mqtt_output_check_space(&client->output, remaining_length) == 0) {
+    mqtt_delete_request(r);
+    return ERR_MEM;
+  }
+
+  LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_sub_unsub: Client (un)subscribe to topic \"%s\", id: %d\n", topic, pkt_id));
+
+  mqtt_output_append_fixed_header(&client->output, sub ? MQTT_MSG_TYPE_SUBSCRIBE : MQTT_MSG_TYPE_UNSUBSCRIBE, 0, 1, 0, remaining_length);
+  /* Packet id */
+  mqtt_output_append_u16(&client->output, pkt_id);
+  /* Topic */
+  mqtt_output_append_string(&client->output, topic, topic_len);
+  /* QoS */
+  if (sub != 0) {
+    mqtt_output_append_u8(&client->output, LWIP_MIN(qos, 2));
+  }
+
+  mqtt_append_request(&client->pend_req_queue, r);
+  mqtt_output_send(&client->output, client->conn);
+  return ERR_OK;
+}
+
+
+/**
+ * @ingroup mqtt
+ * Set callback to handle incoming publish requests from server
+ * @param client MQTT client
+ * @param pub_cb Callback invoked when publish starts, contain topic and total length of payload
+ * @param data_cb Callback for each fragment of payload that arrives
+ * @param arg User supplied argument to both callbacks
+ */
+void
+mqtt_set_inpub_callback(mqtt_client_t *client, mqtt_incoming_publish_cb_t pub_cb,
+                             mqtt_incoming_data_cb_t data_cb, void *arg)
+{
+  LWIP_ASSERT("mqtt_set_inpub_callback: client != NULL", client != NULL);
+  client->data_cb = data_cb;
+  client->pub_cb = pub_cb;
+  client->inpub_arg = arg;
+}
+
+/**
+ * @ingroup mqtt
+ * Create a new MQTT client instance
+ * @return Pointer to instance on success, NULL otherwise
+ */
+mqtt_client_t *
+mqtt_client_new(void)
+{
+  mqtt_client_t *client = (mqtt_client_t *)mem_malloc(sizeof(mqtt_client_t));
+  if (client != NULL) {
+    memset(client, 0, sizeof(mqtt_client_t));
+  }
+  return client;
+}
+
+
+/**
+ * @ingroup mqtt
+ * Connect to MQTT server
+ * @param client MQTT client
+ * @param ip_addr Server IP
+ * @param port Server port
+ * @param cb Connection state change callback
+ * @param arg User supplied argument to connection callback
+ * @param client_info Client identification and connection options
+ * @return ERR_OK if successful, @see err_t enum for other results
+ */
+err_t
+mqtt_client_connect(mqtt_client_t *client, const ip_addr_t *ip_addr, u16_t port, mqtt_connection_cb_t cb, void *arg,
+                    const struct mqtt_connect_client_info_t *client_info)
+{
+  err_t err;
+  size_t len;
+  u16_t client_id_length;
+  /* Length is the sum of 2+"MQTT", protocol level, flags and keep alive */
+  u16_t remaining_length = 2 + 4 + 1 + 1 + 2;
+  u8_t flags = 0, will_topic_len = 0, will_msg_len = 0;
+
+  LWIP_ASSERT("mqtt_client_connect: client != NULL", client != NULL);
+  LWIP_ASSERT("mqtt_client_connect: ip_addr != NULL", ip_addr != NULL);
+  LWIP_ASSERT("mqtt_client_connect: client_info != NULL", client_info != NULL);
+  LWIP_ASSERT("mqtt_client_connect: client_info->client_id != NULL", client_info->client_id != NULL);
+
+  if (client->conn_state != TCP_DISCONNECTED) {
+    LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_client_connect: Already connected\n"));
+    return ERR_ISCONN;
+  }
+
+  /* Wipe clean */
+  memset(client, 0, sizeof(mqtt_client_t));
+  client->connect_arg = arg;
+  client->connect_cb = cb;
+  client->keep_alive = client_info->keep_alive;
+  mqtt_init_requests(client->req_list);
+
+  /* Build connect message */
+  if (client_info->will_topic != NULL && client_info->will_msg != NULL) {
+    flags |= MQTT_CONNECT_FLAG_WILL;
+    flags |= (client_info->will_qos & 3) << 3;
+    if (client_info->will_retain) {
+      flags |= MQTT_CONNECT_FLAG_WILL_RETAIN;
+    }
+    len = strlen(client_info->will_topic);
+    LWIP_ERROR("mqtt_client_connect: client_info->will_topic length overflow", len <= 0xFF, return ERR_VAL);
+    LWIP_ERROR("mqtt_client_connect: client_info->will_topic length must be > 0", len > 0, return ERR_VAL);
+    will_topic_len = (u8_t)len;
+    len = strlen(client_info->will_msg);
+    LWIP_ERROR("mqtt_client_connect: client_info->will_msg length overflow", len <= 0xFF, return ERR_VAL);
+    will_msg_len = (u8_t)len;
+    len = remaining_length + 2 + will_topic_len + 2 + will_msg_len;
+    LWIP_ERROR("mqtt_client_connect: remaining_length overflow", len <= 0xFFFF, return ERR_VAL);
+    remaining_length = (u16_t)len;
+  }
+
+  /* Don't complicate things, always connect using clean session */
+  flags |= MQTT_CONNECT_FLAG_CLEAN_SESSION;
+
+  len = strlen(client_info->client_id);
+  LWIP_ERROR("mqtt_client_connect: client_info->client_id length overflow", len <= 0xFFFF, return ERR_VAL);
+  client_id_length = (u16_t)len;
+  len = remaining_length + 2 + client_id_length;
+  LWIP_ERROR("mqtt_client_connect: remaining_length overflow", len <= 0xFFFF, return ERR_VAL);
+  remaining_length = (u16_t)len;
+
+  if (mqtt_output_check_space(&client->output, remaining_length) == 0) {
+    return ERR_MEM;
+  }
+
+  client->conn = tcp_new();
+  if (client->conn == NULL) {
+    return ERR_MEM;
+  }
+
+  /* Set arg pointer for callbacks */
+  tcp_arg(client->conn, client);
+  /* Any local address, pick random local port number */
+  err = tcp_bind(client->conn, IP_ADDR_ANY, 0);
+  if (err != ERR_OK) {
+    LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_client_connect: Error binding to local ip/port, %d\n", err));
+    goto tcp_fail;
+  }
+  LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_client_connect: Connecting to host: %s at port:%"U16_F"\n", ipaddr_ntoa(ip_addr), port));
+
+  /* Connect to server */
+  err = tcp_connect(client->conn, ip_addr, port, mqtt_tcp_connect_cb);
+  if (err != ERR_OK) {
+    LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_client_connect: Error connecting to remote ip/port, %d\n", err));
+    goto tcp_fail;
+  }
+  /* Set error callback */
+  tcp_err(client->conn, mqtt_tcp_err_cb);
+  client->conn_state = TCP_CONNECTING;
+
+  /* Append fixed header */
+  mqtt_output_append_fixed_header(&client->output, MQTT_MSG_TYPE_CONNECT, 0, 0, 0, remaining_length);
+  /* Append Protocol string */
+  mqtt_output_append_string(&client->output, "MQTT", 4);
+  /* Append Protocol level */
+  mqtt_output_append_u8(&client->output, 4);
+  /* Append connect flags */
+  mqtt_output_append_u8(&client->output, flags);
+  /* Append keep-alive */
+  mqtt_output_append_u16(&client->output, client_info->keep_alive);
+  /* Append client id */
+  mqtt_output_append_string(&client->output, client_info->client_id, client_id_length);
+  /* Append will message if used */
+  if ((flags & MQTT_CONNECT_FLAG_WILL) != 0) {
+    mqtt_output_append_string(&client->output, client_info->will_topic, will_topic_len);
+    mqtt_output_append_string(&client->output, client_info->will_msg, will_msg_len);
+  }
+  return ERR_OK;
+
+tcp_fail:
+  tcp_abort(client->conn);
+  client->conn = NULL;
+  return err;
+}
+
+
+/**
+ * @ingroup mqtt
+ * Disconnect from MQTT server
+ * @param client MQTT client
+ */
+void
+mqtt_disconnect(mqtt_client_t *client)
+{
+  LWIP_ASSERT("mqtt_disconnect: client != NULL", client);
+  /* If connection in not already closed */
+  if (client->conn_state != TCP_DISCONNECTED) {
+    /* Set conn_state before calling mqtt_close to prevent callback from being called */
+    client->conn_state = TCP_DISCONNECTED;
+    mqtt_close(client, (mqtt_connection_status_t)0);
+  }
+}
+
+/**
+ * @ingroup mqtt
+ * Check connection with server
+ * @param client MQTT client
+ * @return 1 if connected to server, 0 otherwise
+ */
+u8_t
+mqtt_client_is_connected(mqtt_client_t *client)
+{
+  LWIP_ASSERT("mqtt_client_is_connected: client != NULL", client);
+  return client->conn_state == MQTT_CONNECTED;
+}
+
+#endif /* LWIP_TCP && LWIP_CALLBACK_API */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f52033e9/net/ip/lwip_base/src/apps/netbiosns/netbiosns.c
----------------------------------------------------------------------
diff --git a/net/ip/lwip_base/src/apps/netbiosns/netbiosns.c b/net/ip/lwip_base/src/apps/netbiosns/netbiosns.c
index 1b1f952..2dfbe65 100644
--- a/net/ip/lwip_base/src/apps/netbiosns/netbiosns.c
+++ b/net/ip/lwip_base/src/apps/netbiosns/netbiosns.c
@@ -46,6 +46,7 @@
 
 #if LWIP_IPV4 && LWIP_UDP  /* don't build if not configured for use in lwipopts.h */
 
+#include "lwip/def.h"
 #include "lwip/udp.h"
 #include "lwip/netif.h"
 
@@ -270,7 +271,7 @@ netbiosns_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t
         /* decode the NetBIOS name */
         netbiosns_name_decode((char*)(netbios_name_hdr->encname), netbios_name, sizeof(netbios_name));
         /* if the packet is for us */
-        if (NETBIOS_STRCMP(netbios_name, NETBIOS_LOCAL_NAME) == 0) {
+        if (lwip_strnicmp(netbios_name, NETBIOS_LOCAL_NAME, sizeof(NETBIOS_LOCAL_NAME)) == 0) {
           struct pbuf *q;
           struct netbios_resp *resp;
 
@@ -327,7 +328,7 @@ netbiosns_init(void)
   netbiosns_pcb = udp_new_ip_type(IPADDR_TYPE_ANY);
   if (netbiosns_pcb != NULL) {
     /* we have to be allowed to send broadcast packets! */
-    netbiosns_pcb->so_options |= SOF_BROADCAST;
+    ip_set_option(netbiosns_pcb, SOF_BROADCAST);
     udp_bind(netbiosns_pcb, IP_ANY_TYPE, NETBIOS_PORT);
     udp_recv(netbiosns_pcb, netbiosns_recv, netbiosns_pcb);
   }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f52033e9/net/ip/lwip_base/src/apps/snmp/snmp_asn1.c
----------------------------------------------------------------------
diff --git a/net/ip/lwip_base/src/apps/snmp/snmp_asn1.c b/net/ip/lwip_base/src/apps/snmp/snmp_asn1.c
index 7b41445..f35b760 100644
--- a/net/ip/lwip_base/src/apps/snmp/snmp_asn1.c
+++ b/net/ip/lwip_base/src/apps/snmp/snmp_asn1.c
@@ -288,7 +288,7 @@ snmp_asn1_enc_oid(struct snmp_pbuf_stream* pbuf_stream, const u32_t *oid, u16_t
 /**
  * Returns octet count for length.
  *
- * @param length
+ * @param length parameter length
  * @param octets_needed points to the return value
  */
 void
@@ -306,7 +306,7 @@ snmp_asn1_enc_length_cnt(u16_t length, u8_t *octets_needed)
 /**
  * Returns octet count for an u32_t.
  *
- * @param value
+ * @param value value to be encoded
  * @param octets_needed points to the return value
  *
  * @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded
@@ -332,7 +332,7 @@ snmp_asn1_enc_u32t_cnt(u32_t value, u16_t *octets_needed)
 /**
  * Returns octet count for an u64_t.
  *
- * @param value
+ * @param value value to be encoded
  * @param octets_needed points to the return value
  *
  * @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded
@@ -357,7 +357,7 @@ snmp_asn1_enc_u64t_cnt(const u32_t *value, u16_t *octets_needed)
 /**
  * Returns octet count for an s32_t.
  *
- * @param value
+ * @param value value to be encoded
  * @param octets_needed points to the return value
  *
  * @note ASN coded integers are _always_ signed.