Commit b96e3147 authored by Marcel Stör's avatar Marcel Stör Committed by GitHub
Browse files

Merge pull request #1774 from nodemcu/dev

2.0.0 master drop
parents 81ec3665 20a591f5
#include "lwip/inet.h"
#include "lwip/err.h"
#include "lwip/err.h"
#include "lwip/pbuf.h"
#include "lwip/udp.h"
#include "lwip/mem.h"
......@@ -25,7 +25,6 @@ static struct udp_pcb *pcb_dhcps = NULL;
static struct ip_addr broadcast_dhcps;
static struct ip_addr server_address;
static struct ip_addr client_address;//added
static struct ip_addr client_address_plus;
static struct dhcps_lease dhcps_lease;
//static bool dhcps_lease_flag = true;
......@@ -34,6 +33,10 @@ static uint8 offer = 0xFF;
static bool renew = false;
#define DHCPS_LEASE_TIME_DEF (120)
uint32 dhcps_lease_time = DHCPS_LEASE_TIME_DEF; //minute
void wifi_softap_dhcps_client_leave(u8 *bssid, struct ip_addr *ip,bool force);
uint32 wifi_softap_dhcps_client_update(u8 *bssid, struct ip_addr *ip);
/******************************************************************************
* FunctionName : node_insert_to_list
* Description : insert the node to the list
......@@ -90,10 +93,12 @@ void ICACHE_FLASH_ATTR node_remove_from_list(list_node **phead, list_node* pdele
} else {
if (plist == pdelete){
*phead = plist->pnext;
pdelete->pnext = NULL;
} else {
while (plist != NULL) {
if (plist->pnext == pdelete){
plist->pnext = pdelete->pnext;
pdelete->pnext = NULL;
}
plist = plist->pnext;
}
......@@ -248,7 +253,7 @@ static void ICACHE_FLASH_ATTR create_msg(struct dhcps_msg *m)
{
struct ip_addr client;
client.addr = *( (uint32_t *) &client_address);
client.addr = client_address.addr;
m->op = DHCP_REPLY;
m->htype = DHCP_HTYPE_ETHERNET;
......@@ -267,7 +272,10 @@ static void ICACHE_FLASH_ATTR create_msg(struct dhcps_msg *m)
os_memset((char *) m->file, 0, sizeof(m->file));
os_memset((char *) m->options, 0, sizeof(m->options));
os_memcpy((char *) m->options, &magic_cookie, sizeof(magic_cookie));
//For xiaomi crash bug
uint32 magic_cookie1 = magic_cookie;
os_memcpy((char *) m->options, &magic_cookie1, sizeof(magic_cookie1));
}
///////////////////////////////////////////////////////////////////////////////////
/*
......@@ -307,12 +315,6 @@ static void ICACHE_FLASH_ATTR send_offer(struct dhcps_msg *m)
for(i=0; i<q->len; i++)
{
data[i] = ((u8_t *) m)[cnt++];
#if DHCPS_DEBUG
os_printf("%02x ",data[i]);
if((i+1)%16 == 0){
os_printf("\n");
}
#endif
}
q = q->next;
......@@ -373,12 +375,6 @@ static void ICACHE_FLASH_ATTR send_nak(struct dhcps_msg *m)
for(i=0; i<q->len; i++)
{
data[i] = ((u8_t *) m)[cnt++];
#if DHCPS_DEBUG
os_printf("%02x ",data[i]);
if((i+1)%16 == 0){
os_printf("\n");
}
#endif
}
q = q->next;
......@@ -440,12 +436,6 @@ static void ICACHE_FLASH_ATTR send_ack(struct dhcps_msg *m)
for(i=0; i<q->len; i++)
{
data[i] = ((u8_t *) m)[cnt++];
#if DHCPS_DEBUG
os_printf("%02x ",data[i]);
if((i+1)%16 == 0){
os_printf("\n");
}
#endif
}
q = q->next;
......@@ -503,6 +493,7 @@ static uint8_t ICACHE_FLASH_ATTR parse_options(uint8_t *optptr, sint16_t len)
break;
case DHCP_OPTION_REQ_IPADDR://50
//os_printf("dhcps:0x%08x,0x%08x\n",client.addr,*(uint32*)(optptr+2));
if( os_memcmp( (char *) &client.addr, (char *) optptr+2,4)==0 ) {
#if DHCPS_DEBUG
os_printf("dhcps: DHCP_OPTION_REQ_IPADDR = 0 ok\n");
......@@ -573,158 +564,24 @@ static uint8_t ICACHE_FLASH_ATTR parse_options(uint8_t *optptr, sint16_t len)
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
static sint16_t ICACHE_FLASH_ATTR parse_msg(struct dhcps_msg *m, u16_t len)
{
if(os_memcmp((char *)m->options,
&magic_cookie,
sizeof(magic_cookie)) == 0){
#if DHCPS_DEBUG
os_printf("dhcps: len = %d\n", len);
#endif
/*
* ��¼��ǰ��xid���ﴦ���?
* �˺�ΪDHCP�ͻ����������û�ͳһ��ȡIPʱ��
*/
// if((old_xid[0] == 0) &&
// (old_xid[1] == 0) &&
// (old_xid[2] == 0) &&
// (old_xid[3] == 0)){
// /*
// * old_xidδ��¼�κ����?
// * �϶��ǵ�һ��ʹ��
// */
// os_memcpy((char *)old_xid, (char *)m->xid, sizeof(m->xid));
// }else{
// /*
// * ���δ����DHCP msg��Я���xid���ϴμ�¼�IJ�ͬ��
// * �϶�Ϊ��ͬ��DHCP�ͻ��˷��ͣ���ʱ����Ҫ����Ŀͻ���IP
// * ���� 192.168.4.100(0x6404A8C0) <--> 192.168.4.200(0xC804A8C0)
// *
// */
// if(os_memcmp((char *)old_xid, (char *)m->xid, sizeof(m->xid)) != 0){
/*
* ��¼���ε�xid�ţ�ͬʱ�����IP����
*/
struct ip_addr addr_tmp;
// os_memcpy((char *)old_xid, (char *)m->xid, sizeof(m->xid));
// {
struct dhcps_pool *pdhcps_pool = NULL;
list_node *pnode = NULL;
list_node *pback_node = NULL;
struct ip_addr first_address;
bool flag = false;
// POOL_START:
first_address.addr = dhcps_lease.start_ip.addr;
client_address.addr = client_address_plus.addr;
renew = false;
// addr_tmp.addr = htonl(client_address_plus.addr);
// addr_tmp.addr++;
// client_address_plus.addr = htonl(addr_tmp.addr);
for (pback_node = plist; pback_node != NULL;pback_node = pback_node->pnext) {
pdhcps_pool = pback_node->pnode;
if (os_memcmp(pdhcps_pool->mac, m->chaddr, sizeof(pdhcps_pool->mac)) == 0){
// os_printf("the same device request ip\n");
if (os_memcmp(&pdhcps_pool->ip.addr, m->ciaddr, sizeof(pdhcps_pool->ip.addr)) == 0) {
renew = true;
}
client_address.addr = pdhcps_pool->ip.addr;
pdhcps_pool->lease_timer = DHCPS_LEASE_TIMER;
pnode = pback_node;
goto POOL_CHECK;
} else if (pdhcps_pool->ip.addr == client_address_plus.addr){
// client_address.addr = client_address_plus.addr;
// os_printf("the ip addr has been request\n");
addr_tmp.addr = htonl(client_address_plus.addr);
addr_tmp.addr++;
client_address_plus.addr = htonl(addr_tmp.addr);
client_address.addr = client_address_plus.addr;
}
if(flag == false) { // search the fisrt unused ip
if(first_address.addr < pdhcps_pool->ip.addr) {
flag = true;
} else {
addr_tmp.addr = htonl(first_address.addr);
addr_tmp.addr++;
first_address.addr = htonl(addr_tmp.addr);
}
}
}
if (client_address_plus.addr > dhcps_lease.end_ip.addr) {
client_address.addr = first_address.addr;
}
if (client_address.addr > dhcps_lease.end_ip.addr) {
client_address_plus.addr = dhcps_lease.start_ip.addr;
pdhcps_pool = NULL;
pnode = NULL;
} else {
pdhcps_pool = (struct dhcps_pool *)os_zalloc(sizeof(struct dhcps_pool));
pdhcps_pool->ip.addr = client_address.addr;
os_memcpy(pdhcps_pool->mac, m->chaddr, sizeof(pdhcps_pool->mac));
pdhcps_pool->lease_timer = DHCPS_LEASE_TIMER;
pnode = (list_node *)os_zalloc(sizeof(list_node ));
pnode->pnode = pdhcps_pool;
pnode->pnext = NULL;
node_insert_to_list(&plist,pnode);
if (client_address.addr == dhcps_lease.end_ip.addr) {
client_address_plus.addr = dhcps_lease.start_ip.addr;
} else {
addr_tmp.addr = htonl(client_address.addr);
addr_tmp.addr++;
client_address_plus.addr = htonl(addr_tmp.addr);
}
}
POOL_CHECK:
if ((client_address.addr > dhcps_lease.end_ip.addr) || (ip_addr_isany(&client_address))){
os_printf("client_address_plus.addr %x %d\n", client_address_plus.addr, system_get_free_heap_size());
if(pnode != NULL) {
node_remove_from_list(&plist,pnode);
os_free(pnode);
pnode = NULL;
}
if (pdhcps_pool != NULL) {
os_free(pdhcps_pool);
pdhcps_pool = NULL;
}
// client_address_plus.addr = dhcps_lease.start_ip.addr;
return 4;
}
sint16_t ret = parse_options(&m->options[4], len);;
if(ret == DHCPS_STATE_RELEASE) {
if(pnode != NULL) {
node_remove_from_list(&plist,pnode);
os_free(pnode);
pnode = NULL;
}
if (pdhcps_pool != NULL) {
os_free(pdhcps_pool);
pdhcps_pool = NULL;
}
os_memset(&client_address,0x0,sizeof(client_address));
}
if (wifi_softap_set_station_info(m->chaddr, &client_address) == false) {
return 0;
}
// }
{
if(os_memcmp((char *)m->options,
&magic_cookie,
sizeof(magic_cookie)) == 0){
struct ip_addr ip;
os_memcpy(&ip.addr,m->ciaddr,sizeof(ip.addr));
client_address.addr = wifi_softap_dhcps_client_update(m->chaddr,&ip);
sint16_t ret = parse_options(&m->options[4], len);
if(ret == DHCPS_STATE_RELEASE) {
wifi_softap_dhcps_client_leave(m->chaddr,&ip,TRUE); // force to delete
client_address.addr = ip.addr;
}
#if DHCPS_DEBUG
os_printf("dhcps: xid changed\n");
os_printf("dhcps: client_address.addr = %x\n", client_address.addr);
#endif
// }
// }
return ret;
}
return 0;
return ret;
}
return 0;
}
///////////////////////////////////////////////////////////////////////////////////
/*
......@@ -772,12 +629,6 @@ static void ICACHE_FLASH_ATTR handle_dhcp(void *arg,
for(i=0; i<p->len; i++){
p_dhcps_msg[dhcps_msg_cnt++] = data[i];
#if DHCPS_DEBUG
os_printf("%02x ",data[i]);
if((i+1)%16 == 0){
os_printf("\n");
}
#endif
}
if(p->next != NULL) {
......@@ -790,12 +641,6 @@ static void ICACHE_FLASH_ATTR handle_dhcp(void *arg,
data = p->next->payload;
for(i=0; i<p->next->len; i++){
p_dhcps_msg[dhcps_msg_cnt++] = data[i];
#if DHCPS_DEBUG
os_printf("%02x ",data[i]);
if((i+1)%16 == 0){
os_printf("\n");
}
#endif
}
}
......@@ -899,7 +744,6 @@ void ICACHE_FLASH_ATTR dhcps_start(struct ip_info *info)
server_address = info->ip;
wifi_softap_init_dhcps_lease(server_address.addr);
client_address_plus.addr = dhcps_lease.start_ip.addr;
udp_bind(pcb_dhcps, IP_ADDR_ANY, DHCPS_SERVER_PORT);
udp_recv(pcb_dhcps, handle_dhcp, NULL);
......@@ -923,11 +767,18 @@ void ICACHE_FLASH_ATTR dhcps_stop(void)
//udp_remove(pcb_dhcps);
list_node *pnode = NULL;
list_node *pback_node = NULL;
struct dhcps_pool* dhcp_node = NULL;
struct ip_addr ip_zero;
os_memset(&ip_zero,0x0,sizeof(ip_zero));
pnode = plist;
while (pnode != NULL) {
pback_node = pnode;
pnode = pback_node->pnext;
node_remove_from_list(&plist, pback_node);
dhcp_node = (struct dhcps_pool*)pback_node->pnode;
//wifi_softap_dhcps_client_leave(dhcp_node->mac,&dhcp_node->ip,TRUE); // force to delete
wifi_softap_set_station_info(dhcp_node->mac, &ip_zero);
os_free(pback_node->pnode);
pback_node->pnode = NULL;
os_free(pback_node);
......@@ -1065,7 +916,9 @@ void ICACHE_FLASH_ATTR dhcps_coarse_tmr(void)
pnode = plist;
while (pnode != NULL) {
pdhcps_pool = pnode->pnode;
pdhcps_pool->lease_timer --;
if ( pdhcps_pool->type == DHCPS_TYPE_DYNAMIC) {
pdhcps_pool->lease_timer --;
}
if (pdhcps_pool->lease_timer == 0){
pback_node = pnode;
pnode = pback_node->pnext;
......@@ -1144,3 +997,184 @@ uint32 ICACHE_FLASH_ATTR wifi_softap_get_dhcps_lease_time(void) // minute
{
return dhcps_lease_time;
}
void ICACHE_FLASH_ATTR wifi_softap_dhcps_client_leave(u8 *bssid, struct ip_addr *ip,bool force)
{
struct dhcps_pool *pdhcps_pool = NULL;
list_node *pback_node = NULL;
if ((bssid == NULL) || (ip == NULL)) {
return;
}
for (pback_node = plist; pback_node != NULL;pback_node = pback_node->pnext) {
pdhcps_pool = pback_node->pnode;
if (os_memcmp(pdhcps_pool->mac, bssid, sizeof(pdhcps_pool->mac)) == 0){
if (os_memcmp(&pdhcps_pool->ip.addr, &ip->addr, sizeof(pdhcps_pool->ip.addr)) == 0) {
if ((pdhcps_pool->type == DHCPS_TYPE_STATIC) || (force)) {
if(pback_node != NULL) {
node_remove_from_list(&plist,pback_node);
os_free(pback_node);
pback_node = NULL;
}
if (pdhcps_pool != NULL) {
os_free(pdhcps_pool);
pdhcps_pool = NULL;
}
} else {
pdhcps_pool->state = DHCPS_STATE_OFFLINE;
}
struct ip_addr ip_zero;
os_memset(&ip_zero,0x0,sizeof(ip_zero));
wifi_softap_set_station_info(bssid, &ip_zero);
break;
}
}
}
}
uint32 ICACHE_FLASH_ATTR wifi_softap_dhcps_client_update(u8 *bssid, struct ip_addr *ip)
{
struct dhcps_pool *pdhcps_pool = NULL;
list_node *pback_node = NULL;
list_node *pmac_node = NULL;
list_node *pip_node = NULL;
bool flag = FALSE;
uint32 start_ip = dhcps_lease.start_ip.addr;
uint32 end_ip = dhcps_lease.end_ip.addr;
dhcps_type_t type = DHCPS_TYPE_DYNAMIC;
if (bssid == NULL) {
return IPADDR_ANY;
}
if (ip) {
if (IPADDR_BROADCAST == ip->addr) {
return IPADDR_ANY;
} else if (IPADDR_ANY == ip->addr) {
ip = NULL;
} else {
type = DHCPS_TYPE_STATIC;
}
}
renew = FALSE;
for (pback_node = plist; pback_node != NULL;pback_node = pback_node->pnext) {
pdhcps_pool = pback_node->pnode;
//os_printf("mac:"MACSTR"bssid:"MACSTR"\r\n",MAC2STR(pdhcps_pool->mac),MAC2STR(bssid));
if (os_memcmp(pdhcps_pool->mac, bssid, sizeof(pdhcps_pool->mac)) == 0){
pmac_node = pback_node;
if (ip == NULL) {
flag = TRUE;
break;
}
}
if (ip != NULL) {
if (os_memcmp(&pdhcps_pool->ip.addr, &ip->addr, sizeof(pdhcps_pool->ip.addr)) == 0) {
pip_node = pback_node;
}
} else if (flag == FALSE){
if (os_memcmp(&pdhcps_pool->ip.addr, &start_ip, sizeof(pdhcps_pool->ip.addr)) != 0) {
flag = TRUE;
} else {
start_ip = htonl((ntohl(start_ip) + 1));
}
}
}
if ((ip == NULL) && (flag == FALSE)) {
if (plist == NULL) {
if (start_ip <= end_ip) {
flag = TRUE;
} else {
return IPADDR_ANY;
}
} else {
if (start_ip > end_ip) {
return IPADDR_ANY;
}
//start_ip = htonl((ntohl(start_ip) + 1));
flag = TRUE;
}
}
if (pmac_node != NULL) { // update new ip
if (pip_node != NULL){
pdhcps_pool = pip_node->pnode;
if (pip_node != pmac_node) {
if(pdhcps_pool->state != DHCPS_STATE_OFFLINE) { // ip is used
return IPADDR_ANY;
}
// mac exists and ip exists in other node,delete mac
node_remove_from_list(&plist,pmac_node);
os_free(pmac_node->pnode);
pmac_node->pnode = NULL;
os_free(pmac_node);
pmac_node = pip_node;
os_memcpy(pdhcps_pool->mac, bssid, sizeof(pdhcps_pool->mac));
} else {
renew = true;
type = DHCPS_TYPE_DYNAMIC;
}
pdhcps_pool->lease_timer = DHCPS_LEASE_TIMER;
pdhcps_pool->type = type;
pdhcps_pool->state = DHCPS_STATE_ONLINE;
} else {
pdhcps_pool = pmac_node->pnode;
if (ip != NULL) {
pdhcps_pool->ip.addr = ip->addr;
} else if (flag == TRUE) {
pdhcps_pool->ip.addr = start_ip;
} else { // no ip to distribute
return IPADDR_ANY;
}
node_remove_from_list(&plist,pmac_node);
pdhcps_pool->lease_timer = DHCPS_LEASE_TIMER;
pdhcps_pool->type = type;
pdhcps_pool->state = DHCPS_STATE_ONLINE;
node_insert_to_list(&plist,pmac_node);
}
} else { // new station
if (pip_node != NULL) { // maybe ip has used
pdhcps_pool = pip_node->pnode;
if (pdhcps_pool->state != DHCPS_STATE_OFFLINE) {
return IPADDR_ANY;
}
os_memcpy(pdhcps_pool->mac, bssid, sizeof(pdhcps_pool->mac));
pdhcps_pool->lease_timer = DHCPS_LEASE_TIMER;
pdhcps_pool->type = type;
pdhcps_pool->state = DHCPS_STATE_ONLINE;
} else {
pdhcps_pool = (struct dhcps_pool *)os_zalloc(sizeof(struct dhcps_pool));
if (ip != NULL) {
pdhcps_pool->ip.addr = ip->addr;
} else if (flag == TRUE) {
pdhcps_pool->ip.addr = start_ip;
} else { // no ip to distribute
os_free(pdhcps_pool);
return IPADDR_ANY;
}
if (pdhcps_pool->ip.addr > end_ip) {
os_free(pdhcps_pool);
return IPADDR_ANY;
}
os_memcpy(pdhcps_pool->mac, bssid, sizeof(pdhcps_pool->mac));
pdhcps_pool->lease_timer = DHCPS_LEASE_TIMER;
pdhcps_pool->type = type;
pdhcps_pool->state = DHCPS_STATE_ONLINE;
pback_node = (list_node *)os_zalloc(sizeof(list_node ));
pback_node->pnode = pdhcps_pool;
pback_node->pnext = NULL;
node_insert_to_list(&plist,pback_node);
}
}
wifi_softap_set_station_info(bssid, &pdhcps_pool->ip);
return pdhcps_pool->ip.addr;
}
......@@ -436,6 +436,39 @@ espconn_sent(struct espconn *espconn, uint8 *psent, uint16 length)
return ESPCONN_ARG;
}
sint16 ICACHE_FLASH_ATTR espconn_recv(struct espconn *espconn, void *mem, size_t len)
{
espconn_msg *pnode = NULL;
bool value = false;
int bytes_used = 0;
if (espconn == NULL || mem == NULL || len == 0)
return ESPCONN_ARG;
/*Find the node depend on the espconn message*/
value = espconn_find_connection(espconn, &pnode);
if (value && espconn->type == ESPCONN_TCP){
if (pnode->readbuf != NULL){
bytes_used = ringbuf_bytes_used(pnode->readbuf);
if (bytes_used != 0) {
if (len > bytes_used) {
len = bytes_used;
}
ringbuf_memcpy_from(mem, pnode->readbuf, len);
espconn_recv_unhold(pnode->pespconn);
return len;
} else {
return ESPCONN_OK;
}
} else{
return ESPCONN_OK;
}
} else{
return ESPCONN_ARG;
}
return ESPCONN_ARG;
}
/******************************************************************************
* FunctionName : espconn_sendto
* Description : send data for UDP
......@@ -954,7 +987,7 @@ espconn_disconnect(struct espconn *espconn)
if (value){
/*protect for redisconnection*/
if (espconn->state == ESPCONN_CLOSE)
if (pnode->preverse == NULL && espconn->state == ESPCONN_CLOSE)
return ESPCONN_INPROGRESS;
espconn_tcp_disconnect(pnode,0); //1 force, 0 normal
return ESPCONN_OK;
......
/*
* espconn_buf.c
*
* Created on: May 25, 2016
* Author: liuhan
*/
#include "lwip/memp.h"
#include "lwip/def.h"
#include "ets_sys.h"
#include "os_type.h"
#include "lwip/app/espconn_buf.h"
#ifdef MEMLEAK_DEBUG
static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
#endif
#if (!defined(lwIP_unlikely))
#define lwIP_unlikely(Expression) !!(Expression)
#endif
#define lwIP_ASSERT(Expression) do{if(!(Expression)) {os_printf("%s %d\n", __func__, __LINE__);return;}}while(0)
ringbuf_t ringbuf_new(size_t capacity)
{
ringbuf_t rb = (ringbuf_t)os_zalloc(sizeof(struct ringbuf_t));
if (rb){
rb->size = capacity + 1;
rb->buf = (uint8*)os_zalloc(rb->size);
if (rb->buf){
ringbuf_reset(rb);
}else{
os_free(rb);
return NULL;
}
}
return rb;
}
size_t ringbuf_buffer_size(const struct ringbuf_t *rb)
{
return rb->size;
}
void ringbuf_reset(ringbuf_t rb)
{
rb ->head = rb->tail = rb->buf;
}
void ringbuf_free(ringbuf_t *rb)
{
lwIP_ASSERT(rb && *rb);
os_free((*rb)->buf);
os_free(*rb);
*rb = NULL;
}
size_t ringbuf_capacity(const struct ringbuf_t *rb)
{
return ringbuf_buffer_size(rb) - 1;
}
static const uint8_t* ringbuf_end(const struct ringbuf_t *rb)
{
return rb->buf + ringbuf_buffer_size(rb);
}
size_t ringbuf_bytes_free(const struct ringbuf_t *rb)
{
if (rb->head >= rb->tail){
return ringbuf_capacity(rb) - (rb->head - rb->tail);
}else{
return rb->tail - rb->head -1;
}
}
size_t ringbuf_bytes_used(const struct ringbuf_t *rb)
{
return ringbuf_capacity(rb) - ringbuf_bytes_free(rb);
}
int ringbuf_is_full(const struct ringbuf_t *rb)
{
return ringbuf_bytes_free(rb) == 0;
}
int ringbuf_is_empty(const struct ringbuf_t *rb)
{
return ringbuf_bytes_free(rb) == ringbuf_capacity(rb);
}
const void* ringbuf_tail(const struct ringbuf_t *rb)
{
return rb->tail;
}
const void* ringbuf_head(const struct ringbuf_t *rb)
{
return rb->head;
}
static uint8_t *ringbuf_nextp(ringbuf_t rb, const uint8_t *p)
{
lwIP_ASSERT((p >= rb->buf) && (p < ringbuf_end(rb)));
return rb->buf + ((++p -rb->buf) % ringbuf_buffer_size(rb));
}
size_t ringbuf_findchr(const struct ringbuf_t *rb, int c, size_t offset)
{
const uint8_t *bufend = ringbuf_end(rb);
size_t bytes_used = ringbuf_bytes_used(rb);
if (offset >= bytes_used)
return bytes_used;
const uint8_t *start = rb ->buf + (((rb->tail - rb->buf) + offset) % ringbuf_buffer_size(rb));
lwIP_ASSERT(bufend > start);
size_t n = LWIP_MIN(bufend - start, bytes_used - offset);
const uint8_t *found = (const uint8_t *)memchr(start, c, n);
if (found)
return offset + (found - start);
else
return ringbuf_findchr(rb, c, offset + n);
}
size_t ringbuf_memset(ringbuf_t dst, int c, size_t len)
{
const uint8_t *bufend = ringbuf_end(dst);
size_t nwritten = 0;
size_t count = LWIP_MIN(len, ringbuf_buffer_size(dst));
int overflow = count > ringbuf_bytes_free(dst);
while (nwritten != count){
lwIP_ASSERT(bufend > dst->head);
size_t n = LWIP_MIN(bufend - dst->head, count - nwritten);
os_memset(dst->head, c, n);
dst->head += n;
nwritten += n;
if (dst->head == bufend)
dst->head = dst->buf;
}
if (overflow){
dst->tail = ringbuf_nextp(dst, dst->head);
lwIP_ASSERT(ringbuf_is_full(dst));
}
return nwritten;
}
void *ringbuf_memcpy_into(ringbuf_t dst,const void *src, size_t count)
{
const uint8_t *u8src = src;
const uint8_t *bufend = ringbuf_end(dst);
int overflow = count > ringbuf_bytes_free(dst);
size_t nread = 0;
while (nread != count){
lwIP_ASSERT(bufend > dst->head);
size_t n = LWIP_MIN(bufend - dst->head, count - nread);
os_memcpy(dst->head, u8src + nread, n);
dst->head += n;
nread += n;
if (dst->head == bufend)
dst->head = dst->buf;
}
if (overflow) {
dst->tail = ringbuf_nextp(dst, dst->head);
lwIP_ASSERT(ringbuf_is_full(dst));
}
return dst->head;
}
void *ringbuf_memcpy_from(void *dst,ringbuf_t src, size_t count)
{
size_t bytes_used = ringbuf_bytes_used(src);
if (count > bytes_used)
return NULL;
const uint8_t *u8dst = dst;
const uint8_t *bufend = ringbuf_end(src);
size_t nwritten = 0;
while (nwritten != count){
lwIP_ASSERT(bufend > src->tail);
size_t n = LWIP_MIN(bufend - src->tail, count - nwritten);
os_memcpy((uint8_t*)u8dst + nwritten, src->tail, n);
src->tail += n;
nwritten += n;
if (src->tail == bufend)
src->tail = src->buf;
}
lwIP_ASSERT(count + ringbuf_bytes_used(src) == bytes_used);
return src->tail;
}
......@@ -219,6 +219,34 @@ struct tcp_pcb *ICACHE_FLASH_ATTR espconn_find_current_pcb(espconn_msg *pcurrent
return NULL;
}
/******************************************************************************
* FunctionName : espconn_tcp_memp_free
* Description : frees the connection memory in the server mode
* Parameters : arg -- Additional argument to pass to the function
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR espconn_tcp_memp_free(espconn_msg *pmemp)
{
struct espconn *espconn = NULL;
if (pmemp == NULL)
return;
if (pmemp->espconn_mode == ESPCONN_TCPSERVER_MODE){
if (pmemp->pespconn != NULL && pmemp->pespconn->proto.tcp != NULL)
os_free(pmemp->pespconn->proto.tcp);
pmemp->pespconn->proto.tcp = NULL;
os_free(pmemp->pespconn);
pmemp->pespconn = NULL;
}
if (pmemp->readbuf != NULL){
ringbuf_free(&pmemp->readbuf);
}
os_free(pmemp);
pmemp = NULL;
}
/******************************************************************************
* FunctionName : espconn_tcp_reconnect
* Description : reconnect with host
......@@ -235,24 +263,15 @@ espconn_tcp_reconnect(void *arg)
espconn_kill_oldest_pcb();
if (precon_cb != NULL) {
struct espconn *espconn = precon_cb->preverse;
re_err = precon_cb->pcommon.err;
if (precon_cb->pespconn != NULL){
if (espconn != NULL){/*Process the server's message block*/
if (precon_cb->pespconn->proto.tcp != NULL){
espconn_copy_partial(espconn, precon_cb->pespconn);
espconn_printf("server: %d.%d.%d.%d : %d reconnection\n", espconn->proto.tcp->remote_ip[0],
espconn->proto.tcp->remote_ip[1],espconn->proto.tcp->remote_ip[2],
espconn->proto.tcp->remote_ip[3],espconn->proto.tcp->remote_port);
os_free(precon_cb->pespconn->proto.tcp);
precon_cb->pespconn->proto.tcp = NULL;
}
os_free(precon_cb->pespconn);
precon_cb->pespconn = NULL;
} else {/*Process the client's message block*/
espconn = precon_cb->pespconn;
espconn_printf("client: %d.%d.%d.%d : %d reconnection\n", espconn->proto.tcp->local_ip[0],
espconn->proto.tcp->local_ip[1],espconn->proto.tcp->local_ip[2],
espconn->proto.tcp->local_ip[3],espconn->proto.tcp->local_port);
}
}
......@@ -267,11 +286,13 @@ espconn_tcp_reconnect(void *arg)
}
os_bzero(&pktinfo[1], sizeof(struct espconn_packet));
os_memcpy(&pktinfo[1], (void*)&precon_cb->pcommon.packet_info, sizeof(struct espconn_packet));
os_free(precon_cb);
precon_cb = NULL;
if (espconn && espconn->proto.tcp && espconn->proto.tcp->reconnect_callback != NULL) {
espconn->proto.tcp->reconnect_callback(espconn, re_err);
}
/*frees the connection memory*/
espconn_tcp_memp_free(precon_cb);
} else {
espconn_printf("espconn_tcp_reconnect err\n");
}
......@@ -300,20 +321,11 @@ espconn_tcp_disconnect_successful(void *arg)
if (espconn != NULL){/*Process the server's message block*/
if (pdiscon_cb->pespconn->proto.tcp != NULL && espconn->proto.tcp){
espconn_copy_partial(espconn, pdiscon_cb->pespconn);
espconn_printf("server: %d.%d.%d.%d : %d disconnect\n", espconn->proto.tcp->remote_ip[0],
espconn->proto.tcp->remote_ip[1],espconn->proto.tcp->remote_ip[2],
espconn->proto.tcp->remote_ip[3],espconn->proto.tcp->remote_port);
os_free(pdiscon_cb->pespconn->proto.tcp);
pdiscon_cb->pespconn->proto.tcp = NULL;
}
os_free(pdiscon_cb->pespconn);
pdiscon_cb->pespconn = NULL;
} else {/*Process the client's message block*/
espconn = pdiscon_cb->pespconn;
espconn_printf("client: %d.%d.%d.%d : %d disconnect\n", espconn->proto.tcp->local_ip[0],
espconn->proto.tcp->local_ip[1],espconn->proto.tcp->local_ip[2],
espconn->proto.tcp->local_ip[3],espconn->proto.tcp->local_port);
}
/*process the current TCP block*/
pcb = espconn_find_current_pcb(pdiscon_cb);
if (pcb != NULL){
......@@ -368,11 +380,13 @@ espconn_tcp_disconnect_successful(void *arg)
}
os_bzero(&pktinfo[0], sizeof(struct espconn_packet));
os_memcpy(&pktinfo[0], (void*)&pdiscon_cb->pcommon.packet_info, sizeof(struct espconn_packet));
os_free(pdiscon_cb);
pdiscon_cb = NULL;
if (espconn->proto.tcp && espconn->proto.tcp->disconnect_callback != NULL) {
espconn->proto.tcp->disconnect_callback(espconn);
}
/*frees the connection memory*/
espconn_tcp_memp_free(pdiscon_cb);
} else {
espconn_printf("espconn_tcp_disconnect err\n");
}
......@@ -387,34 +401,46 @@ espconn_tcp_disconnect_successful(void *arg)
static void ICACHE_FLASH_ATTR
espconn_Task(os_event_t *events)
{
espconn_msg *plist = NULL;
bool active_flag = false;
espconn_msg *task_msg = NULL;
struct espconn *pespconn = NULL;
task_msg = (espconn_msg *) events->par;
switch (events->sig) {
case SIG_ESPCONN_WRITE: {
pespconn = task_msg->pespconn;
if (pespconn == NULL) {
return;
}
/*find the active connection node*/
for (plist = plink_active; plist != NULL; plist = plist->pnext){
if (task_msg == plist) {
active_flag = true;
break;
}
}
if (pespconn->proto.tcp->write_finish_fn != NULL) {
pespconn->proto.tcp->write_finish_fn(pespconn);
if (active_flag){
switch (events->sig) {
case SIG_ESPCONN_WRITE: {
pespconn = task_msg->pespconn;
if (pespconn == NULL) {
return;
}
if (pespconn->proto.tcp->write_finish_fn != NULL) {
pespconn->proto.tcp->write_finish_fn(pespconn);
}
}
break;
case SIG_ESPCONN_ERRER:
/*remove the node from the client's active connection list*/
espconn_list_delete(&plink_active, task_msg);
espconn_tcp_reconnect(task_msg);
break;
case SIG_ESPCONN_CLOSE:
/*remove the node from the client's active connection list*/
espconn_list_delete(&plink_active, task_msg);
espconn_tcp_disconnect_successful(task_msg);
break;
default:
break;
}
break;
case SIG_ESPCONN_ERRER:
/*remove the node from the client's active connection list*/
espconn_list_delete(&plink_active, task_msg);
espconn_tcp_reconnect(task_msg);
break;
case SIG_ESPCONN_CLOSE:
/*remove the node from the client's active connection list*/
espconn_list_delete(&plink_active, task_msg);
espconn_tcp_disconnect_successful(task_msg);
break;
default:
break;
}
}
......@@ -468,9 +494,13 @@ espconn_tcp_sent(void *arg, uint8 *psent, uint16 length)
err = tcp_write(pcb, psent, len, 0);
if (err == ERR_MEM) {
len /= 2;
if(len < 3)
len--;
else
len /= 2;
}
} while (err == ERR_MEM && len > 1);
} while (err == ERR_MEM && len > 0);
/*Find out what we can send and send it, offset the buffer point for next send*/
if (err == ERR_OK) {
......@@ -528,16 +558,22 @@ espconn_client_close(void *arg, struct tcp_pcb *pcb, u8 type)
if(type == 0)
err = tcp_close(pcb);
else
{tcp_abort(pcb); err = ERR_OK;}
else {
tcp_sent(pcb, NULL);
tcp_err(pcb, NULL);
tcp_abort(pcb);
err = ERR_OK;
}
if (err != ERR_OK) {
/* closing failed, try again later */
tcp_recv(pcb, espconn_client_recv);
} else {
/* closing succeeded */
tcp_sent(pcb, NULL);
tcp_err(pcb, NULL);
if (type == 0) {
tcp_sent(pcb, NULL);
tcp_err(pcb, NULL);
}
/*switch the state of espconn for application process*/
pclose->pespconn->state = ESPCONN_CLOSE;
ets_post(espconn_TaskPrio, SIG_ESPCONN_CLOSE, (uint32_t)pclose);
......@@ -599,7 +635,37 @@ espconn_recv_unhold(struct espconn *pespconn)
}
//***********Code for WIFI_BLOCK from upper**************
sint8 ICACHE_FLASH_ATTR
espconn_lock_recv(espconn_msg *plockmsg)
{
if (plockmsg == NULL || plockmsg->pespconn == NULL) {
return ESPCONN_ARG;
}
if (plockmsg->pespconn->recv_callback == NULL){
if (plockmsg->readbuf == NULL){
plockmsg->readbuf = ringbuf_new(TCP_WND);
if (plockmsg->readbuf == NULL)
return ESPCONN_MEM;
}
return espconn_recv_hold(plockmsg->pespconn);
}
return ESPCONN_OK;
}
sint8 ICACHE_FLASH_ATTR
espconn_unlock_recv(espconn_msg *punlockmsg)
{
if (punlockmsg == NULL || punlockmsg->pespconn == NULL) {
return ESPCONN_ARG;
}
if (punlockmsg->pespconn->recv_callback != NULL)
return espconn_recv_unhold(punlockmsg->pespconn);
return ESPCONN_OK;
}
/******************************************************************************
* FunctionName : espconn_client_recv
* Description : Data has been received on this pcb.
......@@ -615,6 +681,8 @@ espconn_client_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
espconn_msg *precv_cb = arg;
tcp_arg(pcb, arg);
/*lock the window because of application layer don't need the data*/
espconn_lock_recv(precv_cb);
if (p != NULL) {
/*To update and advertise a larger window*/
......@@ -624,30 +692,38 @@ espconn_client_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
precv_cb->recv_holded_buf_Len += p->tot_len;
}
if (err == ERR_OK && p != NULL) {
char *pdata = NULL;
u16_t length = 0;
/*Copy the contents of a packet buffer to an application buffer.
*to prevent memory leaks, ensure that each allocated is deleted*/
pdata = (char *)os_zalloc(p ->tot_len + 1);
length = pbuf_copy_partial(p, pdata, p ->tot_len, 0);
pbuf_free(p);
if (length != 0) {
/*switch the state of espconn for application process*/
precv_cb->pespconn ->state = ESPCONN_READ;
precv_cb->pcommon.pcb = pcb;
if (precv_cb->pespconn->recv_callback != NULL) {
precv_cb->pespconn->recv_callback(precv_cb->pespconn, pdata, length);
}
/*switch the state of espconn for next packet copy*/
if (pcb->state == ESTABLISHED)
precv_cb->pespconn ->state = ESPCONN_CONNECT;
}
if (precv_cb->pespconn->recv_callback != NULL){
if (err == ERR_OK && p != NULL) {
char *pdata = NULL;
u16_t length = 0;
/*Copy the contents of a packet buffer to an application buffer.
*to prevent memory leaks, ensure that each allocated is deleted*/
pdata = (char *)os_zalloc(p ->tot_len + 1);
length = pbuf_copy_partial(p, pdata, p ->tot_len, 0);
pbuf_free(p);
if (length != 0) {
/*switch the state of espconn for application process*/
precv_cb->pespconn ->state = ESPCONN_READ;
precv_cb->pcommon.pcb = pcb;
precv_cb->pespconn->recv_callback(precv_cb->pespconn, pdata, length);
/*switch the state of espconn for next packet copy*/
if (pcb->state == ESTABLISHED)
precv_cb->pespconn ->state = ESPCONN_CONNECT;
}
/*to prevent memory leaks, ensure that each allocated is deleted*/
os_free(pdata);
pdata = NULL;
/*to prevent memory leaks, ensure that each allocated is deleted*/
os_free(pdata);
pdata = NULL;
}
} else{
/*unregister receive function*/
struct pbuf *pthis = NULL;
for (pthis = p; pthis != NULL; pthis = pthis->next) {
ringbuf_memcpy_into(precv_cb->readbuf, pthis->payload, pthis->len);
pbuf_free(pthis);
}
}
if (err == ERR_OK && p == NULL) {
......@@ -861,6 +937,8 @@ espconn_client_connect(void *arg, struct tcp_pcb *tpcb, err_t err)
if (espconn_keepalive_disabled(pcon))
espconn_keepalive_enable(tpcb);
// /*lock the window because of application layer don't need the data*/
// espconn_lock_recv(pcon);
} else{
os_printf("err in host connected (%s)\n",lwip_strerr(err));
}
......@@ -924,6 +1002,7 @@ espconn_tcp_client(struct espconn *espconn)
}
#endif
/*Establish the connection*/
pclient->espconn_mode = ESPCONN_TCPCLIENT_MODE;
pclient->pcommon.err = tcp_connect(pcb, &ipaddr,
pclient->pespconn->proto.tcp->remote_port, espconn_client_connect);
if (pclient->pcommon.err == ERR_RTE){
......@@ -958,17 +1037,24 @@ espconn_server_close(void *arg, struct tcp_pcb *pcb,u8 type)
if(type ==0)
err = tcp_close(pcb);
else
{tcp_abort(pcb); err = ERR_OK;}
else {
tcp_poll(pcb, NULL, 0);
tcp_sent(pcb, NULL);
tcp_err(pcb, NULL);
tcp_abort(pcb);
err = ERR_OK;
}
if (err != ERR_OK) {
/* closing failed, try again later */
tcp_recv(pcb, espconn_server_recv);
} else {
/* closing succeeded */
tcp_poll(pcb, NULL, 0);
tcp_sent(pcb, NULL);
tcp_err(pcb, NULL);
if (type == 0) {
tcp_poll(pcb, NULL, 0);
tcp_sent(pcb, NULL);
tcp_err(pcb, NULL);
}
/*switch the state of espconn for application process*/
psclose->pespconn->state = ESPCONN_CLOSE;
ets_post(espconn_TaskPrio, SIG_ESPCONN_CLOSE, (uint32_t)psclose);
......@@ -991,6 +1077,9 @@ espconn_server_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
tcp_arg(pcb, arg);
espconn_printf("server has application data received: %d\n", system_get_free_heap_size());
/*lock the window because of application layer don't need the data*/
espconn_lock_recv(precv_cb);
if (p != NULL) {
/*To update and advertise a larger window*/
if(precv_cb->recv_hold_flag == 0)
......@@ -999,42 +1088,47 @@ espconn_server_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
precv_cb->recv_holded_buf_Len += p->tot_len;
}
if (err == ERR_OK && p != NULL) {
u8_t *data_ptr = NULL;
u32_t data_cntr = 0;
/*clear the count for connection timeout*/
precv_cb->pcommon.recv_check = 0;
/*Copy the contents of a packet buffer to an application buffer.
*to prevent memory leaks, ensure that each allocated is deleted*/
data_ptr = (u8_t *)os_zalloc(p ->tot_len + 1);
data_cntr = pbuf_copy_partial(p, data_ptr, p ->tot_len, 0);
pbuf_free(p);
if (data_cntr != 0) {
/*switch the state of espconn for application process*/
precv_cb->pespconn ->state = ESPCONN_READ;
precv_cb->pcommon.pcb = pcb;
if (precv_cb->pespconn->recv_callback != NULL) {
precv_cb->pespconn->recv_callback(precv_cb->pespconn, data_ptr, data_cntr);
}
/*switch the state of espconn for next packet copy*/
if (pcb->state == ESTABLISHED)
precv_cb->pespconn ->state = ESPCONN_CONNECT;
}
/*to prevent memory leaks, ensure that each allocated is deleted*/
os_free(data_ptr);
data_ptr = NULL;
espconn_printf("server's application data has been processed: %d\n", system_get_free_heap_size());
} else {
if (p != NULL) {
pbuf_free(p);
}
/*register receive function*/
if (precv_cb->pespconn->recv_callback != NULL) {
if (err == ERR_OK && p != NULL) {
u8_t *data_ptr = NULL;
u32_t data_cntr = 0;
/*clear the count for connection timeout*/
precv_cb->pcommon.recv_check = 0;
/*Copy the contents of a packet buffer to an application buffer.
*to prevent memory leaks, ensure that each allocated is deleted*/
data_ptr = (u8_t *) os_zalloc(p ->tot_len + 1);
data_cntr = pbuf_copy_partial(p, data_ptr, p->tot_len, 0);
pbuf_free(p);
if (data_cntr != 0) {
/*switch the state of espconn for application process*/
precv_cb->pespconn->state = ESPCONN_READ;
precv_cb->pcommon.pcb = pcb;
precv_cb->pespconn->recv_callback(precv_cb->pespconn, data_ptr, data_cntr);
/*switch the state of espconn for next packet copy*/
if (pcb->state == ESTABLISHED)
precv_cb->pespconn->state = ESPCONN_CONNECT;
}
espconn_server_close(precv_cb, pcb,0);
}
/*to prevent memory leaks, ensure that each allocated is deleted*/
os_free(data_ptr);
data_ptr = NULL;
espconn_printf("server's application data has been processed: %d\n", system_get_free_heap_size());
}
} else {
/*unregister receive function*/
struct pbuf *pthis = NULL;
for (pthis = p; pthis != NULL; pthis = pthis->next) {
ringbuf_memcpy_into(precv_cb->readbuf, pthis->payload, pthis->len);
pbuf_free(pthis);
}
}
if (err == ERR_OK && p == NULL) {
espconn_server_close(precv_cb, pcb, 0);
}
return ERR_OK;
}
......@@ -1225,6 +1319,7 @@ espconn_tcp_accept(void *arg, struct tcp_pcb *pcb, err_t err)
espconn_list_creat(&plink_active, paccept);
paccept->preverse = espconn;
paccept->espconn_mode = ESPCONN_TCPSERVER_MODE;
paccept->pespconn = (struct espconn *)os_zalloc(sizeof(struct espconn));
if (paccept->pespconn == NULL)
return ERR_MEM;
......@@ -1253,7 +1348,7 @@ espconn_tcp_accept(void *arg, struct tcp_pcb *pcb, err_t err)
* or periodically from active connection*/
tcp_sent(pcb, espconn_server_sent);
tcp_recv(pcb, espconn_server_recv);
tcp_poll(pcb, espconn_server_poll, 8); /* every 1 seconds */
tcp_poll(pcb, espconn_server_poll, 4); /* every 1 seconds */
/*Disable Nagle algorithm default*/
tcp_nagle_disable(pcb);
/*Default set the total number of espconn_buf on the unsent lists for one*/
......@@ -1267,6 +1362,8 @@ espconn_tcp_accept(void *arg, struct tcp_pcb *pcb, err_t err)
if (espconn_keepalive_disabled(paccept))
espconn_keepalive_enable(pcb);
// /*lock the window because of application layer don't need the data*/
// espconn_lock_recv(paccept);
return ERR_OK;
}
......
......@@ -54,8 +54,8 @@ static void ICACHE_FLASH_ATTR espconn_data_sent(void *arg, enum send_opt opt)
if (psent->pcommon.cntr == 0) {
psent->pespconn->state = ESPCONN_CONNECT;
// sys_timeout(10, espconn_data_sentcb, psent->pespconn);
espconn_data_sentcb(psent->pespconn);
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);
......@@ -94,8 +94,8 @@ espconn_udp_sent(void *arg, uint8 *psent, uint16 length)
return ESPCONN_ARG;
}
if (1470 < length) {
datalen = 1470;
if ((IP_FRAG_MAX_MTU - 20 - 8) < length) {
datalen = IP_FRAG_MAX_MTU - 20 - 8;
} else {
datalen = length;
}
......@@ -157,6 +157,7 @@ espconn_udp_sent(void *arg, uint8 *psent, uint16 length)
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;
......@@ -199,8 +200,8 @@ espconn_udp_sendto(void *arg, uint8 *psent, uint16 length)
return ESPCONN_ARG;
}
if (1470 < length) {
datalen = 1470;
if ((IP_FRAG_MAX_MTU - 20 - 8) < length) {
datalen = IP_FRAG_MAX_MTU - 20 - 8;
} else {
datalen = length;
}
......@@ -257,8 +258,8 @@ espconn_udp_sendto(void *arg, uint8 *psent, uint16 length)
pbuf_free(p);
pudp_sent->pcommon.ptrbuf = psent + datalen;
pudp_sent->pcommon.cntr = length - datalen;
if (err == ERR_OK)
espconn_data_sent(pudp_sent, ESPCONN_SENDTO);
pudp_sent->pcommon.err = err;
espconn_data_sent(pudp_sent, ESPCONN_SENDTO);
if (err > 0)
return ESPCONN_IF;
......
......@@ -1096,12 +1096,12 @@ dhcp_renew(struct netif *netif)
}
#endif /* LWIP_NETIF_HOSTNAME */
#if 0
#if 1
dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr));
#endif
#if 0
#if 1
dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4);
dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr));
#endif
......@@ -1159,7 +1159,7 @@ dhcp_rebind(struct netif *netif)
}
#endif /* LWIP_NETIF_HOSTNAME */
#if 0
#if 1
dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr));
......
......@@ -578,7 +578,7 @@ dns_send(u8_t numdns, const char* name, u8_t id)
char *query, *nptr;
const char *pHostname;
u8_t n;
dns_random = (u16_t)os_random();
dns_random = os_random()>>16;
LWIP_DEBUGF(DNS_DEBUG, ("dns_send: dns_servers[%"U16_F"] \"%s\": request\n",
(u16_t)(numdns), name));
LWIP_ASSERT("dns server out of array", numdns < DNS_MAX_SERVERS);
......@@ -706,7 +706,7 @@ dns_check_entry(u8_t i)
case DNS_STATE_DONE: {
/* if the time to live is nul */
if (--pEntry->ttl == 0) {
if ((pEntry->ttl == 0) || (--pEntry->ttl == 0)) {
LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": flush\n", pEntry->name));
/* flush this entry */
pEntry->state = DNS_STATE_UNUSED;
......@@ -782,8 +782,6 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t
if (i < DNS_TABLE_SIZE) {
pEntry = &dns_table[i];
if(pEntry->state == DNS_STATE_ASKING) {
/* This entry is now completed. */
pEntry->state = DNS_STATE_DONE;
pEntry->err = hdr->flags2 & DNS_FLAG2_ERR_MASK;
/* We only care about the question(s) and the answers. The authrr
......@@ -795,8 +793,11 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t
if (((hdr->flags1 & DNS_FLAG1_RESPONSE) == 0) || (pEntry->err != 0) || (nquestions != 1)) {
LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in flags\n", pEntry->name));
/* call callback to indicate error, clean up memory and return */
goto responseerr;
//goto responseerr;
goto memerr;
}
/* This entry is now completed. */
pEntry->state = DNS_STATE_DONE;
#if DNS_DOES_NAME_CHECK
/* Check if the name in the "question" part match with the name in the entry. */
......@@ -832,6 +833,13 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t
if (pEntry->found) {
(*pEntry->found)(pEntry->name, &pEntry->ipaddr, pEntry->arg);
}
if (pEntry->ttl == 0) {
/* RFC 883, page 29: "Zero values are
interpreted to mean that the RR can only be used for the
transaction in progress, and should not be cached."
-> flush this entry now */
goto flushentry;
}
/* deallocate memory and return */
goto memerr;
} else {
......@@ -854,6 +862,7 @@ responseerr:
if (pEntry->found) {
(*pEntry->found)(pEntry->name, NULL, pEntry->arg);
}
flushentry:
/* flush this entry */
pEntry->state = DNS_STATE_UNUSED;
pEntry->found = NULL;
......
......@@ -99,6 +99,13 @@ Steve Reynolds
static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
#endif
//#define DYC_IGMP_DEBUG
#ifdef DYC_IGMP_DEBUG
#define IGMP_LOG os_printf
#else
#define IGMP_LOG //os_printf
#endif
/*
* IGMP constants
*/
......@@ -149,7 +156,7 @@ static err_t igmp_ip_output_if(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
static void igmp_send(struct igmp_group *group, u8_t type)ICACHE_FLASH_ATTR;
static struct igmp_group* igmp_group_list;
static struct igmp_group* igmp_group_list = NULL;
static ip_addr_t allsystems;
static ip_addr_t allrouters;
......@@ -166,22 +173,29 @@ igmp_init(void)
IP4_ADDR(&allrouters, 224, 0, 0, 2);
}
#ifdef LWIP_DEBUG
//#ifdef LWIP_DEBUG
#ifdef DYC_IGMP_DEBUG
/**
* Dump global IGMP groups list
*/
void
igmp_dump_group_list()
{
struct igmp_group *group = igmp_group_list;
while (group != NULL) {
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_dump_group_list: [%"U32_F"] ", (u32_t)(group->group_state)));
ip_addr_debug_print(IGMP_DEBUG, &group->group_address);
LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", group->netif));
group = group->next;
}
LWIP_DEBUGF(IGMP_DEBUG, ("\n"));
struct igmp_group *group = igmp_group_list;
IGMP_LOG("igmp_dump:\n");
while (group != NULL) {
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_dump_group_list: [%"U32_F"] ", (u32_t)(group->group_state)));
ip_addr_debug_print(IGMP_DEBUG, &group->group_address);
LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", group->netif));
if(group!=NULL)
IGMP_LOG("group:%p,netif:%p\n",group,group->netif);
group = group->next;
}
LWIP_DEBUGF(IGMP_DEBUG, ("\n"));
IGMP_LOG("\n");
}
#else
#define igmp_dump_group_list()
......@@ -236,6 +250,9 @@ igmp_stop(struct netif *netif)
next = group->next;
/* is it a group joined on this interface? */
if (group->netif == netif) {
IGMP_LOG("stop igmp:%p,%p,",group,group->netif);
/* is it the first group of the list? */
if (group == igmp_group_list) {
igmp_group_list = next;
......@@ -253,6 +270,9 @@ igmp_stop(struct netif *netif)
}
/* free group */
memp_free(MEMP_IGMP_GROUP, group);
igmp_dump_group_list();
} else {
/* change the "previous" */
prev = group;
......@@ -339,14 +359,14 @@ igmp_lookup_group(struct netif *ifp, ip_addr_t *addr)
group->last_reporter_flag = 0;
group->use = 0;
group->next = igmp_group_list;
igmp_group_list = group;
}
IGMP_LOG("add igmp:%p,%p,",group,group->netif);
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_lookup_group: %sallocated a new group with address ", (group?"":"impossible to ")));
ip_addr_debug_print(IGMP_DEBUG, addr);
LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", ifp));
igmp_dump_group_list();
return group;
}
......@@ -360,7 +380,7 @@ static err_t
igmp_remove_group(struct igmp_group *group)
{
err_t err = ERR_OK;
IGMP_LOG("rmv igmp:%p,%p,",group,group->netif);
/* Is it the first group? */
if (igmp_group_list == group) {
igmp_group_list = group->next;
......@@ -380,6 +400,7 @@ igmp_remove_group(struct igmp_group *group)
/* free group */
memp_free(MEMP_IGMP_GROUP, group);
igmp_dump_group_list();
return err;
}
......@@ -707,6 +728,9 @@ igmp_start_timer(struct igmp_group *group, u8_t max_time)
max_time = 1;
}
/* ensure the random value is > 0 */
if(max_time == 1)
group->timer = 1;
else
group->timer = (LWIP_RAND() % (max_time - 1)) + 1;
}
......
......@@ -900,12 +900,28 @@ mdns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr,
void ICACHE_FLASH_ATTR
mdns_close(void)
{
if (mdns_pcb != NULL && ms_info != NULL)
uint8 text_index = 0;
if (mdns_pcb != NULL && ms_info != NULL) {
udp_remove(mdns_pcb);
for(text_index = 0;text_index < 10;text_index++) {
if(ms_info->txt_data[text_index] != NULL) {
os_free(ms_info->txt_data[text_index]);
ms_info->txt_data[text_index] = NULL;
}
}
if (ms_info->host_name != NULL) {
os_free(ms_info->host_name);
ms_info->host_name = NULL;
}
if (ms_info->server_name != NULL) {
os_free(ms_info->server_name);
ms_info->server_name = NULL;
}
os_free(ms_info);
mdns_pcb = NULL;
ms_info = NULL;
}
}
void ICACHE_FLASH_ATTR
......@@ -1034,9 +1050,23 @@ mdns_init(struct mdns_info *info) {
multicast_addr.addr = DNS_MULTICAST_ADDRESS;
struct ip_addr ap_host_addr;
struct ip_info ipconfig;
uint8 text_index = 0;
ms_info = (struct mdns_info *)os_zalloc(sizeof(struct mdns_info));
if (ms_info != NULL) {
os_memcpy(ms_info,info,sizeof(struct mdns_info));
ms_info->host_name = (char *)os_zalloc(os_strlen(info->host_name)+1);
os_memcpy(ms_info->host_name,info->host_name,os_strlen(info->host_name));
ms_info->server_name = (char *)os_zalloc(os_strlen(info->server_name)+1);
os_memcpy(ms_info->server_name,info->server_name,os_strlen(info->server_name));
for(text_index = 0;text_index < 10;text_index++) {
if(info->txt_data[text_index] != NULL) {
ms_info->txt_data[text_index] = (char *)os_zalloc(os_strlen(info->txt_data[text_index])+1);
os_memcpy(ms_info->txt_data[text_index],info->txt_data[text_index],os_strlen(info->txt_data[text_index]));
} else {
break;
}
}
} else {
os_printf("ms_info alloc failed\n");
return;
......
......@@ -486,6 +486,10 @@ void netif_set_up(struct netif *netif)
*/
void netif_set_down(struct netif *netif)
{
if (netif == NULL) {
return;
}
if (netif->flags & NETIF_FLAG_UP) {
netif->flags &= ~NETIF_FLAG_UP;
#if LWIP_SNMP
......
......@@ -51,7 +51,7 @@
#include "lwip/dns.h"
#include "lwip/ip_addr.h"
#include "lwip/pbuf.h"
#include "lwip/app/time.h"
//#include <string.h>
#if LWIP_UDP
......@@ -148,14 +148,18 @@
#endif
/** SNTP macro to change system time including microseconds */
#ifdef SNTP_SET_SYSTEM_TIME_US
#define SNTP_CALC_TIME_US 1
#define SNTP_RECEIVE_TIME_SIZE 2
#else
#define SNTP_SET_SYSTEM_TIME_US(sec, us)
#define SNTP_CALC_TIME_US 0
#define SNTP_RECEIVE_TIME_SIZE 1
#endif
uint8 sntp_receive_time_size = 1;
#define SNTP_RECEIVE_TIME_SIZE sntp_receive_time_size
#define SNTP_SET_SYSTEM_TIME_US(sec, us) sntp_update_rtc(sec, us)
//#ifdef SNTP_SET_SYSTEM_TIME_US
//#define SNTP_SET_SYSTEM_TIME_US(sec, us) sntp_update_rtc(sec, us)
//#define SNTP_CALC_TIME_US 1
//#define SNTP_RECEIVE_TIME_SIZE 2
//#else
//#define SNTP_SET_SYSTEM_TIME_US(sec, us)
//#define SNTP_CALC_TIME_US 0
//#define SNTP_RECEIVE_TIME_SIZE sntp_receive_time_size
//#endif
/** SNTP macro to get system time, used with SNTP_CHECK_RESPONSE >= 2
* to send in request and compare in response.
......@@ -295,10 +299,12 @@ static ip_addr_t sntp_last_server_address;
* to compare against in response */
static u32_t sntp_last_timestamp_sent[2];
#endif /* SNTP_CHECK_RESPONSE >= 2 */
typedef long time_t;
//uint32 current_stamp_1 = 0;
//uint32 current_stamp_2 = 0;
uint32 realtime_stamp = 0;
static bool sntp_time_flag = false;
static uint32 sntp_update_delay = SNTP_UPDATE_DELAY;
static uint32 realtime_stamp = 0;
LOCAL os_timer_t sntp_timer;
/*****************************************/
#define SECSPERMIN 60L
......@@ -643,13 +649,24 @@ bool ICACHE_FLASH_ATTR
sntp_set_timezone(sint8 timezone)
{
if(timezone >= -11 || timezone <= 13) {
time_zone = timezone;
if (sntp_get_timetype()){
RTC_TZ_SET(time_zone);
} else
time_zone = timezone;
return true;
} else {
return false;
}
}
void ICACHE_FLASH_ATTR sntp_set_daylight(int daylight)
{
if (sntp_get_timetype()){
RTC_DST_SET(daylight);
}
}
void ICACHE_FLASH_ATTR
sntp_time_inc(void)
{
......@@ -665,7 +682,22 @@ sntp_process(u32_t *receive_timestamp)
* @todo: if MSB is 1, SNTP time is 2036-based!
*/
time_t t = (ntohl(receive_timestamp[0]) - DIFF_SEC_1900_1970);
if (sntp_get_timetype()){
u32_t us = ntohl(receive_timestamp[1]) / 4295;
SNTP_SET_SYSTEM_TIME_US(t, us);
/* display local time from GMT time */
LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp_process: %s, %"U32_F" us", ctime(&t), us));
} else{
/* change system time and/or the update the RTC clock */
SNTP_SET_SYSTEM_TIME(t);
/* display local time from GMT time */
t += time_zone * 60 * 60;// format GMT + time_zone TIME ZONE
realtime_stamp = t;
os_timer_disarm(&sntp_timer);
os_timer_setfn(&sntp_timer, (os_timer_func_t *)sntp_time_inc, NULL);
os_timer_arm(&sntp_timer, 1000, 1);
}
#if 0
#if SNTP_CALC_TIME_US
u32_t us = ntohl(receive_timestamp[1]) / 4295;
SNTP_SET_SYSTEM_TIME_US(t, us);
......@@ -682,10 +714,8 @@ sntp_process(u32_t *receive_timestamp)
os_timer_disarm(&sntp_timer);
os_timer_setfn(&sntp_timer, (os_timer_func_t *)sntp_time_inc, NULL);
os_timer_arm(&sntp_timer, 1000, 1);
os_printf("%s\n",sntp_asctime(sntp_localtime (&t)));
// os_printf("%s\n",ctime(&t));
// LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp_process: %s", ctime(&t)));
#endif /* SNTP_CALC_TIME_US */
#endif
}
/**
......@@ -856,9 +886,9 @@ sntp_recv(void *arg, struct udp_pcb* pcb, struct pbuf *p, ip_addr_t *addr, u16_t
sntp_process(receive_timestamp);
/* Set up timeout for next request */
sys_timeout((u32_t)SNTP_UPDATE_DELAY, sntp_request, NULL);
sys_timeout((u32_t)sntp_update_delay, sntp_request, NULL);
LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_recv: Scheduled next time request: %"U32_F" ms\n",
(u32_t)SNTP_UPDATE_DELAY));
(u32_t)sntp_update_delay));
} else if (err == SNTP_ERR_KOD) {
/* Kiss-of-death packet. Use another server or increase UPDATE_DELAY. */
sntp_try_next_server(NULL);
......@@ -1125,4 +1155,31 @@ sntp_getservername(u8_t idx)
}
#endif /* SNTP_SERVER_DNS */
void ICACHE_FLASH_ATTR
sntp_set_update_delay(uint32 ms)
{
sntp_update_delay = ms > 15000?ms:15000;
}
void ICACHE_FLASH_ATTR
sntp_set_timetype(bool type)
{
sntp_time_flag = type;
}
bool sntp_get_timetype(void)
{
return sntp_time_flag;
}
void ICACHE_FLASH_ATTR
sntp_set_receive_time_size(void)
{
if (sntp_get_timetype()){
sntp_receive_time_size = 2;
} else{
sntp_receive_time_size = 1;
}
}
#endif /* LWIP_UDP */
......@@ -511,8 +511,11 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
return ERR_ABRT;
}
#endif /* TCP_LISTEN_BACKLOG */
for(pactive_pcb = tcp_active_pcbs; pactive_pcb != NULL; pactive_pcb = pactive_pcb->next)
active_pcb_num ++;
for(pactive_pcb = tcp_active_pcbs; pactive_pcb != NULL; pactive_pcb = pactive_pcb->next){
if (pactive_pcb->state == ESTABLISHED){
active_pcb_num ++;
}
}
if (active_pcb_num == MEMP_NUM_TCP_PCB){
LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: exceed the number of active TCP connections\n"));
TCP_STATS_INC(tcp.memerr);
......@@ -717,8 +720,9 @@ tcp_process(struct tcp_pcb *pcb)
pcb->rtime = -1;
else {
pcb->rtime = 0;
pcb->nrtx = 0;
// pcb->nrtx = 0;
}
pcb->nrtx = 0;
tcp_seg_free(rseg);
......
......@@ -231,7 +231,7 @@ tcp_pbuf_prealloc(pbuf_layer layer, u16_t length, u16_t max_length,
LWIP_UNUSED_ARG(apiflags);
LWIP_UNUSED_ARG(first_seg);
/* always create MSS-sized pbufs */
alloc = TCP_MSS;
alloc = pcb->mss; //TCP_MSS;
#else /* LWIP_NETIF_TX_SINGLE_PBUF */
if (length < max_length) {
/* Should we allocate an oversized pbuf, or just the minimum
......@@ -420,8 +420,8 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
/* Find the tail of the unsent queue. */
if (pcb->unsent != NULL) {
u16_t space;
u16_t unsent_optlen;
u16_t space = 0;
u16_t unsent_optlen = 0;
/* @todo: this could be sped up by keeping last_unsent in the pcb */
for (last_unsent = pcb->unsent; last_unsent->next != NULL;
......@@ -457,7 +457,11 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
LWIP_ASSERT("inconsistend oversize vs. len", (oversize == 0) || (pos == len));
#endif /* TCP_OVERSIZE */
/*
if (pos > len) {
return ERR_MEM;
}
/*
* Phase 2: Chain a new pbuf to the end of pcb->unsent.
*
* We don't extend segments containing SYN/FIN flags or options
......@@ -955,7 +959,8 @@ tcp_output(struct tcp_pcb *pcb)
/* data available and window allows it to be sent?
*��ǰ��Ч�������?�ķ��ͣ�ѭ�����ͱ��ģ�ֱ�������*/
while (seg != NULL &&
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd
&& (seg->p->ref<2) ) {
LWIP_ASSERT("RST not expected here!",
(TCPH_FLAGS(seg->tcphdr) & TCP_RST) == 0);
/* Stop sending if the nagle algorithm would prevent it
......@@ -1290,6 +1295,7 @@ tcp_rexmit_rto(struct tcp_pcb *pcb)
/* unacked queue is now empty */
pcb->unacked = NULL;
#endif
/* last unsent hasn't changed, no need to reset unsent_oversize */
/* increment number of retransmissions */
++pcb->nrtx;
......
......@@ -152,13 +152,13 @@ udp_input(struct pbuf *p, struct netif *inp)
pcb = inp->dhcp->pcb;
}
}
} else if (dest == DHCP_SERVER_PORT) {
if (src == DHCP_CLIENT_PORT) {
if ( inp->dhcps_pcb != NULL ) {
if ((ip_addr_isany(&inp->dhcps_pcb->local_ip) ||
ip_addr_cmp(&(inp->dhcps_pcb->local_ip), &current_iphdr_dest))) {
pcb = inp->dhcps_pcb;
}
}
} else if (dest == DHCP_SERVER_PORT) {
if (src == DHCP_CLIENT_PORT) {
if ( inp->dhcps_pcb != NULL ) {
if ((ip_addr_isany(&inp->dhcps_pcb->local_ip) ||
ip_addr_cmp(&(inp->dhcps_pcb->local_ip), &current_iphdr_dest))) {
pcb = inp->dhcps_pcb;
}
}
}
......
#############################################################
# Required variables for each makefile
# Discard this section from all parent makefiles
# Expected variables (with automatic defaults):
# CSRCS (all "C" files in the dir)
# SUBDIRS (all subdirs with a Makefile)
# GEN_LIBS - list of libs to be generated ()
# GEN_IMAGES - list of images to be generated ()
# COMPONENTS_xxx - a list of libs/objs in the form
# subdir/lib to be extracted and rolled up into
# a generated lib/image xxx.a ()
#
ifndef PDIR
UP_EXTRACT_DIR = ..
GEN_LIBS = libmbedtls.a
COMPONENTS_libmbedtls = library/liblibrary.a platform/libplatform.a app/libapp.a
endif
#############################################################
# Configuration i.e. compile options etc.
# Target specific stuff (defines etc.) goes in here!
# Generally values applying to a tree are captured in the
# makefile at its root level - these are then overridden
# for a subtree within the makefile rooted therein
#
DEFINES +=
#CCFLAGS += --rename-section .text=.irom0.text --rename-section .literal=.irom0.literal
#############################################################
# Recursion Magic - Don't touch this!!
#
# Each subtree potentially has an include directory
# corresponding to the common APIs applicable to modules
# rooted at that subtree. Accordingly, the INCLUDE PATH
# of a module can only contain the include directories up
# its parent path, and not its siblings
#
# Required for each makefile to inherit from the parent
#
INCLUDES := $(INCLUDES) -I $(PDIR)include
INCLUDES += -I ./
PDIR := ../$(PDIR)
sinclude $(PDIR)Makefile
#include "c_types.h"
#include "mem.h"
#include "user_interface.h"
void *espconn_memzalloc(size_t size, char* file, int line)
{
void *mp = NULL;
if ((mp = (void*)os_malloc(size)) == NULL){
} else{
//os_printf("%s %d %p %d\n",file, line, mp, size);
os_memset(mp, 0, size);
}
return mp;
}
void espconn_memfree(void *fp, char* file, int line)
{
//os_printf("%s %d %p\n",file, line, fp);
os_free(fp);
fp = NULL;
}
void *espconn_memcpy(void *dst, const void *src, size_t size, char *file, int line)
{
char *psrc = NULL;
char *pdst = NULL;
if(NULL == dst || NULL == src)
{
return NULL;
}
//os_printf("%s %d %p %p %d\n",file, line, dst, src, size);
if((src < dst) && (char *)src + size > (char *)dst)
{
psrc = (char *)src + size - 1;
pdst = (char *)dst + size - 1;
while(size--)
{
*pdst-- = *psrc--;
}
}
else
{
psrc = (char *)src;
pdst = (char *)dst;
while(size--)
{
*pdst++ = *psrc++;
}
}
return dst;
}
void *espconn_memcalloc(size_t count, size_t size)
{
void *cp = NULL;
cp = espconn_memzalloc(count * size, __FILE__, __LINE__);
return cp;
}
void espconn_memFree(void *fp)
{
espconn_memfree(fp, __FILE__, __LINE__);
}
void *espconn_memCpy(void *dst, const void *src, size_t size)
{
return espconn_memcpy(dst, src, size, __FILE__, __LINE__);
}
#############################################################
# Required variables for each makefile
# Discard this section from all parent makefiles
# Expected variables (with automatic defaults):
# CSRCS (all "C" files in the dir)
# SUBDIRS (all subdirs with a Makefile)
# GEN_LIBS - list of libs to be generated ()
# GEN_IMAGES - list of images to be generated ()
# COMPONENTS_xxx - a list of libs/objs in the form
# subdir/lib to be extracted and rolled up into
# a generated lib/image xxx.a ()
#
ifndef PDIR
GEN_LIBS = libapp.a
endif
#############################################################
# Configuration i.e. compile options etc.
# Target specific stuff (defines etc.) goes in here!
# Generally values applying to a tree are captured in the
# makefile at its root level - these are then overridden
# for a subtree within the makefile rooted therein
#
#DEFINES +=
#############################################################
# Recursion Magic - Don't touch this!!
#
# Each subtree potentially has an include directory
# corresponding to the common APIs applicable to modules
# rooted at that subtree. Accordingly, the INCLUDE PATH
# of a module can only contain the include directories up
# its parent path, and not its siblings
#
# Required for each makefile to inherit from the parent
#
INCLUDES := $(INCLUDES) -I $(PDIR)include
INCLUDES += -I ./
PDIR := ../$(PDIR)
sinclude $(PDIR)Makefile
/*
* ESPRSSIF MIT License
*
* Copyright (c) 2016 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD>
*
* Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case,
* it is free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#if !defined(ESPCONN_MBEDTLS)
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include "mbedtls/ssl_internal.h"
#include "mem.h"
#ifdef MEMLEAK_DEBUG
static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
#endif
#include "sys/socket.h"
#include "sys/espconn_mbedtls.h"
static os_event_t lwIPThreadQueue[lwIPThreadQueueLen];
static bool lwIPThreadFlag = false;
extern espconn_msg *plink_active;
static espconn_msg *plink_server = NULL;
static pmbedtls_parame def_certificate = NULL;
static pmbedtls_parame def_private_key = NULL;
#if defined(ESP8266_PLATFORM)
#define MBEDTLS_SSL_OUTBUFFER_LEN ( MBEDTLS_SSL_PLAIN_ADD \
+ MBEDTLS_SSL_COMPRESSION_ADD \
+ 29 /* counter + header + IV */ \
+ MBEDTLS_SSL_MAC_ADD \
+ MBEDTLS_SSL_PADDING_ADD \
)
#endif
/* Implementation that should never be optimized out by the compiler */
static void mbedtls_zeroize( void *v, size_t n ) {
volatile unsigned char *p = v; while( n-- ) *p++ = 0;
}
static pmbedtls_parame mbedtls_parame_new(size_t capacity)
{
pmbedtls_parame rb = (pmbedtls_parame)os_zalloc(sizeof(mbedtls_parame));
if (rb && capacity != 0){
rb->parame_datalen = capacity;
rb->parame_data = (uint8*)os_zalloc(rb->parame_datalen + 1);
if (rb->parame_data){
} else{
os_free(rb);
rb = NULL;
}
}
return rb;
}
static void mbedtls_parame_free(pmbedtls_parame *fp)
{
lwIP_ASSERT(fp);
lwIP_ASSERT(*fp);
os_free((*fp)->parame_data);
os_free(*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";
unsigned char *parame_data = NULL;
pmbedtls_parame mbedtls_obj = NULL;
if (type == ESPCONN_PK){
mbedtls_obj = def_private_key;
} else{
mbedtls_obj = def_certificate;
}
if (mbedtls_obj->parame_sec != 0){
#define DATA_OFFSET 4
uint32 data_len = mbedtls_obj->parame_datalen;
parame_data = (unsigned char *)os_zalloc(data_len + DATA_OFFSET);
if (parame_data){
spi_flash_read(mbedtls_obj->parame_sec * FLASH_SECTOR_SIZE, (uint32*)parame_data, data_len);
/*
* Determine buffer content. Buffer contains either one DER certificate or
* one or more PEM certificates.
*/
if ((char*)os_strstr(parame_data, begin) != NULL){
data_len ++;
parame_data[data_len - 1] = '\0';
}
}
*len = data_len;
} else{
parame_data = mbedtls_obj->parame_data;
*len = mbedtls_obj->parame_datalen;
}
*sec = mbedtls_obj->parame_sec;
return parame_data;
}
static int mbedtls_setsockopt(int sock_id, int level, int optname, int optval)
{
return setsockopt(sock_id, level, optname, (void*)&optval, sizeof(optval));
}
static int mbedtls_keep_alive(int sock_id, int onoff, int idle, int intvl, int cnt)
{
int ret = ERR_OK;
if (onoff == 0)
return mbedtls_setsockopt(sock_id, SOL_SOCKET, SO_KEEPALIVE, onoff);;
ret = mbedtls_setsockopt(sock_id, SOL_SOCKET, SO_KEEPALIVE, onoff);
lwIP_REQUIRE_NOERROR(ret, exit);
ret = mbedtls_setsockopt(sock_id, IPPROTO_TCP, TCP_KEEPALIVE, onoff);
lwIP_REQUIRE_NOERROR(ret, exit);
ret = mbedtls_setsockopt(sock_id, IPPROTO_TCP, TCP_KEEPIDLE, idle);
lwIP_REQUIRE_NOERROR(ret, exit);
ret = mbedtls_setsockopt(sock_id, IPPROTO_TCP, TCP_KEEPINTVL, intvl);
lwIP_REQUIRE_NOERROR(ret, exit);
ret = mbedtls_setsockopt(sock_id, IPPROTO_TCP, TCP_KEEPCNT, cnt);
lwIP_REQUIRE_NOERROR(ret, exit);
exit:
return ret;
}
#if defined(ESP8266_PLATFORM)
static pmbedtls_finished mbedtls_finished_new(int len)
{
pmbedtls_finished finished = (pmbedtls_finished)os_zalloc(sizeof(mbedtls_finished));
if (finished)
{
finished->finished_len = len;
finished->finished_buf = (uint8*)os_zalloc(finished->finished_len + 1);
if (finished->finished_buf)
{
}
else
{
os_free(finished);
finished = NULL;
}
}
return finished;
}
static void mbedtls_finished_free(pmbedtls_finished *pfinished)
{
lwIP_ASSERT(pfinished);
lwIP_ASSERT(*pfinished);
os_free((*pfinished)->finished_buf);
os_free(*pfinished);
*pfinished = NULL;
}
#endif
static pmbedtls_espconn mbedtls_espconn_new(void)
{
pmbedtls_espconn mbedtls_conn = NULL;
mbedtls_conn = (pmbedtls_espconn)os_zalloc(sizeof(mbedtls_espconn));
if (mbedtls_conn){
mbedtls_conn->proto.tcp = (esp_tcp *)os_zalloc(sizeof(esp_tcp));
if (mbedtls_conn->proto.tcp == NULL){
os_free(mbedtls_conn);
mbedtls_conn = NULL;
}
}
return mbedtls_conn;
}
static void mbedtls_espconn_free(pmbedtls_espconn *mbedtlsconn)
{
lwIP_ASSERT(mbedtlsconn);
lwIP_ASSERT(*mbedtlsconn);
os_free((*mbedtlsconn)->proto.tcp);
(*mbedtlsconn)->proto.tcp = NULL;
os_free((*mbedtlsconn));
*mbedtlsconn = NULL;
}
static pmbedtls_session mbedtls_session_new(void)
{
pmbedtls_session session = (pmbedtls_session)os_zalloc(sizeof(mbedtls_session));
if (session){
mbedtls_x509_crt_init(&session->cacert);
mbedtls_x509_crt_init(&session->clicert);
mbedtls_pk_init(&session->pkey);
// mbedtls_entropy_init(&session->entropy);
}
return session;
}
static void mbedtls_session_free(pmbedtls_session *session)
{
lwIP_ASSERT(session);
lwIP_ASSERT(*session);
mbedtls_x509_crt_free(&(*session)->cacert);
mbedtls_x509_crt_free(&(*session)->clicert);
mbedtls_pk_free(&(*session)->pkey);
// mbedtls_entropy_free(&(*session)->entropy);
os_free(*session);
*session = NULL;
}
static pmbedtls_msg mbedtls_msg_new(void)
{
pmbedtls_msg msg = (pmbedtls_msg)os_zalloc( sizeof(mbedtls_msg));
if (msg) {
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);
mbedtls_ctr_drbg_init(&msg->ctr_drbg);
mbedtls_entropy_init(&msg->entropy);
} else{
os_free(msg);
msg = NULL;
}
}
return msg;
}
static void mbedtls_msg_server_step(pmbedtls_msg msg)
{
lwIP_ASSERT(msg);
/*to prevent memory leaks, ensure that each allocated is deleted at every handshake*/
if (msg->psession){
mbedtls_session_free(&msg->psession);
}
#if defined(ESP8266_PLATFORM)
if (msg->quiet && msg->ssl.out_buf)
{
mbedtls_zeroize(msg->ssl.out_buf, MBEDTLS_SSL_OUTBUFFER_LEN);
os_free(msg->ssl.out_buf);
msg->ssl.out_buf = NULL;
}
#endif
mbedtls_entropy_free(&msg->entropy);
mbedtls_ssl_free(&msg->ssl);
mbedtls_ssl_config_free(&msg->conf);
mbedtls_ctr_drbg_free(&msg->ctr_drbg);
/*New connection ensure that each initial for next handshake */
os_bzero(msg, sizeof(mbedtls_msg));
msg->psession = mbedtls_session_new();
if (msg->psession){
mbedtls_net_init(&msg->fd);
mbedtls_ssl_init(&msg->ssl);
mbedtls_ssl_config_init(&msg->conf);
mbedtls_ctr_drbg_init(&msg->ctr_drbg);
mbedtls_entropy_init(&msg->entropy);
}
}
static void mbedtls_msg_free(pmbedtls_msg *msg)
{
lwIP_ASSERT(msg);
lwIP_ASSERT(*msg);
/*to prevent memory leaks, ensure that each allocated is deleted at every handshake*/
if ((*msg)->psession){
mbedtls_session_free(&((*msg)->psession));
}
#if defined(ESP8266_PLATFORM)
if ((*msg)->quiet && (*msg)->ssl.out_buf)
{
mbedtls_zeroize((*msg)->ssl.out_buf, MBEDTLS_SSL_OUTBUFFER_LEN);
os_free((*msg)->ssl.out_buf);
(*msg)->ssl.out_buf = NULL;
}
#endif
mbedtls_entropy_free(&(*msg)->entropy);
mbedtls_ssl_free(&(*msg)->ssl);
mbedtls_ssl_config_free(&(*msg)->conf);
mbedtls_ctr_drbg_free(&(*msg)->ctr_drbg);
os_free(*msg);
*msg = NULL;
}
static espconn_msg* mbedtls_msg_find(int sock)
{
espconn_msg *plist = NULL;
pmbedtls_msg msg = NULL;
for (plist = plink_active; plist != NULL; plist = plist->pnext) {
if(plist->pssl != NULL){
msg = plist->pssl;
if (msg->fd.fd == sock)
return plist;
}
}
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;
}
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)
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 (ret != 0) {
char vrfy_buf[512];
os_memset(vrfy_buf, 0, sizeof(vrfy_buf)-1);
mbedtls_x509_crt_verify_info(vrfy_buf, sizeof(vrfy_buf), "!", ret);
os_printf("%s\n", vrfy_buf);
Threadmsg->verify_result = ret;
return false;
} else
return true;
} else
return true;
}else
return false;
}
static void mbedtls_fail_info(espconn_msg *pinfo, int ret)
{
pmbedtls_msg TLSmsg = NULL;
lwIP_REQUIRE_ACTION(pinfo,exit,ret = ERR_ARG);
TLSmsg = pinfo->pssl;
lwIP_REQUIRE_ACTION(TLSmsg,exit,ret = ERR_ARG);
if (TLSmsg->quiet){
if (pinfo->preverse != NULL) {
os_printf("server's data invalid protocol\n");
} else {
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("Reason:[-0x%2x]\n",-ret);
/*Error code convert*/
ret = -ret;
if ((ret & 0xFF) != 0){
ret = ((ret >> 8) + ret);
} else{
ret >>= 8;
}
pinfo->hs_status = -ret;
pinfo->pespconn->state = ESPCONN_CLOSE;
mbedtls_net_free(&TLSmsg->fd);
exit:
return;
}
#if defined(ESP8266_PLATFORM)
int mbedtls_write_finished(mbedtls_ssl_context *ssl)
{
lwIP_ASSERT(ssl);
lwIP_ASSERT(ssl->p_bio);
int ret = ERR_OK;
int fd = ((mbedtls_net_context *) ssl->p_bio)->fd;
espconn_msg *Threadmsg = mbedtls_msg_find(fd);
lwIP_REQUIRE_ACTION(Threadmsg, exit, ret = ERR_MEM);
pmbedtls_msg TLSmsg = Threadmsg->pssl;
lwIP_REQUIRE_ACTION(TLSmsg, exit, ret = ERR_MEM);
TLSmsg->pfinished = mbedtls_finished_new(ssl->out_msglen + 29);
lwIP_REQUIRE_ACTION(TLSmsg->pfinished, exit, ret = ERR_MEM);
os_memcpy(TLSmsg->pfinished->finished_buf, ssl->out_ctr, TLSmsg->pfinished->finished_len);
exit:
return ret;
}
static int mbedtls_hanshake_finished(mbedtls_msg *msg)
{
lwIP_ASSERT(msg);
int ret = ERR_OK;
const size_t len = MBEDTLS_SSL_OUTBUFFER_LEN;
mbedtls_ssl_context *ssl = &msg->ssl;
lwIP_REQUIRE_ACTION(ssl, exit, ret = ERR_MEM);
pmbedtls_finished finished = msg->pfinished;
lwIP_REQUIRE_ACTION(finished, exit, ret = ERR_MEM);
ssl->out_buf = (unsigned char*)os_zalloc(len);
lwIP_REQUIRE_ACTION(ssl->out_buf, exit, ret = MBEDTLS_ERR_SSL_ALLOC_FAILED);
ssl->out_ctr = ssl->out_buf;
ssl->out_hdr = ssl->out_buf + 8;
ssl->out_len = ssl->out_buf + 11;
ssl->out_iv = ssl->out_buf + 13;
ssl->out_msg = ssl->out_buf + 29;
os_memcpy(ssl->out_ctr, finished->finished_buf, finished->finished_len);
mbedtls_finished_free(&msg->pfinished);
exit:
return ret;
}
#endif
static void mbedtls_handshake_succ(mbedtls_ssl_context *ssl)
{
lwIP_ASSERT(ssl);
if( ssl->handshake )
{
mbedtls_ssl_handshake_free( ssl->handshake );
mbedtls_ssl_transform_free( ssl->transform_negotiate );
mbedtls_ssl_session_free( ssl->session_negotiate );
os_free( ssl->handshake );
os_free( ssl->transform_negotiate );
os_free( ssl->session_negotiate );
ssl->handshake = NULL;
ssl->transform_negotiate = NULL;
ssl->session_negotiate = NULL;
}
if( ssl->session )
{
mbedtls_ssl_session_free( ssl->session );
os_free( ssl->session );
ssl->session = NULL;
}
#if defined(MBEDTLS_X509_CRT_PARSE_C)
if( ssl->hostname != NULL )
{
mbedtls_zeroize( ssl->hostname, os_strlen( ssl->hostname ) );
os_free( ssl->hostname );
ssl->hostname = NULL;
}
#endif
}
/******************************************************************************
* FunctionName : espconn_ssl_reconnect
* Description : reconnect with host
* Parameters : arg -- Additional argument to pass to the callback function
* Returns : none
*******************************************************************************/
static void espconn_close_internal(void *arg, netconn_event event_type)
{
espconn_msg *pssl_recon = arg;
struct espconn *espconn = NULL;
sint8 ssl_reerr = 0;
sint16 hs_status = 0;
lwIP_ASSERT(pssl_recon);
espconn = pssl_recon->preverse;
ssl_reerr = pssl_recon->pcommon.err;
hs_status = pssl_recon->hs_status;
if (espconn != NULL) {
espconn = pssl_recon->preverse;
} else {
espconn = pssl_recon->pespconn;
os_free(pssl_recon);
pssl_recon = NULL;
}
espconn_kill_oldest_pcb();
switch (event_type){
case NETCONN_EVENT_ERROR:
if (hs_status == ESPCONN_OK)
ESPCONN_EVENT_ERROR(espconn, ssl_reerr);
else
ESPCONN_EVENT_ERROR(espconn, hs_status);
break;
case NETCONN_EVENT_CLOSE:
if (hs_status == ESPCONN_OK)
ESPCONN_EVENT_CLOSED(espconn);
else
ESPCONN_EVENT_ERROR(espconn, hs_status);
break;
default:
break;
}
}
/******************************************************************************
* FunctionName : espconn_ssl_read_param_from_flash
* Description : load parameter from flash, toggle use two sector by flag value.
* 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)
{
if (param == NULL || (len + offset) > ESPCONN_SECURE_MAX_SIZE) {
return false;
}
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;
}
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;
}
break;
default:
return false;
break;
}
spi_flash_read(FILE_PARAM_START_SEC * 4096 + offset, param, len);
return true;
}
static bool mbedtls_msg_info_load(mbedtls_msg *msg, mbedtls_auth_info *auth_info)
{
const char* const begin = "-----BEGIN";
const char* const type_name = "private_key";
#define FILE_OFFSET 4
int ret = 0;
int32 offerset = 0;
uint8* load_buf = NULL;
size_t load_len = 0;
file_param *pfile_param = NULL;
pfile_param = (file_param *)os_zalloc( sizeof(file_param));
if (pfile_param==NULL)
return false;
again:
espconn_ssl_read_param_from_flash(&pfile_param->file_head, sizeof(file_head), offerset, auth_info);
pfile_param->file_offerset = offerset;
os_printf("%s %d, type[%s],length[%d]\n", __FILE__, __LINE__, pfile_param->file_head.file_name, pfile_param->file_head.file_length);
if (pfile_param->file_head.file_length == 0xFFFF){
os_free(pfile_param);
return false;
} else{
/*Optional is load the private key*/
if (auth_info->auth_type == ESPCONN_PK && os_memcmp(pfile_param->file_head.file_name, type_name, os_strlen(type_name)) != 0){
offerset += sizeof(file_head) + pfile_param->file_head.file_length;
goto again;
}
load_buf = (uint8_t *) os_zalloc( pfile_param->file_head.file_length + FILE_OFFSET);
if (load_buf == NULL){
os_free(pfile_param);
return false;
}
offerset = sizeof(file_head) + pfile_param->file_offerset;
espconn_ssl_read_param_from_flash(load_buf, pfile_param->file_head.file_length, offerset, auth_info);
}
load_len = pfile_param->file_head.file_length;
/*
* Determine buffer content. Buffer contains either one DER certificate or
* one or more PEM certificates.
*/
if ((char*)os_strstr(load_buf, begin) != NULL){
load_len += 1;
load_buf[load_len - 1] = '\0';
}
switch (auth_info->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;
}
exit:
os_free(load_buf);
os_free(pfile_param);
if (ret < 0){
return false;
}else{
return true;
}
}
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));
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 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);
}
}
/*Setup the stuff*/
ret = mbedtls_ssl_config_defaults(&msg->conf, auth_type, 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){
mbedtls_ssl_conf_authmode(&msg->conf, MBEDTLS_SSL_VERIFY_NONE);
}
mbedtls_ssl_conf_rng(&msg->conf, mbedtls_ctr_drbg_random, &msg->ctr_drbg);
mbedtls_ssl_conf_dbg(&msg->conf, NULL, NULL);
ret = mbedtls_ssl_setup(&msg->ssl, &msg->conf);
lwIP_REQUIRE_NOERROR(ret, exit);
mbedtls_ssl_set_bio(&msg->ssl, &msg->fd, mbedtls_net_send, mbedtls_net_recv, NULL);
exit:
if (ret != 0){
return false;
} else{
return true;
}
}
int __attribute__((weak)) mbedtls_parse_internal(int socket, sint8 error)
{
int ret = ERR_OK;
bool config_flag = false;
espconn_msg *Threadmsg = NULL;
pmbedtls_msg TLSmsg = NULL;
Threadmsg = mbedtls_msg_find(socket);
lwIP_REQUIRE_ACTION(Threadmsg, exit, ret = ERR_MEM);
TLSmsg = Threadmsg->pssl;
lwIP_REQUIRE_ACTION(TLSmsg, exit, ret = ERR_MEM);
if (error == ERR_OK){
if (TLSmsg->quiet){
uint8 *TheadBuff = NULL;
size_t ThreadLen = MBEDTLS_SSL_PLAIN_ADD;
TheadBuff = (uint8 *)os_zalloc(ThreadLen + 1);
lwIP_REQUIRE_ACTION(TheadBuff, exit, ret = ERR_MEM);
do {
os_memset(TheadBuff, 0, ThreadLen);
ret = mbedtls_ssl_read(&TLSmsg->ssl, TheadBuff, ThreadLen);
if (ret > 0){
ESPCONN_EVENT_RECV(Threadmsg->pespconn, TheadBuff, ret);
} else{
if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == 0){
ret = ESPCONN_OK;
break;
} else{
break;
}
}
} while(1);
os_free(TheadBuff);
TheadBuff = NULL;
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");
}
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);
system_overclock();
} else{
ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
lwIP_REQUIRE_NOERROR(ret, exit);
}
}
system_soft_wdt_stop();
while ((ret = mbedtls_ssl_handshake(&TLSmsg->ssl)) != 0) {
if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
ret = ESPCONN_OK;
break;
} else{
break;
}
}
system_soft_wdt_restart();
lwIP_REQUIRE_NOERROR(ret, exit);
/**/
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");
}
// 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);
#if defined(ESP8266_PLATFORM)
mbedtls_hanshake_finished(TLSmsg);
#endif
system_restoreclock();
TLSmsg->SentFnFlag = true;
ESPCONN_EVENT_CONNECTED(Threadmsg->pespconn);
} else{
lwIP_REQUIRE_NOERROR_ACTION(TLSmsg->verify_result, exit, ret = TLSmsg->verify_result);
}
}
} else if (error < 0){
Threadmsg->pcommon.err = error;
Threadmsg->pespconn->state = ESPCONN_CLOSE;
mbedtls_net_free(&TLSmsg->fd);
ets_post(lwIPThreadPrio, NETCONN_EVENT_ERROR, (uint32)Threadmsg);
} else {
ret = MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY;
lwIP_REQUIRE_NOERROR(ret, exit);
}
exit:
if (ret != ESPCONN_OK){
mbedtls_fail_info(Threadmsg, ret);
ets_post(lwIPThreadPrio, NETCONN_EVENT_CLOSE,(uint32)Threadmsg);
}
return ret;
}
int __attribute__((weak)) mbedtls_parse_thread(int socket, int event, int error)
{
int ret = ERR_OK;
espconn_msg *Threadmsg = NULL;
pmbedtls_msg TLSmsg = NULL;
Threadmsg = mbedtls_msg_find(socket);
lwIP_REQUIRE_ACTION(Threadmsg, exit, ret = ERR_MEM);
TLSmsg = Threadmsg->pssl;
lwIP_REQUIRE_ACTION(TLSmsg, exit, ret = ERR_MEM);
if (TLSmsg->quiet){
int out_msglen = TLSmsg->ssl.out_msglen + 5;
if (Threadmsg->pcommon.write_flag)
TLSmsg->record.record_len += error;
if (TLSmsg->record.record_len == out_msglen){
TLSmsg->record.record_len = 0;
Threadmsg->pcommon.write_flag = false;
if (Threadmsg->pcommon.cntr != 0){
espconn_ssl_sent(Threadmsg, Threadmsg->pcommon.ptrbuf, Threadmsg->pcommon.cntr);
} else{
TLSmsg->SentFnFlag = true;
ESPCONN_EVENT_SEND(Threadmsg->pespconn);
}
} else{
}
} else{
}
exit:
return ret;
}
/**
* @brief Api_Thread.
* @param events: contain the Api_Thread processing data
* @retval None
*/
static void
mbedtls_thread(os_event_t *events)
{
int ret = ESP_OK;
bool active_flag = false;
espconn_msg *Threadmsg = NULL;
espconn_msg *ListMsg = NULL;
pmbedtls_msg TLSmsg = NULL;
Threadmsg = (espconn_msg *)events->par;
lwIP_REQUIRE_ACTION(Threadmsg,exit,ret = ERR_ARG);
TLSmsg = Threadmsg->pssl;
lwIP_REQUIRE_ACTION(TLSmsg,exit,ret = ERR_ARG);
lwIP_REQUIRE_ACTION(Threadmsg->pespconn,exit,ret = ERR_ARG);
/*find the active connection*/
for (ListMsg = plink_active; ListMsg != NULL; ListMsg = ListMsg->pnext){
if (Threadmsg == ListMsg){
active_flag = true;
break;
}
}
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;
}
switch (events->sig){
case NETCONN_EVENT_ERROR:
espconn_close_internal(Threadmsg, NETCONN_EVENT_ERROR);
break;
case NETCONN_EVENT_CLOSE:
espconn_close_internal(Threadmsg, NETCONN_EVENT_CLOSE);
break;
default:
break;
}
}
exit:
return;
}
static void mbedtls_threadinit(void)
{
ets_task(mbedtls_thread, lwIPThreadPrio, lwIPThreadQueue, lwIPThreadQueueLen);
lwIPThreadFlag = true;
}
sint8 espconn_ssl_client(struct espconn *espconn)
{
int ret = ESPCONN_OK;
struct ip_addr ipaddr;
const char *server_name = NULL;
const char *server_port = NULL;
espconn_msg *pclient = NULL;
pmbedtls_msg mbedTLSMsg = NULL;
if (lwIPThreadFlag == false)
mbedtls_threadinit();
lwIP_REQUIRE_ACTION(espconn, exit, ret = ESPCONN_ARG);
pclient = (espconn_msg *)os_zalloc( sizeof(espconn_msg));
lwIP_REQUIRE_ACTION(pclient, exit, ret = ESPCONN_MEM);
mbedTLSMsg = mbedtls_msg_new();
lwIP_REQUIRE_ACTION(mbedTLSMsg, exit, ret = ESPCONN_MEM);
IP4_ADDR(&ipaddr, espconn->proto.tcp->remote_ip[0],espconn->proto.tcp->remote_ip[1],
espconn->proto.tcp->remote_ip[2],espconn->proto.tcp->remote_ip[3]);
server_name = ipaddr_ntoa(&ipaddr);
server_port = (const char *)sys_itoa(espconn->proto.tcp->remote_port);
/*start the connection*/
ret = mbedtls_net_connect(&mbedTLSMsg->fd, server_name, server_port, MBEDTLS_NET_PROTO_TCP);
lwIP_REQUIRE_NOERROR_ACTION(ret, exit, ret = ESPCONN_MEM);
espconn->state = ESPCONN_WAIT;
pclient->pespconn = espconn;
pclient->pssl = mbedTLSMsg;
pclient->preverse = NULL;
/*insert the node to the active connection list*/
espconn_list_creat(&plink_active, pclient);
exit:
if (ret != ESPCONN_OK){
if (mbedTLSMsg != NULL)
mbedtls_msg_free(&mbedTLSMsg);
if (pclient != NULL)
os_free(pclient);
}
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
* Parameters : void *arg -- client or server to send
* uint8* psent -- Data to send
* uint16 length -- Length of data to send
* Returns : none
*******************************************************************************/
void espconn_ssl_sent(void *arg, uint8 *psent, uint16 length)
{
espconn_msg *Threadmsg = arg;
uint16 out_msglen = length;
int ret = ESPCONN_OK;
lwIP_ASSERT(Threadmsg);
lwIP_ASSERT(psent);
lwIP_ASSERT(length);
pmbedtls_msg mbedTLSMsg = Threadmsg->pssl;
lwIP_ASSERT(mbedTLSMsg);
if (length > MBEDTLS_SSL_PLAIN_ADD){
out_msglen = MBEDTLS_SSL_PLAIN_ADD;
}
Threadmsg->pcommon.write_flag = true;
ret = mbedtls_ssl_write(&mbedTLSMsg->ssl, psent, out_msglen);
if (ret > 0){
Threadmsg->pcommon.ptrbuf = psent + ret;
Threadmsg->pcommon.cntr = length - ret;
} else{
if (ret == MBEDTLS_ERR_SSL_WANT_WRITE || ret == 0) {
} else{
mbedtls_fail_info(Threadmsg, ret);
ets_post(lwIPThreadPrio, NETCONN_EVENT_CLOSE,(uint32)Threadmsg);
}
}
}
/******************************************************************************
* FunctionName : espconn_ssl_disconnect
* Description : A new incoming connection has been disconnected.
* Parameters : espconn -- the espconn used to disconnect with host
* Returns : none
*******************************************************************************/
void espconn_ssl_disconnect(espconn_msg *Threadmsg)
{
lwIP_ASSERT(Threadmsg);
pmbedtls_msg mbedTLSMsg = Threadmsg->pssl;
lwIP_ASSERT(mbedTLSMsg);
mbedtls_net_free(&mbedTLSMsg->fd);
Threadmsg->pespconn->state = ESPCONN_CLOSE;
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
/*
* ESPRSSIF MIT License
*
* Copyright (c) 2016 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD>
*
* Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case,
* it is free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#include "lwip/netif.h"
#include "lwip/inet.h"
#include "netif/etharp.h"
#include "lwip/tcp.h"
#include "lwip/ip.h"
#include "lwip/init.h"
#include "ets_sys.h"
#include "os_type.h"
#ifdef MEMLEAK_DEBUG
static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
#endif
#if !defined(ESPCONN_MBEDTLS)
#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},
0
};
unsigned int max_content_len = ESPCONN_SECURE_DEFAULT_SIZE;
/******************************************************************************
* FunctionName : espconn_encry_connect
* Description : The function given as the connect
* Parameters : espconn -- the espconn used to listen the connection
* Returns : none
*******************************************************************************/
sint8 ICACHE_FLASH_ATTR
espconn_secure_connect(struct espconn *espconn)
{
struct ip_addr ipaddr;
struct ip_info ipinfo;
uint8 connect_status = 0;
uint16 current_size = 0;
if (espconn == NULL || espconn ->type != ESPCONN_TCP)
return ESPCONN_ARG;
if (wifi_get_opmode() == ESPCONN_STA){
wifi_get_ip_info(STA_NETIF, &ipinfo);
if (ipinfo.ip.addr == 0) {
return ESPCONN_RTE;
}
} else if (wifi_get_opmode() == ESPCONN_AP) {
wifi_get_ip_info(AP_NETIF, &ipinfo);
if (ipinfo.ip.addr == 0) {
return ESPCONN_RTE;
}
} else if (wifi_get_opmode() == ESPCONN_AP_STA) {
IP4_ADDR(&ipaddr, espconn->proto.tcp->remote_ip[0],
espconn->proto.tcp->remote_ip[1],
espconn->proto.tcp->remote_ip[2],
espconn->proto.tcp->remote_ip[3]);
ipaddr.addr <<= 8;
wifi_get_ip_info(AP_NETIF, &ipinfo);
ipinfo.ip.addr <<= 8;
espconn_printf("softap_addr = %x, remote_addr = %x\n", ipinfo.ip.addr, ipaddr.addr);
if (ipaddr.addr != ipinfo.ip.addr) {
connect_status = wifi_station_get_connect_status();
if (connect_status == STATION_GOT_IP) {
wifi_get_ip_info(STA_NETIF, &ipinfo);
if (ipinfo.ip.addr == 0)
return ESPCONN_RTE;
} else if (connect_status == STATION_IDLE) {
return ESPCONN_RTE;
} else {
return connect_status;
}
}
}
current_size = espconn_secure_get_size(ESPCONN_CLIENT);
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)
return ESPCONN_MEM;
return espconn_ssl_client(espconn);
}
/******************************************************************************
* FunctionName : espconn_encry_disconnect
* Description : The function given as the disconnect
* Parameters : espconn -- the espconn used to listen the connection
* Returns : none
*******************************************************************************/
sint8 ICACHE_FLASH_ATTR
espconn_secure_disconnect(struct espconn *espconn)
{
espconn_msg *pnode = NULL;
bool value = false;
if (espconn == NULL)
return ESPCONN_ARG;
value = espconn_find_connection(espconn, &pnode);
if (value){
if (pnode->pespconn->state == ESPCONN_CLOSE)
return ESPCONN_INPROGRESS;
espconn_ssl_disconnect(pnode);
return ESPCONN_OK;
}
else
return ESPCONN_ARG;
}
/******************************************************************************
* FunctionName : espconn_encry_sent
* Description : sent data for client or server
* Parameters : espconn -- espconn to set for client or server
* psent -- data to send
* length -- length of data to send
* Returns : none
*******************************************************************************/
sint8 ICACHE_FLASH_ATTR
espconn_secure_sent(struct espconn *espconn, uint8 *psent, uint16 length)
{
espconn_msg *pnode = NULL;
bool value = false;
if (espconn == NULL)
return ESPCONN_ARG;
espconn ->state = ESPCONN_WRITE;
value = espconn_find_connection(espconn, &pnode);
if (value){
pmbedtls_msg pssl = NULL;
pssl = pnode->pssl;
if (pssl->SentFnFlag){
pssl->SentFnFlag = false;
espconn_ssl_sent(pnode, psent, length);
return ESPCONN_OK;
}else
return ESPCONN_INPROGRESS;
}
else
return ESPCONN_ARG;
}
/******************************************************************************
* FunctionName : espconn_secure_send
* Description : send data for client or server
* Parameters : espconn -- espconn to set for client or server
* psent -- data to send
* length -- length of data to send
* Returns : none
*******************************************************************************/
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_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
* as client or server
* Parameters : level -- set for client or server
* 1: client,2:server,3:client and server
* flash_sector -- flash sector for save certificate
* Returns : result true or false
*******************************************************************************/
bool ICACHE_FLASH_ATTR espconn_secure_ca_enable(uint8 level, uint32 flash_sector )
{
if (level >= ESPCONN_MAX || level <= ESPCONN_IDLE || 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;
}
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;
}
/******************************************************************************
* FunctionName : espconn_secure_ca_disable
* Description : disable the certificate authenticate as client or server
* Parameters : level -- set for client or server
* 1: client,2:server,3:client and server
* Returns : result true or false
*******************************************************************************/
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) {
ssl_option.client.cert_ca_sector.flag = false;
ssl_option.server.cert_ca_sector.flag = false;
}
return true;
}
/******************************************************************************
* FunctionName : espconn_secure_cert_req_enable
* Description : enable the client certificate authenticate and set the flash sector
* as client or server
* Parameters : level -- set for client or server
* 1: client,2:server,3:client and server
* flash_sector -- flash sector for save certificate
* Returns : result true or false
*******************************************************************************/
bool ICACHE_FLASH_ATTR espconn_secure_cert_req_enable(uint8 level, uint32 flash_sector )
{
if (level >= ESPCONN_MAX || level <= ESPCONN_IDLE || 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;
}
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;
}
/******************************************************************************
* FunctionName : espconn_secure_ca_disable
* Description : disable the client certificate authenticate as client or server
* Parameters : level -- set for client or server
* 1: client,2:server,3:client and server
* Returns : result true or false
*******************************************************************************/
bool ICACHE_FLASH_ATTR espconn_secure_cert_req_disable(uint8 level)
{
if (level >= ESPCONN_MAX || level <= ESPCONN_IDLE)
return false;
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;
}
/******************************************************************************
* 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);
}
/******************************************************************************
* 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
/*
* ESPRSSIF MIT License
*
* Copyright (c) 2016 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD>
*
* Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case,
* it is free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#include "lwip/memp.h"
#include "lwip/def.h"
#include "ets_sys.h"
#include "os_type.h"
#include "sys/ringbuf.h"
#include "sys/socket.h"
#ifdef MEMLEAK_DEBUG
static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
#endif
ringbuf_t ringbuf_new(size_t capacity)
{
ringbuf_t rb = (ringbuf_t)os_zalloc(sizeof(struct ringbuf_t));
if (rb){
rb->size = capacity + 1;
rb->buf = (uint8*)os_zalloc(rb->size);
if (rb->buf){
ringbuf_reset(rb);
}else{
os_free(rb);
return NULL;
}
}
return rb;
}
size_t ringbuf_buffer_size(const struct ringbuf_t *rb)
{
return rb->size;
}
void ringbuf_reset(ringbuf_t rb)
{
rb ->head = rb->tail = rb->buf;
}
void ringbuf_free(ringbuf_t *rb)
{
lwIP_ASSERT(rb && *rb);
os_free((*rb)->buf);
os_free(*rb);
*rb = NULL;
}
size_t ringbuf_capacity(const struct ringbuf_t *rb)
{
return ringbuf_buffer_size(rb) - 1;
}
static const uint8_t* ringbuf_end(const struct ringbuf_t *rb)
{
return rb->buf + ringbuf_buffer_size(rb);
}
size_t ringbuf_bytes_free(const struct ringbuf_t *rb)
{
if (rb->head >= rb->tail){
return ringbuf_capacity(rb) - (rb->head - rb->tail);
}else{
return rb->tail - rb->head -1;
}
}
size_t ringbuf_bytes_used(const struct ringbuf_t *rb)
{
return ringbuf_capacity(rb) - ringbuf_bytes_free(rb);
}
int ringbuf_is_full(const struct ringbuf_t *rb)
{
return ringbuf_bytes_free(rb) == 0;
}
int ringbuf_is_empty(const struct ringbuf_t *rb)
{
return ringbuf_bytes_free(rb) == ringbuf_capacity(rb);
}
const void* ringbuf_tail(const struct ringbuf_t *rb)
{
return rb->tail;
}
const void* ringbuf_head(const struct ringbuf_t *rb)
{
return rb->head;
}
static uint8_t *ringbuf_nextp(ringbuf_t rb, const uint8_t *p)
{
lwIP_ASSERT((p >= rb->buf) && (p < ringbuf_end(rb)));
return rb->buf + ((++p -rb->buf) % ringbuf_buffer_size(rb));
}
size_t ringbuf_findchr(const struct ringbuf_t *rb, int c, size_t offset)
{
const uint8_t *bufend = ringbuf_end(rb);
size_t bytes_used = ringbuf_bytes_used(rb);
if (offset >= bytes_used)
return bytes_used;
const uint8_t *start = rb ->buf + (((rb->tail - rb->buf) + offset) % ringbuf_buffer_size(rb));
lwIP_ASSERT(bufend > start);
size_t n = LWIP_MIN(bufend - start, bytes_used - offset);
const uint8_t *found = (const uint8_t *)memchr(start, c, n);
if (found)
return offset + (found - start);
else
return ringbuf_findchr(rb, c, offset + n);
}
size_t ringbuf_memset(ringbuf_t dst, int c, size_t len)
{
const uint8_t *bufend = ringbuf_end(dst);
size_t nwritten = 0;
size_t count = LWIP_MIN(len, ringbuf_buffer_size(dst));
int overflow = count > ringbuf_bytes_free(dst);
while (nwritten != count){
lwIP_ASSERT(bufend > dst->head);
size_t n = LWIP_MIN(bufend - dst->head, count - nwritten);
os_memset(dst->head, c, n);
dst->head += n;
nwritten += n;
if (dst->head == bufend)
dst->head = dst->buf;
}
if (overflow){
dst->tail = ringbuf_nextp(dst, dst->head);
lwIP_ASSERT(ringbuf_is_full(dst));
}
return nwritten;
}
void *ringbuf_memcpy_into(ringbuf_t dst,const void *src, size_t count)
{
const uint8_t *u8src = src;
const uint8_t *bufend = ringbuf_end(dst);
int overflow = count > ringbuf_bytes_free(dst);
size_t nread = 0;
while (nread != count){
lwIP_ASSERT(bufend > dst->head);
size_t n = LWIP_MIN(bufend - dst->head, count - nread);
os_memcpy(dst->head, u8src + nread, n);
dst->head += n;
nread += n;
if (dst->head == bufend)
dst->head = dst->buf;
}
if (overflow) {
dst->tail = ringbuf_nextp(dst, dst->head);
lwIP_ASSERT(ringbuf_is_full(dst));
}
return dst->head;
}
void *ringbuf_memcpy_from(void *dst,ringbuf_t src, size_t count)
{
size_t bytes_used = ringbuf_bytes_used(src);
if (count > bytes_used)
return NULL;
const uint8_t *u8dst = dst;
const uint8_t *bufend = ringbuf_end(src);
size_t nwritten = 0;
while (nwritten != count){
lwIP_ASSERT(bufend > src->tail);
size_t n = LWIP_MIN(bufend - src->tail, count - nwritten);
os_memcpy((uint8_t*)u8dst + nwritten, src->tail, n);
src->tail += n;
nwritten += n;
if (src->tail == bufend)
src->tail = src->buf;
}
lwIP_ASSERT(count + ringbuf_bytes_used(src) == bytes_used);
return src->tail;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment