mirror of
https://github.com/nodemcu/nodemcu-firmware.git
synced 2025-01-30 21:12:55 +08:00
af426d0315
* 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. * 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. * espconn: remove scary global pktinfo A write-only global! How about that. * 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. * 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. * espconn_secure: more code removal * 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. * 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 * 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. * tls: add deprecation warnings * luacheck: net.ifinfo is a thing now * tls: remove use of espconn->reverse * 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. * mqtt: remove redundant pointer to connect_info Everywhere we have the mqtt_state_t we also have the lmqtt_userdata. * mqtt: doc fixes * mqtt: note bug * tls: allow :on(...,nil) to unregister a callback
389 lines
12 KiB
C
389 lines
12 KiB
C
/******************************************************************************
|
|
* Copyright 2013-2014 Espressif Systems (Wuxi)
|
|
*
|
|
* FileName: espconn_udp.c
|
|
*
|
|
* Description: udp proto interface
|
|
*
|
|
* Modification history:
|
|
* 2014/3/31, v1.0 create this file.
|
|
*******************************************************************************/
|
|
|
|
#include "ets_sys.h"
|
|
#include "os_type.h"
|
|
//#include "os.h"
|
|
|
|
#include "lwip/inet.h"
|
|
#include "lwip/err.h"
|
|
#include "lwip/pbuf.h"
|
|
#include "lwip/mem.h"
|
|
#include "lwip/tcp_impl.h"
|
|
#include "lwip/udp.h"
|
|
|
|
#include "lwip/app/espconn_udp.h"
|
|
|
|
#ifdef MEMLEAK_DEBUG
|
|
static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
|
|
#endif
|
|
|
|
extern espconn_msg *plink_active;
|
|
extern uint8 default_interface;
|
|
|
|
enum send_opt{
|
|
ESPCONN_SENDTO,
|
|
ESPCONN_SEND
|
|
};
|
|
static void ICACHE_FLASH_ATTR espconn_data_sentcb(struct espconn *pespconn)
|
|
{
|
|
if (pespconn == NULL) {
|
|
return;
|
|
}
|
|
|
|
if (pespconn->sent_callback != NULL) {
|
|
pespconn->sent_callback(pespconn);
|
|
}
|
|
}
|
|
|
|
static void ICACHE_FLASH_ATTR espconn_data_sent(void *arg, enum send_opt opt)
|
|
{
|
|
espconn_msg *psent = arg;
|
|
|
|
if (psent == NULL) {
|
|
return;
|
|
}
|
|
|
|
if (psent->pcommon.cntr == 0) {
|
|
psent->pespconn->state = ESPCONN_CONNECT;
|
|
if (psent->pcommon.err == 0)
|
|
espconn_data_sentcb(psent->pespconn);
|
|
} else {
|
|
if (opt == ESPCONN_SEND){
|
|
espconn_udp_sent(arg, psent->pcommon.ptrbuf, psent->pcommon.cntr);
|
|
} else {
|
|
espconn_udp_sendto(arg, psent->pcommon.ptrbuf, psent->pcommon.cntr);
|
|
}
|
|
}
|
|
}
|
|
|
|
/******************************************************************************
|
|
* FunctionName : espconn_udp_sent
|
|
* Description : sent data for client or server
|
|
* Parameters : void *arg -- client or server to send
|
|
* uint8* psent -- Data to send
|
|
* uint16 length -- Length of data to send
|
|
* Returns : return espconn error code.
|
|
* - ESPCONN_OK. Successful. No error occured.
|
|
* - ESPCONN_MEM. Out of memory.
|
|
* - ESPCONN_RTE. Could not find route to destination address.
|
|
* - More errors could be returned by lower protocol layers.
|
|
*******************************************************************************/
|
|
err_t ICACHE_FLASH_ATTR
|
|
espconn_udp_sent(void *arg, uint8 *psent, uint16 length)
|
|
{
|
|
espconn_msg *pudp_sent = arg;
|
|
struct udp_pcb *upcb = pudp_sent->pcommon.pcb;
|
|
struct pbuf *p, *q ,*p_temp;
|
|
u8_t *data = NULL;
|
|
u16_t cnt = 0;
|
|
u16_t datalen = 0;
|
|
u16_t i = 0;
|
|
err_t err;
|
|
LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %d %p\n", __LINE__, length, upcb));
|
|
|
|
if (pudp_sent == NULL || upcb == NULL || psent == NULL || length == 0) {
|
|
return ESPCONN_ARG;
|
|
}
|
|
|
|
if ((IP_FRAG_MAX_MTU - 20 - 8) < length) {
|
|
datalen = IP_FRAG_MAX_MTU - 20 - 8;
|
|
} else {
|
|
datalen = length;
|
|
}
|
|
|
|
p = pbuf_alloc(PBUF_TRANSPORT, datalen, PBUF_RAM);
|
|
LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %p\n", __LINE__, p));
|
|
|
|
if (p != NULL) {
|
|
q = p;
|
|
|
|
while (q != NULL) {
|
|
data = (u8_t *)q->payload;
|
|
LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %p\n", __LINE__, data));
|
|
|
|
for (i = 0; i < q->len; i++) {
|
|
data[i] = ((u8_t *) psent)[cnt++];
|
|
}
|
|
|
|
q = q->next;
|
|
}
|
|
} else {
|
|
return ESPCONN_MEM;
|
|
}
|
|
|
|
upcb->remote_port = pudp_sent->pespconn->proto.udp->remote_port;
|
|
IP4_ADDR(&upcb->remote_ip, pudp_sent->pespconn->proto.udp->remote_ip[0],
|
|
pudp_sent->pespconn->proto.udp->remote_ip[1],
|
|
pudp_sent->pespconn->proto.udp->remote_ip[2],
|
|
pudp_sent->pespconn->proto.udp->remote_ip[3]);
|
|
|
|
LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %x %d\n", __LINE__, upcb->remote_ip, upcb->remote_port));
|
|
|
|
struct netif *sta_netif = (struct netif *)eagle_lwip_getif(0x00);
|
|
struct netif *ap_netif = (struct netif *)eagle_lwip_getif(0x01);
|
|
|
|
if(wifi_get_opmode() == ESPCONN_AP_STA && default_interface == ESPCONN_AP_STA && sta_netif != NULL && ap_netif != NULL)
|
|
{
|
|
if(netif_is_up(sta_netif) && netif_is_up(ap_netif) && \
|
|
ip_addr_isbroadcast(&upcb->remote_ip, sta_netif) && \
|
|
ip_addr_isbroadcast(&upcb->remote_ip, ap_netif)) {
|
|
|
|
p_temp = pbuf_alloc(PBUF_TRANSPORT, datalen, PBUF_RAM);
|
|
if (pbuf_copy (p_temp,p) != ERR_OK) {
|
|
LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent: copying to new pbuf failed\n"));
|
|
return ESPCONN_ARG;
|
|
}
|
|
netif_set_default(sta_netif);
|
|
err = udp_send(upcb, p_temp);
|
|
pbuf_free(p_temp);
|
|
netif_set_default(ap_netif);
|
|
}
|
|
}
|
|
err = udp_send(upcb, p);
|
|
|
|
LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %d\n", __LINE__, err));
|
|
|
|
if (p->ref != 0) {
|
|
LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %p\n", __LINE__, p));
|
|
pbuf_free(p);
|
|
pudp_sent->pcommon.ptrbuf = psent + datalen;
|
|
pudp_sent->pcommon.cntr = length - datalen;
|
|
pudp_sent->pcommon.err = err;
|
|
espconn_data_sent(pudp_sent, ESPCONN_SEND);
|
|
if (err > 0)
|
|
return ESPCONN_IF;
|
|
return err;
|
|
} else {
|
|
pbuf_free(p);
|
|
return ESPCONN_RTE;
|
|
}
|
|
}
|
|
|
|
/******************************************************************************
|
|
* FunctionName : espconn_udp_sendto
|
|
* Description : sent data for UDP
|
|
* Parameters : void *arg -- UDP to send
|
|
* uint8* psent -- Data to send
|
|
* uint16 length -- Length of data to send
|
|
* Returns : return espconn error code.
|
|
* - ESPCONN_OK. Successful. No error occured.
|
|
* - ESPCONN_MEM. Out of memory.
|
|
* - ESPCONN_RTE. Could not find route to destination address.
|
|
* - More errors could be returned by lower protocol layers.
|
|
*******************************************************************************/
|
|
err_t ICACHE_FLASH_ATTR
|
|
espconn_udp_sendto(void *arg, uint8 *psent, uint16 length)
|
|
{
|
|
espconn_msg *pudp_sent = arg;
|
|
struct udp_pcb *upcb = pudp_sent->pcommon.pcb;
|
|
struct espconn *pespconn = pudp_sent->pespconn;
|
|
struct pbuf *p, *q ,*p_temp;
|
|
struct ip_addr dst_ip;
|
|
u16_t dst_port;
|
|
u8_t *data = NULL;
|
|
u16_t cnt = 0;
|
|
u16_t datalen = 0;
|
|
u16_t i = 0;
|
|
err_t err;
|
|
LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %d %p\n", __LINE__, length, upcb));
|
|
|
|
if (pudp_sent == NULL || upcb == NULL || psent == NULL || length == 0) {
|
|
return ESPCONN_ARG;
|
|
}
|
|
|
|
if ((IP_FRAG_MAX_MTU - 20 - 8) < length) {
|
|
datalen = IP_FRAG_MAX_MTU - 20 - 8;
|
|
} else {
|
|
datalen = length;
|
|
}
|
|
|
|
p = pbuf_alloc(PBUF_TRANSPORT, datalen, PBUF_RAM);
|
|
LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %p\n", __LINE__, p));
|
|
|
|
if (p != NULL) {
|
|
q = p;
|
|
|
|
while (q != NULL) {
|
|
data = (u8_t *)q->payload;
|
|
LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %p\n", __LINE__, data));
|
|
|
|
for (i = 0; i < q->len; i++) {
|
|
data[i] = ((u8_t *) psent)[cnt++];
|
|
}
|
|
|
|
q = q->next;
|
|
}
|
|
} else {
|
|
return ESPCONN_MEM;
|
|
}
|
|
|
|
dst_port = pespconn->proto.udp->remote_port;
|
|
IP4_ADDR(&dst_ip, pespconn->proto.udp->remote_ip[0],
|
|
pespconn->proto.udp->remote_ip[1], pespconn->proto.udp->remote_ip[2],
|
|
pespconn->proto.udp->remote_ip[3]);
|
|
LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %x %d\n", __LINE__, upcb->remote_ip, upcb->remote_port));
|
|
|
|
struct netif *sta_netif = (struct netif *)eagle_lwip_getif(0x00);
|
|
struct netif *ap_netif = (struct netif *)eagle_lwip_getif(0x01);
|
|
|
|
if(wifi_get_opmode() == ESPCONN_AP_STA && default_interface == ESPCONN_AP_STA && sta_netif != NULL && ap_netif != NULL)
|
|
{
|
|
if( netif_is_up(sta_netif) && \
|
|
netif_is_up(ap_netif) && \
|
|
ip_addr_isbroadcast(&dst_ip, sta_netif) && \
|
|
ip_addr_isbroadcast(&dst_ip, ap_netif)) {
|
|
|
|
p_temp = pbuf_alloc(PBUF_TRANSPORT, datalen, PBUF_RAM);
|
|
if (pbuf_copy (p_temp,p) != ERR_OK) {
|
|
LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sendto: copying to new pbuf failed\n"));
|
|
return ESPCONN_ARG;
|
|
}
|
|
netif_set_default(sta_netif);
|
|
err = udp_sendto(upcb, p_temp, &dst_ip, dst_port);
|
|
pbuf_free(p_temp);
|
|
netif_set_default(ap_netif);
|
|
}
|
|
}
|
|
err = udp_sendto(upcb, p, &dst_ip, dst_port);
|
|
|
|
if (p->ref != 0) {
|
|
pbuf_free(p);
|
|
pudp_sent->pcommon.ptrbuf = psent + datalen;
|
|
pudp_sent->pcommon.cntr = length - datalen;
|
|
pudp_sent->pcommon.err = err;
|
|
espconn_data_sent(pudp_sent, ESPCONN_SENDTO);
|
|
|
|
if (err > 0)
|
|
return ESPCONN_IF;
|
|
return err;
|
|
} else {
|
|
pbuf_free(p);
|
|
return ESPCONN_RTE;
|
|
}
|
|
}
|
|
|
|
/******************************************************************************
|
|
* FunctionName : espconn_udp_server_recv
|
|
* Description : This callback will be called when receiving a datagram.
|
|
* Parameters : arg -- user supplied argument
|
|
* upcb -- the udp_pcb which received data
|
|
* p -- the packet buffer that was received
|
|
* addr -- the remote IP address from which the packet was received
|
|
* port -- the remote port from which the packet was received
|
|
* Returns : none
|
|
*******************************************************************************/
|
|
static void ICACHE_FLASH_ATTR
|
|
espconn_udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p,
|
|
struct ip_addr *addr, u16_t port)
|
|
{
|
|
espconn_msg *precv = arg;
|
|
struct pbuf *q = NULL;
|
|
u8_t *pdata = NULL;
|
|
u16_t length = 0;
|
|
struct ip_info ipconfig;
|
|
|
|
LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_server_recv %d %p\n", __LINE__, upcb));
|
|
|
|
precv->pcommon.remote_ip[0] = ip4_addr1_16(addr);
|
|
precv->pcommon.remote_ip[1] = ip4_addr2_16(addr);
|
|
precv->pcommon.remote_ip[2] = ip4_addr3_16(addr);
|
|
precv->pcommon.remote_ip[3] = ip4_addr4_16(addr);
|
|
precv->pcommon.remote_port = port;
|
|
precv->pcommon.pcb = upcb;
|
|
|
|
if (wifi_get_opmode() != 1) {
|
|
wifi_get_ip_info(1, &ipconfig);
|
|
|
|
if (!ip_addr_netcmp(addr, &ipconfig.ip, &ipconfig.netmask)) {
|
|
wifi_get_ip_info(0, &ipconfig);
|
|
}
|
|
} else {
|
|
wifi_get_ip_info(0, &ipconfig);
|
|
}
|
|
|
|
precv->pespconn->proto.udp->local_ip[0] = ip4_addr1_16(&ipconfig.ip);
|
|
precv->pespconn->proto.udp->local_ip[1] = ip4_addr2_16(&ipconfig.ip);
|
|
precv->pespconn->proto.udp->local_ip[2] = ip4_addr3_16(&ipconfig.ip);
|
|
precv->pespconn->proto.udp->local_ip[3] = ip4_addr4_16(&ipconfig.ip);
|
|
|
|
if (p != NULL) {
|
|
pdata = (u8_t *)os_zalloc(p ->tot_len + 1);
|
|
length = pbuf_copy_partial(p, pdata, p ->tot_len, 0);
|
|
precv->pcommon.pcb = upcb;
|
|
pbuf_free(p);
|
|
if (length != 0) {
|
|
if (precv->pespconn->recv_callback != NULL) {
|
|
precv->pespconn->recv_callback(precv->pespconn, pdata, length);
|
|
}
|
|
}
|
|
os_free(pdata);
|
|
} else {
|
|
return;
|
|
}
|
|
}
|
|
|
|
/******************************************************************************
|
|
* FunctionName : espconn_udp_disconnect
|
|
* Description : A new incoming connection has been disconnected.
|
|
* Parameters : espconn -- the espconn used to disconnect with host
|
|
* Returns : none
|
|
*******************************************************************************/
|
|
void ICACHE_FLASH_ATTR espconn_udp_disconnect(espconn_msg *pdiscon)
|
|
{
|
|
if (pdiscon == NULL) {
|
|
return;
|
|
}
|
|
|
|
struct udp_pcb *upcb = pdiscon->pcommon.pcb;
|
|
|
|
udp_disconnect(upcb);
|
|
|
|
udp_remove(upcb);
|
|
|
|
espconn_list_delete(&plink_active, pdiscon);
|
|
|
|
os_free(pdiscon);
|
|
pdiscon = NULL;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* FunctionName : espconn_udp_server
|
|
* Description : Initialize the server: set up a PCB and bind it to the port
|
|
* Parameters : pespconn -- the espconn used to build server
|
|
* Returns : none
|
|
*******************************************************************************/
|
|
sint8 ICACHE_FLASH_ATTR
|
|
espconn_udp_server(struct espconn *pespconn)
|
|
{
|
|
struct udp_pcb *upcb = NULL;
|
|
espconn_msg *pserver = NULL;
|
|
upcb = udp_new();
|
|
|
|
if (upcb == NULL) {
|
|
return ESPCONN_MEM;
|
|
} else {
|
|
pserver = (espconn_msg *)os_zalloc(sizeof(espconn_msg));
|
|
|
|
if (pserver == NULL) {
|
|
udp_remove(upcb);
|
|
return ESPCONN_MEM;
|
|
}
|
|
|
|
pserver->pcommon.pcb = upcb;
|
|
pserver->pespconn = pespconn;
|
|
espconn_list_creat(&plink_active, pserver);
|
|
udp_bind(upcb, IP_ADDR_ANY, pserver->pespconn->proto.udp->local_port);
|
|
udp_recv(upcb, espconn_udp_recv, (void *)pserver);
|
|
return ESPCONN_OK;
|
|
}
|
|
}
|