1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-07-07 06:01:35 +03:00

move lwIP source to sdk and add a build hook instead of variant

This commit is contained in:
Me No Dev
2016-04-10 23:57:26 +03:00
parent 589b86b9bf
commit 0addae0084
105 changed files with 20 additions and 126 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,134 @@
/******************************************************************************
* 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);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,423 @@
/******************************************************************************
* 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 (1470 < length) {
datalen = 1470;
} 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 (1470 < length) {
datalen = 1470;
} 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(&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_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;
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, (char *)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;
}
}
/******************************************************************************
* 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;
}

View File

@ -0,0 +1,369 @@
/**
* @file
* MetIO Server
*
*/
/*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
*/
#include "lwip/opt.h"
#if LWIP_TCP
#include "lwip/tcp.h"
#ifdef MEMLEAK_DEBUG
static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
#endif
/*
* This implements a netio server.
* The client sends a command word (4 bytes) then a data length word (4 bytes).
* If the command is "receive", the server is to consume "data length" bytes into
* a circular buffer until the first byte is non-zero, then it is to consume
* another command/data pair.
* If the command is "send", the server is to send "data length" bytes from a circular
* buffer with the first byte being zero, until "some time" (6 seconds in the
* current netio126.zip download) has passed and then send one final buffer with
* the first byte being non-zero. Then it is to consume another command/data pair.
*/
/* See http://www.nwlab.net/art/netio/netio.html to get the netio tool */
/* implementation options */
#define NETIO_BUF_SIZE (4 * 1024)
#define NETIO_USE_STATIC_BUF 0
/* NetIO server state definition */
#define NETIO_STATE_WAIT_FOR_CMD 0
#define NETIO_STATE_RECV_DATA 1
#define NETIO_STATE_SEND_DATA 2
#define NETIO_STATE_SEND_DATA_LAST 3
#define NETIO_STATE_DONE 4
struct netio_state {
u32_t state;
u32_t cmd;
u32_t data_len;
u32_t cntr;
u8_t * buf_ptr;
u32_t buf_pos;
u32_t first_byte;
u32_t time_stamp;
};
/* NetIO command protocol definition */
#define NETIO_CMD_QUIT 0
#define NETIO_CMD_C2S 1
#define NETIO_CMD_S2C 2
#define NETIO_CMD_RES 3
static err_t netio_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err);
static void ICACHE_FLASH_ATTR
netio_close(void *arg, struct tcp_pcb *pcb)
{
err_t err;
struct netio_state *ns = arg;
ns->state = NETIO_STATE_DONE;
tcp_recv(pcb, NULL);
err = tcp_close(pcb);
if (err != ERR_OK) {
/* closing failed, try again later */
tcp_recv(pcb, netio_recv);
} else {
/* closing succeeded */
#if NETIO_USE_STATIC_BUF != 1
if(ns->buf_ptr != NULL){
mem_free(ns->buf_ptr);
}
#endif
tcp_arg(pcb, NULL);
tcp_poll(pcb, NULL, 0);
tcp_sent(pcb, NULL);
if (arg != NULL) {
mem_free(arg);
}
}
}
static err_t ICACHE_FLASH_ATTR
netio_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
{
struct netio_state *ns = arg;
u8_t * data_ptr;
u32_t data_cntr;
struct pbuf *q = p;
u16_t len;
if (p != NULL) {
tcp_recved(pcb, p->tot_len);
}
if (err == ERR_OK && q != NULL) {
while (q != NULL) {
data_cntr = q->len;
data_ptr = q->payload;
while (data_cntr--) {
if (ns->state == NETIO_STATE_DONE){
netio_close(ns, pcb);
break;
} else if (ns->state == NETIO_STATE_WAIT_FOR_CMD) {
if (ns->cntr < 4) {
/* build up the CMD field */
ns->cmd <<= 8;
ns->cmd |= *data_ptr++;
ns->cntr++;
} else if (ns->cntr < 8) {
/* build up the DATA field */
ns->data_len <<= 8;
ns->data_len |= *data_ptr++;
ns->cntr++;
if (ns->cntr == 8) {
/* now we have full command and data words */
ns->cntr = 0;
ns->buf_pos = 0;
ns->buf_ptr[0] = 0;
if (ns->cmd == NETIO_CMD_C2S) {
ns->state = NETIO_STATE_RECV_DATA;
} else if (ns->cmd == NETIO_CMD_S2C) {
ns->state = NETIO_STATE_SEND_DATA;
/* start timer */
ns->time_stamp = sys_now();
/* send first round of data */
len = tcp_sndbuf(pcb);
len = LWIP_MIN(len, ns->data_len - ns->cntr);
len = LWIP_MIN(len, NETIO_BUF_SIZE - ns->buf_pos);
do {
err = tcp_write(pcb, ns->buf_ptr + ns->buf_pos, len, TCP_WRITE_FLAG_COPY);
if (err == ERR_MEM) {
len /= 2;
}
} while ((err == ERR_MEM) && (len > 1));
ns->buf_pos += len;
ns->cntr += len;
} else {
/* unrecognized command, punt */
ns->cntr = 0;
ns->buf_pos = 0;
ns->buf_ptr[0] = 0;
netio_close(ns, pcb);
break;
}
}
} else {
/* in trouble... shouldn't be in this state! */
}
} else if (ns->state == NETIO_STATE_RECV_DATA) {
if(ns->cntr == 0){
/* save the first byte of this new round of data
* this will not match ns->buf_ptr[0] in the case that
* NETIO_BUF_SIZE is less than ns->data_len.
*/
ns->first_byte = *data_ptr;
}
ns->buf_ptr[ns->buf_pos++] = *data_ptr++;
ns->cntr++;
if (ns->buf_pos == NETIO_BUF_SIZE) {
/* circularize the buffer */
ns->buf_pos = 0;
}
if(ns->cntr == ns->data_len){
ns->cntr = 0;
if (ns->first_byte != 0) {
/* if this last round did not start with 0,
* go look for another command */
ns->state = NETIO_STATE_WAIT_FOR_CMD;
ns->data_len = 0;
ns->cmd = 0;
/* TODO LWIP_DEBUGF( print out some throughput calculation results... ); */
} else {
/* stay here and wait on more data */
}
}
} else if (ns->state == NETIO_STATE_SEND_DATA
|| ns->state == NETIO_STATE_SEND_DATA_LAST) {
/* I don't think this should happen... */
} else {
/* done / quit */
netio_close(ns, pcb);
break;
} /* end of ns->state condition */
} /* end of while data still in this pbuf */
q = q->next;
}
pbuf_free(p);
} else {
/* error or closed by other side */
if (p != NULL) {
pbuf_free(p);
}
/* close the connection */
netio_close(ns, pcb);
}
return ERR_OK;
}
static err_t ICACHE_FLASH_ATTR
netio_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
{
struct netio_state *ns = arg;
err_t err = ERR_OK;
if (ns->cntr >= ns->data_len && ns->state == NETIO_STATE_SEND_DATA) {
/* done with this round of sending */
ns->buf_pos = 0;
ns->cntr = 0;
/* check if timer expired */
if (sys_now() - ns->time_stamp > 600) {
ns->buf_ptr[0] = 1;
ns->state = NETIO_STATE_SEND_DATA_LAST;
} else {
ns->buf_ptr[0] = 0;
}
}
if(ns->state == NETIO_STATE_SEND_DATA_LAST || ns->state == NETIO_STATE_SEND_DATA){
len = tcp_sndbuf(pcb);
len = LWIP_MIN(len, ns->data_len - ns->cntr);
len = LWIP_MIN(len, NETIO_BUF_SIZE - ns->buf_pos);
if(ns->cntr < ns->data_len){
do {
err = tcp_write(pcb, ns->buf_ptr + ns->buf_pos, len, TCP_WRITE_FLAG_COPY);
if (err == ERR_MEM) {
len /= 2;
}
} while ((err == ERR_MEM) && (len > 1));
ns->buf_pos += len;
if(ns->buf_pos >= NETIO_BUF_SIZE){
ns->buf_pos = 0;
}
ns->cntr += len;
}
}
if(ns->cntr >= ns->data_len && ns->state == NETIO_STATE_SEND_DATA_LAST){
/* we have buffered up all our data to send this last round, go look for a command */
ns->state = NETIO_STATE_WAIT_FOR_CMD;
ns->cntr = 0;
/* TODO LWIP_DEBUGF( print out some throughput calculation results... ); */
}
return ERR_OK;
}
static err_t ICACHE_FLASH_ATTR
netio_poll(void *arg, struct tcp_pcb *pcb)
{
struct netio_state * ns = arg;
if(ns->state == NETIO_STATE_SEND_DATA){
} else if(ns->state == NETIO_STATE_DONE){
netio_close(ns, pcb);
}
return ERR_OK;
}
#if NETIO_USE_STATIC_BUF == 1
static u8_t netio_buf[NETIO_BUF_SIZE];
#endif
static err_t ICACHE_FLASH_ATTR
netio_accept(void *arg, struct tcp_pcb *pcb, err_t err)
{
struct netio_state * ns;
LWIP_UNUSED_ARG(err);
ns = (struct netio_state *)mem_malloc(sizeof(struct netio_state));
if(ns == NULL){
return ERR_MEM;
}
ns->state = NETIO_STATE_WAIT_FOR_CMD;
ns->data_len = 0;
ns->cmd = 0;
ns->cntr = 0;
ns->buf_pos = 0;
#if NETIO_USE_STATIC_BUF == 1
ns->buf_ptr = netio_buf;
#else
ns->buf_ptr = (u8_t *)mem_malloc(NETIO_BUF_SIZE);
if(ns->buf_ptr == NULL){
mem_free(ns);
return ERR_MEM;
}
#endif
ns->buf_ptr[0] = 0;
tcp_arg(pcb, ns);
tcp_sent(pcb, netio_sent);
tcp_recv(pcb, netio_recv);
tcp_poll(pcb, netio_poll, 4); /* every 2 seconds */
return ERR_OK;
}
void ICACHE_FLASH_ATTR netio_init(void)
{
struct tcp_pcb *pcb;
pcb = tcp_new();
tcp_bind(pcb, IP_ADDR_ANY, 18767);
pcb = tcp_listen(pcb);
tcp_accept(pcb, netio_accept);
}
#endif /* LWIP_TCP */

View File

@ -0,0 +1,329 @@
/**
* @file
* Ping sender module
*
*/
/*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
*/
/**
* This is an example of a "ping" sender (with raw API and socket API).
* It can be used as a start point to maintain opened a network connection, or
* like a network "watchdog" for your device.
*
*/
/*
* copyright (c) 2010 - 2011 Espressif System
*/
#include "lwip/opt.h"
#if LWIP_RAW /* don't build if not configured for use in lwipopts.h */
#include "lwip/mem.h"
#include "lwip/raw.h"
#include "lwip/icmp.h"
#include "lwip/netif.h"
#include "lwip/sys.h"
#include "lwip/timers.h"
#include "lwip/inet_chksum.h"
#include "os_type.h"
#include "osapi.h"
#include "lwip/app/ping.h"
#if PING_USE_SOCKETS
#include "lwip/sockets.h"
#include "lwip/inet.h"
#endif /* PING_USE_SOCKETS */
#ifdef MEMLEAK_DEBUG
static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
#endif
/* ping variables */
static u16_t ping_seq_num = 0;
static u32_t ping_time;
static void ICACHE_FLASH_ATTR ping_timeout(void* arg)
{
struct ping_msg *pingmsg = (struct ping_msg *)arg;
pingmsg->timeout_count ++;
if (pingmsg->ping_opt->recv_function == NULL){
os_printf("ping timeout\n");
} else {
struct ping_resp pingresp;
os_bzero(&pingresp, sizeof(struct ping_resp));
pingresp.ping_err = -1;
pingmsg->ping_opt->recv_function(pingmsg->ping_opt, (void*)&pingresp);
}
}
/** Prepare a echo ICMP request */
static void ICACHE_FLASH_ATTR
ping_prepare_echo( struct icmp_echo_hdr *iecho, u16_t len)
{
size_t i = 0;
size_t data_len = len - sizeof(struct icmp_echo_hdr);
ICMPH_TYPE_SET(iecho, ICMP_ECHO);
ICMPH_CODE_SET(iecho, 0);
iecho->chksum = 0;
iecho->id = PING_ID;
++ ping_seq_num;
if (ping_seq_num == 0x7fff)
ping_seq_num = 0;
iecho->seqno = htons(ping_seq_num);
/* fill the additional data buffer with some data */
for(i = 0; i < data_len; i++) {
((char*)iecho)[sizeof(struct icmp_echo_hdr) + i] = (char)i;
}
iecho->chksum = inet_chksum(iecho, len);
}
/*
static void ICACHE_FLASH_ATTR
ping_prepare_er(struct icmp_echo_hdr *iecho, u16_t len)
{
ICMPH_TYPE_SET(iecho, ICMP_ER);
ICMPH_CODE_SET(iecho, 0);
iecho->chksum = 0;
iecho->chksum = inet_chksum(iecho, len);
}
*/
/* Ping using the raw ip */
static u8_t ICACHE_FLASH_ATTR
ping_recv(void *arg, struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *addr)
{
struct icmp_echo_hdr *iecho = NULL;
static u16_t seqno = 0;
struct ping_msg *pingmsg = (struct ping_msg*)arg;
LWIP_UNUSED_ARG(arg);
LWIP_UNUSED_ARG(pcb);
LWIP_UNUSED_ARG(addr);
LWIP_ASSERT("p != NULL", p != NULL);
if (pbuf_header( p, -PBUF_IP_HLEN)==0) {
iecho = (struct icmp_echo_hdr *)p->payload;
if ((iecho->id == PING_ID) && (iecho->seqno == htons(ping_seq_num)) && iecho->type == ICMP_ER) {
LWIP_DEBUGF( PING_DEBUG, ("ping: recv "));
ip_addr_debug_print(PING_DEBUG, addr);
LWIP_DEBUGF( PING_DEBUG, (" %"U32_F" ms\n", (sys_now()-ping_time)));
if (iecho->seqno != seqno){
/* do some ping result processing */
{
struct ip_hdr *iphdr = NULL;
char ipaddrstr[16];
ip_addr_t source_ip;
sys_untimeout(ping_timeout, pingmsg);
os_bzero(&source_ip, sizeof(ip_addr_t));
os_bzero(ipaddrstr, sizeof(ipaddrstr));
uint32 delay = system_relative_time(pingmsg->ping_sent);
delay /= PING_COARSE;
iphdr = (struct ip_hdr*)((u8*)iecho - PBUF_IP_HLEN);
source_ip.addr = iphdr->src.addr;
ipaddr_ntoa_r(&source_ip,ipaddrstr, sizeof(ipaddrstr));
if (pingmsg->ping_opt->recv_function == NULL){
os_printf("recv %s: byte = %d, time = %d ms, seq = %d\n",ipaddrstr, PING_DATA_SIZE, delay, ntohs(iecho->seqno));
} else {
struct ping_resp pingresp;
os_bzero(&pingresp, sizeof(struct ping_resp));
pingresp.bytes = PING_DATA_SIZE;
pingresp.resp_time = delay;
pingresp.seqno = ntohs(iecho->seqno);
pingresp.ping_err = 0;
pingmsg->ping_opt->recv_function(pingmsg->ping_opt,(void*) &pingresp);
}
}
seqno = iecho->seqno;
}
PING_RESULT(1);
pbuf_free(p);
return 1; /* eat the packet */
}
// } else if(iecho->type == ICMP_ECHO){
// struct pbuf *q = NULL;
// os_printf("receive ping request:seq=%d\n", ntohs(iecho->seqno));
// q = pbuf_alloc(PBUF_IP, (u16_t)p->tot_len, PBUF_RAM);
// if (q!=NULL) {
// pbuf_copy(q, p);
// iecho = (struct icmp_echo_hdr *)q->payload;
// ping_prepare_er(iecho, q->tot_len);
// raw_sendto(pcb, q, addr);
// pbuf_free(q);
// }
// pbuf_free(p);
// return 1;
// }
}
return 0; /* don't eat the packet */
}
static void ICACHE_FLASH_ATTR
ping_send(struct raw_pcb *raw, ip_addr_t *addr)
{
struct pbuf *p = NULL;
struct icmp_echo_hdr *iecho = NULL;
size_t ping_size = sizeof(struct icmp_echo_hdr) + PING_DATA_SIZE;
LWIP_DEBUGF( PING_DEBUG, ("ping: send "));
ip_addr_debug_print(PING_DEBUG, addr);
LWIP_DEBUGF( PING_DEBUG, ("\n"));
LWIP_ASSERT("ping_size <= 0xffff", ping_size <= 0xffff);
p = pbuf_alloc(PBUF_IP, (u16_t)ping_size, PBUF_RAM);
if (!p) {
return;
}
if ((p->len == p->tot_len) && (p->next == NULL)) {
iecho = (struct icmp_echo_hdr *)p->payload;
ping_prepare_echo(iecho, (u16_t)ping_size);
raw_sendto(raw, p, addr);
ping_time = sys_now();
}
pbuf_free(p);
}
static void ICACHE_FLASH_ATTR
ping_coarse_tmr(void *arg)
{
struct ping_msg *pingmsg = (struct ping_msg*)arg;
struct ping_option *ping_opt= NULL;
struct ping_resp pingresp;
ip_addr_t ping_target;
LWIP_ASSERT("ping_timeout: no pcb given!", pingmsg != NULL);
ping_target.addr = pingmsg->ping_opt->ip;
ping_opt = pingmsg->ping_opt;
if (--pingmsg->sent_count != 0){
pingmsg ->ping_sent = system_get_time();
ping_send(pingmsg->ping_pcb, &ping_target);
sys_timeout(PING_TIMEOUT_MS, ping_timeout, pingmsg);
sys_timeout(pingmsg->coarse_time, ping_coarse_tmr, pingmsg);
} else {
uint32 delay = system_relative_time(pingmsg->ping_start);
delay /= PING_COARSE;
// ping_seq_num = 0;
if (ping_opt->sent_function == NULL){
os_printf("ping %d, timeout %d, total payload %d bytes, %d ms\n",
pingmsg->max_count, pingmsg->timeout_count, PING_DATA_SIZE*(pingmsg->max_count - pingmsg->timeout_count),delay);
} else {
os_bzero(&pingresp, sizeof(struct ping_resp));
pingresp.total_count = pingmsg->max_count;
pingresp.timeout_count = pingmsg->timeout_count;
pingresp.total_bytes = PING_DATA_SIZE*(pingmsg->max_count - pingmsg->timeout_count);
pingresp.total_time = delay;
pingresp.ping_err = 0;
}
sys_untimeout(ping_coarse_tmr, pingmsg);
raw_remove(pingmsg->ping_pcb);
os_free(pingmsg);
if (ping_opt->sent_function != NULL)
ping_opt->sent_function(ping_opt,(uint8*)&pingresp);
}
}
static bool ICACHE_FLASH_ATTR
ping_raw_init(struct ping_msg *pingmsg)
{
if (pingmsg == NULL)
return false;
ip_addr_t ping_target;
pingmsg->ping_pcb = raw_new(IP_PROTO_ICMP);
LWIP_ASSERT("ping_pcb != NULL", pingmsg->ping_pcb != NULL);
raw_recv(pingmsg->ping_pcb, ping_recv, pingmsg);
raw_bind(pingmsg->ping_pcb, IP_ADDR_ANY);
ping_target.addr = pingmsg->ping_opt->ip;
pingmsg ->ping_sent = system_get_time();
ping_send(pingmsg->ping_pcb, &ping_target);
sys_timeout(PING_TIMEOUT_MS, ping_timeout, pingmsg);
sys_timeout(pingmsg->coarse_time, ping_coarse_tmr, pingmsg);
return true;
}
bool ICACHE_FLASH_ATTR
ping_start(struct ping_option *ping_opt)
{
struct ping_msg *pingmsg = NULL;
pingmsg = (struct ping_msg *)os_zalloc(sizeof(struct ping_msg));
if (pingmsg == NULL || ping_opt == NULL)
return false;
pingmsg->ping_opt = ping_opt;
if (ping_opt->count != 0)
pingmsg->max_count = ping_opt->count;
else
pingmsg->max_count = DEFAULT_PING_MAX_COUNT;
if (ping_opt->coarse_time != 0)
pingmsg->coarse_time = ping_opt->coarse_time * PING_COARSE;
else
pingmsg->coarse_time = PING_COARSE;
pingmsg->ping_start = system_get_time();
pingmsg->sent_count = pingmsg->max_count;
return ping_raw_init(pingmsg);
}
bool ICACHE_FLASH_ATTR
ping_regist_recv(struct ping_option *ping_opt, ping_recv_function ping_recv)
{
if (ping_opt == NULL)
return false;
ping_opt ->recv_function = ping_recv;
return true;
}
bool ICACHE_FLASH_ATTR
ping_regist_sent(struct ping_option *ping_opt, ping_sent_function ping_sent)
{
if (ping_opt == NULL)
return false;
ping_opt ->sent_function = ping_sent;
return true;
}
#endif /* LWIP_RAW */