From dd7ef729c1efae8a60d5977e15247e30b8691552 Mon Sep 17 00:00:00 2001 From: Nathaniel Wesley Filardo Date: Thu, 27 Feb 2020 16:39:12 +0000 Subject: [PATCH 01/17] luacheck: net.ifinfo is a thing now --- tools/luacheck_config.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/luacheck_config.lua b/tools/luacheck_config.lua index 85147ec788..c5f20aab69 100644 --- a/tools/luacheck_config.lua +++ b/tools/luacheck_config.lua @@ -381,6 +381,7 @@ stds.nodemcu_libs = { setdnsserver = empty } }, + ifinfo = empty, multicastJoin = empty, multicastLeave = empty } From b7ca96b301c45f4cc387b0cab31a9522d369a4e3 Mon Sep 17 00:00:00 2001 From: Nathaniel Wesley Filardo Date: Sun, 5 Jan 2020 09:23:48 +0000 Subject: [PATCH 02/17] espconn: remove unused espconn code, take 1 This is the easiest part of https://github.com/nodemcu/nodemcu-firmware/issues/3004 . It removes a bunch of functions that were never called in our tree. --- app/include/lwip/app/espconn.h | 245 ----------------- app/include/sys/espconn_mbedtls.h | 11 - app/include/user_mbedtls.h | 6 - app/lwip/app/espconn.c | 437 ------------------------------ app/lwip/app/espconn_mdns.c | 134 --------- app/lwip/app/espconn_udp.c | 37 --- app/mbedtls/app/espconn_secure.c | 44 +-- 7 files changed, 3 insertions(+), 911 deletions(-) delete mode 100644 app/lwip/app/espconn_mdns.c diff --git a/app/include/lwip/app/espconn.h b/app/include/lwip/app/espconn.h index f0ee73e24b..75e7a1f66d 100644 --- a/app/include/lwip/app/espconn.h +++ b/app/include/lwip/app/espconn.h @@ -149,12 +149,6 @@ enum espconn_option{ ESPCONN_END }; -enum espconn_level{ - ESPCONN_KEEPIDLE, - ESPCONN_KEEPINTVL, - ESPCONN_KEEPCNT -}; - enum espconn_mode{ ESPCONN_NOMODE, ESPCONN_TCPSERVER_MODE, @@ -300,16 +294,6 @@ bool espconn_find_connection(struct espconn *pespconn, espconn_msg **pnode); sint8 espconn_get_connection_info(struct espconn *pespconn, remot_info **pcon_info, uint8 typeflags); -/****************************************************************************** - * FunctionName : espconn_get_packet_info - * Description : get the packet info with host - * Parameters : espconn -- the espconn used to disconnect the connection - * infoarg -- the packet info - * Returns : the errur code -*******************************************************************************/ - -sint8 espconn_get_packet_info(struct espconn *espconn, struct espconn_packet* infoarg); - /****************************************************************************** * FunctionName : espconn_connect * Description : The function given as the connect @@ -355,23 +339,6 @@ extern sint8 espconn_accept(struct espconn *espconn); extern sint8 espconn_create(struct espconn *espconn); -/****************************************************************************** - * FunctionName : espconn_tcp_get_wnd - * Description : get the window size of simulatenously active TCP connections - * Parameters : none - * Returns : the number of TCP_MSS active TCP connections -*******************************************************************************/ -extern uint8 espconn_tcp_get_wnd(void); - -/****************************************************************************** - * FunctionName : espconn_tcp_set_max_con - * Description : set the window size simulatenously active TCP connections - * Parameters : num -- the number of TCP_MSS - * Returns : ESPCONN_ARG -- Illegal argument - * ESPCONN_OK -- No error -*******************************************************************************/ -extern sint8 espconn_tcp_set_wnd(uint8 num); - /****************************************************************************** * FunctionName : espconn_tcp_get_max_con * Description : get the number of simulatenously active TCP connections @@ -381,50 +348,6 @@ extern sint8 espconn_tcp_set_wnd(uint8 num); extern uint8 espconn_tcp_get_max_con(void); -/****************************************************************************** - * FunctionName : espconn_tcp_set_max_con - * Description : set the number of simulatenously active TCP connections - * Parameters : num -- total number - * Returns : none -*******************************************************************************/ - -extern sint8 espconn_tcp_set_max_con(uint8 num); - -/****************************************************************************** - * FunctionName : espconn_tcp_get_max_retran - * Description : get the Maximum number of retransmissions of data active TCP connections - * Parameters : none - * Returns : the Maximum number of retransmissions -*******************************************************************************/ -extern uint8 espconn_tcp_get_max_retran(void); - -/****************************************************************************** - * FunctionName : espconn_tcp_set_max_retran - * Description : set the Maximum number of retransmissions of data active TCP connections - * Parameters : num -- the Maximum number of retransmissions - * Returns : result -*******************************************************************************/ - -extern sint8 espconn_tcp_set_max_retran(uint8 num); - -/****************************************************************************** - * FunctionName : espconn_tcp_get_max_syn - * Description : get the Maximum number of retransmissions of SYN segments - * Parameters : none - * Returns : the Maximum number of retransmissions -*******************************************************************************/ - -extern uint8 espconn_tcp_get_max_syn(void); - -/****************************************************************************** - * FunctionName : espconn_tcp_set_max_syn - * Description : set the Maximum number of retransmissions of SYN segments - * Parameters : num -- the Maximum number of retransmissions - * Returns : result -*******************************************************************************/ - -extern sint8 espconn_tcp_set_max_syn(uint8 num); - /****************************************************************************** * FunctionName : espconn_tcp_get_max_con_allow * Description : get the count of simulatenously active connections on the server @@ -434,15 +357,6 @@ extern sint8 espconn_tcp_set_max_syn(uint8 num); extern sint8 espconn_tcp_get_max_con_allow(struct espconn *espconn); -/****************************************************************************** - * FunctionName : espconn_tcp_set_max_con_allow - * Description : set the count of simulatenously active connections on the server - * Parameters : espconn -- espconn to set the count - * Returns : result -*******************************************************************************/ - -extern sint8 espconn_tcp_set_max_con_allow(struct espconn *espconn, uint8 num); - /****************************************************************************** * FunctionName : espconn_tcp_set_buf_count * Description : set the total number of espconn_buf on the unsent lists @@ -561,36 +475,6 @@ extern sint8 espconn_regist_disconcb(struct espconn *espconn, espconn_connect_ca extern uint32 espconn_port(void); -/****************************************************************************** - * FunctionName : espconn_set_opt - * Description : access port value for client so that we don't end up bouncing - * all connections at the same time . - * Parameters : none - * Returns : access port value -*******************************************************************************/ -extern sint8 espconn_set_opt(struct espconn *espconn, uint8 opt); - -/****************************************************************************** - * FunctionName : espconn_set_keepalive - * Description : access level value for connection so that we set the value for - * keep alive - * Parameters : espconn -- the espconn used to set the connection - * level -- the connection's level - * value -- the value of time(s) - * Returns : access port value -*******************************************************************************/ -extern sint8 espconn_set_keepalive(struct espconn *espconn, uint8 level, void* optarg); - -/****************************************************************************** - * FunctionName : espconn_get_keepalive - * Description : access level value for connection so that we get the value for - * keep alive - * Parameters : espconn -- the espconn used to get the connection - * level -- the connection's level - * Returns : access keep alive value -*******************************************************************************/ -extern sint8 espconn_get_keepalive(struct espconn *espconn, uint8 level, void *optarg); - /****************************************************************************** * FunctionName : espconn_gethostbyname * Description : Resolve a hostname (string) into an IP address. @@ -611,15 +495,6 @@ extern sint8 espconn_get_keepalive(struct espconn *espconn, uint8 level, void *o extern err_t espconn_gethostbyname(struct espconn *pespconn, const char *name, ip_addr_t *addr, dns_found_callback found); -/****************************************************************************** - * FunctionName : espconn_abort - * Description : Forcely abort with host - * Parameters : espconn -- the espconn used to connect with the host - * Returns : result -*******************************************************************************/ - -extern sint8 espconn_abort(struct espconn *espconn); - /****************************************************************************** * FunctionName : espconn_encry_connect * Description : The function given as connection @@ -660,27 +535,6 @@ extern sint8 espconn_secure_send(struct espconn *espconn, uint8 *psent, uint16 l extern sint8 espconn_secure_sent(struct espconn *espconn, uint8 *psent, uint16 length); -/****************************************************************************** - * FunctionName : espconn_secure_set_size - * Description : set the buffer size for client or server - * Parameters : level -- set for client or server - * 1: client,2:server,3:client and server - * size -- buffer size - * Returns : true or false -*******************************************************************************/ - -extern bool espconn_secure_set_size(uint8 level, uint16 size); - -/****************************************************************************** - * FunctionName : espconn_secure_get_size - * Description : get buffer size for client or server - * Parameters : level -- set for client or server - * 1: client,2:server,3:client and server - * Returns : buffer size for client or server -*******************************************************************************/ - -extern sint16 espconn_secure_get_size(uint8 level); - /****************************************************************************** * FunctionName : espconn_secure_ca_enable * Description : enable the certificate authenticate and set the flash sector @@ -767,24 +621,6 @@ extern sint8 espconn_secure_accept(struct espconn *espconn); extern sint8 espconn_secure_delete(struct espconn *espconn); -/****************************************************************************** - * FunctionName : espconn_igmp_join - * Description : join a multicast group - * Parameters : host_ip -- the ip address of udp server - * multicast_ip -- multicast ip given by user - * Returns : none -*******************************************************************************/ -extern sint8 espconn_igmp_join(ip_addr_t *host_ip, ip_addr_t *multicast_ip); - -/****************************************************************************** - * FunctionName : espconn_igmp_leave - * Description : leave a multicast group - * Parameters : host_ip -- the ip address of udp server - * multicast_ip -- multicast ip given by user - * Returns : none -*******************************************************************************/ -extern sint8 espconn_igmp_leave(ip_addr_t *host_ip, ip_addr_t *multicast_ip); - /****************************************************************************** * FunctionName : espconn_recv_hold * Description : hold tcp receive @@ -801,86 +637,5 @@ extern sint8 espconn_recv_hold(struct espconn *pespconn); *******************************************************************************/ extern sint8 espconn_recv_unhold(struct espconn *pespconn); -/****************************************************************************** - * FunctionName : espconn_mdns_init - * Description : register a device with mdns - * Parameters : ipAddr -- the ip address of device - * hostname -- the hostname of device - * Returns : none -*******************************************************************************/ -extern void espconn_mdns_init(struct mdns_info *info); -/****************************************************************************** - * FunctionName : espconn_mdns_init - * Description : close mdns socket - * Parameters : void - * Returns : none -*******************************************************************************/ -extern void espconn_mdns_close(void); -/****************************************************************************** - * FunctionName : mdns_server_register - * Description : register a server and join a multicast group - * Parameters : none - * Returns : none -*******************************************************************************/ -extern void espconn_mdns_server_register(void); -/****************************************************************************** - * FunctionName : mdns_server_register - * Description : unregister server and leave multicast group - * Parameters : none - * Returns : none -*******************************************************************************/ -extern void espconn_mdns_server_unregister(void); -/****************************************************************************** - * FunctionName : espconn_mdns_get_servername - * Description : get server name - * Parameters : none - * Returns : server name -*******************************************************************************/ -extern char* espconn_mdns_get_servername(void); -/****************************************************************************** - * FunctionName : espconn_mdns_get_servername - * Description : set server name - * Parameters : server name - * Returns : none -*******************************************************************************/ -extern void espconn_mdns_set_servername(const char *name); -/****************************************************************************** - * FunctionName : espconn_mdns_set_hostname - * Description : set host name - * Parameters : host name - * Returns : none -*******************************************************************************/ -extern void espconn_mdns_set_hostname(char *name); -/****************************************************************************** - * FunctionName : espconn_mdns_init - * Description : get host name - * Parameters : void - * Returns : hostname -*******************************************************************************/ -extern char* espconn_mdns_get_hostname(void); -/****************************************************************************** - * FunctionName : espconn_mdns_disable - * Description : join a multicast group - * Parameters : host_ip -- the ip address of udp server - * multicast_ip -- multicast ip given by user - * Returns : none -*******************************************************************************/ -extern void espconn_mdns_disable(void); -/****************************************************************************** - * FunctionName : espconn_mdns_enable - * Description : enable mdns - * Parameters : void - * Returns : none -*******************************************************************************/ -extern void espconn_mdns_enable(void); -/****************************************************************************** - * FunctionName : espconn_dns_setserver - * Description : Initialize one of the DNS servers. - * Parameters : numdns -- the index of the DNS server to set must - * be < DNS_MAX_SERVERS = 2 - * dnsserver -- IP address of the DNS server to set - * Returns : none -*******************************************************************************/ -extern void espconn_dns_setserver(u8_t numdns, ip_addr_t *dnsserver); #endif diff --git a/app/include/sys/espconn_mbedtls.h b/app/include/sys/espconn_mbedtls.h index 79e4c92fa3..9d105c6c88 100644 --- a/app/include/sys/espconn_mbedtls.h +++ b/app/include/sys/espconn_mbedtls.h @@ -122,7 +122,6 @@ enum { #define ESPCONN_SECURE_MAX_SIZE 8192 #define ESPCONN_SECURE_DEFAULT_HEAP 0x3800 -#define ESPCONN_SECURE_DEFAULT_SIZE SSL_BUFFER_SIZE #define ESPCONN_HANDSHAKE_TIMEOUT 0x3C #define ESPCONN_INVALID_TYPE 0xFFFFFFFF #define MBEDTLS_SSL_PLAIN_ADD TCP_MSS @@ -248,16 +247,6 @@ extern void espconn_ssl_sent(void *arg, uint8 *psent, uint16 length); extern void espconn_ssl_disconnect(espconn_msg *pdis); -/****************************************************************************** - * FunctionName : espconn_secure_get_size - * Description : get buffer size for client or server - * Parameters : level -- set for client or server - * 1: client,2:server,3:client and server - * Returns : buffer size for client or server -*******************************************************************************/ - -extern sint16 espconn_secure_get_size(uint8 level); - #endif diff --git a/app/include/user_mbedtls.h b/app/include/user_mbedtls.h index ea9cfaf8bd..03af8bc195 100644 --- a/app/include/user_mbedtls.h +++ b/app/include/user_mbedtls.h @@ -303,17 +303,11 @@ extern void mbedtls_free_wrap(void *p); //#define MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT 86400 /**< 1 day */ //#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /**< Maximum entries in cache */ -#if 0 -// dynamic buffer sizing with espconn_secure_set_size() -extern unsigned int max_content_len; -#define MBEDTLS_SSL_MAX_CONTENT_LEN max_content_len; -#else // the current mbedtls integration doesn't allow to set the buffer size dynamically: // MBEDTLS_SSL_MAX_FRAGMENT_LENGTH feature and dynamic sizing are mutually exclusive // due to non-constant initializer element in app/mbedtls/library/ssl_tls.c:150 // the buffer size is hardcoded here and value is taken from SSL_BUFFER_SIZE (user_config.h) #define MBEDTLS_SSL_MAX_CONTENT_LEN SSL_BUFFER_SIZE /**< Maxium fragment length in bytes, determines the size of each of the two internal I/O buffers */ -#endif //#define MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */ //#define MBEDTLS_PSK_MAX_LEN 32 /**< Max size of TLS pre-shared keys, in bytes (default 256 bits) */ diff --git a/app/lwip/app/espconn.c b/app/lwip/app/espconn.c index 5817f396e1..93b16abc63 100644 --- a/app/lwip/app/espconn.c +++ b/app/lwip/app/espconn.c @@ -472,33 +472,6 @@ sint16 ICACHE_FLASH_ATTR espconn_recv(struct espconn *espconn, void *mem, size_t return ESPCONN_ARG; } -/****************************************************************************** - * FunctionName : espconn_sendto - * Description : send data for UDP - * Parameters : espconn -- espconn to set for UDP - * psent -- data to send - * length -- length of data to send - * Returns : error -*******************************************************************************/ -sint16 ICACHE_FLASH_ATTR -espconn_sendto(struct espconn *espconn, uint8 *psent, uint16 length) -{ - espconn_msg *pnode = NULL; - bool value = false; - err_t error = ESPCONN_OK; - - if (espconn == NULL || psent == NULL || length == 0) { - return ESPCONN_ARG; - } - - /*Find the node depend on the espconn message*/ - value = espconn_find_connection(espconn, &pnode); - if (value && espconn->type == ESPCONN_UDP) - return espconn_udp_sendto(pnode, psent, length); - else - return ESPCONN_ARG; -} - /****************************************************************************** * FunctionName : espconn_send * Description : sent data for client or server @@ -510,51 +483,6 @@ espconn_sendto(struct espconn *espconn, uint8 *psent, uint16 length) sint8 espconn_send(struct espconn *espconn, uint8 *psent, uint16 length) __attribute__((alias("espconn_sent"))); -/****************************************************************************** - * FunctionName : espconn_tcp_get_wnd - * Description : get the window size of simulatenously active TCP connections - * Parameters : none - * Returns : the number of TCP_MSS active TCP connections -*******************************************************************************/ -uint8 ICACHE_FLASH_ATTR espconn_tcp_get_wnd(void) -{ - uint8 tcp_num = 0; - - tcp_num = (TCP_WND / TCP_MSS); - - return tcp_num; -} -/****************************************************************************** - * FunctionName : espconn_tcp_set_max_con - * Description : set the window size simulatenously active TCP connections - * Parameters : num -- the number of TCP_MSS - * Returns : ESPCONN_ARG -- Illegal argument - * ESPCONN_OK -- No error -*******************************************************************************/ -sint8 ICACHE_FLASH_ATTR espconn_tcp_set_wnd(uint8 num) -{ - if (num == 0 || num > linkMax) - return ESPCONN_ARG; - - TCP_WND = (num * TCP_MSS); - return ESPCONN_OK; -} - -/****************************************************************************** - * FunctionName : espconn_tcp_get_mss - * Description : get the mss size of simulatenously active TCP connections - * Parameters : none - * Returns : the size of TCP_MSS active TCP connections -*******************************************************************************/ -uint16 ICACHE_FLASH_ATTR espconn_tcp_get_mss(void) -{ - uint16 tcp_num = 0; - - tcp_num = TCP_MSS; - - return tcp_num; -} - /****************************************************************************** * FunctionName : espconn_tcp_get_max_con * Description : get the number of simulatenously active TCP connections @@ -570,81 +498,6 @@ uint8 ICACHE_FLASH_ATTR espconn_tcp_get_max_con(void) return tcp_num; } -/****************************************************************************** - * FunctionName : espconn_tcp_set_max_con - * Description : set the number of simulatenously active TCP connections - * Parameters : espconn -- espconn to set the connect callback - * Returns : none -*******************************************************************************/ -sint8 ICACHE_FLASH_ATTR espconn_tcp_set_max_con(uint8 num) -{ - if (num == 0 || num > linkMax) - return ESPCONN_ARG; - - MEMP_NUM_TCP_PCB = num; - return ESPCONN_OK; -} - -/****************************************************************************** - * FunctionName : espconn_tcp_get_max_retran - * Description : get the Maximum number of retransmissions of data active TCP connections - * Parameters : none - * Returns : the Maximum number of retransmissions -*******************************************************************************/ -uint8 ICACHE_FLASH_ATTR espconn_tcp_get_max_retran(void) -{ - uint8 tcp_num = 0; - - tcp_num = TCP_MAXRTX; - - return tcp_num; -} - -/****************************************************************************** - * FunctionName : espconn_tcp_set_max_retran - * Description : set the Maximum number of retransmissions of data active TCP connections - * Parameters : num -- the Maximum number of retransmissions - * Returns : result -*******************************************************************************/ -sint8 ICACHE_FLASH_ATTR espconn_tcp_set_max_retran(uint8 num) -{ - if (num == 0 || num > 12) - return ESPCONN_ARG; - - TCP_MAXRTX = num; - return ESPCONN_OK; -} - -/****************************************************************************** - * FunctionName : espconn_tcp_get_max_syn - * Description : get the Maximum number of retransmissions of SYN segments - * Parameters : none - * Returns : the Maximum number of retransmissions -*******************************************************************************/ -uint8 ICACHE_FLASH_ATTR espconn_tcp_get_max_syn(void) -{ - uint8 tcp_num = 0; - - tcp_num = TCP_SYNMAXRTX; - - return tcp_num; -} - -/****************************************************************************** - * FunctionName : espconn_tcp_set_max_syn - * Description : set the Maximum number of retransmissions of SYN segments - * Parameters : num -- the Maximum number of retransmissions - * Returns : result -*******************************************************************************/ -sint8 ICACHE_FLASH_ATTR espconn_tcp_set_max_syn(uint8 num) -{ - if (num == 0 || num > 12) - return ESPCONN_ARG; - - TCP_SYNMAXRTX = num; - return ESPCONN_OK; -} - /****************************************************************************** * FunctionName : espconn_tcp_get_max_con_allow * Description : get the count of simulatenously active connections on the server @@ -667,29 +520,6 @@ sint8 ICACHE_FLASH_ATTR espconn_tcp_get_max_con_allow(struct espconn *espconn) return ESPCONN_ARG; } -/****************************************************************************** - * FunctionName : espconn_tcp_set_max_con_allow - * Description : set the count of simulatenously active connections on the server - * Parameters : espconn -- espconn to set the count - * Returns : result -*******************************************************************************/ -sint8 ICACHE_FLASH_ATTR espconn_tcp_set_max_con_allow(struct espconn *espconn, uint8 num) -{ - espconn_msg *pset_msg = NULL; - if ((espconn == NULL) || (num > MEMP_NUM_TCP_PCB) || (espconn->type == ESPCONN_UDP)) - return ESPCONN_ARG; - - pset_msg = pserver_list; - while (pset_msg != NULL){ - if (pset_msg->pespconn == espconn){ - pset_msg->count_opt = num; - return ESPCONN_OK; - } - pset_msg = pset_msg->pnext; - } - return ESPCONN_ARG; -} - /****************************************************************************** * FunctionName : espconn_tcp_set_buf_count * Description : set the total number of espconn_buf on the unsent lists for one @@ -998,258 +828,6 @@ espconn_disconnect(struct espconn *espconn) return ESPCONN_ARG; } -/****************************************************************************** - * FunctionName : espconn_abort - * Description : Forcely abort with host - * Parameters : espconn -- the espconn used to disconnect the connection - * Returns : none -*******************************************************************************/ -sint8 ICACHE_FLASH_ATTR -espconn_abort(struct espconn *espconn) -{ - espconn_msg *pnode = NULL; - bool value = false; - - if (espconn == NULL) { - return ESPCONN_ARG;; - } else if (espconn ->type != ESPCONN_TCP) - return ESPCONN_ARG; - - /*Find the node depend on the espconn message*/ - value = espconn_find_connection(espconn, &pnode); - - if (value){ - /*protect for redisconnection*/ - if (espconn->state == ESPCONN_CLOSE) - return ESPCONN_INPROGRESS; - espconn_tcp_disconnect(pnode,1); //1 force, 0 normal - return ESPCONN_OK; - } else - return ESPCONN_ARG; -} - - -/****************************************************************************** - * FunctionName : espconn_get_packet_info - * Description : get the packet info with host - * Parameters : espconn -- the espconn used to disconnect the connection - * infoarg -- the packet info - * Returns : the errur code -*******************************************************************************/ -sint8 ICACHE_FLASH_ATTR -espconn_get_packet_info(struct espconn *espconn, struct espconn_packet* infoarg) -{ - espconn_msg *pnode = NULL; - err_t err; - bool value = false; - - if (espconn == NULL || infoarg == NULL) { - return ESPCONN_ARG;; - } else if (espconn->type != ESPCONN_TCP) - return ESPCONN_ARG; - - /*Find the node depend on the espconn message*/ - value = espconn_find_connection(espconn, &pnode); - if (value) { - struct tcp_pcb *pcb = pnode->pcommon.pcb; - if (pcb == NULL) - return ESPCONN_ARG; - - pnode->pcommon.packet_info.packseq_nxt = pcb->rcv_nxt; - pnode->pcommon.packet_info.packseqno = pcb->snd_nxt; - pnode->pcommon.packet_info.snd_buf_size = pcb->snd_buf; - pnode->pcommon.packet_info.total_queuelen = TCP_SND_QUEUELEN; - pnode->pcommon.packet_info.snd_queuelen = pnode->pcommon.packet_info.total_queuelen - pcb->snd_queuelen; - os_memcpy(infoarg,(void*)&pnode->pcommon.packet_info, sizeof(struct espconn_packet)); - return ESPCONN_OK; - } else { - switch (espconn->state){ - case ESPCONN_CLOSE: - os_memcpy(infoarg,(void*)&pktinfo[0], sizeof(struct espconn_packet)); - err = ESPCONN_OK; - break; - case ESPCONN_NONE: - os_memcpy(infoarg,(void*)&pktinfo[1], sizeof(struct espconn_packet)); - err = ESPCONN_OK; - break; - default: - err = ESPCONN_ARG; - break; - } - return err; - } -} - -/****************************************************************************** - * FunctionName : espconn_set_opt - * Description : set the option for connections so that we don't end up bouncing - * all connections at the same time . - * Parameters : espconn -- the espconn used to set the connection - * opt -- the option for set - * Returns : the result -*******************************************************************************/ -sint8 ICACHE_FLASH_ATTR -espconn_set_opt(struct espconn *espconn, uint8 opt) -{ - espconn_msg *pnode = NULL; - struct tcp_pcb *tpcb; - bool value = false; - - if (espconn == NULL) { - return ESPCONN_ARG;; - } else if (espconn->type != ESPCONN_TCP) - return ESPCONN_ARG; - - /*Find the node depend on the espconn message*/ - value = espconn_find_connection(espconn, &pnode); - if (value) { - pnode->pcommon.espconn_opt |= opt; - tpcb = pnode->pcommon.pcb; - if (NULL == tpcb) - return ESPCONN_OK; - if (espconn_delay_disabled(pnode)) - tcp_nagle_disable(tpcb); - - if (espconn_keepalive_disabled(pnode)) - espconn_keepalive_enable(tpcb); - - return ESPCONN_OK; - } else - return ESPCONN_ARG; -} - -/****************************************************************************** - * FunctionName : espconn_clear_opt - * Description : clear the option for connections so that we don't end up bouncing - * all connections at the same time . - * Parameters : espconn -- the espconn used to set the connection - * opt -- the option for clear - * Returns : the result -*******************************************************************************/ -sint8 ICACHE_FLASH_ATTR -espconn_clear_opt(struct espconn *espconn, uint8 opt) -{ - espconn_msg *pnode = NULL; - struct tcp_pcb *tpcb; - bool value = false; - - if (espconn == NULL) { - return ESPCONN_ARG;; - } else if (espconn->type != ESPCONN_TCP) - return ESPCONN_ARG; - - /*Find the node depend on the espconn message*/ - value = espconn_find_connection(espconn, &pnode); - if (value) { - pnode->pcommon.espconn_opt &= ~opt; - tpcb = pnode->pcommon.pcb; - if (espconn_keepalive_enabled(pnode)) - espconn_keepalive_disable(tpcb); - if (NULL == tpcb) - return ESPCONN_OK; - if (espconn_delay_enabled(pnode)) - tcp_nagle_enable(tpcb); - - return ESPCONN_OK; - } else - return ESPCONN_ARG; -} - -/****************************************************************************** - * FunctionName : espconn_set_keepalive - * Description : access level value for connection so that we set the value for - * keep alive - * Parameters : espconn -- the espconn used to set the connection - * level -- the connection's level - * value -- the value of time(s) - * Returns : access port value -*******************************************************************************/ -sint8 ICACHE_FLASH_ATTR espconn_set_keepalive(struct espconn *espconn, uint8 level, void* optarg) -{ - espconn_msg *pnode = NULL; - bool value = false; - sint8 ret = ESPCONN_OK; - - if (espconn == NULL || optarg == NULL) { - return ESPCONN_ARG;; - } else if (espconn->type != ESPCONN_TCP) - return ESPCONN_ARG; - - /*Find the node depend on the espconn message*/ - value = espconn_find_connection(espconn, &pnode); - if (value && espconn_keepalive_disabled(pnode)) { - struct tcp_pcb *pcb = pnode->pcommon.pcb; - if (NULL == pcb) - return ESPCONN_OK; - switch (level){ - case ESPCONN_KEEPIDLE: - pcb->keep_idle = 1000 * (u32_t)(*(int*)optarg); - ret = ESPCONN_OK; - break; - case ESPCONN_KEEPINTVL: - pcb->keep_intvl = 1000 * (u32_t)(*(int*)optarg); - ret = ESPCONN_OK; - break; - case ESPCONN_KEEPCNT: - pcb->keep_cnt = (u32_t)(*(int*)optarg); - ret = ESPCONN_OK; - break; - default: - ret = ESPCONN_ARG; - break; - } - return ret; - } else - return ESPCONN_ARG; -} - -/****************************************************************************** - * FunctionName : espconn_get_keepalive - * Description : access level value for connection so that we get the value for - * keep alive - * Parameters : espconn -- the espconn used to get the connection - * level -- the connection's level - * Returns : access keep alive value -*******************************************************************************/ -sint8 ICACHE_FLASH_ATTR espconn_get_keepalive(struct espconn *espconn, uint8 level, void *optarg) -{ - espconn_msg *pnode = NULL; - bool value = false; - sint8 ret = ESPCONN_OK; - - if (espconn == NULL || optarg == NULL) { - return ESPCONN_ARG;; - } else if (espconn->type != ESPCONN_TCP) - return ESPCONN_ARG; - - /*Find the node depend on the espconn message*/ - value = espconn_find_connection(espconn, &pnode); - if (value && espconn_keepalive_disabled(pnode)) { - struct tcp_pcb *pcb = pnode->pcommon.pcb; - if (NULL == pcb) - return ESPCONN_OK; - switch (level) { - case ESPCONN_KEEPIDLE: - *(int*)optarg = (int)(pcb->keep_idle/1000); - ret = ESPCONN_OK; - break; - case ESPCONN_KEEPINTVL: - *(int*)optarg = (int)(pcb->keep_intvl/1000); - ret = ESPCONN_OK; - break; - case ESPCONN_KEEPCNT: - *(int*)optarg = (int)(pcb->keep_cnt); - ret = ESPCONN_OK; - break; - default: - ret = ESPCONN_ARG; - break; - } - return ret; - } else - return ESPCONN_ARG; -} - /****************************************************************************** * FunctionName : espconn_delete * Description : disconnect with host @@ -1332,18 +910,3 @@ espconn_gethostbyname(struct espconn *pespconn, const char *hostname, ip_addr_t { return dns_gethostbyname(hostname, addr, found, pespconn); } - -/****************************************************************************** - * FunctionName : espconn_dns_setserver - * Description : Initialize one of the DNS servers. - * Parameters : numdns -- the index of the DNS server to set must - * be < DNS_MAX_SERVERS = 2 - * dnsserver -- IP address of the DNS server to set - * Returns : none -*******************************************************************************/ -void ICACHE_FLASH_ATTR -espconn_dns_setserver(u8_t numdns, ip_addr_t *dnsserver) -{ - dns_setserver(numdns,dnsserver); -} - diff --git a/app/lwip/app/espconn_mdns.c b/app/lwip/app/espconn_mdns.c deleted file mode 100644 index a29c64a54b..0000000000 --- a/app/lwip/app/espconn_mdns.c +++ /dev/null @@ -1,134 +0,0 @@ -/****************************************************************************** - * Copyright 2013-2014 Espressif Systems (Wuxi) - * - * FileName: espconn_mdns.c - * - * Description: udp proto interface - * - * Modification history: - * 2014/3/31, v1.0 create this file. -*******************************************************************************/ - -#include "ets_sys.h" -#include "os_type.h" - -#include "lwip/mdns.h" - -/****************************************************************************** - * FunctionName : espconn_mdns_enable - * Description : join a multicast group - * Parameters : host_ip -- the ip address of udp server - * multicast_ip -- multicast ip given by user - * Returns : none -*******************************************************************************/ -void ICACHE_FLASH_ATTR -espconn_mdns_enable(void) -{ - mdns_enable(); -} -/****************************************************************************** - * FunctionName : espconn_mdns_disable - * Description : join a multicast group - * Parameters : host_ip -- the ip address of udp server - * multicast_ip -- multicast ip given by user - * Returns : none -*******************************************************************************/ -void ICACHE_FLASH_ATTR -espconn_mdns_disable(void) -{ - mdns_disable(); -} - -/****************************************************************************** - * FunctionName : espconn_mdns_set_hostname - * Description : join a multicast group - * Parameters : host_ip -- the ip address of udp server - * multicast_ip -- multicast ip given by user - * Returns : none -*******************************************************************************/ -void ICACHE_FLASH_ATTR -espconn_mdns_set_hostname(char *name) -{ - mdns_set_hostname(name); -} - -/****************************************************************************** - * FunctionName : espconn_mdns_init - * Description : join a multicast group - * Parameters : host_ip -- the ip address of udp server - * multicast_ip -- multicast ip given by user - * Returns : none -*******************************************************************************/ -char* ICACHE_FLASH_ATTR -espconn_mdns_get_hostname(void) -{ - return (char *)mdns_get_hostname(); -} -/****************************************************************************** - * FunctionName : espconn_mdns_get_servername - * Description : join a multicast group - * Parameters : info -- the info of mdns - * Returns : none -*******************************************************************************/ -void ICACHE_FLASH_ATTR -espconn_mdns_set_servername(const char *name) -{ - mdns_set_servername(name); -} -/****************************************************************************** - * FunctionName : espconn_mdns_get_servername - * Description : join a multicast group - * Parameters : info -- the info of mdns - * Returns : none -*******************************************************************************/ -char* ICACHE_FLASH_ATTR -espconn_mdns_get_servername(void) -{ - return (char *)mdns_get_servername(); -} -/****************************************************************************** - * FunctionName : mdns_server_register - * Description : join a multicast group - * Parameters : info -- the info of mdns - * Returns : none -*******************************************************************************/ -void ICACHE_FLASH_ATTR -espconn_mdns_server_register(void) -{ - mdns_server_register(); -} -/****************************************************************************** - * FunctionName : mdns_server_register - * Description : join a multicast group - * Parameters : info -- the info of mdns - * Returns : none -*******************************************************************************/ -void ICACHE_FLASH_ATTR -espconn_mdns_server_unregister(void) -{ - mdns_server_unregister(); -} -/****************************************************************************** - * FunctionName : espconn_mdns_init - * Description : join a multicast group - * Parameters : host_ip -- the ip address of udp server - * multicast_ip -- multicast ip given by user - * Returns : none -*******************************************************************************/ -void ICACHE_FLASH_ATTR -espconn_mdns_close(void) -{ - mdns_close(); -} -/****************************************************************************** - * FunctionName : espconn_mdns_init - * Description : join a multicast group - * Parameters : host_ip -- the ip address of udp server - * multicast_ip -- multicast ip given by user - * Returns : none -*******************************************************************************/ -void ICACHE_FLASH_ATTR -espconn_mdns_init(struct mdns_info *info) -{ - mdns_init(info); -} diff --git a/app/lwip/app/espconn_udp.c b/app/lwip/app/espconn_udp.c index f1058e0fcc..8a23900c69 100644 --- a/app/lwip/app/espconn_udp.c +++ b/app/lwip/app/espconn_udp.c @@ -386,40 +386,3 @@ espconn_udp_server(struct espconn *pespconn) return ESPCONN_OK; } } - -/****************************************************************************** - * FunctionName : espconn_igmp_leave - * Description : leave a multicast group - * Parameters : host_ip -- the ip address of udp server - * multicast_ip -- multicast ip given by user - * Returns : none -*******************************************************************************/ -sint8 ICACHE_FLASH_ATTR -espconn_igmp_leave(ip_addr_t *host_ip, ip_addr_t *multicast_ip) -{ - if (igmp_leavegroup(host_ip, multicast_ip) != ERR_OK) { - LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("udp_leave_multigrup failed!\n")); - return -1; - }; - - return ESPCONN_OK; -} - -/****************************************************************************** - * FunctionName : espconn_igmp_join - * Description : join a multicast group - * Parameters : host_ip -- the ip address of udp server - * multicast_ip -- multicast ip given by user - * Returns : none -*******************************************************************************/ -sint8 ICACHE_FLASH_ATTR -espconn_igmp_join(ip_addr_t *host_ip, ip_addr_t *multicast_ip) -{ - if (igmp_joingroup(host_ip, multicast_ip) != ERR_OK) { - LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("udp_join_multigrup failed!\n")); - return -1; - }; - - /* join to any IP address at the port */ - return ESPCONN_OK; -} diff --git a/app/mbedtls/app/espconn_secure.c b/app/mbedtls/app/espconn_secure.c index 911cd4cfe7..34b6a6429d 100644 --- a/app/mbedtls/app/espconn_secure.c +++ b/app/mbedtls/app/espconn_secure.c @@ -40,12 +40,11 @@ static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__; #include "sys/espconn_mbedtls.h" ssl_opt ssl_option = { - {NULL, ESPCONN_SECURE_DEFAULT_SIZE, 0, false, 0, false}, - {NULL, ESPCONN_SECURE_DEFAULT_SIZE, 0, false, 0, false}, + {NULL, SSL_BUFFER_SIZE, 0, false, 0, false}, + {NULL, SSL_BUFFER_SIZE, 0, false, 0, false}, 0 }; -unsigned int max_content_len = ESPCONN_SECURE_DEFAULT_SIZE; /****************************************************************************** * FunctionName : espconn_encry_connect * Description : The function given as the connect @@ -95,7 +94,7 @@ espconn_secure_connect(struct espconn *espconn) } } } - current_size = espconn_secure_get_size(ESPCONN_CLIENT); + current_size = SSL_BUFFER_SIZE; current_size += ESPCONN_SECURE_DEFAULT_HEAP; // ssl_printf("heap_size %d %d\n", system_get_free_heap_size(), current_size); if (system_get_free_heap_size() <= current_size) @@ -182,43 +181,6 @@ espconn_secure_accept(struct espconn *espconn) return espconn_ssl_server(espconn); } -/****************************************************************************** - * FunctionName : espconn_secure_set_size - * Description : set the buffer size for client or server - * Parameters : level -- set for client or server - * 1: client,2:server,3:client and server - * size -- buffer size - * Returns : true or false -*******************************************************************************/ -bool ICACHE_FLASH_ATTR espconn_secure_set_size(uint8 level, uint16 size) -{ - size = (size < 4096) ? 4096 : size; - - if (level >= ESPCONN_MAX || level <= ESPCONN_IDLE) - return false; - - if (size > ESPCONN_SECURE_MAX_SIZE || size < ESPCONN_SECURE_DEFAULT_SIZE) - return false; - - max_content_len = size; - return true; -} - -/****************************************************************************** - * FunctionName : espconn_secure_get_size - * Description : get buffer size for client or server - * Parameters : level -- set for client or server - * 1: client,2:server,3:client and server - * Returns : buffer size for client or server -*******************************************************************************/ -sint16 ICACHE_FLASH_ATTR espconn_secure_get_size(uint8 level) -{ - if (level >= ESPCONN_MAX || level <= ESPCONN_IDLE) - return ESPCONN_ARG; - - return max_content_len; -} - /****************************************************************************** * FunctionName : espconn_secure_ca_enable * Description : enable the certificate authenticate and set the flash sector From c4e3e21d328bee7500233ec8bbf469eb58561f7c Mon Sep 17 00:00:00 2001 From: Nathaniel Wesley Filardo Date: Mon, 6 Jan 2020 16:31:04 +0000 Subject: [PATCH 03/17] espconn: De-orbit espconn_gethostbyname Further work on https://github.com/nodemcu/nodemcu-firmware/issues/3004 While here, remove `mqtt`'s charming DNS-retry logic (which is neither shared with nor duplicated in other modules) and update its :connect() return value behavior and documentation. --- app/http/httpclient.c | 9 ++-- app/include/lwip/app/espconn.h | 20 --------- app/lwip/app/espconn.c | 23 ----------- app/modules/mqtt.c | 73 +++++++++++++-------------------- app/websocket/websocketclient.c | 4 +- docs/modules/mqtt.md | 4 +- 6 files changed, 37 insertions(+), 96 deletions(-) diff --git a/app/http/httpclient.c b/app/http/httpclient.c index 1419d59771..a73f76279f 100644 --- a/app/http/httpclient.c +++ b/app/http/httpclient.c @@ -563,21 +563,20 @@ void ICACHE_FLASH_ATTR http_raw_request( const char * hostname, int port, bool s req->redirect_follow_count = redirect_follow_count; ip_addr_t addr; - err_t error = espconn_gethostbyname( (struct espconn *) req, /* It seems we don't need a real espconn pointer here. */ - hostname, &addr, http_dns_callback ); + err_t error = dns_gethostbyname( hostname, &addr, http_dns_callback, req ); - if ( error == ESPCONN_INPROGRESS ) + if ( error == ERR_INPROGRESS ) { HTTPCLIENT_DEBUG( "DNS pending" ); } - else if ( error == ESPCONN_OK ) + else if ( error == ERR_OK ) { /* Already in the local names table (or hostname was an IP address), execute the callback ourselves. */ http_dns_callback( hostname, &addr, req ); } else { - if ( error == ESPCONN_ARG ) + if ( error == ERR_ARG ) { HTTPCLIENT_ERR( "DNS arg error %s", hostname ); }else { diff --git a/app/include/lwip/app/espconn.h b/app/include/lwip/app/espconn.h index 75e7a1f66d..5769d7378d 100644 --- a/app/include/lwip/app/espconn.h +++ b/app/include/lwip/app/espconn.h @@ -475,26 +475,6 @@ extern sint8 espconn_regist_disconcb(struct espconn *espconn, espconn_connect_ca extern uint32 espconn_port(void); -/****************************************************************************** - * FunctionName : espconn_gethostbyname - * Description : Resolve a hostname (string) into an IP address. - * Parameters : pespconn -- espconn to resolve a hostname - * hostname -- the hostname that is to be queried - * addr -- pointer to a ip_addr_t where to store the address if - * it is already cached in the dns_table (only valid if - * ESPCONN_OK is returned!) - * found -- a callback function to be called on success, failure - * or timeout (only if ERR_INPROGRESS is returned!) - * Returns : err_t return code - * - ESPCONN_OK if hostname is a valid IP address string or the host - * name is already in the local names table. - * - ESPCONN_INPROGRESS enqueue a request to be sent to the DNS server - * for resolution if no errors are present. - * - ESPCONN_ARG: dns client not initialized or invalid hostname -*******************************************************************************/ - -extern err_t espconn_gethostbyname(struct espconn *pespconn, const char *name, ip_addr_t *addr, dns_found_callback found); - /****************************************************************************** * FunctionName : espconn_encry_connect * Description : The function given as connection diff --git a/app/lwip/app/espconn.c b/app/lwip/app/espconn.c index 93b16abc63..739bec8eeb 100644 --- a/app/lwip/app/espconn.c +++ b/app/lwip/app/espconn.c @@ -887,26 +887,3 @@ espconn_port(void) return port; } - -/****************************************************************************** - * FunctionName : espconn_gethostbyname - * Description : Resolve a hostname (string) into an IP address. - * Parameters : pespconn -- espconn to resolve a hostname - * hostname -- the hostname that is to be queried - * addr -- pointer to a ip_addr_t where to store the address if - * it is already cached in the dns_table (only valid if - * ESPCONN_OK is returned!) - * found -- a callback function to be called on success, failure - * or timeout (only if ERR_INPROGRESS is returned!) - * Returns : err_t return code - * - ESPCONN_OK if hostname is a valid IP address string or the host - * name is already in the local names table. - * - ESPCONN_INPROGRESS enqueue a request to be sent to the DNS server - * for resolution if no errors are present. - * - ESPCONN_ARG: dns client not initialized or invalid hostname -*******************************************************************************/ -err_t ICACHE_FLASH_ATTR -espconn_gethostbyname(struct espconn *pespconn, const char *hostname, ip_addr_t *addr, dns_found_callback found) -{ - return dns_gethostbyname(hostname, addr, found, pespconn); -} diff --git a/app/modules/mqtt.c b/app/modules/mqtt.c index 09b4d4544a..c0cc1cebc3 100644 --- a/app/modules/mqtt.c +++ b/app/modules/mqtt.c @@ -1168,21 +1168,13 @@ static sint8 socket_connect(struct espconn *pesp_conn) return espconn_status; } -static sint8 socket_dns_found(const char *name, ip_addr_t *ipaddr, void *arg); -static int dns_reconn_count = 0; -static ip_addr_t host_ip; // for dns - -/* wrapper for using socket_dns_found() as callback function */ -static void socket_dns_foundcb(const char *name, ip_addr_t *ipaddr, void *arg) -{ - socket_dns_found(name, ipaddr, arg); -} - static sint8 socket_dns_found(const char *name, ip_addr_t *ipaddr, void *arg) { + lmqtt_userdata *mud = arg; + NODE_DBG("enter socket_dns_found.\n"); sint8 espconn_status = ESPCONN_OK; - struct espconn *pesp_conn = arg; + struct espconn *pesp_conn = mud->pesp_conn; if(pesp_conn == NULL){ NODE_DBG("pesp_conn null.\n"); return -1; @@ -1190,42 +1182,34 @@ static sint8 socket_dns_found(const char *name, ip_addr_t *ipaddr, void *arg) if(ipaddr == NULL) { - dns_reconn_count++; - if( dns_reconn_count >= 5 ){ - NODE_DBG( "DNS Fail!\n" ); - // Note: should delete the pesp_conn or unref self_ref here. - - struct espconn *pesp_conn = arg; - if(pesp_conn != NULL) { - lmqtt_userdata *mud = (lmqtt_userdata *)pesp_conn->reverse; - if(mud != NULL) { - mqtt_connack_fail(mud, MQTT_CONN_FAIL_DNS); - } - } + mqtt_connack_fail(mud, MQTT_CONN_FAIL_DNS); - mqtt_socket_disconnected(arg); // although not connected, but fire disconnect callback to release every thing. - return -1; - } - NODE_DBG( "DNS retry %d!\n", dns_reconn_count ); - host_ip.addr = 0; - return espconn_gethostbyname(pesp_conn, name, &host_ip, socket_dns_foundcb); + // although not connected, but fire disconnect callback to release every thing. + mqtt_socket_disconnected(arg); + return -1; } // ipaddr->addr is a uint32_t ip if(ipaddr->addr != 0) { - dns_reconn_count = 0; memcpy(pesp_conn->proto.tcp->remote_ip, &(ipaddr->addr), 4); NODE_DBG("TCP ip is set: "); NODE_DBG(IPSTR, IP2STR(&(ipaddr->addr))); NODE_DBG("\n"); espconn_status = socket_connect(pesp_conn); } + NODE_DBG("leave socket_dns_found.\n"); return espconn_status; } +/* wrapper for using socket_dns_found() as callback function */ +static void socket_dns_foundcb(const char *name, ip_addr_t *ipaddr, void *arg) +{ + socket_dns_found(name, ipaddr, arg); +} + #include "pm/swtimer.h" // Lua: mqtt:connect( host, port, secure, function(client), function(client, connect_return_code) ) static int mqtt_socket_connect( lua_State* L ) @@ -1239,7 +1223,6 @@ static int mqtt_socket_connect( lua_State* L ) int stack = 1; unsigned secure = 0; int top = lua_gettop(L); - sint8 espconn_status; mud = (lmqtt_userdata *)luaL_checkudata(L, stack, "mqtt.socket"); luaL_argcheck(L, mud, stack, "mqtt.socket expected"); @@ -1342,8 +1325,8 @@ static int mqtt_socket_connect( lua_State* L ) luaL_unref(L, LUA_REGISTRYINDEX, mud->self_ref); mud->self_ref = luaL_ref(L, LUA_REGISTRYINDEX); - espconn_status = espconn_regist_connectcb(pesp_conn, mqtt_socket_connected); - espconn_status |= espconn_regist_reconcb(pesp_conn, mqtt_socket_reconnected); + espconn_regist_connectcb(pesp_conn, mqtt_socket_connected); + espconn_regist_reconcb(pesp_conn, mqtt_socket_reconnected); os_timer_disarm(&mud->mqttTimer); os_timer_setfn(&mud->mqttTimer, (os_timer_func_t *)mqtt_socket_timer, mud); @@ -1354,25 +1337,27 @@ static int mqtt_socket_connect( lua_State* L ) if((ipaddr.addr == IPADDR_NONE) && (memcmp(domain,"255.255.255.255",16) != 0)) { - host_ip.addr = 0; - dns_reconn_count = 0; - if(ESPCONN_OK == espconn_gethostbyname(pesp_conn, domain, &host_ip, socket_dns_foundcb)){ - espconn_status |= socket_dns_found(domain, &host_ip, pesp_conn); // ip is returned in host_ip. + ip_addr_t host_ip; + switch (dns_gethostbyname(domain, &host_ip, socket_dns_foundcb, mud)) + { + case ERR_OK: + socket_dns_found(domain, &host_ip, mud); // ip is returned in host_ip. + break; + case ERR_INPROGRESS: + break; + default: + // Something has gone wrong; bail out? + mqtt_connack_fail(mud, MQTT_CONN_FAIL_DNS); } } else { - espconn_status |= socket_connect(pesp_conn); + socket_connect(pesp_conn); } NODE_DBG("leave mqtt_socket_connect.\n"); - if (espconn_status == ESPCONN_OK) { - lua_pushboolean(L, 1); - } else { - lua_pushboolean(L, 0); - } - return 1; + return 0; } // Lua: mqtt:close() diff --git a/app/websocket/websocketclient.c b/app/websocket/websocketclient.c index b03fad4dd9..4996af8d92 100644 --- a/app/websocket/websocketclient.c +++ b/app/websocket/websocketclient.c @@ -824,9 +824,9 @@ void ws_connect(ws_info *ws, const char *url) { // Attempt to resolve hostname address ip_addr_t addr; - err_t result = espconn_gethostbyname(conn, hostname, &addr, dns_callback); + err_t result = dns_gethostbyname(hostname, &addr, dns_callback, conn); - if (result == ESPCONN_INPROGRESS) { + if (result == ERR_INPROGRESS) { NODE_DBG("DNS pending\n"); } else { dns_callback(hostname, &addr, conn); diff --git a/docs/modules/mqtt.md b/docs/modules/mqtt.md index f9944baa9e..0163ee1a72 100644 --- a/docs/modules/mqtt.md +++ b/docs/modules/mqtt.md @@ -135,11 +135,11 @@ Connects to the broker specified by the given host, port, and secure options. !!! attention - Secure (`https`) connections come with quite a few limitations. Please see + Secure (`mqtts`) connections come with quite a few limitations. Please see the warnings in the [tls module](tls.md)'s documentation. #### Returns -`true` on success, `false` otherwise +`nil`; use callbacks to observe the outcome. #### Notes From ea2b37836dac9327381a68f13945eeff555335c4 Mon Sep 17 00:00:00 2001 From: Nathaniel Wesley Filardo Date: Mon, 6 Jan 2020 17:23:32 +0000 Subject: [PATCH 04/17] espconn: remove scary global pktinfo A write-only global! How about that. --- app/lwip/app/espconn.c | 2 -- app/lwip/app/espconn_tcp.c | 5 ----- 2 files changed, 7 deletions(-) diff --git a/app/lwip/app/espconn.c b/app/lwip/app/espconn.c index 739bec8eeb..5c4e961be2 100644 --- a/app/lwip/app/espconn.c +++ b/app/lwip/app/espconn.c @@ -33,8 +33,6 @@ espconn_msg *plink_active = NULL; espconn_msg *pserver_list = NULL; remot_info premot[linkMax]; -struct espconn_packet pktinfo[2]; - static uint8 espconn_tcp_get_buf_count(espconn_buf *pesp_buf); /****************************************************************************** * FunctionName : espconn_copy_partial diff --git a/app/lwip/app/espconn_tcp.c b/app/lwip/app/espconn_tcp.c index b1ebfde4ea..21941014ee 100644 --- a/app/lwip/app/espconn_tcp.c +++ b/app/lwip/app/espconn_tcp.c @@ -30,7 +30,6 @@ static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__; extern espconn_msg *plink_active; extern espconn_msg *pserver_list; -extern struct espconn_packet pktinfo[2]; extern struct tcp_pcb ** const tcp_pcb_lists[]; os_event_t espconn_TaskQueue[espconn_TaskQueueLen]; @@ -288,8 +287,6 @@ espconn_tcp_reconnect(void *arg) os_free(perr_back); perr_back = NULL; } - os_bzero(&pktinfo[1], sizeof(struct espconn_packet)); - os_memcpy(&pktinfo[1], (void*)&precon_cb->pcommon.packet_info, sizeof(struct espconn_packet)); if (espconn && espconn->proto.tcp && espconn->proto.tcp->reconnect_callback != NULL) { espconn->proto.tcp->reconnect_callback(espconn, re_err); @@ -382,8 +379,6 @@ espconn_tcp_disconnect_successful(void *arg) os_free(pdis_back); pdis_back = NULL; } - os_bzero(&pktinfo[0], sizeof(struct espconn_packet)); - os_memcpy(&pktinfo[0], (void*)&pdiscon_cb->pcommon.packet_info, sizeof(struct espconn_packet)); if (espconn->proto.tcp && espconn->proto.tcp->disconnect_callback != NULL) { espconn->proto.tcp->disconnect_callback(espconn); From 75c4f3c9b1410abdb7cb85f9e64d73143632b753 Mon Sep 17 00:00:00 2001 From: Nathaniel Wesley Filardo Date: Sun, 2 Feb 2020 15:24:48 +0000 Subject: [PATCH 05/17] net: remove deprecated methods All the TLS stuff moved over there a long time ago, and net_createUDPSocket should just do what it says on the tin. --- app/modules/net.c | 43 +------------------------------------------ docs/modules/net.md | 38 ++++++++------------------------------ 2 files changed, 9 insertions(+), 72 deletions(-) diff --git a/app/modules/net.c b/app/modules/net.c index 4565f53d35..3286a1388e 100644 --- a/app/modules/net.c +++ b/app/modules/net.c @@ -20,10 +20,6 @@ #include "lwip/udp.h" #include "lwip/dhcp.h" -#if defined(CLIENT_SSL_ENABLE) && defined(LUA_USE_MODULES_NET) && defined(LUA_USE_MODULES_TLS) -#define TLS_MODULE_PRESENT -#endif - typedef enum net_type { TYPE_TCP_SERVER = 0, TYPE_TCP_CLIENT, @@ -291,10 +287,6 @@ static err_t net_accept_cb(void *arg, struct tcp_pcb *newpcb, err_t err) { #pragma mark - Lua API - create -#ifdef TLS_MODULE_PRESENT -extern int tls_socket_create( lua_State *L ); -#endif - // Lua: net.createUDPSocket() int net_createUDPSocket( lua_State *L ) { net_create(L, TYPE_UDP_SOCKET); @@ -305,14 +297,7 @@ int net_createUDPSocket( lua_State *L ) { int net_createServer( lua_State *L ) { int type, timeout; - type = luaL_optlong(L, 1, TYPE_TCP); - timeout = luaL_optlong(L, 2, 30); - - if (type == TYPE_UDP) { - platform_print_deprecation_note("net.createServer with net.UDP type", "in next version"); - return net_createUDPSocket( L ); - } - if (type != TYPE_TCP) return luaL_error(L, "invalid type"); + timeout = luaL_optlong(L, 1, 30); lnet_userdata *u = net_create(L, TYPE_TCP_SERVER); u->server.timeout = timeout; @@ -321,24 +306,7 @@ int net_createServer( lua_State *L ) { // Lua: net.createConnection(type, secure) int net_createConnection( lua_State *L ) { - int type, secure; - - type = luaL_optlong(L, 1, TYPE_TCP); - secure = luaL_optlong(L, 2, 0); - if (type == TYPE_UDP) { - platform_print_deprecation_note("net.createConnection with net.UDP type", "in next version"); - return net_createUDPSocket( L ); - } - if (type != TYPE_TCP) return luaL_error(L, "invalid type"); - if (secure) { - platform_print_deprecation_note("net.createConnection with secure flag", "in next version"); -#ifdef TLS_MODULE_PRESENT - return tls_socket_create( L ); -#else - return luaL_error(L, "secure connections not enabled"); -#endif - } net_create(L, TYPE_TCP_CLIENT); return 1; } @@ -1039,10 +1007,6 @@ static int net_ifinfo( lua_State* L ) { #pragma mark - Tables -#ifdef TLS_MODULE_PRESENT -LROT_EXTERN(tls_cert); -#endif - // Module function map LROT_BEGIN(net_tcpserver) LROT_FUNCENTRY( listen, net_listen ) @@ -1096,11 +1060,6 @@ LROT_BEGIN(net) LROT_FUNCENTRY( multicastJoin, net_multicastJoin ) LROT_FUNCENTRY( multicastLeave, net_multicastLeave ) LROT_TABENTRY( dns, net_dns ) -#ifdef TLS_MODULE_PRESENT - LROT_TABENTRY( cert, tls_cert ) -#endif - LROT_NUMENTRY( TCP, TYPE_TCP ) - LROT_NUMENTRY( UDP, TYPE_UDP ) LROT_TABENTRY( __metatable, net ) LROT_END( net, net, 0 ) diff --git a/docs/modules/net.md b/docs/modules/net.md index d15cec4276..751abc8b3d 100644 --- a/docs/modules/net.md +++ b/docs/modules/net.md @@ -10,58 +10,36 @@ Constants to be used in other functions: `net.TCP`, `net.UDP` ## net.createConnection() -Creates a client. +Creates a TCP client. #### Syntax -`net.createConnection([type[, secure]])` - -#### Parameters -- `type` `net.TCP` (default) or `net.UDP` -- `secure` 1 for encrypted, 0 for plain (default) - -!!! attention - This will change in upcoming releases so that `net.createConnection` will always create an unencrypted TCP connection. - - There's no such thing as a UDP _connection_ because UDP is connection*less*. Thus no connection `type` parameter should be required. For UDP use [net.createUDPSocket()](#netcreateudpsocket) instead. To create *secure* connections use [tls.createConnection()](tls.md#tlscreateconnection) instead. +`net.createConnection()` #### Returns -- for `net.TCP` - net.socket sub module -- for `net.UDP` - net.udpsocket sub module -- for `net.TCP` with `secure` - tls.socket sub module - -#### Example - -```lua -net.createConnection(net.TCP, 0) -``` +- net.socket sub module #### See also [`net.createServer()`](#netcreateserver), [`net.createUDPSocket()`](#netcreateudpsocket), [`tls.createConnection()`](tls.md#tlscreateconnection) ## net.createServer() -Creates a server. +Creates a TCP listening socket (a server). #### Syntax -`net.createServer([type[, timeout]])` +`net.createServer(timeout)` #### Parameters -- `type` `net.TCP` (default) or `net.UDP` -- `timeout` for a TCP server timeout is 1~28'800 seconds, 30 sec by default (for an inactive client to be disconnected) - -!!! attention - The `type` parameter will be removed in upcoming releases so that `net.createServer` will always create a TCP-based server. For UDP use [net.createUDPSocket()](#netcreateudpsocket) instead. +- `timeout`: seconds until disconnecting an inactive client; 1~28'800 seconds, 30 sec by default. #### Returns -- for `net.TCP` - net.server sub module -- for `net.UDP` - net.udpsocket sub module +- net.server sub module #### Example ```lua -net.createServer(net.TCP, 30) -- 30s timeout +net.createServer(30) -- 30s timeout ``` #### See also From ce0fd5eeed699fe8f06327bf9b0ac2d4e58965ed Mon Sep 17 00:00:00 2001 From: Nathaniel Wesley Filardo Date: Fri, 14 Feb 2020 09:08:40 +0000 Subject: [PATCH 06/17] espconn_secure: remove ESPCONN_SERVER support We can barely function as a TLS client; being a TLS server seems like a real stretch. This code was never called from Lua anyway. --- app/include/lwip/app/espconn.h | 19 -- app/include/sys/espconn_mbedtls.h | 15 -- app/mbedtls/app/espconn_mbedtls.c | 278 ++++------------------------- app/mbedtls/app/espconn_secure.c | 97 ++-------- app/mbedtls/app/lwIPSocket.c | 121 ------------- app/mbedtls/platform/mbedtls_net.c | 4 + app/modules/tls.c | 8 +- 7 files changed, 51 insertions(+), 491 deletions(-) diff --git a/app/include/lwip/app/espconn.h b/app/include/lwip/app/espconn.h index 5769d7378d..d204ab6bca 100644 --- a/app/include/lwip/app/espconn.h +++ b/app/include/lwip/app/espconn.h @@ -582,25 +582,6 @@ extern bool espconn_secure_set_default_certificate(const uint8* certificate, uin extern bool espconn_secure_set_default_private_key(const uint8* private_key, uint16 length); -/****************************************************************************** - * FunctionName : espconn_secure_accept - * Description : The function given as the listen - * Parameters : espconn -- the espconn used to listen the connection - * Returns : result -*******************************************************************************/ - -extern sint8 espconn_secure_accept(struct espconn *espconn); - -/****************************************************************************** - * FunctionName : espconn_secure_accepts - * Description : delete the secure server host - * Parameters : espconn -- the espconn used to listen the connection - * Returns : result -*******************************************************************************/ - -extern sint8 espconn_secure_delete(struct espconn *espconn); - - /****************************************************************************** * FunctionName : espconn_recv_hold * Description : hold tcp receive diff --git a/app/include/sys/espconn_mbedtls.h b/app/include/sys/espconn_mbedtls.h index 9d105c6c88..717c437f61 100644 --- a/app/include/sys/espconn_mbedtls.h +++ b/app/include/sys/espconn_mbedtls.h @@ -51,7 +51,6 @@ typedef struct{ int record_len; pmbedtls_session psession; mbedtls_net_context fd; - mbedtls_net_context listen_fd; mbedtls_ctr_drbg_context ctr_drbg; mbedtls_ssl_context ssl; mbedtls_ssl_config conf; @@ -71,8 +70,6 @@ typedef enum { typedef enum { ESPCONN_IDLE = 0, ESPCONN_CLIENT, - ESPCONN_SERVER, - ESPCONN_BOTH, ESPCONN_MAX }espconn_level; @@ -99,14 +96,12 @@ struct ssl_packet{ }; typedef struct _ssl_opt { - struct ssl_packet server; struct ssl_packet client; uint8 type; }ssl_opt; typedef struct{ mbedtls_auth_type auth_type; - espconn_level auth_level; }mbedtls_auth_info; #define SSL_KEEP_INTVL 1 @@ -207,16 +202,6 @@ typedef enum{ *******************************************************************************/ bool mbedtls_load_default_obj(uint32 flash_sector, int obj_type, const unsigned char *load_buf, uint16 length); -/****************************************************************************** - * FunctionName : sslserver_start - * Description : Initialize the server: set up a listen PCB and bind it to - * the defined port - * Parameters : espconn -- the espconn used to build client - * Returns : none -*******************************************************************************/ - -extern sint8 espconn_ssl_server(struct espconn *espconn); - /****************************************************************************** * FunctionName : espconn_ssl_client * Description : Initialize the client: set up a connect PCB and bind it to diff --git a/app/mbedtls/app/espconn_mbedtls.c b/app/mbedtls/app/espconn_mbedtls.c index cced9a27dc..778eb46020 100644 --- a/app/mbedtls/app/espconn_mbedtls.c +++ b/app/mbedtls/app/espconn_mbedtls.c @@ -252,7 +252,6 @@ static pmbedtls_msg mbedtls_msg_new(void) os_bzero(msg, sizeof(mbedtls_msg)); msg->psession = mbedtls_session_new(); if (msg->psession) { - mbedtls_net_init(&msg->listen_fd); mbedtls_net_init(&msg->fd); mbedtls_ssl_init(&msg->ssl); mbedtls_ssl_config_init(&msg->conf); @@ -325,13 +324,6 @@ static espconn_msg* mbedtls_msg_find(int sock) } } - for (plist = plink_server; plist != NULL; plist = plist->pnext) { - if(plist->pssl != NULL) { - msg = plist->pssl; - if (msg->listen_fd.fd == sock) - return plist; - } - } return NULL; } @@ -346,14 +338,8 @@ static bool mbedtls_handshake_result(const pmbedtls_msg Threadmsg) return false; if (Threadmsg->ssl.state == MBEDTLS_SSL_HANDSHAKE_OVER) { - int ret = 0; - if (Threadmsg->listen_fd.fd == -1) - ret = ssl_option.client.cert_ca_sector.flag; - else - ret = ssl_option.server.cert_ca_sector.flag; - - if (ret == 1) { - ret = mbedtls_ssl_get_verify_result(&Threadmsg->ssl); + if (ssl_option.client.cert_ca_sector.flag) { + int ret = mbedtls_ssl_get_verify_result(&Threadmsg->ssl); if (ret != 0) { char vrfy_buf[512]; os_memset(vrfy_buf, 0, sizeof(vrfy_buf)-1); @@ -381,18 +367,10 @@ static void mbedtls_fail_info(espconn_msg *pinfo, int ret) */ if (ret != MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { if (TLSmsg->quiet) { - if (pinfo->preverse != NULL) { - os_printf("server's data invalid protocol\n"); - } else { - os_printf("client's data invalid protocol\n"); - } + os_printf("client's data invalid protocol\n"); mbedtls_ssl_close_notify(&TLSmsg->ssl); } else { - if (pinfo->preverse != NULL) { - os_printf("server handshake failed!\n"); - } else { - os_printf("client handshake failed!\n"); - } + os_printf("client handshake failed!\n"); } } @@ -509,36 +487,16 @@ static bool espconn_ssl_read_param_from_flash(void *param, uint16 len, int32 off } uint32 FILE_PARAM_START_SEC = 0x3B; - switch (auth_info->auth_level) { - case ESPCONN_CLIENT: - switch (auth_info->auth_type) { - case ESPCONN_CERT_AUTH: - FILE_PARAM_START_SEC = ssl_option.client.cert_ca_sector.sector; - break; - case ESPCONN_CERT_OWN: - case ESPCONN_PK: - FILE_PARAM_START_SEC = ssl_option.client.cert_req_sector.sector; - break; - default: - return false; - } + switch (auth_info->auth_type) { + case ESPCONN_CERT_AUTH: + FILE_PARAM_START_SEC = ssl_option.client.cert_ca_sector.sector; break; - case ESPCONN_SERVER: - switch (auth_info->auth_type) { - case ESPCONN_CERT_AUTH: - FILE_PARAM_START_SEC = ssl_option.server.cert_ca_sector.sector; - break; - case ESPCONN_CERT_OWN: - case ESPCONN_PK: - FILE_PARAM_START_SEC = ssl_option.server.cert_req_sector.sector; - break; - default: - return false; - } + case ESPCONN_CERT_OWN: + case ESPCONN_PK: + FILE_PARAM_START_SEC = ssl_option.client.cert_req_sector.sector; break; default: return false; - break; } spi_flash_read(FILE_PARAM_START_SEC * 4096 + offset, param, len); @@ -627,83 +585,37 @@ mbedtls_dbg(void *p, int level, const char *file, int line, const char *str) static bool mbedtls_msg_config(mbedtls_msg *msg) { - const char *pers = NULL; - uint8 auth_type = 0; bool load_flag = false; int ret = ESPCONN_OK; mbedtls_auth_info auth_info; - /*end_point mode*/ - if (msg->listen_fd.fd == -1) { - pers = "client"; - auth_type = MBEDTLS_SSL_IS_CLIENT; - } else { - pers = "server"; - auth_type = MBEDTLS_SSL_IS_SERVER; - } - /*Initialize the RNG and the session data*/ - ret = mbedtls_ctr_drbg_seed(&msg->ctr_drbg, mbedtls_entropy_func, &msg->entropy, (const unsigned char*) pers, os_strlen(pers)); + ret = mbedtls_ctr_drbg_seed(&msg->ctr_drbg, mbedtls_entropy_func, &msg->entropy, "client", 6); lwIP_REQUIRE_NOERROR(ret, exit); - if (auth_type == MBEDTLS_SSL_IS_SERVER) { - uint32 flash_sector = 0; - /*Load the certificate*/ - unsigned int def_certificate_len = 0; - unsigned char *def_certificate = NULL; - def_certificate = (unsigned char *)mbedtls_get_default_obj(&flash_sector,ESPCONN_CERT_OWN, &def_certificate_len); - lwIP_REQUIRE_ACTION(def_certificate, exit, ret = MBEDTLS_ERR_SSL_ALLOC_FAILED); - ret = mbedtls_x509_crt_parse(&msg->psession->clicert, (const unsigned char *)def_certificate, def_certificate_len); - if (flash_sector != 0) - os_free(def_certificate); - lwIP_REQUIRE_NOERROR(ret, exit); - - /*Load the private RSA key*/ - unsigned int def_private_key_len = 0; - unsigned char *def_private_key = NULL; - def_private_key = (unsigned char *)mbedtls_get_default_obj(&flash_sector,ESPCONN_PK, &def_private_key_len); - lwIP_REQUIRE_ACTION(def_private_key, exit, ret = MBEDTLS_ERR_SSL_ALLOC_FAILED); - ret = mbedtls_pk_parse_key(&msg->psession->pkey, (const unsigned char *)def_private_key, def_private_key_len, NULL, 0); - if (flash_sector != 0) - os_free(def_private_key); - lwIP_REQUIRE_NOERROR(ret, exit); - ret = mbedtls_ssl_conf_own_cert(&msg->conf, &msg->psession->clicert, &msg->psession->pkey); - lwIP_REQUIRE_NOERROR(ret, exit); - - /*Load the trusted CA*/ - if (ssl_option.server.cert_ca_sector.flag) { - auth_info.auth_level = ESPCONN_SERVER; - auth_info.auth_type = ESPCONN_CERT_AUTH; - load_flag = mbedtls_msg_info_load(msg, &auth_info); - lwIP_REQUIRE_ACTION(load_flag, exit, ret = ESPCONN_MEM); - } - } else { - /*Load the certificate and private RSA key*/ - if (ssl_option.client.cert_req_sector.flag) { - auth_info.auth_level = ESPCONN_CLIENT; - auth_info.auth_type = ESPCONN_CERT_OWN; - load_flag = mbedtls_msg_info_load(msg, &auth_info); - lwIP_REQUIRE_ACTION(load_flag, exit, ret = ESPCONN_MEM); - auth_info.auth_type = ESPCONN_PK; - load_flag = mbedtls_msg_info_load(msg, &auth_info); - lwIP_REQUIRE_ACTION(load_flag, exit, ret = ESPCONN_MEM); - } + /*Load the certificate and private RSA key*/ + if (ssl_option.client.cert_req_sector.flag) { + auth_info.auth_type = ESPCONN_CERT_OWN; + load_flag = mbedtls_msg_info_load(msg, &auth_info); + lwIP_REQUIRE_ACTION(load_flag, exit, ret = ESPCONN_MEM); + auth_info.auth_type = ESPCONN_PK; + load_flag = mbedtls_msg_info_load(msg, &auth_info); + lwIP_REQUIRE_ACTION(load_flag, exit, ret = ESPCONN_MEM); + } - /*Load the trusted CA*/ - if(ssl_option.client.cert_ca_sector.flag) { - auth_info.auth_level = ESPCONN_CLIENT; - auth_info.auth_type = ESPCONN_CERT_AUTH; - load_flag = mbedtls_msg_info_load(msg, &auth_info); - lwIP_REQUIRE_ACTION(load_flag, exit, ret = ESPCONN_MEM); - } + /*Load the trusted CA*/ + if(ssl_option.client.cert_ca_sector.flag) { + auth_info.auth_type = ESPCONN_CERT_AUTH; + load_flag = mbedtls_msg_info_load(msg, &auth_info); + lwIP_REQUIRE_ACTION(load_flag, exit, ret = ESPCONN_MEM); } /*Setup the stuff*/ - ret = mbedtls_ssl_config_defaults(&msg->conf, auth_type, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT); + ret = mbedtls_ssl_config_defaults(&msg->conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT); lwIP_REQUIRE_NOERROR(ret, exit); /*OPTIONAL is not optimal for security, but makes interop easier in this session*/ - if (auth_type == MBEDTLS_SSL_IS_CLIENT && ssl_option.client.cert_ca_sector.flag == false) { + if (ssl_option.client.cert_ca_sector.flag == false) { mbedtls_ssl_conf_authmode(&msg->conf, MBEDTLS_SSL_VERIFY_NONE); } mbedtls_ssl_conf_rng(&msg->conf, mbedtls_ctr_drbg_random, &msg->ctr_drbg); @@ -761,37 +673,7 @@ int espconn_mbedtls_parse_internal(int socket, sint8 error) lwIP_REQUIRE_NOERROR(ret, exit); } else { if (TLSmsg->ssl.state == MBEDTLS_SSL_HELLO_REQUEST) { - if (Threadmsg->preverse != NULL) { - struct espconn *accept_conn = NULL; - struct espconn *espconn = Threadmsg->preverse; - struct sockaddr_in name; - socklen_t name_len = sizeof(name); - remot_info *pinfo = NULL; - espconn_get_connection_info(espconn, &pinfo, ESPCONN_SSL); - if (espconn->link_cnt == 0x01) - return ERR_ISCONN; - - ret = mbedtls_net_accept(&TLSmsg->listen_fd, &TLSmsg->fd, NULL, 0, NULL); - lwIP_REQUIRE_NOERROR(ret, exit); - accept_conn = mbedtls_espconn_new(); - lwIP_REQUIRE_ACTION(accept_conn, exit, ret = ERR_MEM); - Threadmsg->pespconn = accept_conn; - /*get the remote information*/ - getpeername(TLSmsg->fd.fd, (struct sockaddr*)&name, &name_len); - Threadmsg->pcommon.remote_port = htons(name.sin_port); - os_memcpy(Threadmsg->pcommon.remote_ip, &name.sin_addr.s_addr, 4); - - espconn->proto.tcp->remote_port = htons(name.sin_port); - os_memcpy(espconn->proto.tcp->remote_ip, &name.sin_addr.s_addr, 4); - - espconn_copy_partial(accept_conn, espconn); - - /*insert the node to the active connection list*/ - espconn_list_creat(&plink_active, Threadmsg); - os_printf("server handshake start.\n"); - } else { - os_printf("client handshake start.\n"); - } + os_printf("client handshake start.\n"); config_flag = mbedtls_msg_config(TLSmsg); if (config_flag) { // mbedtls_keep_alive(TLSmsg->fd.fd, 1, SSL_KEEP_IDLE, SSL_KEEP_INTVL, SSL_KEEP_CNT); @@ -821,11 +703,7 @@ int espconn_mbedtls_parse_internal(int socket, sint8 error) /**/ TLSmsg->quiet = mbedtls_handshake_result(TLSmsg); if (TLSmsg->quiet) { - if (Threadmsg->preverse != NULL) { - os_printf("server handshake ok!\n"); - } else { - os_printf("client handshake ok!\n"); - } + os_printf("client handshake ok!\n"); // mbedtls_keep_alive(TLSmsg->fd.fd, 0, SSL_KEEP_IDLE, SSL_KEEP_INTVL, SSL_KEEP_CNT); mbedtls_session_free(&TLSmsg->psession); mbedtls_handshake_succ(&TLSmsg->ssl); @@ -917,14 +795,8 @@ mbedtls_thread(os_event_t *events) if (active_flag) { /*remove the node from the active connection list*/ espconn_list_delete(&plink_active, Threadmsg); - if (TLSmsg->listen_fd.fd != -1) { - mbedtls_msg_server_step(TLSmsg); - espconn_copy_partial(Threadmsg->preverse, Threadmsg->pespconn); - mbedtls_espconn_free(&Threadmsg->pespconn); - } else { - mbedtls_msg_free(&TLSmsg); - Threadmsg->pssl = NULL; - } + mbedtls_msg_free(&TLSmsg); + Threadmsg->pssl = NULL; switch (events->sig) { case NETCONN_EVENT_ERROR: @@ -987,94 +859,6 @@ sint8 espconn_ssl_client(struct espconn *espconn) return ret; } -/****************************************************************************** - * FunctionName : espconn_ssl_server - * Description : as - * Parameters : - * Returns : -*******************************************************************************/ -sint8 espconn_ssl_server(struct espconn *espconn) -{ - int ret = ESPCONN_OK; - struct ip_addr ipaddr; - - const char *server_port = NULL; - espconn_msg *pserver = NULL; - pmbedtls_msg mbedTLSMsg = NULL; - if (lwIPThreadFlag == false) - mbedtls_threadinit(); - - if (plink_server != NULL) - return ESPCONN_INPROGRESS; - - lwIP_REQUIRE_ACTION(espconn, exit, ret = ESPCONN_ARG); - /*Creates a new server control message*/ - pserver = (espconn_msg *) os_zalloc( sizeof(espconn_msg)); - lwIP_REQUIRE_ACTION(espconn, exit, ret = ESPCONN_MEM); - mbedTLSMsg = mbedtls_msg_new(); - lwIP_REQUIRE_ACTION(mbedTLSMsg, exit, ret = ESPCONN_MEM); - - server_port = (const char *)sys_itoa(espconn->proto.tcp->local_port); - /*start the connection*/ - ret = mbedtls_net_bind(&mbedTLSMsg->listen_fd, NULL, server_port, MBEDTLS_NET_PROTO_TCP); - lwIP_REQUIRE_NOERROR_ACTION(ret, exit, ret = ESPCONN_MEM); - espconn->state = ESPCONN_LISTEN; - pserver->pespconn = NULL; - pserver->pssl = mbedTLSMsg; - pserver->preverse = espconn; - pserver->count_opt = MEMP_NUM_TCP_PCB; - pserver->pcommon.timeout = 0x0a; - espconn->state = ESPCONN_LISTEN; - plink_server = pserver; -exit: - if (ret != ESPCONN_OK) { - if (mbedTLSMsg != NULL) - mbedtls_msg_free(&mbedTLSMsg); - if (pserver != NULL) - os_free(pserver); - } - return ret; -} - -/****************************************************************************** - * FunctionName : espconn_ssl_delete - * Description : delete the server: delete a listening PCB and free it - * Parameters : pdeletecon -- the espconn used to delete a server - * Returns : none -*******************************************************************************/ -sint8 espconn_ssl_delete(struct espconn *pdeletecon) -{ - remot_info *pinfo = NULL; - espconn_msg *pdelete_msg = NULL; - pmbedtls_msg mbedTLSMsg = NULL; - - if (pdeletecon == NULL) - return ESPCONN_ARG; - - espconn_get_connection_info(pdeletecon, &pinfo, ESPCONN_SSL); - /*make sure all the active connection have been disconnect*/ - if (pdeletecon->link_cnt != 0) - return ESPCONN_INPROGRESS; - else { - pdelete_msg = plink_server; - if (pdelete_msg != NULL && pdelete_msg->preverse == pdeletecon) { - mbedTLSMsg = pdelete_msg->pssl; - espconn_kill_pcb(pdeletecon->proto.tcp->local_port); - mbedtls_net_free(&mbedTLSMsg->listen_fd); - mbedtls_msg_free(&mbedTLSMsg); - pdelete_msg->pssl = mbedTLSMsg; - os_free(pdelete_msg); - pdelete_msg = NULL; - plink_server = pdelete_msg; - mbedtls_parame_free(&def_private_key); - mbedtls_parame_free(&def_certificate); - return ESPCONN_OK; - } else { - return ESPCONN_ARG; - } - } -} - /****************************************************************************** * FunctionName : espconn_ssl_write * Description : sent data for client or server diff --git a/app/mbedtls/app/espconn_secure.c b/app/mbedtls/app/espconn_secure.c index 34b6a6429d..98f22668b2 100644 --- a/app/mbedtls/app/espconn_secure.c +++ b/app/mbedtls/app/espconn_secure.c @@ -40,7 +40,6 @@ static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__; #include "sys/espconn_mbedtls.h" ssl_opt ssl_option = { - {NULL, SSL_BUFFER_SIZE, 0, false, 0, false}, {NULL, SSL_BUFFER_SIZE, 0, false, 0, false}, 0 }; @@ -172,15 +171,6 @@ espconn_secure_sent(struct espconn *espconn, uint8 *psent, uint16 length) sint8 espconn_secure_send(struct espconn *espconn, uint8 *psent, uint16 length) __attribute__((alias("espconn_secure_sent"))); -sint8 ICACHE_FLASH_ATTR -espconn_secure_accept(struct espconn *espconn) -{ - if (espconn == NULL || espconn ->type != ESPCONN_TCP) - return ESPCONN_ARG; - - return espconn_ssl_server(espconn); -} - /****************************************************************************** * FunctionName : espconn_secure_ca_enable * Description : enable the certificate authenticate and set the flash sector @@ -192,26 +182,16 @@ espconn_secure_accept(struct espconn *espconn) *******************************************************************************/ bool ICACHE_FLASH_ATTR espconn_secure_ca_enable(uint8 level, uint32 flash_sector ) { - if (level >= ESPCONN_MAX || level <= ESPCONN_IDLE || flash_sector <= 0) + if (flash_sector <= 0) return false; if (level == ESPCONN_CLIENT){ ssl_option.client.cert_ca_sector.sector = flash_sector; ssl_option.client.cert_ca_sector.flag = true; + return true; } - if (level == ESPCONN_SERVER){ - ssl_option.server.cert_ca_sector.sector = flash_sector; - ssl_option.server.cert_ca_sector.flag = true; - } - - if (level == ESPCONN_BOTH) { - ssl_option.client.cert_ca_sector.sector = flash_sector; - ssl_option.server.cert_ca_sector.sector = flash_sector; - ssl_option.client.cert_ca_sector.flag = true; - ssl_option.server.cert_ca_sector.flag = true; - } - return true; + return false; } /****************************************************************************** @@ -223,21 +203,12 @@ bool ICACHE_FLASH_ATTR espconn_secure_ca_enable(uint8 level, uint32 flash_sector *******************************************************************************/ bool ICACHE_FLASH_ATTR espconn_secure_ca_disable(uint8 level) { - if (level >= ESPCONN_MAX || level <= ESPCONN_IDLE) - return false; - - if (level == ESPCONN_CLIENT) - ssl_option.client.cert_ca_sector.flag = false; - - if (level == ESPCONN_SERVER) - ssl_option.server.cert_ca_sector.flag = false; - - if (level == ESPCONN_BOTH) { + if (level == ESPCONN_CLIENT) { ssl_option.client.cert_ca_sector.flag = false; - ssl_option.server.cert_ca_sector.flag = false; + return true; } - return true; + return false; } /****************************************************************************** @@ -251,26 +222,16 @@ bool ICACHE_FLASH_ATTR espconn_secure_ca_disable(uint8 level) *******************************************************************************/ bool ICACHE_FLASH_ATTR espconn_secure_cert_req_enable(uint8 level, uint32 flash_sector ) { - if (level >= ESPCONN_MAX || level <= ESPCONN_IDLE || flash_sector <= 0) + if (flash_sector <= 0) return false; if (level == ESPCONN_CLIENT){ ssl_option.client.cert_req_sector.sector = flash_sector; ssl_option.client.cert_req_sector.flag = true; + return true; } - if (level == ESPCONN_SERVER){ - ssl_option.server.cert_req_sector.sector = flash_sector; - ssl_option.server.cert_req_sector.flag = true; - } - - if (level == ESPCONN_BOTH) { - ssl_option.client.cert_req_sector.sector = flash_sector; - ssl_option.server.cert_req_sector.sector = flash_sector; - ssl_option.client.cert_req_sector.flag = true; - ssl_option.server.cert_req_sector.flag = true; - } - return true; + return false; } /****************************************************************************** @@ -282,21 +243,12 @@ bool ICACHE_FLASH_ATTR espconn_secure_cert_req_enable(uint8 level, uint32 flash_ *******************************************************************************/ bool ICACHE_FLASH_ATTR espconn_secure_cert_req_disable(uint8 level) { - if (level >= ESPCONN_MAX || level <= ESPCONN_IDLE) - return false; - - if (level == ESPCONN_CLIENT) + if (level == ESPCONN_CLIENT) { ssl_option.client.cert_req_sector.flag = false; - - if (level == ESPCONN_SERVER) - ssl_option.server.cert_req_sector.flag = false; - - if (level == ESPCONN_BOTH) { - ssl_option.client.cert_req_sector.flag = false; - ssl_option.server.cert_req_sector.flag = false; + return true; } - return true; + return false; } /****************************************************************************** @@ -331,29 +283,4 @@ bool ICACHE_FLASH_ATTR espconn_secure_set_default_private_key(const uint8* priva return mbedtls_load_default_obj(0, ESPCONN_PK, private_key, length); } -/****************************************************************************** - * FunctionName : espconn_secure_delete - * Description : delete the secure server host - * Parameters : espconn -- espconn to set for client or server - * Returns : result -*******************************************************************************/ -sint8 ICACHE_FLASH_ATTR espconn_secure_delete(struct espconn *espconn) -{ - sint8 error = ESPCONN_OK; - error = espconn_ssl_delete(espconn); - - return error; -} - -bool espconn_secure_obj_load(int obj_type, uint32 flash_sector, uint16 length) -{ - if (length > ESPCONN_SECURE_MAX_SIZE || length == 0) - return false; - - if (obj_type != ESPCONN_PK && obj_type != ESPCONN_CERT_OWN) - return false; - - return mbedtls_load_default_obj(flash_sector, obj_type, NULL, length); -} - #endif diff --git a/app/mbedtls/app/lwIPSocket.c b/app/mbedtls/app/lwIPSocket.c index f1014cf2d9..8c798f1c8f 100644 --- a/app/mbedtls/app/lwIPSocket.c +++ b/app/mbedtls/app/lwIPSocket.c @@ -255,39 +255,6 @@ static void setup_tcp(lwIP_netconn *conn) return; } -static err_t do_accepted(void *arg, struct tcp_pcb *newpcb, err_t err) -{ - lwIP_netconn *newconn = NULL; - lwIP_netconn *conn = arg; - err = ERR_OK; - - //Avoid two TCP connections coming in simultaneously - struct tcp_pcb *pactive_pcb; - int active_pcb_num=0; - for(pactive_pcb = tcp_active_pcbs; pactive_pcb != NULL; pactive_pcb = pactive_pcb->next){ - if (pactive_pcb->state == ESTABLISHED ||pactive_pcb->state == SYN_RCVD){ - active_pcb_num++; - if (active_pcb_num > MEMP_NUM_TCP_PCB){ - ESP_LOG("%s %d active_pcb_number:%d\n",__FILE__, __LINE__,active_pcb_num); - return ERR_MEM; - } - } - } - - lwIP_REQUIRE_ACTION(conn, exit, err = ESP_ARG); - /* We have to set the callback here even though - * the new socket is unknown. conn->socket is marked as -1. */ - newconn = netconn_alloc(conn->type, newpcb); - lwIP_REQUIRE_ACTION(conn, exit, err = ERR_MEM); - newconn->tcp = newpcb; - setup_tcp(newconn); - newconn->state = NETCONN_STATE_ESTABLISHED; - conn->acceptmbox = newconn; - espconn_mbedtls_parse_internal(find_socket(conn), ERR_OK); -exit: - return err; -} - sint8 netconn_delete(lwIP_netconn *conn) { sint8 error = ESP_OK; @@ -335,44 +302,6 @@ sint8 netconn_connect(lwIP_netconn *conn, ip_addr_t *addr, u16_t port) return error; } -err_t netconn_accept(lwIP_netconn *conn, lwIP_netconn **new_conn) -{ - err_t error = ESP_OK; - lwIP_netconn *newconn = NULL; - lwIP_REQUIRE_ACTION(conn, exit, error = ESP_ARG); - lwIP_REQUIRE_ACTION(new_conn, exit, error = ESP_ARG); - *new_conn = NULL; - newconn = (lwIP_netconn *)conn->acceptmbox; - conn->acceptmbox = NULL; - lwIP_REQUIRE_ACTION(newconn, exit, error = ERR_CLSD); - *new_conn = newconn; -exit: - return error; -} - -sint8 netconn_listen(lwIP_netconn *conn) -{ - sint8 error = ESP_OK; - struct tcp_pcb *lpcb = NULL; - - lwIP_REQUIRE_ACTION(conn, exit, error = ESP_ARG); - lwIP_REQUIRE_ACTION(conn->tcp, exit, error = ESP_ARG); - - setup_tcp(conn); - lpcb = conn->tcp; - conn->tcp = tcp_listen(conn->tcp); - if (conn->tcp != NULL) - { - tcp_accept(conn->tcp, do_accepted); - } - else - { - conn->tcp = lpcb; - } -exit: - return error; -} - static int alloc_socket(lwIP_netconn *newconn, int accepted) { int i = 0; @@ -553,56 +482,6 @@ uint32_t lwip_getul(char *str) return ret; } -int lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen) -{ - lwIP_sock *sock = NULL; - err_t err = ERR_OK; - lwIP_netconn *newconn = NULL; - int newsock = -1; - sock = get_socket(s); - if (!sock) - { - return -1; - } - - /* wait for a new connection */ - err = netconn_accept(sock->conn, &newconn); - lwIP_REQUIRE_NOERROR(err, exit); - newsock = alloc_socket(newconn, 0); - if (newsock == -1) - { - goto exit; - } - newconn->socket = newsock; -exit: - if (newsock == -1) - { - netconn_delete(newconn); - } - return newsock; -} - -int lwip_listen(int s, int backlog) -{ - lwIP_sock *sock = NULL; - err_t err = ERR_OK; - sock = get_socket(s); - if (!sock) - { - return -1; - } - err = netconn_listen(sock->conn); - if (err != ERR_OK) - { - ESP_LOG("lwip_connect(%d) failed, err=%d\n", s, err); - return -1; - } - - ESP_LOG("lwip_connect(%d) succeeded\n", s); - - return ERR_OK; -} - int lwip_recvfrom(int s, void *mem, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen) { lwIP_sock *sock = NULL; diff --git a/app/mbedtls/platform/mbedtls_net.c b/app/mbedtls/platform/mbedtls_net.c index 03cf22a2d6..3cbab2b6e9 100644 --- a/app/mbedtls/platform/mbedtls_net.c +++ b/app/mbedtls/platform/mbedtls_net.c @@ -104,6 +104,7 @@ int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, const char return( ret ); } +#if 0 // NodeMCU does not support being a TLS server /* * Create a listening socket on bind_ip:port */ @@ -155,6 +156,7 @@ int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char return( ret ); } +#endif /* * Check if the requested operation would be blocking on a non-blocking socket @@ -167,6 +169,7 @@ static int net_would_block( const mbedtls_net_context *ctx ) return( 0 ); } +#if 0 // NodeMCU does not support being a TLS server /* * Accept a connection from a remote client */ @@ -208,6 +211,7 @@ int mbedtls_net_accept( mbedtls_net_context *bind_ctx, return( ret ); return( 0 ); } +#endif /* * Set the socket blocking or non-blocking diff --git a/app/modules/tls.c b/app/modules/tls.c index 72cc0d95a5..1db3f4c0fb 100644 --- a/app/modules/tls.c +++ b/app/modules/tls.c @@ -557,9 +557,9 @@ static int tls_cert_auth(lua_State *L) if (tls_client_cert_area[0] == 0x00 || tls_client_cert_area[0] == 0xff) { return luaL_error( L, "no certificates found" ); } - rc = espconn_secure_cert_req_enable(1, flash_offset / INTERNAL_FLASH_SECTOR_SIZE); + rc = espconn_secure_cert_req_enable(ESPCONN_CLIENT, flash_offset / INTERNAL_FLASH_SECTOR_SIZE); } else { - rc = espconn_secure_cert_req_disable(1); + rc = espconn_secure_cert_req_disable(ESPCONN_CLIENT); } lua_pushboolean(L, rc); @@ -598,9 +598,9 @@ static int tls_cert_verify(lua_State *L) if (tls_server_cert_area[0] == 0x00 || tls_server_cert_area[0] == 0xff) { return luaL_error( L, "no certificates found" ); } - rc = espconn_secure_ca_enable(1, flash_offset / INTERNAL_FLASH_SECTOR_SIZE); + rc = espconn_secure_ca_enable(ESPCONN_CLIENT, flash_offset / INTERNAL_FLASH_SECTOR_SIZE); } else { - rc = espconn_secure_ca_disable(1); + rc = espconn_secure_ca_disable(ESPCONN_CLIENT); } lua_pushboolean(L, rc); From ece3a93c3369c85d14653004f51f7494b4a25bbb Mon Sep 17 00:00:00 2001 From: Nathaniel Wesley Filardo Date: Fri, 14 Feb 2020 11:00:43 +0000 Subject: [PATCH 07/17] espconn_secure: simplify ssl options structure There is nothing "ssl_packet" about this structure. Get rid of the terrifying "pbuffer" pointer. Squash two structure types together and eliminate an unused field. --- app/include/sys/espconn_mbedtls.h | 10 ++-------- app/mbedtls/app/espconn_mbedtls.c | 12 ++++++------ app/mbedtls/app/espconn_secure.c | 17 +++++++---------- 3 files changed, 15 insertions(+), 24 deletions(-) diff --git a/app/include/sys/espconn_mbedtls.h b/app/include/sys/espconn_mbedtls.h index 717c437f61..9e28d0d60d 100644 --- a/app/include/sys/espconn_mbedtls.h +++ b/app/include/sys/espconn_mbedtls.h @@ -88,18 +88,12 @@ typedef struct _ssl_sector{ bool flag; }ssl_sector; -struct ssl_packet{ - uint8* pbuffer; +struct ssl_options { uint16 buffer_size; ssl_sector cert_ca_sector; ssl_sector cert_req_sector; }; -typedef struct _ssl_opt { - struct ssl_packet client; - uint8 type; -}ssl_opt; - typedef struct{ mbedtls_auth_type auth_type; }mbedtls_auth_info; @@ -122,7 +116,7 @@ enum { #define MBEDTLS_SSL_PLAIN_ADD TCP_MSS #define FLASH_SECTOR_SIZE 4096 -extern ssl_opt ssl_option; +extern struct ssl_options ssl_client_options; typedef struct{ uint32 parame_sec; diff --git a/app/mbedtls/app/espconn_mbedtls.c b/app/mbedtls/app/espconn_mbedtls.c index 778eb46020..c1866ae173 100644 --- a/app/mbedtls/app/espconn_mbedtls.c +++ b/app/mbedtls/app/espconn_mbedtls.c @@ -338,7 +338,7 @@ static bool mbedtls_handshake_result(const pmbedtls_msg Threadmsg) return false; if (Threadmsg->ssl.state == MBEDTLS_SSL_HANDSHAKE_OVER) { - if (ssl_option.client.cert_ca_sector.flag) { + if (ssl_client_options.cert_ca_sector.flag) { int ret = mbedtls_ssl_get_verify_result(&Threadmsg->ssl); if (ret != 0) { char vrfy_buf[512]; @@ -489,11 +489,11 @@ static bool espconn_ssl_read_param_from_flash(void *param, uint16 len, int32 off uint32 FILE_PARAM_START_SEC = 0x3B; switch (auth_info->auth_type) { case ESPCONN_CERT_AUTH: - FILE_PARAM_START_SEC = ssl_option.client.cert_ca_sector.sector; + FILE_PARAM_START_SEC = ssl_client_options.cert_ca_sector.sector; break; case ESPCONN_CERT_OWN: case ESPCONN_PK: - FILE_PARAM_START_SEC = ssl_option.client.cert_req_sector.sector; + FILE_PARAM_START_SEC = ssl_client_options.cert_req_sector.sector; break; default: return false; @@ -594,7 +594,7 @@ static bool mbedtls_msg_config(mbedtls_msg *msg) lwIP_REQUIRE_NOERROR(ret, exit); /*Load the certificate and private RSA key*/ - if (ssl_option.client.cert_req_sector.flag) { + if (ssl_client_options.cert_req_sector.flag) { auth_info.auth_type = ESPCONN_CERT_OWN; load_flag = mbedtls_msg_info_load(msg, &auth_info); lwIP_REQUIRE_ACTION(load_flag, exit, ret = ESPCONN_MEM); @@ -604,7 +604,7 @@ static bool mbedtls_msg_config(mbedtls_msg *msg) } /*Load the trusted CA*/ - if(ssl_option.client.cert_ca_sector.flag) { + if(ssl_client_options.cert_ca_sector.flag) { auth_info.auth_type = ESPCONN_CERT_AUTH; load_flag = mbedtls_msg_info_load(msg, &auth_info); lwIP_REQUIRE_ACTION(load_flag, exit, ret = ESPCONN_MEM); @@ -615,7 +615,7 @@ static bool mbedtls_msg_config(mbedtls_msg *msg) lwIP_REQUIRE_NOERROR(ret, exit); /*OPTIONAL is not optimal for security, but makes interop easier in this session*/ - if (ssl_option.client.cert_ca_sector.flag == false) { + if (ssl_client_options.cert_ca_sector.flag == false) { mbedtls_ssl_conf_authmode(&msg->conf, MBEDTLS_SSL_VERIFY_NONE); } mbedtls_ssl_conf_rng(&msg->conf, mbedtls_ctr_drbg_random, &msg->ctr_drbg); diff --git a/app/mbedtls/app/espconn_secure.c b/app/mbedtls/app/espconn_secure.c index 98f22668b2..9a2d82326a 100644 --- a/app/mbedtls/app/espconn_secure.c +++ b/app/mbedtls/app/espconn_secure.c @@ -39,10 +39,7 @@ static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__; #include "sys/espconn_mbedtls.h" -ssl_opt ssl_option = { - {NULL, SSL_BUFFER_SIZE, 0, false, 0, false}, - 0 -}; +struct ssl_options ssl_client_options = {SSL_BUFFER_SIZE, 0, false, 0, false}; /****************************************************************************** * FunctionName : espconn_encry_connect @@ -186,8 +183,8 @@ bool ICACHE_FLASH_ATTR espconn_secure_ca_enable(uint8 level, uint32 flash_sector return false; if (level == ESPCONN_CLIENT){ - ssl_option.client.cert_ca_sector.sector = flash_sector; - ssl_option.client.cert_ca_sector.flag = true; + ssl_client_options.cert_ca_sector.sector = flash_sector; + ssl_client_options.cert_ca_sector.flag = true; return true; } @@ -204,7 +201,7 @@ bool ICACHE_FLASH_ATTR espconn_secure_ca_enable(uint8 level, uint32 flash_sector bool ICACHE_FLASH_ATTR espconn_secure_ca_disable(uint8 level) { if (level == ESPCONN_CLIENT) { - ssl_option.client.cert_ca_sector.flag = false; + ssl_client_options.cert_ca_sector.flag = false; return true; } @@ -226,8 +223,8 @@ bool ICACHE_FLASH_ATTR espconn_secure_cert_req_enable(uint8 level, uint32 flash_ return false; if (level == ESPCONN_CLIENT){ - ssl_option.client.cert_req_sector.sector = flash_sector; - ssl_option.client.cert_req_sector.flag = true; + ssl_client_options.cert_req_sector.sector = flash_sector; + ssl_client_options.cert_req_sector.flag = true; return true; } @@ -244,7 +241,7 @@ bool ICACHE_FLASH_ATTR espconn_secure_cert_req_enable(uint8 level, uint32 flash_ bool ICACHE_FLASH_ATTR espconn_secure_cert_req_disable(uint8 level) { if (level == ESPCONN_CLIENT) { - ssl_option.client.cert_req_sector.flag = false; + ssl_client_options.cert_req_sector.flag = false; return true; } From e7bae8775eb572e4e8384661822429b3681b2646 Mon Sep 17 00:00:00 2001 From: Nathaniel Wesley Filardo Date: Fri, 14 Feb 2020 09:30:17 +0000 Subject: [PATCH 08/17] espconn_secure: more code removal --- app/include/lwip/app/espconn.h | 22 ----- app/include/sys/espconn_mbedtls.h | 14 --- app/mbedtls/app/espconn_mbedtls.c | 145 +++--------------------------- app/mbedtls/app/espconn_secure.c | 32 ------- 4 files changed, 11 insertions(+), 202 deletions(-) diff --git a/app/include/lwip/app/espconn.h b/app/include/lwip/app/espconn.h index d204ab6bca..ac9a5dbbfe 100644 --- a/app/include/lwip/app/espconn.h +++ b/app/include/lwip/app/espconn.h @@ -560,28 +560,6 @@ extern bool espconn_secure_cert_req_enable(uint8 level, uint32 flash_sector ); extern bool espconn_secure_cert_req_disable(uint8 level); -/****************************************************************************** - * FunctionName : espconn_secure_set_default_certificate - * Description : Load the certificates in memory depending on compile-time - * and user options. - * Parameters : certificate -- Load the certificate - * length -- Load the certificate length - * Returns : result true or false -*******************************************************************************/ - -extern bool espconn_secure_set_default_certificate(const uint8* certificate, uint16 length); - -/****************************************************************************** - * FunctionName : espconn_secure_set_default_private_key - * Description : Load the key in memory depending on compile-time - * and user options. - * Parameters : private_key -- Load the key - * length -- Load the key length - * Returns : result true or false -*******************************************************************************/ - -extern bool espconn_secure_set_default_private_key(const uint8* private_key, uint16 length); - /****************************************************************************** * FunctionName : espconn_recv_hold * Description : hold tcp receive diff --git a/app/include/sys/espconn_mbedtls.h b/app/include/sys/espconn_mbedtls.h index 9e28d0d60d..c586492d0d 100644 --- a/app/include/sys/espconn_mbedtls.h +++ b/app/include/sys/espconn_mbedtls.h @@ -64,7 +64,6 @@ typedef enum { ESPCONN_CERT_OWN, ESPCONN_CERT_AUTH, ESPCONN_PK, - ESPCONN_PASSWORD }mbedtls_auth_type; typedef enum { @@ -94,10 +93,6 @@ struct ssl_options { ssl_sector cert_req_sector; }; -typedef struct{ - mbedtls_auth_type auth_type; -}mbedtls_auth_info; - #define SSL_KEEP_INTVL 1 #define SSL_KEEP_CNT 5 #define SSL_KEEP_IDLE 90 @@ -187,15 +182,6 @@ typedef enum{ } \ } while (0) -/****************************************************************************** - * FunctionName : mbedtls_load_default_obj - * Description : Initialize the server: set up a listen PCB and bind it to - * the defined port - * Parameters : espconn -- the espconn used to build client - * Returns : none -*******************************************************************************/ -bool mbedtls_load_default_obj(uint32 flash_sector, int obj_type, const unsigned char *load_buf, uint16 length); - /****************************************************************************** * FunctionName : espconn_ssl_client * Description : Initialize the client: set up a connect PCB and bind it to diff --git a/app/mbedtls/app/espconn_mbedtls.c b/app/mbedtls/app/espconn_mbedtls.c index c1866ae173..aa4bebcae7 100644 --- a/app/mbedtls/app/espconn_mbedtls.c +++ b/app/mbedtls/app/espconn_mbedtls.c @@ -80,56 +80,6 @@ static void mbedtls_parame_free(pmbedtls_parame *fp) *fp = NULL; } -bool mbedtls_load_default_obj(uint32 flash_sector, int obj_type, const unsigned char *load_buf, uint16 length) -{ - pmbedtls_parame mbedtls_write = NULL; - uint32 mbedtls_head = 0; - bool mbedtls_load_flag = false; - - if (flash_sector != 0) { - spi_flash_read(flash_sector * FLASH_SECTOR_SIZE, (uint32*)&mbedtls_head, 4); - if (mbedtls_head != ESPCONN_INVALID_TYPE) { - mbedtls_write = mbedtls_parame_new(0); - mbedtls_write->parame_datalen = length; - } - } else { - const char* const begin = "-----BEGIN"; - int format_type = ESPCONN_FORMAT_INIT; - /* - * Determine data content. data contains either one DER certificate or - * one or more PEM certificates. - */ - if ((char*)os_strstr(load_buf, begin) != NULL) { - format_type = ESPCONN_FORMAT_PEM; - } else { - format_type = ESPCONN_FORMAT_DER; - } - - if (format_type == ESPCONN_FORMAT_PEM) { - length += 1; - } - - mbedtls_write = mbedtls_parame_new(length); - if (mbedtls_write) { - os_memcpy(mbedtls_write->parame_data, load_buf, length); - if (format_type == ESPCONN_FORMAT_PEM) - mbedtls_write->parame_data[length - 1] = '\0'; - } - } - - if (mbedtls_write) { - mbedtls_load_flag = true; - mbedtls_write->parame_type = obj_type; - mbedtls_write->parame_sec = flash_sector; - if (obj_type == ESPCONN_PK) { - def_private_key = mbedtls_write; - } else { - def_certificate = mbedtls_write; - } - } - return mbedtls_load_flag; -} - static unsigned char* mbedtls_get_default_obj(uint32 *sec, uint32 type, uint32 *len) { const char* const begin = "-----BEGIN"; @@ -327,11 +277,6 @@ static espconn_msg* mbedtls_msg_find(int sock) return NULL; } -void mbedtls_handshake_heap(mbedtls_ssl_context *ssl) -{ - os_printf("mbedtls_handshake_heap %d %d\n", ssl->state, system_get_free_heap_size()); -} - static bool mbedtls_handshake_result(const pmbedtls_msg Threadmsg) { if (Threadmsg == NULL) @@ -448,7 +393,6 @@ static void espconn_close_internal(void *arg, netconn_event event_type) pssl_recon->pcommon.ptrbuf = NULL; pssl_recon->pcommon.cntr = 0; pssl_recon->pcommon.err = 0; - espconn = pssl_recon->preverse; } else { espconn = pssl_recon->pespconn; os_free(pssl_recon); @@ -480,14 +424,14 @@ static void espconn_close_internal(void *arg, netconn_event event_type) * Parameters : param--the parame point which write the flash * Returns : none *******************************************************************************/ -static bool espconn_ssl_read_param_from_flash(void *param, uint16 len, int32 offset, mbedtls_auth_info *auth_info) +static bool espconn_ssl_read_param_from_flash(void *param, uint16 len, int32 offset, mbedtls_auth_type auth_type) { if (param == NULL || (len + offset) > ESPCONN_SECURE_MAX_SIZE) { return false; } uint32 FILE_PARAM_START_SEC = 0x3B; - switch (auth_info->auth_type) { + switch (auth_type) { case ESPCONN_CERT_AUTH: FILE_PARAM_START_SEC = ssl_client_options.cert_ca_sector.sector; break; @@ -504,7 +448,7 @@ static bool espconn_ssl_read_param_from_flash(void *param, uint16 len, int32 off return true; } -static bool mbedtls_msg_info_load(mbedtls_msg *msg, mbedtls_auth_info *auth_info) +static bool mbedtls_msg_info_load(mbedtls_msg *msg, mbedtls_auth_type auth_type) { const char* const begin = "-----BEGIN"; const char* const type_name = "private_key"; @@ -518,19 +462,19 @@ static bool mbedtls_msg_info_load(mbedtls_msg *msg, mbedtls_auth_info *auth_info bzero(&file_param, sizeof(file_param)); again: - espconn_ssl_read_param_from_flash(&file_param.file_head, sizeof(file_head), offerset, auth_info); + espconn_ssl_read_param_from_flash(&file_param.file_head, sizeof(file_head), offerset, auth_type); file_param.file_offerset = offerset; os_printf("%s %d, type[%s],length[%d]\n", __FILE__, __LINE__, file_param.file_head.file_name, file_param.file_head.file_length); if (file_param.file_head.file_length == 0xFFFF) { return false; } else { /*Optional is load the private key*/ - if (auth_info->auth_type == ESPCONN_PK && os_memcmp(&file_param.file_head.file_name, type_name, os_strlen(type_name)) != 0) { + if (auth_type == ESPCONN_PK && os_memcmp(&file_param.file_head.file_name, type_name, os_strlen(type_name)) != 0) { offerset += sizeof(file_head) + file_param.file_head.file_length; goto again; } /*Optional is load the cert*/ - if (auth_info->auth_type == ESPCONN_CERT_OWN && os_memcmp(file_param.file_head.file_name, "certificate", os_strlen("certificate")) != 0) { + if (auth_type == ESPCONN_CERT_OWN && os_memcmp(file_param.file_head.file_name, "certificate", os_strlen("certificate")) != 0) { offerset += sizeof(file_head) + file_param.file_head.file_length; goto again; } @@ -539,7 +483,7 @@ static bool mbedtls_msg_info_load(mbedtls_msg *msg, mbedtls_auth_info *auth_info return false; } offerset = sizeof(file_head) + file_param.file_offerset; - espconn_ssl_read_param_from_flash(load_buf, file_param.file_head.file_length, offerset, auth_info); + espconn_ssl_read_param_from_flash(load_buf, file_param.file_head.file_length, offerset, auth_type); } load_len = file_param.file_head.file_length; @@ -551,7 +495,7 @@ static bool mbedtls_msg_info_load(mbedtls_msg *msg, mbedtls_auth_info *auth_info load_len += 1; load_buf[load_len - 1] = '\0'; } - switch (auth_info->auth_type) { + switch (auth_type) { case ESPCONN_CERT_AUTH: /*Optional is not optimal for security*/ ret = mbedtls_x509_crt_parse(&msg->psession->cacert, (const uint8*) load_buf,load_len); @@ -587,7 +531,6 @@ static bool mbedtls_msg_config(mbedtls_msg *msg) { bool load_flag = false; int ret = ESPCONN_OK; - mbedtls_auth_info auth_info; /*Initialize the RNG and the session data*/ ret = mbedtls_ctr_drbg_seed(&msg->ctr_drbg, mbedtls_entropy_func, &msg->entropy, "client", 6); @@ -595,18 +538,15 @@ static bool mbedtls_msg_config(mbedtls_msg *msg) /*Load the certificate and private RSA key*/ if (ssl_client_options.cert_req_sector.flag) { - auth_info.auth_type = ESPCONN_CERT_OWN; - load_flag = mbedtls_msg_info_load(msg, &auth_info); + load_flag = mbedtls_msg_info_load(msg, ESPCONN_CERT_OWN); lwIP_REQUIRE_ACTION(load_flag, exit, ret = ESPCONN_MEM); - auth_info.auth_type = ESPCONN_PK; - load_flag = mbedtls_msg_info_load(msg, &auth_info); + load_flag = mbedtls_msg_info_load(msg, ESPCONN_PK); lwIP_REQUIRE_ACTION(load_flag, exit, ret = ESPCONN_MEM); } /*Load the trusted CA*/ if(ssl_client_options.cert_ca_sector.flag) { - auth_info.auth_type = ESPCONN_CERT_AUTH; - load_flag = mbedtls_msg_info_load(msg, &auth_info); + load_flag = mbedtls_msg_info_load(msg, ESPCONN_CERT_AUTH); lwIP_REQUIRE_ACTION(load_flag, exit, ret = ESPCONN_MEM); } @@ -914,67 +854,4 @@ void espconn_ssl_disconnect(espconn_msg *Threadmsg) ets_post(lwIPThreadPrio, NETCONN_EVENT_CLOSE, (uint32)Threadmsg); } -/* - * Checkup routine - */ -int mbedtls_x509_test(int verbose, char *ca_crt, size_t ca_crt_len, char *cli_crt, size_t cli_crt_len) -{ -#if defined(MBEDTLS_SHA1_C) - int ret; - uint32_t flags; - mbedtls_x509_crt cacert; - mbedtls_x509_crt clicert; - - if( verbose != 0 ) - os_printf( " X.509 certificate load: " ); - - mbedtls_x509_crt_init( &clicert ); - - ret = mbedtls_x509_crt_parse( &clicert, (const unsigned char *) cli_crt, - cli_crt_len ); - if( ret != 0 ) - { - if( verbose != 0 ) - os_printf( "failed\n" ); - - return( ret ); - } - - mbedtls_x509_crt_init( &cacert ); - - ret = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) ca_crt, - ca_crt_len ); - if( ret != 0 ) - { - if( verbose != 0 ) - os_printf( "failed\n" ); - - return( ret ); - } - - if( verbose != 0 ) - os_printf( "passed\n X.509 signature verify: "); - - ret = mbedtls_x509_crt_verify( &clicert, &cacert, NULL, NULL, &flags, NULL, NULL ); - if( ret != 0 ) - { - if( verbose != 0 ) - os_printf( "failed\n" ); - - return( ret ); - } - - if( verbose != 0 ) - os_printf( "passed\n\n"); - - mbedtls_x509_crt_free( &cacert ); - mbedtls_x509_crt_free( &clicert ); - - return( 0 ); -#else - ((void) verbose); - return( 0 ); -#endif /* MBEDTLS_CERTS_C && MBEDTLS_SHA1_C */ -} - #endif diff --git a/app/mbedtls/app/espconn_secure.c b/app/mbedtls/app/espconn_secure.c index 9a2d82326a..7b6ab94a65 100644 --- a/app/mbedtls/app/espconn_secure.c +++ b/app/mbedtls/app/espconn_secure.c @@ -248,36 +248,4 @@ bool ICACHE_FLASH_ATTR espconn_secure_cert_req_disable(uint8 level) return false; } -/****************************************************************************** - * FunctionName : espconn_secure_set_default_certificate - * Description : Load the certificates in memory depending on compile-time - * and user options. - * Parameters : certificate -- Load the certificate - * length -- Load the certificate length - * Returns : result true or false -*******************************************************************************/ -bool ICACHE_FLASH_ATTR espconn_secure_set_default_certificate(const uint8* certificate, uint16 length) -{ - if (certificate == NULL || length > ESPCONN_SECURE_MAX_SIZE) - return false; - - return mbedtls_load_default_obj(0, ESPCONN_CERT_OWN, certificate, length); -} - -/****************************************************************************** - * FunctionName : espconn_secure_set_default_private_key - * Description : Load the key in memory depending on compile-time - * and user options. - * Parameters : private_key -- Load the key - * length -- Load the key length - * Returns : result true or false -*******************************************************************************/ -bool ICACHE_FLASH_ATTR espconn_secure_set_default_private_key(const uint8* private_key, uint16 length) -{ - if (private_key == NULL || length > ESPCONN_SECURE_MAX_SIZE) - return false; - - return mbedtls_load_default_obj(0, ESPCONN_PK, private_key, length); -} - #endif From 1eeed46cf9e04ae82e1d3e62fa79dac5859dce77 Mon Sep 17 00:00:00 2001 From: Nathaniel Wesley Filardo Date: Fri, 14 Feb 2020 11:13:04 +0000 Subject: [PATCH 09/17] espconn_secure: refactor mbedtls_msg_info_load Split out espconn_mbedtls_parse, which we can use as part of our effort towards addressing https://github.com/nodemcu/nodemcu-firmware/issues/3032 --- app/mbedtls/app/espconn_mbedtls.c | 48 ++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/app/mbedtls/app/espconn_mbedtls.c b/app/mbedtls/app/espconn_mbedtls.c index aa4bebcae7..638fb40259 100644 --- a/app/mbedtls/app/espconn_mbedtls.c +++ b/app/mbedtls/app/espconn_mbedtls.c @@ -448,6 +448,34 @@ static bool espconn_ssl_read_param_from_flash(void *param, uint16 len, int32 off return true; } +static bool +espconn_mbedtls_parse(mbedtls_msg *msg, mbedtls_auth_type auth_type, const uint8_t *buf, size_t len) +{ + int ret; + + switch (auth_type) { + case ESPCONN_CERT_AUTH: + ret = mbedtls_x509_crt_parse(&msg->psession->cacert, buf, len); + lwIP_REQUIRE_NOERROR(ret, exit); + mbedtls_ssl_conf_authmode(&msg->conf, MBEDTLS_SSL_VERIFY_REQUIRED); + mbedtls_ssl_conf_ca_chain(&msg->conf, &msg->psession->cacert, NULL); + break; + case ESPCONN_CERT_OWN: + ret = mbedtls_x509_crt_parse(&msg->psession->clicert, buf, len); + break; + case ESPCONN_PK: + ret = mbedtls_pk_parse_key(&msg->psession->pkey, buf, len, NULL, 0); + lwIP_REQUIRE_NOERROR(ret, exit); + ret = mbedtls_ssl_conf_own_cert(&msg->conf, &msg->psession->clicert, &msg->psession->pkey); + break; + default: + return false; + } + +exit: + return (ret >= 0); +} + static bool mbedtls_msg_info_load(mbedtls_msg *msg, mbedtls_auth_type auth_type) { const char* const begin = "-----BEGIN"; @@ -495,23 +523,9 @@ static bool mbedtls_msg_info_load(mbedtls_msg *msg, mbedtls_auth_type auth_type) load_len += 1; load_buf[load_len - 1] = '\0'; } - switch (auth_type) { - case ESPCONN_CERT_AUTH: - /*Optional is not optimal for security*/ - ret = mbedtls_x509_crt_parse(&msg->psession->cacert, (const uint8*) load_buf,load_len); - lwIP_REQUIRE_NOERROR(ret, exit); - mbedtls_ssl_conf_authmode(&msg->conf, MBEDTLS_SSL_VERIFY_REQUIRED); - mbedtls_ssl_conf_ca_chain(&msg->conf, &msg->psession->cacert, NULL); - break; - case ESPCONN_CERT_OWN: - ret = mbedtls_x509_crt_parse(&msg->psession->clicert, (const uint8*) load_buf,load_len); - break; - case ESPCONN_PK: - ret = mbedtls_pk_parse_key(&msg->psession->pkey, (const uint8*) load_buf,load_len, NULL, 0); - lwIP_REQUIRE_NOERROR(ret, exit); - ret = mbedtls_ssl_conf_own_cert(&msg->conf, &msg->psession->clicert, &msg->psession->pkey); - break; - } + + ret = espconn_mbedtls_parse(msg, auth_type, load_buf, load_len) ? 0 : -1; + exit: os_free(load_buf); if (ret < 0) { From 8ef4e79f9db3f8cacf4de6149d42fe6eec3e5220 Mon Sep 17 00:00:00 2001 From: Nathaniel Wesley Filardo Date: Fri, 14 Feb 2020 14:49:53 +0000 Subject: [PATCH 10/17] espconn_secure: introduce TLS cert/key callbacks The new feature part of https://github.com/nodemcu/nodemcu-firmware/issues/3032 Subsequent work will remove the old mechanism. --- app/include/sys/espconn_mbedtls.h | 3 ++ app/mbedtls/app/espconn_mbedtls.c | 90 ++++++++++++++++++++++++++++++- app/mbedtls/app/espconn_secure.c | 4 +- app/modules/tls.c | 22 ++++++++ docs/modules/tls.md | 22 +++++++- 5 files changed, 137 insertions(+), 4 deletions(-) diff --git a/app/include/sys/espconn_mbedtls.h b/app/include/sys/espconn_mbedtls.h index c586492d0d..2d8e35bc5d 100644 --- a/app/include/sys/espconn_mbedtls.h +++ b/app/include/sys/espconn_mbedtls.h @@ -91,6 +91,9 @@ struct ssl_options { uint16 buffer_size; ssl_sector cert_ca_sector; ssl_sector cert_req_sector; + + int cert_verify_callback; + int cert_auth_callback; }; #define SSL_KEEP_INTVL 1 diff --git a/app/mbedtls/app/espconn_mbedtls.c b/app/mbedtls/app/espconn_mbedtls.c index 638fb40259..b5da2531b5 100644 --- a/app/mbedtls/app/espconn_mbedtls.c +++ b/app/mbedtls/app/espconn_mbedtls.c @@ -34,6 +34,8 @@ #include "mem.h" +#include "lauxlib.h" + #ifdef MEMLEAK_DEBUG static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__; #endif @@ -476,6 +478,79 @@ espconn_mbedtls_parse(mbedtls_msg *msg, mbedtls_auth_type auth_type, const uint8 return (ret >= 0); } +/* + * Three-way return: + * 0 for no commitment, -1 to fail the connection, 1 on success + */ +static int +nodemcu_tls_cert_get(mbedtls_msg *msg, mbedtls_auth_type auth_type) +{ + int cbref; + int cbarg; + int loop = 0; + + switch(auth_type) { + case ESPCONN_CERT_AUTH: + loop = 1; + cbarg = 1; + cbref = ssl_client_options.cert_verify_callback; + break; + case ESPCONN_PK: + loop = 0; + cbarg = 0; + cbref = ssl_client_options.cert_auth_callback; + break; + case ESPCONN_CERT_OWN: + loop = 1; + cbarg = 1; + cbref = ssl_client_options.cert_auth_callback; + break; + default: + return 0; + } + + if (cbref == LUA_NOREF) + return 0; + + lua_State *L = lua_getstate(); + + do { + lua_rawgeti(L, LUA_REGISTRYINDEX, cbref); + lua_pushinteger(L, cbarg); + if (lua_pcall(L, 1, 1, 0) != 0) { + /* call failure; fail the connection attempt */ + lua_pop(L, 1); /* pcall will have pushed an error message */ + return -1; + } + if (lua_isnil(L, -1)) { + /* nil return; stop iteration */ + lua_pop(L, 1); + break; + } + size_t resl; + const char *res = lua_tolstring(L, -1, &resl); + if (res == NULL) { + /* conversion failure; fail the connection attempt */ + lua_pop(L, 1); + return -1; + } + if (!espconn_mbedtls_parse(msg, auth_type, res, resl+1)) { + /* parsing failure; fail the connction attempt */ + lua_pop(L, 1); + return -1; + } + + /* + * Otherwise, parsing successful; if this is a loopy kind of + * callback, then increment the argument and loop. + */ + lua_pop(L, 1); + cbarg++; + } while (loop); + + return 1; +} + static bool mbedtls_msg_info_load(mbedtls_msg *msg, mbedtls_auth_type auth_type) { const char* const begin = "-----BEGIN"; @@ -487,6 +562,14 @@ static bool mbedtls_msg_info_load(mbedtls_msg *msg, mbedtls_auth_type auth_type) size_t load_len = 0; file_param file_param; + /* Override with Lua callbacks, if registered */ + switch(nodemcu_tls_cert_get(msg, auth_type)) { + case -1: + return false; + case 1: + return true; + } + bzero(&file_param, sizeof(file_param)); again: @@ -551,7 +634,9 @@ static bool mbedtls_msg_config(mbedtls_msg *msg) lwIP_REQUIRE_NOERROR(ret, exit); /*Load the certificate and private RSA key*/ - if (ssl_client_options.cert_req_sector.flag) { + if (ssl_client_options.cert_req_sector.flag + || (ssl_client_options.cert_auth_callback != LUA_NOREF)) { + load_flag = mbedtls_msg_info_load(msg, ESPCONN_CERT_OWN); lwIP_REQUIRE_ACTION(load_flag, exit, ret = ESPCONN_MEM); load_flag = mbedtls_msg_info_load(msg, ESPCONN_PK); @@ -559,7 +644,8 @@ static bool mbedtls_msg_config(mbedtls_msg *msg) } /*Load the trusted CA*/ - if(ssl_client_options.cert_ca_sector.flag) { + if(ssl_client_options.cert_ca_sector.flag + || (ssl_client_options.cert_verify_callback != LUA_NOREF)) { load_flag = mbedtls_msg_info_load(msg, ESPCONN_CERT_AUTH); lwIP_REQUIRE_ACTION(load_flag, exit, ret = ESPCONN_MEM); } diff --git a/app/mbedtls/app/espconn_secure.c b/app/mbedtls/app/espconn_secure.c index 7b6ab94a65..ce0f635023 100644 --- a/app/mbedtls/app/espconn_secure.c +++ b/app/mbedtls/app/espconn_secure.c @@ -31,6 +31,8 @@ #include "ets_sys.h" #include "os_type.h" +#include "lauxlib.h" + #ifdef MEMLEAK_DEBUG static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__; #endif @@ -39,7 +41,7 @@ static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__; #include "sys/espconn_mbedtls.h" -struct ssl_options ssl_client_options = {SSL_BUFFER_SIZE, 0, false, 0, false}; +struct ssl_options ssl_client_options = {SSL_BUFFER_SIZE, 0, false, 0, false, LUA_NOREF, LUA_NOREF}; /****************************************************************************** * FunctionName : espconn_encry_connect diff --git a/app/modules/tls.c b/app/modules/tls.c index 1db3f4c0fb..4082458e46 100644 --- a/app/modules/tls.c +++ b/app/modules/tls.c @@ -529,6 +529,17 @@ static const char *fill_page_with_pem(lua_State *L, const unsigned char *flash_m // Lua: tls.cert.auth(true / false) static int tls_cert_auth(lua_State *L) { + if (ssl_client_options.cert_auth_callback != LUA_NOREF) { + lua_unref(L, ssl_client_options.cert_auth_callback); + ssl_client_options.cert_auth_callback = LUA_NOREF; + } + if ((lua_type(L, 1) == LUA_TFUNCTION) + || (lua_type(L, 1) == LUA_TLIGHTFUNCTION)) { + ssl_client_options.cert_auth_callback = lua_ref(L, 1); + lua_pushboolean(L, true); + return 1; + } + int enable; uint32_t flash_offset = platform_flash_mapped2phys((uint32_t) &tls_client_cert_area[0]); @@ -570,6 +581,17 @@ static int tls_cert_auth(lua_State *L) // Lua: tls.cert.verify(true / false) static int tls_cert_verify(lua_State *L) { + if (ssl_client_options.cert_verify_callback != LUA_NOREF) { + lua_unref(L, ssl_client_options.cert_verify_callback); + ssl_client_options.cert_verify_callback = LUA_NOREF; + } + if ((lua_type(L, 1) == LUA_TFUNCTION) + || (lua_type(L, 1) == LUA_TLIGHTFUNCTION)) { + ssl_client_options.cert_verify_callback = lua_ref(L, 1); + lua_pushboolean(L, true); + return 1; + } + int enable; uint32_t flash_offset = platform_flash_mapped2phys((uint32_t) &tls_server_cert_area[0]); diff --git a/docs/modules/tls.md b/docs/modules/tls.md index a6333c28c3..52e78335db 100644 --- a/docs/modules/tls.md +++ b/docs/modules/tls.md @@ -263,10 +263,19 @@ Controls the certificate verification process when the NodeMCU makes a secure co `tls.cert.verify(pemdata[, pemdata])` +`tls.cert.verify(callback)` + #### Parameters - `enable` A boolean which indicates whether verification should be enabled or not. The default at boot is `false`. - `pemdata` A string containing the CA certificate to use for verification. There can be several of these. +- `callback` A Lua function which returns TLS keys and certificates for use + with connections. The callback should expect one, integer argument; for + value k, the callback should return the k-th CA certificate (in either DER or + PEM form) it wishes to use to validate the remote endpoint, or `nil` if no + such CA certificate exists. If no certificates are returned, the device will + not validate the remote endpoint. + #### Returns `true` if it worked. @@ -325,6 +334,9 @@ The alternative approach is easier for development, and that is to supply the PE will store the certificate into the flash chip and turn on verification for that certificate. Subsequent boots of the ESP can then use `tls.cert.verify(true)` and use the stored certificate. +The `callback`-based version will override the in-flash information until the callback +is unregistered *or* one of the other call forms is made. + ## tls.cert.auth() Controls the client key and certificate used when the ESP creates a TLS connection (for example, @@ -335,10 +347,17 @@ through `tls.createConnection` or `https` or `MQTT` connections with `secure = t `tls.cert.auth(pemdata[, pemdata])` +`tls.cert.auth(callback)` + #### Parameters - `enable` A boolean, specifying whether subsequent TLS connections will present a client certificate. The default at boot is `false`. - `pemdata` Two strings, the first containing the PEM-encoded client's certificate and the second containing the PEM-encoded client's private key. +- `callback` A Lua function which returns TLS keys and certificates for use with connections. + The callback should expect one, integer argument; if that is 0, the callback should return + the device's private key. Otherwise, for argument k, the callback should return the k-th + certificate (in either DER or PEM form) in the devices' certificate chain. + #### Returns `true` if it worked. @@ -379,7 +398,8 @@ It can be supplied by passing the PEM data as a string value to `tls.cert.auth`. will store the certificate into the flash chip and turn on proofing with that certificate. Subsequent boots of the ESP can then use `tls.cert.auth(true)` and use the stored certificate. - +The `callback`-based version will override the in-flash information until the callback +is unregistered *or* one of the other call forms is made. # tls.setDebug function From d37a4eb742c2071e795e7eb0643a9a0d475e4ea9 Mon Sep 17 00:00:00 2001 From: Nathaniel Wesley Filardo Date: Fri, 14 Feb 2020 18:07:51 +0000 Subject: [PATCH 11/17] tls: add deprecation warnings --- app/modules/tls.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/modules/tls.c b/app/modules/tls.c index 4082458e46..b52769ff15 100644 --- a/app/modules/tls.c +++ b/app/modules/tls.c @@ -539,6 +539,9 @@ static int tls_cert_auth(lua_State *L) lua_pushboolean(L, true); return 1; } + if (lua_type(L, 1) != LUA_TNIL) { + platform_print_deprecation_note("tls.cert.auth's old interface", "soon"); + } int enable; @@ -591,6 +594,9 @@ static int tls_cert_verify(lua_State *L) lua_pushboolean(L, true); return 1; } + if (lua_type(L, 1) != LUA_TNIL) { + platform_print_deprecation_note("tls.cert.verify's old interface", "soon"); + } int enable; From d0552ba4ede61150d4c04813577689c9b1a8a46a Mon Sep 17 00:00:00 2001 From: Nathaniel Wesley Filardo Date: Thu, 2 Apr 2020 05:28:25 +0100 Subject: [PATCH 12/17] tls: remove use of espconn->reverse --- app/modules/tls.c | 98 ++++++++++++++++++++--------------------------- 1 file changed, 41 insertions(+), 57 deletions(-) diff --git a/app/modules/tls.c b/app/modules/tls.c index b52769ff15..bfd38f05f8 100644 --- a/app/modules/tls.c +++ b/app/modules/tls.c @@ -30,11 +30,8 @@ __attribute__((section(".servercert.flash"))) unsigned char tls_server_cert_area __attribute__((section(".clientcert.flash"))) unsigned char tls_client_cert_area[INTERNAL_FLASH_SECTOR_SIZE]; -extern int tls_socket_create( lua_State *L ); -LROT_EXTERN(tls_cert); - typedef struct { - struct espconn *pesp_conn; + struct espconn pesp_conn; int self_ref; int cb_connect_ref; int cb_reconnect_ref; @@ -47,7 +44,8 @@ typedef struct { int tls_socket_create( lua_State *L ) { tls_socket_ud *ud = (tls_socket_ud*) lua_newuserdata(L, sizeof(tls_socket_ud)); - ud->pesp_conn = NULL; + bzero(&ud->pesp_conn, sizeof(ud->pesp_conn)); + ud->self_ref = ud->cb_connect_ref = ud->cb_reconnect_ref = @@ -63,7 +61,7 @@ int tls_socket_create( lua_State *L ) { } static void tls_socket_onconnect( struct espconn *pesp_conn ) { - tls_socket_ud *ud = (tls_socket_ud *)pesp_conn->reverse; + tls_socket_ud *ud = (tls_socket_ud *)pesp_conn; if (!ud || ud->self_ref == LUA_NOREF) return; if (ud->cb_connect_ref != LUA_NOREF) { lua_State *L = lua_getstate(); @@ -74,14 +72,10 @@ static void tls_socket_onconnect( struct espconn *pesp_conn ) { } static void tls_socket_cleanup(tls_socket_ud *ud) { - if (ud->pesp_conn) { - espconn_secure_disconnect(ud->pesp_conn); - if (ud->pesp_conn->proto.tcp) { - free(ud->pesp_conn->proto.tcp); - ud->pesp_conn->proto.tcp = NULL; - } - free(ud->pesp_conn); - ud->pesp_conn = NULL; + if (ud->pesp_conn.proto.tcp) { + espconn_secure_disconnect(&ud->pesp_conn); + free(ud->pesp_conn.proto.tcp); + ud->pesp_conn.proto.tcp = NULL; } lua_State *L = lua_getstate(); lua_gc(L, LUA_GCSTOP, 0); @@ -91,7 +85,7 @@ static void tls_socket_cleanup(tls_socket_ud *ud) { } static void tls_socket_ondisconnect( struct espconn *pesp_conn ) { - tls_socket_ud *ud = (tls_socket_ud *)pesp_conn->reverse; + tls_socket_ud *ud = (tls_socket_ud *)pesp_conn; if (!ud || ud->self_ref == LUA_NOREF) return; tls_socket_cleanup(ud); if (ud->cb_disconnect_ref != LUA_NOREF) { @@ -104,7 +98,7 @@ static void tls_socket_ondisconnect( struct espconn *pesp_conn ) { } static void tls_socket_onreconnect( struct espconn *pesp_conn, s8 err ) { - tls_socket_ud *ud = (tls_socket_ud *)pesp_conn->reverse; + tls_socket_ud *ud = (tls_socket_ud *)pesp_conn; if (!ud || ud->self_ref == LUA_NOREF) return; if (ud->cb_reconnect_ref != LUA_NOREF) { const char* reason = NULL; @@ -132,7 +126,7 @@ static void tls_socket_onreconnect( struct espconn *pesp_conn, s8 err ) { } static void tls_socket_onrecv( struct espconn *pesp_conn, char *buf, u16 length ) { - tls_socket_ud *ud = (tls_socket_ud *)pesp_conn->reverse; + tls_socket_ud *ud = (tls_socket_ud *)pesp_conn; if (!ud || ud->self_ref == LUA_NOREF) return; if (ud->cb_receive_ref != LUA_NOREF) { lua_State *L = lua_getstate(); @@ -144,7 +138,7 @@ static void tls_socket_onrecv( struct espconn *pesp_conn, char *buf, u16 length } static void tls_socket_onsent( struct espconn *pesp_conn ) { - tls_socket_ud *ud = (tls_socket_ud *)pesp_conn->reverse; + tls_socket_ud *ud = (tls_socket_ud *)pesp_conn; if (!ud || ud->self_ref == LUA_NOREF) return; if (ud->cb_sent_ref != LUA_NOREF) { lua_State *L = lua_getstate(); @@ -178,8 +172,8 @@ static void tls_socket_dns_cb( const char* domain, const ip_addr_t *ip_addr, tls ud->self_ref = LUA_NOREF; lua_gc(L, LUA_GCRESTART, 0); } else { - os_memcpy(ud->pesp_conn->proto.tcp->remote_ip, &addr.addr, 4); - espconn_secure_connect(ud->pesp_conn); + os_memcpy(ud->pesp_conn.proto.tcp->remote_ip, &addr.addr, 4); + espconn_secure_connect(&ud->pesp_conn); } } @@ -191,7 +185,7 @@ static int tls_socket_connect( lua_State *L ) { return 0; } - if (ud->pesp_conn) { + if (ud->pesp_conn.proto.tcp) { return luaL_error(L, "already connected"); } @@ -205,25 +199,19 @@ static int tls_socket_connect( lua_State *L ) { if (domain == NULL) return luaL_error(L, "invalid domain"); - ud->pesp_conn = (struct espconn*)calloc(1,sizeof(struct espconn)); - if(!ud->pesp_conn) - return luaL_error(L, "not enough memory"); - ud->pesp_conn->proto.udp = NULL; - ud->pesp_conn->proto.tcp = (esp_tcp *)calloc(1,sizeof(esp_tcp)); - if(!ud->pesp_conn->proto.tcp){ - free(ud->pesp_conn); - ud->pesp_conn = NULL; + ud->pesp_conn.proto.udp = NULL; + ud->pesp_conn.proto.tcp = (esp_tcp *)calloc(1,sizeof(esp_tcp)); + if(!ud->pesp_conn.proto.tcp){ return luaL_error(L, "not enough memory"); } - ud->pesp_conn->type = ESPCONN_TCP; - ud->pesp_conn->state = ESPCONN_NONE; - ud->pesp_conn->reverse = ud; - ud->pesp_conn->proto.tcp->remote_port = port; - espconn_regist_connectcb(ud->pesp_conn, (espconn_connect_callback)tls_socket_onconnect); - espconn_regist_disconcb(ud->pesp_conn, (espconn_connect_callback)tls_socket_ondisconnect); - espconn_regist_reconcb(ud->pesp_conn, (espconn_reconnect_callback)tls_socket_onreconnect); - espconn_regist_recvcb(ud->pesp_conn, (espconn_recv_callback)tls_socket_onrecv); - espconn_regist_sentcb(ud->pesp_conn, (espconn_sent_callback)tls_socket_onsent); + ud->pesp_conn.type = ESPCONN_TCP; + ud->pesp_conn.state = ESPCONN_NONE; + ud->pesp_conn.proto.tcp->remote_port = port; + espconn_regist_connectcb(&ud->pesp_conn, (espconn_connect_callback)tls_socket_onconnect); + espconn_regist_disconcb(&ud->pesp_conn, (espconn_connect_callback)tls_socket_ondisconnect); + espconn_regist_reconcb(&ud->pesp_conn, (espconn_reconnect_callback)tls_socket_onreconnect); + espconn_regist_recvcb(&ud->pesp_conn, (espconn_recv_callback)tls_socket_onrecv); + espconn_regist_sentcb(&ud->pesp_conn, (espconn_sent_callback)tls_socket_onsent); if (ud->self_ref == LUA_NOREF) { lua_pushvalue(L, 1); // copy to the top of stack @@ -289,7 +277,7 @@ static int tls_socket_send( lua_State *L ) { return 0; } - if(ud->pesp_conn == NULL) { + if(ud->pesp_conn.proto.tcp == NULL) { NODE_DBG("not connected"); return 0; } @@ -300,7 +288,7 @@ static int tls_socket_send( lua_State *L ) { return luaL_error(L, "wrong arg type"); } - espconn_secure_send(ud->pesp_conn, (void*)buf, sl); + espconn_secure_send(&ud->pesp_conn, (void*)buf, sl); return 0; } @@ -312,12 +300,12 @@ static int tls_socket_hold( lua_State *L ) { return 0; } - if(ud->pesp_conn == NULL) { + if(ud->pesp_conn.proto.tcp == NULL) { NODE_DBG("not connected"); return 0; } - espconn_recv_hold(ud->pesp_conn); + espconn_recv_hold(&ud->pesp_conn); return 0; } @@ -329,12 +317,12 @@ static int tls_socket_unhold( lua_State *L ) { return 0; } - if(ud->pesp_conn == NULL) { + if(ud->pesp_conn.proto.tcp == NULL) { NODE_DBG("not connected"); return 0; } - espconn_recv_unhold(ud->pesp_conn); + espconn_recv_unhold(&ud->pesp_conn); return 0; } @@ -347,11 +335,11 @@ static int tls_socket_getpeer( lua_State *L ) { return 0; } - if(ud->pesp_conn && ud->pesp_conn->proto.tcp->remote_port != 0){ + if(ud->pesp_conn.proto.tcp && ud->pesp_conn.proto.tcp->remote_port != 0){ char temp[20] = {0}; - sprintf(temp, IPSTR, IP2STR( &(ud->pesp_conn->proto.tcp->remote_ip) ) ); + sprintf(temp, IPSTR, IP2STR( &(ud->pesp_conn.proto.tcp->remote_ip) ) ); lua_pushstring( L, temp ); - lua_pushinteger( L, ud->pesp_conn->proto.tcp->remote_port ); + lua_pushinteger( L, ud->pesp_conn.proto.tcp->remote_port ); } else { lua_pushnil( L ); lua_pushnil( L ); @@ -366,8 +354,8 @@ static int tls_socket_close( lua_State *L ) { return 0; } - if (ud->pesp_conn) { - espconn_secure_disconnect(ud->pesp_conn); + if (ud->pesp_conn.proto.tcp) { + espconn_secure_disconnect(&ud->pesp_conn); } return 0; @@ -379,14 +367,10 @@ static int tls_socket_delete( lua_State *L ) { NODE_DBG("userdata is nil.\n"); return 0; } - if (ud->pesp_conn) { - espconn_secure_disconnect(ud->pesp_conn); - if (ud->pesp_conn->proto.tcp) { - free(ud->pesp_conn->proto.tcp); - ud->pesp_conn->proto.tcp = NULL; - } - free(ud->pesp_conn); - ud->pesp_conn = NULL; + if (ud->pesp_conn.proto.tcp) { + espconn_secure_disconnect(&ud->pesp_conn); + free(ud->pesp_conn.proto.tcp); + ud->pesp_conn.proto.tcp = NULL; } luaL_unref(L, LUA_REGISTRYINDEX, ud->cb_connect_ref); From 7274ee0817c2f575e07cecafa795ed2324efd83f Mon Sep 17 00:00:00 2001 From: Nathaniel Wesley Filardo Date: Sun, 5 Apr 2020 23:39:20 +0100 Subject: [PATCH 13/17] tls: allow :on(...,nil) to unregister a callback --- app/modules/tls.c | 43 +++++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/app/modules/tls.c b/app/modules/tls.c index bfd38f05f8..affe33d375 100644 --- a/app/modules/tls.c +++ b/app/modules/tls.c @@ -242,30 +242,29 @@ static int tls_socket_on( lua_State *L ) { if (method == NULL) return luaL_error( L, "wrong arg type" ); - luaL_checkanyfunction(L, 3); - lua_pushvalue(L, 3); // copy argument (func) to the top of stack - - if (strcmp(method, "connection") == 0) { - luaL_unref(L, LUA_REGISTRYINDEX, ud->cb_connect_ref); - ud->cb_connect_ref = luaL_ref(L, LUA_REGISTRYINDEX); - } else if (strcmp(method, "disconnection") == 0) { - luaL_unref(L, LUA_REGISTRYINDEX, ud->cb_disconnect_ref); - ud->cb_disconnect_ref = luaL_ref(L, LUA_REGISTRYINDEX); - } else if (strcmp(method, "reconnection") == 0) { - luaL_unref(L, LUA_REGISTRYINDEX, ud->cb_reconnect_ref); - ud->cb_reconnect_ref = luaL_ref(L, LUA_REGISTRYINDEX); - } else if (strcmp(method, "receive") == 0) { - luaL_unref(L, LUA_REGISTRYINDEX, ud->cb_receive_ref); - ud->cb_receive_ref = luaL_ref(L, LUA_REGISTRYINDEX); - } else if (strcmp(method, "sent") == 0) { - luaL_unref(L, LUA_REGISTRYINDEX, ud->cb_sent_ref); - ud->cb_sent_ref = luaL_ref(L, LUA_REGISTRYINDEX); - } else if (strcmp(method, "dns") == 0) { - luaL_unref(L, LUA_REGISTRYINDEX, ud->cb_dns_ref); - ud->cb_dns_ref = luaL_ref(L, LUA_REGISTRYINDEX); - } else { + int *cbp; + + if (strcmp(method, "connection" ) == 0) { cbp = &ud->cb_connect_ref ; } + else if (strcmp(method, "disconnection") == 0) { cbp = &ud->cb_disconnect_ref; } + else if (strcmp(method, "reconnection" ) == 0) { cbp = &ud->cb_reconnect_ref ; } + else if (strcmp(method, "receive" ) == 0) { cbp = &ud->cb_receive_ref ; } + else if (strcmp(method, "sent" ) == 0) { cbp = &ud->cb_sent_ref ; } + else if (strcmp(method, "dns" ) == 0) { cbp = &ud->cb_dns_ref ; } + else { return luaL_error(L, "invalid method"); } + + if (lua_isanyfunction(L, 3)) { + lua_pushvalue(L, 3); // copy argument (func) to the top of stack + luaL_unref(L, LUA_REGISTRYINDEX, *cbp); + *cbp = luaL_ref(L, LUA_REGISTRYINDEX); + } else if (lua_isnil(L, 3)) { + luaL_unref(L, LUA_REGISTRYINDEX, *cbp); + *cbp = LUA_NOREF; + } else { + return luaL_error(L, "invalid callback function"); + } + return 0; } From ad9c964b300afc7574cf202598bb31c5bfd6515e Mon Sep 17 00:00:00 2001 From: Nathaniel Wesley Filardo Date: Sun, 2 Feb 2020 14:52:21 +0000 Subject: [PATCH 14/17] mqtt: remove redundant pointer to connect_info Everywhere we have the mqtt_state_t we also have the lmqtt_userdata. --- app/modules/mqtt.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/app/modules/mqtt.c b/app/modules/mqtt.c index c0cc1cebc3..cba11b5dfa 100644 --- a/app/modules/mqtt.c +++ b/app/modules/mqtt.c @@ -60,7 +60,6 @@ typedef enum { typedef struct mqtt_state_t { uint16_t port; - mqtt_connect_info_t* connect_info; msg_queue_t* pending_msg_q; uint16_t next_message_id; @@ -781,7 +780,7 @@ static void mqtt_socket_connected(void *arg) mqtt_message_buffer_t msgb; mqtt_msg_init(&msgb, temp_buffer, MQTT_BUF_SIZE); - mqtt_message_t* temp_msg = mqtt_msg_connect(&msgb, mud->mqtt_state.connect_info); + mqtt_message_t* temp_msg = mqtt_msg_connect(&msgb, &mud->connect_info); NODE_DBG("Send MQTT connection infomation, data len: %d, d[0]=%d \r\n", temp_msg->length, temp_msg->data[0]); mud->event_timeout = MQTT_SEND_TIMEOUT; @@ -883,7 +882,7 @@ void mqtt_socket_timer(void *arg) } else { // no queued event. mud->keep_alive_tick ++; - if(mud->keep_alive_tick > mud->mqtt_state.connect_info->keepalive){ + if(mud->keep_alive_tick > mud->connect_info.keepalive){ if (mud->keepalive_sent) { // Oh dear -- keepalive timer expired and still no ack of previous message mqtt_socket_reconnected(mud->pesp_conn, 0); @@ -1037,7 +1036,6 @@ static int mqtt_socket_client( lua_State* L ) mud->mqtt_state.pending_msg_q = NULL; mud->mqtt_state.port = 1883; - mud->mqtt_state.connect_info = &mud->connect_info; mud->mqtt_state.recv_buffer = NULL; mud->mqtt_state.recv_buffer_size = 0; mud->mqtt_state.recv_buffer_state = MQTT_RECV_NORMAL; From 03862b6276fa4b9caadb15b9a441c0d5b0720198 Mon Sep 17 00:00:00 2001 From: Nathaniel Wesley Filardo Date: Sun, 2 Feb 2020 13:44:52 +0000 Subject: [PATCH 15/17] mqtt: stop using espconn->reverse Instead, just place the espconn structure itself at the top of the user data. This enlarges the structure somewhat but removes one more layer of dynamic heap usage and NULL checks. While here, simplify the code a bit. --- app/modules/mqtt.c | 259 ++++++++++++--------------------------------- 1 file changed, 66 insertions(+), 193 deletions(-) diff --git a/app/modules/mqtt.c b/app/modules/mqtt.c index cba11b5dfa..50738bd85b 100644 --- a/app/modules/mqtt.c +++ b/app/modules/mqtt.c @@ -76,7 +76,7 @@ typedef struct mqtt_state_t typedef struct lmqtt_userdata { - struct espconn *pesp_conn; + struct espconn pesp_conn; int self_ref; int cb_connect_ref; int cb_connect_fail_ref; @@ -102,7 +102,7 @@ typedef struct lmqtt_userdata // How large MQTT messages to accept by default #define DEFAULT_MAX_MESSAGE_LENGTH 1024 -static sint8 socket_connect(struct espconn *pesp_conn); +static sint8 mqtt_socket_do_connect(struct lmqtt_userdata *); static void mqtt_socket_reconnected(void *arg, sint8_t err); static void mqtt_socket_connected(void *arg); static void mqtt_connack_fail(lmqtt_userdata * mud, int reason_code); @@ -119,11 +119,8 @@ static uint16_t mqtt_next_message_id(lmqtt_userdata * mud) static void mqtt_socket_disconnected(void *arg) // tcp only { NODE_DBG("enter mqtt_socket_disconnected.\n"); - struct espconn *pesp_conn = arg; bool call_back = false; - if(pesp_conn == NULL) - return; - lmqtt_userdata *mud = (lmqtt_userdata *)pesp_conn->reverse; + lmqtt_userdata *mud = arg; if(mud == NULL) return; @@ -147,14 +144,9 @@ static void mqtt_socket_disconnected(void *arg) // tcp only mud->mqtt_state.recv_buffer_size = 0; mud->mqtt_state.recv_buffer_state = MQTT_RECV_NORMAL; - if(mud->pesp_conn){ - mud->pesp_conn->reverse = NULL; - if(mud->pesp_conn->proto.tcp) - free(mud->pesp_conn->proto.tcp); - mud->pesp_conn->proto.tcp = NULL; - free(mud->pesp_conn); - mud->pesp_conn = NULL; - } + if(mud->pesp_conn.proto.tcp) + free(mud->pesp_conn.proto.tcp); + mud->pesp_conn.proto.tcp = NULL; mud->connected = false; luaL_unref(L, LUA_REGISTRYINDEX, mud->self_ref); @@ -167,14 +159,22 @@ static void mqtt_socket_disconnected(void *arg) // tcp only NODE_DBG("leave mqtt_socket_disconnected.\n"); } +static void mqtt_socket_do_disconnect(struct lmqtt_userdata *mud) +{ +#ifdef CLIENT_SSL_ENABLE + if (mud->secure) { + espconn_secure_disconnect(&mud->pesp_conn); + } else +#endif + { + espconn_disconnect(&mud->pesp_conn); + } +} + static void mqtt_socket_reconnected(void *arg, sint8_t err) { NODE_DBG("enter mqtt_socket_reconnected.\n"); - // mqtt_socket_disconnected(arg); - struct espconn *pesp_conn = arg; - if(pesp_conn == NULL) - return; - lmqtt_userdata *mud = (lmqtt_userdata *)pesp_conn->reverse; + lmqtt_userdata *mud = arg; if(mud == NULL) return; @@ -182,14 +182,7 @@ static void mqtt_socket_reconnected(void *arg, sint8_t err) mud->event_timeout = 0; // no need to count anymore -#ifdef CLIENT_SSL_ENABLE - if (mud->secure) { - espconn_secure_disconnect(pesp_conn); - } else -#endif - { - espconn_disconnect(pesp_conn); - } + mqtt_socket_do_disconnect(mud); mqtt_connack_fail(mud, MQTT_CONN_FAIL_SERVER_NOT_FOUND); @@ -250,14 +243,8 @@ static void mqtt_connack_fail(lmqtt_userdata * mud, int reason_code) lua_call(L, 2, 0); } -static sint8 mqtt_send_if_possible(struct espconn *pesp_conn) +static sint8 mqtt_send_if_possible(struct lmqtt_userdata *mud) { - if(pesp_conn == NULL) - return ESPCONN_OK; - lmqtt_userdata *mud = (lmqtt_userdata *)pesp_conn->reverse; - if(mud == NULL) - return ESPCONN_OK; - sint8 espconn_status = ESPCONN_OK; // This indicates if we have sent something and are waiting for something to @@ -270,12 +257,12 @@ static sint8 mqtt_send_if_possible(struct espconn *pesp_conn) #ifdef CLIENT_SSL_ENABLE if( mud->secure ) { - espconn_status = espconn_secure_send( pesp_conn, pending_msg->msg.data, pending_msg->msg.length ); + espconn_status = espconn_secure_send(&mud->pesp_conn, pending_msg->msg.data, pending_msg->msg.length ); } else #endif { - espconn_status = espconn_send( pesp_conn, pending_msg->msg.data, pending_msg->msg.length ); + espconn_status = espconn_send(&mud->pesp_conn, pending_msg->msg.data, pending_msg->msg.length ); } mud->keep_alive_tick = 0; } @@ -296,10 +283,7 @@ static void mqtt_socket_received(void *arg, char *pdata, unsigned short len) uint8_t *continuation_buffer = NULL; uint8_t *temp_pdata = NULL; - struct espconn *pesp_conn = arg; - if(pesp_conn == NULL) - return; - lmqtt_userdata *mud = (lmqtt_userdata *)pesp_conn->reverse; + lmqtt_userdata *mud = arg; if(mud == NULL) return; @@ -314,14 +298,7 @@ static void mqtt_socket_received(void *arg, char *pdata, unsigned short len) temp_pdata = calloc(1,mud->mqtt_state.recv_buffer_size + len); if(temp_pdata == NULL) { NODE_DBG("MQTT[buffering-short]: Failed to allocate %u bytes, disconnecting...\n", mud->mqtt_state.recv_buffer_size + len); -#ifdef CLIENT_SSL_ENABLE - if (mud->secure) { - espconn_secure_disconnect(pesp_conn); - } else -#endif - { - espconn_disconnect(pesp_conn); - } + mqtt_socket_do_disconnect(mud); return; } @@ -420,19 +397,8 @@ static void mqtt_socket_received(void *arg, char *pdata, unsigned short len) if(mqtt_get_type(in_buffer) != MQTT_MSG_TYPE_CONNACK){ NODE_DBG("MQTT: Invalid packet\r\n"); mud->connState = MQTT_INIT; -#ifdef CLIENT_SSL_ENABLE - if(mud->secure) - { - espconn_secure_disconnect(pesp_conn); - } - else -#endif - { - espconn_disconnect(pesp_conn); - } - + mqtt_socket_do_disconnect(mud); mqtt_connack_fail(mud, MQTT_CONN_FAIL_NOT_A_CONNACK_MSG); - break; } else if (mqtt_get_connect_ret_code(in_buffer) != MQTT_CONNACK_ACCEPTED) { @@ -440,19 +406,8 @@ static void mqtt_socket_received(void *arg, char *pdata, unsigned short len) mud->connState = MQTT_INIT; -#ifdef CLIENT_SSL_ENABLE - if(mud->secure) - { - espconn_secure_disconnect(pesp_conn); - } - else -#endif - { - espconn_disconnect(pesp_conn); - } - + mqtt_socket_do_disconnect(mud); mqtt_connack_fail(mud, mqtt_get_connect_ret_code(in_buffer)); - break; } else { @@ -543,14 +498,7 @@ static void mqtt_socket_received(void *arg, char *pdata, unsigned short len) mud->mqtt_state.recv_buffer = calloc(1,alloc_size); if (mud->mqtt_state.recv_buffer == NULL) { NODE_DBG("MQTT: Failed to allocate %u bytes, disconnecting...\n", alloc_size); -#ifdef CLIENT_SSL_ENABLE - if (mud->secure) { - espconn_secure_disconnect(pesp_conn); - } else -#endif - { - espconn_disconnect(pesp_conn); - } + mqtt_socket_do_disconnect(mud); return; } @@ -708,7 +656,7 @@ static void mqtt_socket_received(void *arg, char *pdata, unsigned short len) free(temp_pdata); } - mqtt_send_if_possible(pesp_conn); + mqtt_send_if_possible(mud); NODE_DBG("leave mqtt_socket_received\n"); return; } @@ -716,10 +664,7 @@ static void mqtt_socket_received(void *arg, char *pdata, unsigned short len) static void mqtt_socket_sent(void *arg) { NODE_DBG("enter mqtt_socket_sent.\n"); - struct espconn *pesp_conn = arg; - if(pesp_conn == NULL) - return; - lmqtt_userdata *mud = (lmqtt_userdata *)pesp_conn->reverse; + lmqtt_userdata *mud = arg; if(mud == NULL) return; if(!mud->connected) @@ -756,7 +701,7 @@ static void mqtt_socket_sent(void *arg) try_send = 0; } if (try_send) { - mqtt_send_if_possible(mud->pesp_conn); + mqtt_send_if_possible(mud); } NODE_DBG("sent2, queue size: %d\n", msg_size(&(mud->mqtt_state.pending_msg_q))); NODE_DBG("leave mqtt_socket_sent.\n"); @@ -765,12 +710,10 @@ static void mqtt_socket_sent(void *arg) static void mqtt_socket_connected(void *arg) { NODE_DBG("enter mqtt_socket_connected.\n"); - struct espconn *pesp_conn = arg; - if(pesp_conn == NULL) - return; - lmqtt_userdata *mud = (lmqtt_userdata *)pesp_conn->reverse; + lmqtt_userdata *mud = arg; if(mud == NULL) return; + struct espconn *pesp_conn = &mud->pesp_conn; mud->connected = true; espconn_regist_recvcb(pesp_conn, mqtt_socket_received); espconn_regist_sentcb(pesp_conn, mqtt_socket_sent); @@ -809,8 +752,9 @@ void mqtt_socket_timer(void *arg) if(mud == NULL) return; - if(mud->pesp_conn == NULL){ - NODE_DBG("mud->pesp_conn is NULL.\n"); + + if(mud->connected == 0){ + NODE_DBG("MQTT not connected\n"); os_timer_disarm(&mud->mqttTimer); return; } @@ -833,59 +777,31 @@ void mqtt_socket_timer(void *arg) if(mud->connState == MQTT_INIT){ // socket connect time out. NODE_DBG("Can not connect to broker.\n"); os_timer_disarm(&mud->mqttTimer); + mqtt_socket_do_disconnect(mud); mqtt_connack_fail(mud, MQTT_CONN_FAIL_SERVER_NOT_FOUND); -#ifdef CLIENT_SSL_ENABLE - if(mud->secure) - { - espconn_secure_disconnect(mud->pesp_conn); - } - else -#endif - { - espconn_disconnect(mud->pesp_conn); - } } else if(mud->connState == MQTT_CONNECT_SENDING){ // MQTT_CONNECT send time out. NODE_DBG("sSend MQTT_CONNECT failed.\n"); mud->connState = MQTT_INIT; + mqtt_socket_do_disconnect(mud); mqtt_connack_fail(mud, MQTT_CONN_FAIL_TIMEOUT_SENDING); -#ifdef CLIENT_SSL_ENABLE - if(mud->secure) - { - espconn_secure_disconnect(mud->pesp_conn); - } - else -#endif - { - espconn_disconnect(mud->pesp_conn); - } mud->keep_alive_tick = 0; // not need count anymore } else if(mud->connState == MQTT_CONNECT_SENT) { // wait for CONACK time out. NODE_DBG("MQTT_CONNECT timeout.\n"); mud->connState = MQTT_INIT; - -#ifdef CLIENT_SSL_ENABLE - if(mud->secure) - { - espconn_secure_disconnect(mud->pesp_conn); - } - else -#endif - { - espconn_disconnect(mud->pesp_conn); - } + mqtt_socket_do_disconnect(mud); mqtt_connack_fail(mud, MQTT_CONN_FAIL_TIMEOUT_RECEIVING); } else if(mud->connState == MQTT_DATA){ msg_queue_t *pending_msg = msg_peek(&(mud->mqtt_state.pending_msg_q)); if(pending_msg){ - mqtt_send_if_possible(mud->pesp_conn); + mqtt_send_if_possible(mud); } else { // no queued event. mud->keep_alive_tick ++; if(mud->keep_alive_tick > mud->connect_info.keepalive){ if (mud->keepalive_sent) { // Oh dear -- keepalive timer expired and still no ack of previous message - mqtt_socket_reconnected(mud->pesp_conn, 0); + mqtt_socket_reconnected(&mud->pesp_conn, 0); } else { uint8_t temp_buffer[MQTT_BUF_SIZE]; mqtt_message_buffer_t msgb; @@ -897,7 +813,7 @@ void mqtt_socket_timer(void *arg) 0, MQTT_MSG_TYPE_PINGREQ, (int)mqtt_get_qos(temp_msg->data) ); mud->keepalive_sent = 1; mud->keep_alive_tick = 0; // Need to reset to zero in case flow control stopped. - mqtt_send_if_possible(mud->pesp_conn); + mqtt_send_if_possible(mud); } } } @@ -1062,14 +978,10 @@ static int mqtt_delete( lua_State* L ) mud->connected = false; // ---- alloc-ed in mqtt_socket_connect() - if(mud->pesp_conn){ // for client connected to tcp server, this should set NULL in disconnect cb - mud->pesp_conn->reverse = NULL; - if(mud->pesp_conn->proto.tcp) - free(mud->pesp_conn->proto.tcp); - mud->pesp_conn->proto.tcp = NULL; - free(mud->pesp_conn); - mud->pesp_conn = NULL; // for socket, it will free this when disconnected - } + if(mud->pesp_conn.proto.tcp) + free(mud->pesp_conn.proto.tcp); + mud->pesp_conn.proto.tcp = NULL; + while(mud->mqtt_state.pending_msg_q) { msg_destroy(msg_dequeue(&(mud->mqtt_state.pending_msg_q))); } @@ -1133,30 +1045,23 @@ static int mqtt_delete( lua_State* L ) return 0; } -static sint8 socket_connect(struct espconn *pesp_conn) +static sint8 mqtt_socket_do_connect(struct lmqtt_userdata *mud) { NODE_DBG("enter socket_connect.\n"); - sint8 espconn_status; - if(pesp_conn == NULL) - return ESPCONN_CONN; - lmqtt_userdata *mud = (lmqtt_userdata *)pesp_conn->reverse; - if(mud == NULL) - return ESPCONN_ARG; - mud->event_timeout = MQTT_CONNECT_TIMEOUT; mud->connState = MQTT_INIT; #ifdef CLIENT_SSL_ENABLE if(mud->secure) { - espconn_status = espconn_secure_connect(pesp_conn); + espconn_status = espconn_secure_connect(&mud->pesp_conn); } else #endif { - espconn_status = espconn_connect(pesp_conn); + espconn_status = espconn_connect(&mud->pesp_conn); } os_timer_arm(&mud->mqttTimer, 1000, 1); @@ -1172,11 +1077,6 @@ static sint8 socket_dns_found(const char *name, ip_addr_t *ipaddr, void *arg) NODE_DBG("enter socket_dns_found.\n"); sint8 espconn_status = ESPCONN_OK; - struct espconn *pesp_conn = mud->pesp_conn; - if(pesp_conn == NULL){ - NODE_DBG("pesp_conn null.\n"); - return -1; - } if(ipaddr == NULL) { @@ -1190,11 +1090,11 @@ static sint8 socket_dns_found(const char *name, ip_addr_t *ipaddr, void *arg) // ipaddr->addr is a uint32_t ip if(ipaddr->addr != 0) { - memcpy(pesp_conn->proto.tcp->remote_ip, &(ipaddr->addr), 4); + memcpy(&mud->pesp_conn.proto.tcp->remote_ip, &(ipaddr->addr), 4); NODE_DBG("TCP ip is set: "); NODE_DBG(IPSTR, IP2STR(&(ipaddr->addr))); NODE_DBG("\n"); - espconn_status = socket_connect(pesp_conn); + espconn_status = mqtt_socket_do_connect(mud); } NODE_DBG("leave socket_dns_found.\n"); @@ -1232,24 +1132,16 @@ static int mqtt_socket_connect( lua_State* L ) return luaL_error(L, "already connected"); } - struct espconn *pesp_conn = mud->pesp_conn; - if(!pesp_conn) { - pesp_conn = mud->pesp_conn = (struct espconn *)calloc(1,sizeof(struct espconn)); - } else { - espconn_delete(pesp_conn); - } + struct espconn *pesp_conn = &mud->pesp_conn; - if(!pesp_conn) - return luaL_error(L, "not enough memory"); if (!pesp_conn->proto.tcp) pesp_conn->proto.tcp = (esp_tcp *)calloc(1,sizeof(esp_tcp)); - if(!pesp_conn->proto.tcp){ - free(pesp_conn); - pesp_conn = mud->pesp_conn = NULL; + + if(!pesp_conn->proto.tcp) { return luaL_error(L, "not enough memory"); } + // reverse is for the callback function - pesp_conn->reverse = mud; pesp_conn->type = ESPCONN_TCP; pesp_conn->state = ESPCONN_NONE; mud->connected = false; @@ -1350,7 +1242,7 @@ static int mqtt_socket_connect( lua_State* L ) } else { - socket_connect(pesp_conn); + mqtt_socket_do_connect(mud); } NODE_DBG("leave mqtt_socket_connect.\n"); @@ -1368,7 +1260,7 @@ static int mqtt_socket_close( lua_State* L ) mud = (lmqtt_userdata *)luaL_checkudata(L, 1, "mqtt.socket"); luaL_argcheck(L, mud, 1, "mqtt.socket expected"); - if (mud == NULL || mud->pesp_conn == NULL) { + if (mud == NULL) { lua_pushboolean(L, 0); return 1; } @@ -1385,15 +1277,15 @@ static int mqtt_socket_close( lua_State* L ) #ifdef CLIENT_SSL_ENABLE if(mud->secure) { - espconn_status = espconn_secure_send(mud->pesp_conn, temp_msg->data, temp_msg->length); - if(mud->pesp_conn->proto.tcp->remote_port || mud->pesp_conn->proto.tcp->local_port) - espconn_status |= espconn_secure_disconnect(mud->pesp_conn); + espconn_status = espconn_secure_send(&mud->pesp_conn, temp_msg->data, temp_msg->length); + if(mud->pesp_conn.proto.tcp->remote_port || mud->pesp_conn.proto.tcp->local_port) + espconn_status |= espconn_secure_disconnect(&mud->pesp_conn); } else #endif { - espconn_status = espconn_send(mud->pesp_conn, temp_msg->data, temp_msg->length); - if(mud->pesp_conn->proto.tcp->remote_port || mud->pesp_conn->proto.tcp->local_port) - espconn_status |= espconn_disconnect(mud->pesp_conn); + espconn_status = espconn_send(&mud->pesp_conn, temp_msg->data, temp_msg->length); + if(mud->pesp_conn.proto.tcp->remote_port || mud->pesp_conn.proto.tcp->local_port) + espconn_status |= espconn_disconnect(&mud->pesp_conn); } } mud->connected = 0; @@ -1485,12 +1377,6 @@ static int mqtt_socket_unsubscribe( lua_State* L ) { return 1; } - if(mud->pesp_conn == NULL){ - NODE_DBG("mud->pesp_conn is NULL.\n"); - lua_pushboolean(L, 0); - return 1; - } - if(!mud->connected){ luaL_error( L, "not connected" ); lua_pushboolean(L, 0); @@ -1568,7 +1454,7 @@ static int mqtt_socket_unsubscribe( lua_State* L ) { sint8 espconn_status = ESPCONN_IF; - espconn_status = mqtt_send_if_possible(mud->pesp_conn); + espconn_status = mqtt_send_if_possible(mud); if(!node || espconn_status != ESPCONN_OK){ lua_pushboolean(L, 0); @@ -1600,12 +1486,6 @@ static int mqtt_socket_subscribe( lua_State* L ) { return 1; } - if(mud->pesp_conn == NULL){ - NODE_DBG("mud->pesp_conn is NULL.\n"); - lua_pushboolean(L, 0); - return 1; - } - if(!mud->connected){ luaL_error( L, "not connected" ); lua_pushboolean(L, 0); @@ -1686,7 +1566,7 @@ static int mqtt_socket_subscribe( lua_State* L ) { sint8 espconn_status = ESPCONN_IF; - espconn_status = mqtt_send_if_possible(mud->pesp_conn); + espconn_status = mqtt_send_if_possible(mud); if(!node || espconn_status != ESPCONN_OK){ lua_pushboolean(L, 0); @@ -1702,7 +1582,6 @@ static int mqtt_socket_subscribe( lua_State* L ) { static int mqtt_socket_publish( lua_State* L ) { NODE_DBG("enter mqtt_socket_publish.\n"); - struct espconn *pesp_conn = NULL; lmqtt_userdata *mud; size_t l; uint8_t stack = 1; @@ -1717,12 +1596,6 @@ static int mqtt_socket_publish( lua_State* L ) return 1; } - if(mud->pesp_conn == NULL){ - NODE_DBG("mud->pesp_conn is NULL.\n"); - lua_pushboolean(L, 0); - return 1; - } - if(!mud->connected){ return luaL_error( L, "not connected" ); } @@ -1763,7 +1636,7 @@ static int mqtt_socket_publish( lua_State* L ) sint8 espconn_status = ESPCONN_OK; - espconn_status = mqtt_send_if_possible(mud->pesp_conn); + espconn_status = mqtt_send_if_possible(mud); if(!node || espconn_status != ESPCONN_OK){ lua_pushboolean(L, 0); From 5026516b0f3dd6fab897101841ebe30f4456db01 Mon Sep 17 00:00:00 2001 From: Nathaniel Wesley Filardo Date: Sun, 23 Feb 2020 06:15:29 +0000 Subject: [PATCH 16/17] mqtt: note bug --- app/modules/mqtt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/app/modules/mqtt.c b/app/modules/mqtt.c index 50738bd85b..0d6766999b 100644 --- a/app/modules/mqtt.c +++ b/app/modules/mqtt.c @@ -1275,6 +1275,7 @@ static int mqtt_socket_close( lua_State* L ) mqtt_message_t* temp_msg = mqtt_msg_disconnect(&msgb); NODE_DBG("Send MQTT disconnect infomation, data len: %d, d[0]=%d \r\n", temp_msg->length, temp_msg->data[0]); + /* XXX This fails to actually send the disconnect message before hanging up */ #ifdef CLIENT_SSL_ENABLE if(mud->secure) { espconn_status = espconn_secure_send(&mud->pesp_conn, temp_msg->data, temp_msg->length); From 493b789c87927358034c73267baa625996c0a5a6 Mon Sep 17 00:00:00 2001 From: Nathaniel Wesley Filardo Date: Sun, 2 Feb 2020 15:04:22 +0000 Subject: [PATCH 17/17] mqtt: doc fixes --- docs/modules/mqtt.md | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/docs/modules/mqtt.md b/docs/modules/mqtt.md index 0163ee1a72..289550c7bb 100644 --- a/docs/modules/mqtt.md +++ b/docs/modules/mqtt.md @@ -191,17 +191,24 @@ use the *boolean* `false` or `true` instead. ## mqtt.client:lwt() -Setup [Last Will and Testament](http://www.hivemq.com/blog/mqtt-essentials-part-9-last-will-and-testament) (optional). A broker will publish a message with qos = 0, retain = 0, data = "offline" to topic "/lwt" if client does not send keepalive packet. +Setup [Last Will and Testament](http://www.hivemq.com/blog/mqtt-essentials-part-9-last-will-and-testament). As the last will is sent to the broker when connecting, `lwt()` must be called BEFORE calling `connect()`.   -The broker will publish a client's last will message once he NOTICES that the connection to the client is broken. The broker will notice this when: +The broker will publish a client's last will message once it notices that the connection to the client is broken; that occurs when...  - The client fails to send a keepalive packet for as long as specified in `mqtt.Client()` -  - The tcp-connection is properly closed (without closing the mqtt-connection before) - - The broker tries to send data to the client and fails to do so, because the tcp-connection is not longer open. +  - The TCP connection is properly closed (without closing the mqtt-connection before) + - The broker tries to send data to the client and the TCP connection breaks. This means if you specified 120 as keepalive timer, just turn off the client device and the broker does not send any data to the client, the last will message will be published 120s after turning off the device. +!!! note + + There is at present a bug in the NodeMCU MQTT library that results in all disconnections + appearing as unexpected disconnects -- the MQTT-level disconnection message is not set + before the TCP connection is torn down. As a result, LWT messages will almost always be + published. See https://github.com/nodemcu/nodemcu-firmware/issues/3031 + #### Syntax `mqtt:lwt(topic, message[, qos[, retain]])`